[openwrt/openwrt] kernel: 5.10: dsa: don't set skb->offload_fwd_mark when not offloading bridge

LEDE Commits lede-commits at lists.infradead.org
Thu Oct 7 05:22:43 PDT 2021


rmilecki pushed a commit to openwrt/openwrt.git, branch master:
https://git.openwrt.org/2e4193f3cfa23f6c85f479ef10bf779406538f3c

commit 2e4193f3cfa23f6c85f479ef10bf779406538f3c
Author: Matthew Hagan <mnhagan88 at gmail.com>
AuthorDate: Sun Sep 26 11:23:27 2021 +0000

    kernel: 5.10: dsa: don't set skb->offload_fwd_mark when not offloading bridge
    
    Add Vladimir Oltean's "net: dsa: don't set skb->offload_fwd_mark when
    not offloading the bridge"
    
    This covers cases where packets received by an upstream switch must be
    forwarded back on the same port, which skb->offload_fwd_mark normally
    prevents.
    
    Signed-off-by: Matthew Hagan <mnhagan88 at gmail.com>
---
 ...-t-set-skb-offload_fwd_mark-when-not-offl.patch | 138 +++++++++++++++++++++
 1 file changed, 138 insertions(+)

diff --git a/target/linux/generic/backport-5.10/794-v5.15-net-dsa-don-t-set-skb-offload_fwd_mark-when-not-offl.patch b/target/linux/generic/backport-5.10/794-v5.15-net-dsa-don-t-set-skb-offload_fwd_mark-when-not-offl.patch
new file mode 100644
index 0000000000..ab4fdf8509
--- /dev/null
+++ b/target/linux/generic/backport-5.10/794-v5.15-net-dsa-don-t-set-skb-offload_fwd_mark-when-not-offl.patch
@@ -0,0 +1,138 @@
+From bea7907837c57a0aaac009931eb14efb056dafab Mon Sep 17 00:00:00 2001
+From: Vladimir Oltean <vladimir.oltean at nxp.com>
+Date: Thu, 29 Jul 2021 17:56:00 +0300
+Subject: [PATCH] net: dsa: don't set skb->offload_fwd_mark when not offloading
+ the bridge
+
+DSA has gained the recent ability to deal gracefully with upper
+interfaces it cannot offload, such as the bridge, bonding or team
+drivers. When such uppers exist, the ports are still in standalone mode
+as far as the hardware is concerned.
+
+But when we deliver packets to the software bridge in order for that to
+do the forwarding, there is an unpleasant surprise in that the bridge
+will refuse to forward them. This is because we unconditionally set
+skb->offload_fwd_mark = true, meaning that the bridge thinks the frames
+were already forwarded in hardware by us.
+
+Since dp->bridge_dev is populated only when there is hardware offload
+for it, but not in the software fallback case, let's introduce a new
+helper that can be called from the tagger data path which sets the
+skb->offload_fwd_mark accordingly to zero when there is no hardware
+offload for bridging. This lets the bridge forward packets back to other
+interfaces of our switch, if needed.
+
+Signed-off-by: Vladimir Oltean <vladimir.oltean at nxp.com>
+Reviewed-by: Tobias Waldekranz <tobias at waldekranz.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ net/dsa/dsa_priv.h         | 14 ++++++++++++++
+ net/dsa/tag_brcm.c         |  4 ++--
+ net/dsa/tag_dsa.c          | 15 +++++++++++----
+ net/dsa/tag_ksz.c          |  2 +-
+ net/dsa/tag_lan9303.c      |  3 ++-
+ net/dsa/tag_mtk.c          |  2 +-
+ net/dsa/tag_ocelot.c       |  2 +-
+ net/dsa/tag_rtl4_a.c       |  2 +-
+ net/dsa/tag_sja1105.c      | 20 ++++++++++++++------
+ 9 files changed, 47 insertions(+), 17 deletions(-)
+
+--- a/net/dsa/dsa_priv.h
++++ b/net/dsa/dsa_priv.h
+@@ -266,6 +266,20 @@ static inline struct sk_buff *dsa_untag_
+ 	return skb;
+ }
+ 
++/* If the ingress port offloads the bridge, we mark the frame as autonomously
++ * forwarded by hardware, so the software bridge doesn't forward in twice, back
++ * to us, because we already did. However, if we're in fallback mode and we do
++ * software bridging, we are not offloading it, therefore the dp->bridge_dev
++ * pointer is not populated, and flooding needs to be done by software (we are
++ * effectively operating in standalone ports mode).
++ */
++static inline void dsa_default_offload_fwd_mark(struct sk_buff *skb)
++{
++	struct dsa_port *dp = dsa_slave_to_port(skb->dev);
++
++	skb->offload_fwd_mark = !!(dp->bridge_dev);
++}
++
+ /* switch.c */
+ int dsa_switch_register_notifier(struct dsa_switch *ds);
+ void dsa_switch_unregister_notifier(struct dsa_switch *ds);
+--- a/net/dsa/tag_brcm.c
++++ b/net/dsa/tag_brcm.c
+@@ -166,7 +166,7 @@ static struct sk_buff *brcm_tag_rcv_ll(s
+ 	/* Remove Broadcom tag and update checksum */
+ 	skb_pull_rcsum(skb, BRCM_TAG_LEN);
+ 
+-	skb->offload_fwd_mark = 1;
++	dsa_default_offload_fwd_mark(skb);
+ 
+ 	return skb;
+ }
+@@ -270,7 +270,7 @@ static struct sk_buff *brcm_leg_tag_rcv(
+ 	/* Remove Broadcom tag and update checksum */
+ 	skb_pull_rcsum(skb, BRCM_LEG_TAG_LEN);
+ 
+-	skb->offload_fwd_mark = 1;
++	dsa_default_offload_fwd_mark(skb);
+ 
+ 	/* Move the Ethernet DA and SA */
+ 	memmove(skb->data - ETH_HLEN,
+--- a/net/dsa/tag_ksz.c
++++ b/net/dsa/tag_ksz.c
+@@ -24,7 +24,7 @@ static struct sk_buff *ksz_common_rcv(st
+ 
+ 	pskb_trim_rcsum(skb, skb->len - len);
+ 
+-	skb->offload_fwd_mark = true;
++	dsa_default_offload_fwd_mark(skb);
+ 
+ 	return skb;
+ }
+--- a/net/dsa/tag_lan9303.c
++++ b/net/dsa/tag_lan9303.c
+@@ -115,7 +115,8 @@ static struct sk_buff *lan9303_rcv(struc
+ 	skb_pull_rcsum(skb, 2 + 2);
+ 	memmove(skb->data - ETH_HLEN, skb->data - (ETH_HLEN + LAN9303_TAG_LEN),
+ 		2 * ETH_ALEN);
+-	skb->offload_fwd_mark = !(lan9303_tag1 & LAN9303_TAG_RX_TRAPPED_TO_CPU);
++	if (!(lan9303_tag1 & LAN9303_TAG_RX_TRAPPED_TO_CPU))
++		dsa_default_offload_fwd_mark(skb);
+ 
+ 	return skb;
+ }
+--- a/net/dsa/tag_mtk.c
++++ b/net/dsa/tag_mtk.c
+@@ -104,7 +104,7 @@ static struct sk_buff *mtk_tag_rcv(struc
+ 
+ 	/* Only unicast or broadcast frames are offloaded */
+ 	if (likely(!is_multicast_skb))
+-		skb->offload_fwd_mark = 1;
++		dsa_default_offload_fwd_mark(skb);
+ 
+ 	return skb;
+ }
+--- a/net/dsa/tag_ocelot.c
++++ b/net/dsa/tag_ocelot.c
+@@ -225,7 +225,7 @@ static struct sk_buff *ocelot_rcv(struct
+ 		 */
+ 		return NULL;
+ 
+-	skb->offload_fwd_mark = 1;
++	dsa_default_offload_fwd_mark(skb);
+ 	skb->priority = qos_class;
+ 
+ 	/* Ocelot switches copy frames unmodified to the CPU. However, it is
+--- a/net/dsa/tag_rtl4_a.c
++++ b/net/dsa/tag_rtl4_a.c
+@@ -115,7 +115,7 @@ static struct sk_buff *rtl4a_tag_rcv(str
+ 		skb->data - ETH_HLEN - RTL4_A_HDR_LEN,
+ 		2 * ETH_ALEN);
+ 
+-	skb->offload_fwd_mark = 1;
++	dsa_default_offload_fwd_mark(skb);
+ 
+ 	return skb;
+ }



More information about the lede-commits mailing list