Skip to content

Commit d13fa62

Browse files
committed
Add GPON stick compatibility dialog to SFP tweaks (#596)
* Add Zyxel PMG3000-D20B pre-flight instructions dialog to SFP tweaks * Restructure dialog for general GPON stick guidance with Zyxel-specific commands * Add removal guidance to GPON compatibility alert * Fix HTML comment to match broadened dialog scope * Fix modal scrolling on mobile - allow overlay to scroll when content exceeds viewport
1 parent 199fc07 commit d13fa62

1 file changed

Lines changed: 118 additions & 3 deletions

File tree

src/NetworkOptimizer.Web/Components/Pages/PerformanceTweaks.razor

Lines changed: 118 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@
323323
@if (def.Id == "sfp-sgmiiplus" || def.Id == "sfp-sgmiiplus-port6")
324324
{
325325
<div class="alert alert-warning" style="margin-top: 0.75rem;">
326-
<strong>Compatibility note:</strong> Zyxel PMG3000-D20B support is currently being tested. If you have this module (or another GPON stick that may not negotiate 2.5 G cleanly with the UniFi host), feel free to try the patch, but be prepared to remove it if the link doesn't come up and stabilize.
326+
<strong>GPON stick compatibility:</strong> Some SFP GPON ONTs (particularly the Zyxel PMG3000-D20B) may not negotiate 2.5 G cleanly with the UniFi host without extra configuration. If your stick won't link up after deploying, <a href="javascript:void(0)" @onclick="() => _showZyxelInstructions = true" @onclick:stopPropagation="true" class="pt-inline-link">check these pre-flight steps</a>, and Remove the SFP tweak to restore the link if all else fails.
327327
</div>
328328
}
329329

@@ -524,6 +524,57 @@
524524
</div>
525525
}
526526

