| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- From bea7907837c57a0aaac009931eb14efb056dafab Mon Sep 17 00:00:00 2001
- From: Vladimir Oltean <[email protected]>
- 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 <[email protected]>
- Reviewed-by: Tobias Waldekranz <[email protected]>
- Signed-off-by: David S. Miller <[email protected]>
- ---
- 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
- @@ -25,7 +25,7 @@ static struct sk_buff *ksz_common_rcv(st
- if (pskb_trim_rcsum(skb, skb->len - len))
- return NULL;
-
- - 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;
- }
|