From 4cef63200ff749a9c5545ef3292d0b971fa1d457 Mon Sep 17 00:00:00 2001 From: "Mark H. Spatz" Date: Sat, 7 Mar 2026 14:48:04 -0500 Subject: [PATCH] Fix "Get Configuration" on vlan.html I noticed that entering some vlan config, clicking "Update/Create", then clicking "Get Configuration" resulted in Tagged/Untagged/PVID displaying completely wrong data. It looks like the parisng in fetchVLAN() in vlan.js was just completely disconnected from the layout of the registers read by vlan_get() in rtl837x_port.c. Who knows how that happened. 1. Fix fetchVLAN() member/untag parsing: the old code read bits [9:0] as untagged and bits [10:19] as tagged, but the VLAN table register layout is members in [9:0] and untag in [19:10]. Now correctly derives tagged (member && !untag) and untagged (member && untag). 2. Add PVID to vlan.json response: PVID is stored per-port in separate PVID registers (RTL837x_PVID_BASE_REG), not in the VLAN table entry. The old code nonsensically tried to read it from bits [20:29] of the VLAN table. Add port_pvid_get() and build a pvid bitmask in send_vlan() so the JS can parse it correctly. 3. Remove auto-PVID logic from setC(): setC() is called by fetchVLAN() while it's loading existing config, and so this logic mangled the display of the existing config. Also, it doesn't make sense to auto-set the PVID for tagged members (PVID relates to untagged ingress.) --- html/vlan.js | 17 +++++++++-------- httpd/page_impl.c | 8 ++++++++ rtl837x_port.c | 11 +++++++++++ rtl837x_port.h | 1 + 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/html/vlan.js b/html/vlan.js index d783534..8a2c3b1 100644 --- a/html/vlan.js +++ b/html/vlan.js @@ -39,11 +39,6 @@ function vlanForm() { function setC(t, p, c){ document.getElementById(t+'port'+p).checked=c; - // When a tagged port is checked, automatically select the PVID port as well - const tportElem = document.getElementById('tport'+p); - if (tportElem && tportElem.checked) { - document.getElementById('pport'+p).checked=true; - } } function utClicked(t){ @@ -70,10 +65,16 @@ function fetchVLAN() { console.log("VLAN: ", JSON.stringify(s)); m = parseInt(s.members, 16); document.getElementById('vname').value = s.name; + var members = m & 0x3FF; + var untag = (m >> 10) & 0x3FF; + var pvid = parseInt(s.pvid, 16); for (let i = 1; i <= numPorts; i++) { - setC('t', i, (m>>(10+i-1))&1); - setC('u', i, (m>>(i-1))&1); - setC('p', i, (m>>(20+i-1))&1); + var bit = i - 1; + var isMember = (members >> bit) & 1; + var isUntag = (untag >> bit) & 1; + setC('t', i, isMember && !isUntag); + setC('u', i, isMember && isUntag); + setC('p', i, (pvid >> bit) & 1); } } }; diff --git a/httpd/page_impl.c b/httpd/page_impl.c index 9769311..0618758 100644 --- a/httpd/page_impl.c +++ b/httpd/page_impl.c @@ -270,6 +270,14 @@ void send_vlan(uint16_t vlan) while(vlan_names[n] && vlan_names[n] != ' ') char_to_html(vlan_names[n++]); } + slen += strtox(outbuf + slen, "\",\"pvid\":\"0x"); + uint16_t pvid_mask = 0; + for (uint8_t i = machine.min_port; i <= machine.max_port; i++) { + if (port_pvid_get(i) == vlan) + pvid_mask |= (1 << i); +} + byte_to_html(pvid_mask >> 8); + byte_to_html(pvid_mask); slen += strtox(outbuf + slen, "\"}"); } diff --git a/rtl837x_port.c b/rtl837x_port.c index 4e12a6d..1a28c69 100644 --- a/rtl837x_port.c +++ b/rtl837x_port.c @@ -78,6 +78,17 @@ void port_pvid_set(uint8_t port, __xdata uint16_t pvid) __banked } } +uint16_t port_pvid_get(uint8_t port) __banked +{ + uint16_t reg = RTL837x_PVID_BASE_REG + ((port >> 1) << 2); + reg_read_m(reg); + if (port & 0x1) { + return (sfr_data[1] << 4) | (sfr_data[2] >> 4); + } else { + return ((sfr_data[2] & 0x0f) << 8) | sfr_data[3]; + } +} + void vlan_delete(uint16_t vlan) __banked { diff --git a/rtl837x_port.h b/rtl837x_port.h index 480f2e8..60e2282 100644 --- a/rtl837x_port.h +++ b/rtl837x_port.h @@ -28,6 +28,7 @@ int8_t vlan_get(register uint16_t vlan) __banked; __xdata uint16_t vlan_name(register uint16_t vlan) __banked; void vlan_setup(void) __banked; void port_pvid_set(uint8_t port, __xdata uint16_t pvid) __banked; +uint16_t port_pvid_get(uint8_t port) __banked; void vlan_create(void) __banked; void vlan_delete(uint16_t vlan) __banked; void port_mirror_set(register uint8_t port, __xdata uint16_t rx_pmask, __xdata uint16_t tx_pmask) __banked;