From a6c5f558bf02e83420b709923fa044d7d57947a7 Mon Sep 17 00:00:00 2001 From: d00f Date: Wed, 12 Aug 2026 19:34:25 +0200 Subject: [PATCH] stp: do not arm the management failsafe while the config replays The failsafe is a commit confirm window for an interactive change: turn STP on, and if management goes quiet for stp_failsafe_s seconds the switch undoes it. The three places that arm it sit in the command parser, and execute_config() drives that same parser at boot, so a saved "stp on" arms the window too. A switch that reboots with nobody watching then turns its own STP back off. Measured on a SWTGW218AS with "stp failsafe 180" in the saved config: cold boot, no HTTP and no console for four minutes, and "STP failsafe: disabling" arrives on time, with stp.json reporting on:0 and fsT:1. execute_config() already clears save_cmd while it replays and sets it again at the end, so the three parser sites can just test it. The two on the protocol side, the loop latch and the root guard, stay unconditional. They react to what arrived on the wire, which is the case the failsafe exists for, and they only run once the replay is long finished. BANK2 grows 24 bytes. Nothing else moves. --- rtl837x_stp.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/rtl837x_stp.c b/rtl837x_stp.c index a0387e4..e4af019 100644 --- a/rtl837x_stp.c +++ b/rtl837x_stp.c @@ -34,6 +34,7 @@ extern __xdata uint16_t management_vlan; /* owned by rtlplayground.c; suppressed extern __xdata uint8_t cmd_buffer[CMD_BUF_SIZE]; extern __xdata uint8_t cmd_words_len; extern __xdata uint8_t cmd_words_b[15]; +extern __xdata char save_cmd; /* 0 while execute_config() replays the saved config */ uint8_t cmd_compare(uint8_t start, __code uint8_t * cmd); uint8_t atoi_byte(__xdata uint8_t *out, uint8_t idx); @@ -741,7 +742,7 @@ void stp_parse(void) __banked __reentrant print_string("STP enabled\n"); stp_failsafe_tripped = 0; stp_failsafe_cnt = stp_failsafe_s; - stp_failsafe_armed = stp_failsafe_s ? 1 : 0; + stp_failsafe_armed = (stp_failsafe_s && save_cmd) ? 1 : 0; mgmt_alive = 0; stpEnabled = 1; stp_setup(); @@ -775,7 +776,7 @@ void stp_parse(void) __banked __reentrant if (stpEnabled) { /* (re)join: listen first */ stp_state_set(port, 0b01); port_timers[port] = (uint16_t)stp_fwddelay_s * STP_HZ; - if (stp_failsafe_s) { + if (stp_failsafe_s && save_cmd) { stp_failsafe_armed = 1; stp_failsafe_cnt = stp_failsafe_s; mgmt_alive = 0; @@ -885,7 +886,7 @@ void stp_parse(void) __banked __reentrant /* 0 never arms; otherwise the length of the armed window */ stp_failsafe_s = stp_scratch; stp_failsafe_cnt = stp_scratch; - stp_failsafe_armed = (stp_scratch && stpEnabled) ? 1 : 0; + stp_failsafe_armed = (stp_scratch && stpEnabled && save_cmd) ? 1 : 0; mgmt_alive = 0; } else { goto err;