From 38b8e38c04d08b4f5d6702f428846e2e34b6e4c9 Mon Sep 17 00:00:00 2001
From: d00f <8052722+DrDoof@users.noreply.github.com>
Date: Sun, 6 Sep 2026 00:09:22 +0200
Subject: [PATCH 1/2] ports: show the SFP port in the table, and read the right
link state
The port table skipped every SFP port outright, so on a SWTGW218AS the
uplink simply was not there. Of the seven columns only Set Speed is
meaningless for a module: the name, the link speed and the devices behind
the port all are worth showing, and the name in particular was accepted on
another page and then never displayed anywhere. The MTU table further down
the same page has always drawn the port, so the page disagreed with itself.
Give an SFP port its row and leave the three control cells empty. Whether
speed and disable should work for a module is a separate question and
untested, so this does not offer a button for it.
The link state was read one port too far. main.js fills pState by
portNum - 1, updatePortTable() reads pState[i-1], and createPortTable()
read pState[i], so every row started out showing the next port's link
speed until the first refresh corrected it. On the last copper port that
meant showing the uplink's speed. Feeding the real status.json of a nine
port switch through both versions:
expected 7 7 7 1 7 1 7 7 6
before 7 7 1 7 1 7 7 6
after 7 7 7 1 7 1 7 7 6
Dropping the skip also removes a trap rather than papering over it.
updatePortTable() addresses rows as tbl.rows[i], which only lined up with
port i because the SFP port happens to be last on this board. With a
module in the middle every row after it would have been off by one.
---
html/ports.js | 13 ++++++-------
1 file changed, 6 insertions(+), 7 deletions(-)
diff --git a/html/ports.js b/html/ports.js
index cf99d47a..f84986b1 100644
--- a/html/ports.js
+++ b/html/ports.js
@@ -14,15 +14,16 @@ function createPortTable() {
+ '';
const dSwitch = ''
for (let i = 1; i <= numPorts; i++) {
- if (pIsSFP[i-1])
- continue;
- console.log("Table row: " + i + "pState: " + pState[i-2]);
const tr = tbl.insertRow();
let td = tr.insertCell(); td.appendChild(document.createTextNode(t('common_port') + i));
let portName = portNames[physToLogPort[i-1]] || '';
td = tr.insertCell(); td.appendChild(document.createTextNode(portName));
- td = tr.insertCell(); td.innerHTML = linkText(pState[i] + 1);
+ td = tr.insertCell(); td.innerHTML = linkText(pState[i-1] + 1);
tr.insertCell(); // filled by devRender()
+ if (pIsSFP[i-1]) {
+ tr.insertCell(); tr.insertCell(); tr.insertCell();
+ continue;
+ }
td = tr.insertCell(); td.innerHTML = sSelect.replaceAll("speed_sel", "speed_sel_" + i);
td = tr.insertCell(); td.innerHTML = dSwitch.replaceAll("disable_port", "disable_port_" + i)
.replace("portOnOff()", "portOnOff(" + i + ")");
@@ -67,9 +68,9 @@ function updatePortTable() {
if (tbl.rows.length <= 2 || !numPorts)
return;
for (let i = 1; i <= numPorts ; i++) {
+ tbl.rows[i].cells[2].innerHTML = linkText(pState[i-1]+1);
if (pIsSFP[i-1])
continue;
- tbl.rows[i].cells[2].innerHTML = linkText(pState[i-1]+1);
if (!clicked[i] && pState[i - 1] < 0) {
document.getElementById('speed_sel_' + i).disabled = true;
document.getElementById('disable_port_' + i).checked = true;
@@ -133,8 +134,6 @@ function devRender(entries) {
perPort[e.port].push(e.mac);
}
for (let i = 1; i <= numPorts; i++) {
- if (pIsSFP[i-1])
- continue;
var cell = tbl.rows[i].cells[3];
var macs = perPort[i] || [];
if (macs.length == 1) {
From 30547cc453d7b99099b7913f1c2d7c1a978b86b6 Mon Sep 17 00:00:00 2001
From: d00f <8052722+DrDoof@users.noreply.github.com>
Date: Sun, 6 Sep 2026 21:13:23 +0200
Subject: [PATCH 2/2] ports: drop the SFP row, keep the link-state index fix
Leaving SFP ports out of the table is deliberate for now, and being able to
force a module's speed belongs in a feature of its own rather than arriving
inside a fix, so that half goes again.
What remains is the off-by-one: createPortTable() read pState[i] where the
array is filled by portNum - 1, so every row started out showing the next
port's link speed until the first refresh corrected it. The debug line above
it goes too; it printed a third index, pState[i-2].
---
html/ports.js | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/html/ports.js b/html/ports.js
index f84986b1..f76534f2 100644
--- a/html/ports.js
+++ b/html/ports.js
@@ -14,16 +14,14 @@ function createPortTable() {
+ '';
const dSwitch = ''
for (let i = 1; i <= numPorts; i++) {
+ if (pIsSFP[i-1])
+ continue;
const tr = tbl.insertRow();
let td = tr.insertCell(); td.appendChild(document.createTextNode(t('common_port') + i));
let portName = portNames[physToLogPort[i-1]] || '';
td = tr.insertCell(); td.appendChild(document.createTextNode(portName));
td = tr.insertCell(); td.innerHTML = linkText(pState[i-1] + 1);
tr.insertCell(); // filled by devRender()
- if (pIsSFP[i-1]) {
- tr.insertCell(); tr.insertCell(); tr.insertCell();
- continue;
- }
td = tr.insertCell(); td.innerHTML = sSelect.replaceAll("speed_sel", "speed_sel_" + i);
td = tr.insertCell(); td.innerHTML = dSwitch.replaceAll("disable_port", "disable_port_" + i)
.replace("portOnOff()", "portOnOff(" + i + ")");
@@ -68,9 +66,9 @@ function updatePortTable() {
if (tbl.rows.length <= 2 || !numPorts)
return;
for (let i = 1; i <= numPorts ; i++) {
- tbl.rows[i].cells[2].innerHTML = linkText(pState[i-1]+1);
if (pIsSFP[i-1])
continue;
+ tbl.rows[i].cells[2].innerHTML = linkText(pState[i-1]+1);
if (!clicked[i] && pState[i - 1] < 0) {
document.getElementById('speed_sel_' + i).disabled = true;
document.getElementById('disable_port_' + i).checked = true;
@@ -134,6 +132,8 @@ function devRender(entries) {
perPort[e.port].push(e.mac);
}
for (let i = 1; i <= numPorts; i++) {
+ if (pIsSFP[i-1])
+ continue;
var cell = tbl.rows[i].cells[3];
var macs = perPort[i] || [];
if (macs.length == 1) {