From 0631c813e27b6ad9580fdf8f821b3c3418287a60 Mon Sep 17 00:00:00 2001 From: bloqaudio Date: Fri, 18 Sep 2026 13:56:53 -0500 Subject: [PATCH 1/3] cmd: parse the port of an eee command from the start of the word parse_eee() sniffs word 2 for a trailing 'g' or 'm' to tell a speed from a port number, and advances idx past the digits to do so. The port branch then hands that advanced idx to cmd_parse_port_separator(), which expects the first character of the number and finds the separator instead, so it returns 0 and the command is rejected. Every other caller passes cmd_words_b[]. The result is that no eee command carrying a port number works, in any argument order, and the stored per-port lines a saved configuration replays are silently dropped. Reported by tofurky in issue #459, along with this fix. --- cmd_parser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd_parser.c b/cmd_parser.c index d4c4df8b..33d4c6c3 100644 --- a/cmd_parser.c +++ b/cmd_parser.c @@ -1419,7 +1419,7 @@ void parse_eee(void) speed_word = 2; } else if (cmd_is_space_or_nul(idx)) { // Word 2 is a port number - if (cmd_parse_port_separator(idx) == 0) { + if (cmd_parse_port_separator(cmd_words_b[2]) == 0) { cmd_error("Speed word invalid, use: [100m|1g|2g5]\n"); return; } From 0a65536a7ffcc97f83bcba6b20b2be6f0acc4e5f Mon Sep 17 00:00:00 2001 From: bloqaudio Date: Fri, 18 Sep 2026 13:57:07 -0500 Subject: [PATCH 2/3] web: send an eee command in the documented argument order The EEE toggle posted `eee `, the reverse of the `eee [on|off|status] [port] [100m|1g|2g5]` the parser and the documentation describe, so the switch answered with its usage line and the checkbox sprang back. The multi-page UI this replaced sent `eee on` with no port at all, which toggled every port instead of one. Moving the port to the end breaks the stored-configuration merge, which builds its drop key as a line prefix: with the port trailing, a per-port line matches the bare eee entry and replaces every eee line in the configuration rather than the one for that port. Give the command its own case beside the bandwidth one, so a line with a port replaces only that port and a line without one clears them all, and accept the optional speed word the command has always taken. Reported by tofurky in issue #459. --- html/app.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/html/app.js b/html/app.js index 0a50b322..497a2ce9 100644 --- a/html/app.js +++ b/html/app.js @@ -434,7 +434,7 @@ var CONF_CMDS=[ /^ingress(\s+\d{1,2}[tua])+$/,/^ingress\s+[tua]$/, /^port\s+\d{1,2}\s+(10m|100m|1g|2g5|5g|10g|auto|on|off)(\s+(half|full))?$/, /^port\s+\d{1,2}\s+name\s+\S+$/, - /^eee(\s+\d{1,2})?\s+(on|off)$/, + /^eee\s+(on|off)(\s+\d{1,2})?(\s+(100m|1g|2g5))?$/, /^mirror(\s+\d{1,2})(\s+\d{1,2}[tr]?)+$/,/^mirror\s+off$/, /^lag\s+[1-4](\s+\d{1,2})+$/,/^lag\s+[1-4]\s+d$/,/^laghash\s+[1-4](\s+\w+)+$/, /^isolate\s+\d{1,2}(\s+(off|\d{1,2}))+$/, @@ -1424,7 +1424,7 @@ function eeeLoad(){ var on=parseInt(p.eee,2)!==0; var sw=h("label",{class:"switch"},[ h("input",{type:"checkbox",onchange:function(){ - postCmd("eee "+p.portNum+" "+(this.checked?"on":"off")) + postCmd("eee "+(this.checked?"on":"off")+" "+p.portNum) .then(function(){setTimeout(eeeLoad,300)}).catch(function(){}); }}),h("i")]); sw.firstChild.checked=on; @@ -1616,7 +1616,7 @@ var CONF_OVERWRITE=[ /^vlan\s+\d{1,4}\s+mgmt$/,/^vlan\s+\d{1,4}(?!\s+mgmt\b)/, /^pvid\s+\d{1,2}\b/,/^ingress\b/, /^port\s+\d{1,2}(?!\s+name\b)/,/^port\s+\d{1,2}\s+name\b/, - /^eee\s+\d{1,2}\b/,/^eee\b/,/^mirror\b/, + /^mirror\b/, /^lag\s+\d\b/,/^laghash\s+\d\b/,/^isolate\s+\d{1,2}\b/, /^stp\s+(prio|hello|maxage|fwd|txhold|version)\b/, /^stp\s+(port\s+\d{1,2}|lag\s+[1-4])\s+(edge|cost|prio|guard|filter|p2p)\b/, @@ -1633,6 +1633,11 @@ function mergeConf(base,texts){ var m; if((m=line.match(/^vlan (\d{1,4}) d$/))){drop(new RegExp("^vlan "+m[1]+"( |$)"));return;} if((m=line.match(/^lag (\d) d$/))){drop(new RegExp("^lag(hash)? "+m[1]+"( |$)"));return;} + if((m=line.match(/^eee (on|off)(?: (\d{1,2}))?(?: (?:100m|1g|2g5))?$/))){ + if(m[2])drop(new RegExp("^eee (on|off) "+m[2]+"\\b")); + else drop(/^eee /); + conf.push(line);return; + } if(line==="mirror off"){drop(/^mirror /);return;} if(!isConfCmd(line))return; if((m=line.match(/^bw (in|out) (\d{1,2}) (\S+)$/))){ From fd058ea74dfa2af470cba040305ca9bb1e1b5d5c Mon Sep 17 00:00:00 2001 From: bloqaudio Date: Fri, 18 Sep 2026 14:59:47 -0500 Subject: [PATCH 3/3] port: name the port an eee command acted on the way the user wrote it port_eee_enable() and port_eee_disable() report the port with print_byte(), which prints the internal index in hex, so turning EEE off on port 5 answers "EEE off for 04". port_eee_status() in the same file already uses print_phys_port(), and the status listing it produces counts from one, so the two halves of the same command disagreed. Use print_phys_port() in all three messages. --- rtl837x_port.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rtl837x_port.c b/rtl837x_port.c index 8ee105c6..0383aae3 100644 --- a/rtl837x_port.c +++ b/rtl837x_port.c @@ -590,12 +590,12 @@ void port_eee_enable(__xdata uint8_t port,__xdata uint8_t speed) __banked if (machine.is_sfp[port]) { - print_string("EEE can't be enabled for SFP port "); print_byte(port); print_string("\n"); + print_string("EEE can't be enabled for SFP port "); print_phys_port(port); print_string("\n"); return; } REG_SET(RTL837X_EEE_CTRL_BASE + (port << 8), EEE_RX_ENABLE | EEE_TX_ENABLE); - print_string("EEE on for "); print_byte(port); print_string(" speed "); + print_string("EEE on for "); print_phys_port(port); print_string(" speed "); // Enable all speeds up to the specified speed if (speed & EEE_100) { print_string("100m\n"); @@ -654,7 +654,7 @@ void port_eee_disable(uint8_t port) __banked if (machine.is_sfp[port]) return; - print_string("EEE off for "); print_byte(port); write_char('\n'); + print_string("EEE off for "); print_phys_port(port); write_char('\n'); REG_SET(RTL837X_EEE_CTRL_BASE + (port << 8), 0); // Disable EEE advertisement for 100/1000BASE-T via EEE Advertisement Reg phy_write(port, PHY_MMD_AN, PHY_EEE_ADV, 0);