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.
This commit is contained in:
d00f
2026-08-18 23:28:38 +02:00
committed by d00f
parent 0ce5fb4af3
commit 2cf60e177b
+14 -2
View File
@@ -289,8 +289,20 @@ void stp_cnf_send(uint8_t port) __reentrant
STP_O->msg_len = HTONS(0x27); STP_O->msg_len = HTONS(0x27);
STP_O->version = 0x02; /* RSTP */ STP_O->version = 0x02; /* RSTP */
STP_O->bpdu_type = 0x02; /* Rapid Spanning Tree BPDU */ STP_O->bpdu_type = 0x02; /* Rapid Spanning Tree BPDU */
/* flags: role designated (0b11 << 2) + learning + forwarding */ /* Flags describe this port, so derive them instead of announcing
STP_O->flags = 0x3c; * 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 { } else {
/* 802.3 length = LLC (3) + Config BPDU body (35) */ /* 802.3 length = LLC (3) + Config BPDU body (35) */
STP_O->msg_len = HTONS(0x26); STP_O->msg_len = HTONS(0x26);