| From 282bfd22055b34a12c025ef72796a480a24facb2 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Wed, 18 May 2022 02:58:40 +0200 |
| Subject: net: bridge: Clear offload_fwd_mark when passing frame up bridge |
| interface. |
| |
| From: Andrew Lunn <andrew@lunn.ch> |
| |
| [ Upstream commit fbb3abdf2223cd0dfc07de85fe5a43ba7f435bdf ] |
| |
| It is possible to stack bridges on top of each other. Consider the |
| following which makes use of an Ethernet switch: |
| |
| br1 |
| / \ |
| / \ |
| / \ |
| br0.11 wlan0 |
| | |
| br0 |
| / | \ |
| p1 p2 p3 |
| |
| br0 is offloaded to the switch. Above br0 is a vlan interface, for |
| vlan 11. This vlan interface is then a slave of br1. br1 also has a |
| wireless interface as a slave. This setup trunks wireless lan traffic |
| over the copper network inside a VLAN. |
| |
| A frame received on p1 which is passed up to the bridge has the |
| skb->offload_fwd_mark flag set to true, indicating that the switch has |
| dealt with forwarding the frame out ports p2 and p3 as needed. This |
| flag instructs the software bridge it does not need to pass the frame |
| back down again. However, the flag is not getting reset when the frame |
| is passed upwards. As a result br1 sees the flag, wrongly interprets |
| it, and fails to forward the frame to wlan0. |
| |
| When passing a frame upwards, clear the flag. This is the Rx |
| equivalent of br_switchdev_frame_unmark() in br_dev_xmit(). |
| |
| Fixes: f1c2eddf4cb6 ("bridge: switchdev: Use an helper to clear forward mark") |
| Signed-off-by: Andrew Lunn <andrew@lunn.ch> |
| Reviewed-by: Ido Schimmel <idosch@nvidia.com> |
| Tested-by: Ido Schimmel <idosch@nvidia.com> |
| Acked-by: Nikolay Aleksandrov <razor@blackwall.org> |
| Link: https://lore.kernel.org/r/20220518005840.771575-1-andrew@lunn.ch |
| Signed-off-by: Paolo Abeni <pabeni@redhat.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| net/bridge/br_input.c | 7 +++++++ |
| 1 file changed, 7 insertions(+) |
| |
| diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c |
| index 59a318b9f646..bf5bf148091f 100644 |
| --- a/net/bridge/br_input.c |
| +++ b/net/bridge/br_input.c |
| @@ -43,6 +43,13 @@ static int br_pass_frame_up(struct sk_buff *skb) |
| u64_stats_update_end(&brstats->syncp); |
| |
| vg = br_vlan_group_rcu(br); |
| + |
| + /* Reset the offload_fwd_mark because there could be a stacked |
| + * bridge above, and it should not think this bridge it doing |
| + * that bridge's work forwarding out its ports. |
| + */ |
| + br_switchdev_frame_unmark(skb); |
| + |
| /* Bridge is just like any other port. Make sure the |
| * packet is allowed except in promisc modue when someone |
| * may be running packet capture. |
| -- |
| 2.35.1 |
| |