ab4fdf85093a90a27f24cd154695e79c49df37d0
[openwrt/staging/ldir.git] /
1 From bea7907837c57a0aaac009931eb14efb056dafab Mon Sep 17 00:00:00 2001
2 From: Vladimir Oltean <vladimir.oltean@nxp.com>
3 Date: Thu, 29 Jul 2021 17:56:00 +0300
4 Subject: [PATCH] net: dsa: don't set skb->offload_fwd_mark when not offloading
5 the bridge
6
7 DSA has gained the recent ability to deal gracefully with upper
8 interfaces it cannot offload, such as the bridge, bonding or team
9 drivers. When such uppers exist, the ports are still in standalone mode
10 as far as the hardware is concerned.
11
12 But when we deliver packets to the software bridge in order for that to
13 do the forwarding, there is an unpleasant surprise in that the bridge
14 will refuse to forward them. This is because we unconditionally set
15 skb->offload_fwd_mark = true, meaning that the bridge thinks the frames
16 were already forwarded in hardware by us.
17
18 Since dp->bridge_dev is populated only when there is hardware offload
19 for it, but not in the software fallback case, let's introduce a new
20 helper that can be called from the tagger data path which sets the
21 skb->offload_fwd_mark accordingly to zero when there is no hardware
22 offload for bridging. This lets the bridge forward packets back to other
23 interfaces of our switch, if needed.
24
25 Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
26 Reviewed-by: Tobias Waldekranz <tobias@waldekranz.com>
27 Signed-off-by: David S. Miller <davem@davemloft.net>
28 ---
29 net/dsa/dsa_priv.h | 14 ++++++++++++++
30 net/dsa/tag_brcm.c | 4 ++--
31 net/dsa/tag_dsa.c | 15 +++++++++++----
32 net/dsa/tag_ksz.c | 2 +-
33 net/dsa/tag_lan9303.c | 3 ++-
34 net/dsa/tag_mtk.c | 2 +-
35 net/dsa/tag_ocelot.c | 2 +-
36 net/dsa/tag_rtl4_a.c | 2 +-
37 net/dsa/tag_sja1105.c | 20 ++++++++++++++------
38 9 files changed, 47 insertions(+), 17 deletions(-)
39
40 --- a/net/dsa/dsa_priv.h
41 +++ b/net/dsa/dsa_priv.h
42 @@ -266,6 +266,20 @@ static inline struct sk_buff *dsa_untag_
43 return skb;
44 }
45
46 +/* If the ingress port offloads the bridge, we mark the frame as autonomously
47 + * forwarded by hardware, so the software bridge doesn't forward in twice, back
48 + * to us, because we already did. However, if we're in fallback mode and we do
49 + * software bridging, we are not offloading it, therefore the dp->bridge_dev
50 + * pointer is not populated, and flooding needs to be done by software (we are
51 + * effectively operating in standalone ports mode).
52 + */
53 +static inline void dsa_default_offload_fwd_mark(struct sk_buff *skb)
54 +{
55 + struct dsa_port *dp = dsa_slave_to_port(skb->dev);
56 +
57 + skb->offload_fwd_mark = !!(dp->bridge_dev);
58 +}
59 +
60 /* switch.c */
61 int dsa_switch_register_notifier(struct dsa_switch *ds);
62 void dsa_switch_unregister_notifier(struct dsa_switch *ds);
63 --- a/net/dsa/tag_brcm.c
64 +++ b/net/dsa/tag_brcm.c
65 @@ -166,7 +166,7 @@ static struct sk_buff *brcm_tag_rcv_ll(s
66 /* Remove Broadcom tag and update checksum */
67 skb_pull_rcsum(skb, BRCM_TAG_LEN);
68
69 - skb->offload_fwd_mark = 1;
70 + dsa_default_offload_fwd_mark(skb);
71
72 return skb;
73 }
74 @@ -270,7 +270,7 @@ static struct sk_buff *brcm_leg_tag_rcv(
75 /* Remove Broadcom tag and update checksum */
76 skb_pull_rcsum(skb, BRCM_LEG_TAG_LEN);
77
78 - skb->offload_fwd_mark = 1;
79 + dsa_default_offload_fwd_mark(skb);
80
81 /* Move the Ethernet DA and SA */
82 memmove(skb->data - ETH_HLEN,
83 --- a/net/dsa/tag_ksz.c
84 +++ b/net/dsa/tag_ksz.c
85 @@ -24,7 +24,7 @@ static struct sk_buff *ksz_common_rcv(st
86
87 pskb_trim_rcsum(skb, skb->len - len);
88
89 - skb->offload_fwd_mark = true;
90 + dsa_default_offload_fwd_mark(skb);
91
92 return skb;
93 }
94 --- a/net/dsa/tag_lan9303.c
95 +++ b/net/dsa/tag_lan9303.c
96 @@ -115,7 +115,8 @@ static struct sk_buff *lan9303_rcv(struc
97 skb_pull_rcsum(skb, 2 + 2);
98 memmove(skb->data - ETH_HLEN, skb->data - (ETH_HLEN + LAN9303_TAG_LEN),
99 2 * ETH_ALEN);
100 - skb->offload_fwd_mark = !(lan9303_tag1 & LAN9303_TAG_RX_TRAPPED_TO_CPU);
101 + if (!(lan9303_tag1 & LAN9303_TAG_RX_TRAPPED_TO_CPU))
102 + dsa_default_offload_fwd_mark(skb);
103
104 return skb;
105 }
106 --- a/net/dsa/tag_mtk.c
107 +++ b/net/dsa/tag_mtk.c
108 @@ -104,7 +104,7 @@ static struct sk_buff *mtk_tag_rcv(struc
109
110 /* Only unicast or broadcast frames are offloaded */
111 if (likely(!is_multicast_skb))
112 - skb->offload_fwd_mark = 1;
113 + dsa_default_offload_fwd_mark(skb);
114
115 return skb;
116 }
117 --- a/net/dsa/tag_ocelot.c
118 +++ b/net/dsa/tag_ocelot.c
119 @@ -225,7 +225,7 @@ static struct sk_buff *ocelot_rcv(struct
120 */
121 return NULL;
122
123 - skb->offload_fwd_mark = 1;
124 + dsa_default_offload_fwd_mark(skb);
125 skb->priority = qos_class;
126
127 /* Ocelot switches copy frames unmodified to the CPU. However, it is
128 --- a/net/dsa/tag_rtl4_a.c
129 +++ b/net/dsa/tag_rtl4_a.c
130 @@ -115,7 +115,7 @@ static struct sk_buff *rtl4a_tag_rcv(str
131 skb->data - ETH_HLEN - RTL4_A_HDR_LEN,
132 2 * ETH_ALEN);
133
134 - skb->offload_fwd_mark = 1;
135 + dsa_default_offload_fwd_mark(skb);
136
137 return skb;
138 }