527+
<!-- GPON Stick Pre-Flight Instructions Modal -->
528+
@if (_showZyxelInstructions)
529+
{
530+
<div class="pt-modal-overlay" @onclick="() => _showZyxelInstructions = false">
531+
<div class="pt-modal pt-modal-wide" @onclick:stopPropagation="true">
532+
<div class="pt-modal-header">
533+
<h3>GPON Stick Compatibility - Pre-Flight Steps</h3>
534+
</div>
535+
<div class="pt-modal-body pt-instructions">
536+
<p>Some GPON ONT SFP modules default to a link mode that won't negotiate 2.5 G with the UniFi host. If your stick doesn't link up after deploying the SGMII+ patch, you likely need to switch it to 2.5/1 G auto-negotiation mode first.</p>
537+
538+
<p>The general process is:</p>
539+
<ol>
540+
<li>SSH into your SFP stick and configure it for 2.5/1 G auto-negotiation</li>
541+
<li>Deploy the SGMII+ patch from this page</li>
542+
<li>If it links up, persist the configuration so it survives SFP reboots</li>
543+
</ol>
544+
<p>The exact commands vary by stick. If yours isn't listed below, check your stick's documentation or community wiki for the equivalent auto-negotiation command.</p>
545+
546+
<h4>If it doesn't work</h4>
547+
<p>If the link and data path don't come up after deploying, use the Remove button on the tweak card to unload the module - this should restore normal functionality. If the link still doesn't recover after removal, reboot the SFP stick.</p>
548+
549+
<h4>Zyxel PMG3000-D20B</h4>
550+
551+
<p><strong>Configure auto-negotiation.</strong> SSH to the stick and run:</p>
552+
<pre><code>linuxshell
553+
onu lanpcs 0 1 -1 4 15 1 0 5 0 0 1518 1 3 0 0 0</code></pre>
554+
<p>The <code>linuxshell</code> command breaks out of the Zyxel CLI into a Linux shell. The <code>onu lanpcs</code> command switches the SFP interface to 2.5/1 G auto-negotiation mode. It resets on SFP reboot, so you always have a way out.</p>
555+
556+
<p><strong>Deploy the patch.</strong> Come back here and deploy the SGMII+ patch. After about a minute, the link should come up and you should have data path again.</p>
557+
558+
<p><strong>Persist across reboots.</strong> If it works, make the command run automatically on every SFP boot. SSH to the stick again and run:</p>
559+
<pre><code># Enter the Linux shell first (if a new SSH session)
560+
linuxshell
561+
562+
# Check if the boot script file already exists
563+
ls -la /var/config/run-syslog.sh</code></pre>
564+
565+
<p>If the file <strong>does not exist</strong> (you see "No such file or directory"):</p>
566+
<pre><code>echo 'onu lanpcs 0 1 -1 4 15 1 0 5 0 0 1518 1 3 0 0 0' > /var/config/run-syslog.sh</code></pre>
567+
568+
<p>If the file <strong>already exists</strong>, safely append the command:</p>
569+
<pre><code>grep -q 'lanpcs' /var/config/run-syslog.sh 2>/dev/null || echo 'onu lanpcs 0 1 -1 4 15 1 0 5 0 0 1518 1 3 0 0 0' >> /var/config/run-syslog.sh</code></pre>
570+
</div>
571+
<div class="pt-modal-footer">
572+
<button class="btn btn-primary btn-sm" @onclick="() => _showZyxelInstructions = false">Got It</button>
573+
</div>
574+
</div>
575+
</div>
576+
}
577+
527578
<style>
528579
.pt-container {
529580
display: flex;
@@ -723,17 +774,20 @@
723774
bottom: 0;
724775
background: rgba(0, 0, 0, 0.6);
725776
display: flex;
726-
align-items: center;
777+
align-items: flex-start;
727778
justify-content: center;
728779
z-index: 1000;
729-
padding: 1rem;
780+
padding: 2rem 1rem;
781+
overflow-y: auto;
782+
-webkit-overflow-scrolling: touch;
730783
}
731784
732785
.pt-modal {
733786
background: var(--bg-secondary);
734787
border-radius: 0.75rem;
735788
max-width: 540px;
736789
width: 100%;
790+
margin: auto 0;
737791
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.4);
738792
}
739793
@@ -800,6 +854,66 @@
800854
width: 100%;
801855
}
802856
}
857+
858+
/* Inline action link */
859+
.pt-inline-link {
860+
color: var(--primary-color);
861+
text-decoration: underline;
862+
cursor: pointer;
863+
}
864+
865+
.pt-inline-link:hover {
866+
color: var(--primary-hover);
867+
}
868+
869+
/* Wide modal variant */
870+
.pt-modal-wide {
871+
max-width: 640px;
872+
}
873+
874+
/* Instructional modal body */
875+
.pt-instructions h4 {
876+
color: var(--text-primary);
877+
font-size: 0.95rem;
878+
margin: 1.25rem 0 0.5rem 0;
879+
}
880+
881+
.pt-instructions h4:first-child {
882+
margin-top: 0;
883+
}
884+
885+
.pt-instructions p {
886+
color: var(--text-secondary);
887+
font-size: 0.85rem;
888+
line-height: 1.5;
889+
margin: 0 0 0.5rem 0;
890+
}
891+
892+
.pt-instructions pre {
893+
background: var(--bg-primary);
894+
border-radius: 0.375rem;
895+
padding: 0.75rem 1rem;
896+
margin: 0.5rem 0 0.75rem 0;
897+
overflow-x: auto;
898+
}
899+
900+
.pt-instructions code {
901+
font-family: 'SF Mono', 'Cascadia Code', 'Fira Code', monospace;
902+
font-size: 0.8rem;
903+
color: var(--text-primary);
904+
}
905+
906+
.pt-instructions ol {
907+
color: var(--text-secondary);
908+
font-size: 0.85rem;
909+
line-height: 1.5;
910+
margin: 0 0 0.75rem 0;
911+
padding-left: 1.25rem;
912+
}
913+
914+
.pt-instructions li {
915+
margin-bottom: 0.25rem;
916+
}
803917
</style>
804918

805919
@code {
@@ -819,6 +933,7 @@
819933
private bool _confirmRisk;
820934
private bool _showRemoveConfirm;
821935
private string? _pendingRemoveTweakId;
936+
private bool _showZyxelInstructions;
822937
private bool _allConfirmed => _confirmBackup && _confirmBackupDownloaded && _confirmWarranty && _confirmRisk;
823938
private bool _canDeploy => _status?.UdmBootInstalled == true && _status?.FirmwareSupported == true;
824939
private List<string> _deploySteps = new();

0 commit comments

Comments
 (0)