From eb51128ec74cf3a23487ef2846afe29a1fa0bc2d Mon Sep 17 00:00:00 2001 From: d00f <8052722+DrDoof@users.noreply.github.com> Date: Wed, 14 Oct 2026 22:45:22 +0200 Subject: [PATCH] stp: a port without carrier does not become the root port stp_reselect() took every port with fresh information as a candidate, so a BPDU credited to a port whose carrier the once-a-second link poll had not seen yet made that port the root port before the port was set up for it. A candidate now needs its link bit as well; the poll that sees the carrier a moment later runs the selection again. Scenario 54. --- rtl837x_stp.c | 2 +- test/stp/stp_sim.c | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/rtl837x_stp.c b/rtl837x_stp.c index 2976206e..b147c3c2 100644 --- a/rtl837x_stp.c +++ b/rtl837x_stp.c @@ -660,7 +660,7 @@ static void stp_reselect(void) continue; if (!(stp_pflags[stp_j] & STP_PF_ENABLED) || (stp_pflags[stp_j] & STP_PF_ROOTGUARD)) continue; - if (!stp_info_fresh(stp_j)) + if (!((stp_link_now >> stp_j) & 1) || !stp_info_fresh(stp_j)) continue; if (!cmpBytes(stp_dbridge[stp_j].mac, uip_ethaddr.addr, 6)) continue; diff --git a/test/stp/stp_sim.c b/test/stp/stp_sim.c index 34149c2b..e9e68e72 100644 --- a/test/stp/stp_sim.c +++ b/test/stp/stp_sim.c @@ -2113,6 +2113,24 @@ static void scen_tc_needs_forwarding(void) check(stp_tc_count == tc + 1 && flush_count[0] > 0, "now the same TC is passed on"); } +static void scen_root_port_needs_link(void) +{ + struct sim_bpdu r; + + printf("54. a BPDU credited to a port without carrier does not pick the root port\n"); + reset_all(); + links_set(1 << 2); + secs(1); + r = root_on(0); + bpdu_in(&r); + tick(2); + check(stp_root_port == 0xff, "the bridge stays its own root"); + links_set((1 << 0) | (1 << 2)); + secs(1); + check(stp_root_port == 0, "once the carrier is seen the port becomes the root port"); + check_state(0, 3, "and forwards"); +} + int main(int argc, char **argv) { verbose = argc > 1 && argv[1][0] == '-' ? (argv[1][1] == 'd' ? 2 : 1) : 0; @@ -2169,6 +2187,7 @@ int main(int argc, char **argv) scen_last_tc(); scen_lag(); scen_tc_needs_forwarding(); + scen_root_port_needs_link(); if (failures) { printf("\n%d check(s) failed\n", failures); return 1;