From 2cf60e177b4cfc13a2b9164e23c419445e459bd1 Mon Sep 17 00:00:00 2001 From: d00f Date: Sat, 8 Aug 2026 05:04:42 +0200 Subject: [PATCH] stp: derive the BPDU flags from the port state Every RST BPDU we sent carried flags 0x3c - designated, learning, forwarding - whatever the port was actually doing. A blocked port kept announcing itself as forwarding, and the root port would have called itself designated. Nothing on this bench acted on it, but it is a lie in the protocol frame and the kind that surfaces in somebody else's mixed network. Derive the flags instead: the root port reports the root role, every other transmitting port is designated (alternates do not transmit at all), and the learning and forwarding bits mirror the ASIC state, so a listening port now sends 0x0c. TC and TCA stay dynamic as before. Legacy Config BPDUs are unchanged - their flags only ever carried TC and TCA. Costs nothing in internal RAM; the state comes from the register scratch that is already there. --- rtl837x_stp.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/rtl837x_stp.c b/rtl837x_stp.c index 1ce1a2a..8999e3b 100644 --- a/rtl837x_stp.c +++ b/rtl837x_stp.c @@ -289,8 +289,20 @@ void stp_cnf_send(uint8_t port) __reentrant STP_O->msg_len = HTONS(0x27); STP_O->version = 0x02; /* RSTP */ STP_O->bpdu_type = 0x02; /* Rapid Spanning Tree BPDU */ - /* flags: role designated (0b11 << 2) + learning + forwarding */ - STP_O->flags = 0x3c; + /* Flags describe this port, so derive them instead of announcing + * designated+learning+forwarding unconditionally: a blocked port + * claiming to forward, or the root port claiming designated, is a + * lie on the wire even when nothing downstream acts on it (yet). + * Role is root on the root port and designated everywhere else - + * there is no alternate/backup role computation, so a port blocked + * by loop detection still transmits as designated, just with the + * learning and forwarding bits clear. Those two mirror the ASIC + * state (0b11 = forwarding); a listening or blocked port sends + * neither. */ + reg_read_m(RTL837X_MSTP_STATES); + STP_O->flags = (uint8_t)((port == stp_root_port ? 0b10 : 0b11) << 2); + if (((sfr_data[3 - (port >> 2)] >> ((port << 1) & 0x7)) & 0b11) == 0b11) + STP_O->flags |= 0x30; /* learning + forwarding */ } else { /* 802.3 length = LLC (3) + Config BPDU body (35) */ STP_O->msg_len = HTONS(0x26);