Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: dsa: tag_brcm: do not mark link local traffic as offloaded

Broadcom switches locally terminate link local traffic and do not
forward it, so we should not mark it as offloaded.

In some situations we still want/need to flood this traffic, e.g. if STP
is disabled, or it is explicitly enabled via the group_fwd_mask. But if
the skb is marked as offloaded, the kernel will assume this was already
done in hardware, and the packets never reach other bridge ports.

So ensure that link local traffic is never marked as offloaded, so that
the kernel can forward/flood these packets in software if needed.

Since the local termination in not configurable, check the destination
MAC, and never mark packets as offloaded if it is a link local ether
address.

While modern switches set the tag reason code to BRCM_EG_RC_PROT_TERM
for trapped link local traffic, they also set it for link local traffic
that is flooded (01:80:c2:00:00:10 to 01:80:c2:00:00:2f), so we cannot
use it and need to look at the destination address for them as well.

Fixes: 964dbf186eaa ("net: dsa: tag_brcm: add support for legacy tags")
Fixes: 0e62f543bed0 ("net: dsa: Fix duplicate frames flooded by learning")
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
Link: https://patch.msgid.link/20251109134635.243951-1-jonas.gorski@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Jonas Gorski and committed by
Jakub Kicinski
762e7e17 60260ad9

+4 -2
+4 -2
net/dsa/tag_brcm.c
··· 176 176 /* Remove Broadcom tag and update checksum */ 177 177 skb_pull_rcsum(skb, BRCM_TAG_LEN); 178 178 179 - dsa_default_offload_fwd_mark(skb); 179 + if (likely(!is_link_local_ether_addr(eth_hdr(skb)->h_dest))) 180 + dsa_default_offload_fwd_mark(skb); 180 181 181 182 return skb; 182 183 } ··· 251 250 /* Remove Broadcom tag and update checksum */ 252 251 skb_pull_rcsum(skb, len); 253 252 254 - dsa_default_offload_fwd_mark(skb); 253 + if (likely(!is_link_local_ether_addr(eth_hdr(skb)->h_dest))) 254 + dsa_default_offload_fwd_mark(skb); 255 255 256 256 dsa_strip_etype_header(skb, len); 257 257