From 85d1d7520a417d95abdf7fd081f1d302e27690f6 Mon Sep 17 00:00:00 2001 From: d00f <8052722+DrDoof@users.noreply.github.com> Date: Mon, 17 Aug 2026 18:58:44 +0200 Subject: [PATCH] stp: send BPDUs with a per port source address 802.1D puts the port's own address in the source field and the bridge address only in the Bridge Identifier. We used the bridge address for both, and on this hardware that costs the management path. Measured on a SWTGW218AS: the ASIC learns the source address of a frame addressed to 01:80:c2:00:00:00, and the bridge's own address is not exempt. A BPDU that leaves a blocked port and comes back on a forwarding one therefore moves the management address off the CPU port, and frames for it are then sent down that port instead of to the CPU. Traffic between other stations is unaffected, which is what makes it look like the CPU port has been blocked. The derived address keeps the bridge address and sets the locally administered bit, so it differs from the bridge address in the first octet for any globally assigned OUI, with the port number in the low nibble of the last octet. Nothing here reads the source address of a received BPDU; the loop check compares the Bridge Identifier. --- rtl837x_stp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rtl837x_stp.c b/rtl837x_stp.c index 46e8770..f82afa3 100644 --- a/rtl837x_stp.c +++ b/rtl837x_stp.c @@ -381,6 +381,8 @@ void stp_cnf_send(uint8_t port) __reentrant stp_tx_flags_extra = 0; memcpy(STP_O->src_addr, uip_ethaddr.addr, 6); + STP_O->src_addr[0] |= 0x02; + STP_O->src_addr[5] = (uip_ethaddr.addr[5] & 0xf0) | port; memcpy(STP_O->root.mac, root_bridge.mac, 6); memcpy(STP_O->bridge.mac, uip_ethaddr.addr, 6);