From 53dd60474356e294a623c99457c10264f0d6834e Mon Sep 17 00:00:00 2001 From: Thomas Lamprecht Date: Fri, 2 Jul 2021 16:21:08 +0200 Subject: [PATCH] net: bridge: sync fdb to new unicast-filtering ports Signed-off-by: Thomas Lamprecht --- ...c-fdb-to-new-unicast-filtering-ports.patch | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 patches/kernel/0006-net-bridge-sync-fdb-to-new-unicast-filtering-ports.patch diff --git a/patches/kernel/0006-net-bridge-sync-fdb-to-new-unicast-filtering-ports.patch b/patches/kernel/0006-net-bridge-sync-fdb-to-new-unicast-filtering-ports.patch new file mode 100644 index 0000000..043287e --- /dev/null +++ b/patches/kernel/0006-net-bridge-sync-fdb-to-new-unicast-filtering-ports.patch @@ -0,0 +1,68 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Wolfgang Bumiller +Date: Fri, 2 Jul 2021 14:07:36 +0200 +Subject: [PATCH] net: bridge: sync fdb to new unicast-filtering ports + +Since commit 2796d0c648c9 ("bridge: Automatically manage +port promiscuous mode.") +bridges with `vlan_filtering 1` and only 1 auto-port don't +set IFF_PROMISC for unicast-filtering-capable ports. + +Normally on port changes `br_manage_promisc` is called to +update the promisc flags and unicast filters if necessary, +but it cannot distinguish between *new* ports and ones +losing their promisc flag, and new ports end up not +receiving the MAC address list. + +Fix this by calling `br_fdb_sync_static` in `br_add_if` +after the port promisc flags are updated and the unicast +filter was supposed to have been filled. + +Fixes: 2796d0c648c9 ("bridge: Automatically manage port promiscuous mode.") +Signed-off-by: Wolfgang Bumiller +--- + net/bridge/br_if.c | 17 ++++++++++++++++- + 1 file changed, 16 insertions(+), 1 deletion(-) + +diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c +index f7d2f472ae24..6e4a32354a13 100644 +--- a/net/bridge/br_if.c ++++ b/net/bridge/br_if.c +@@ -562,7 +562,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev, + struct net_bridge_port *p; + int err = 0; + unsigned br_hr, dev_hr; +- bool changed_addr; ++ bool changed_addr, fdb_synced = false; + + /* Don't allow bridging non-ethernet like devices. */ + if ((dev->flags & IFF_LOOPBACK) || +@@ -652,6 +652,19 @@ int br_add_if(struct net_bridge *br, struct net_device *dev, + list_add_rcu(&p->list, &br->port_list); + + nbp_update_port_count(br); ++ if (!br_promisc_port(p) && (p->dev->priv_flags & IFF_UNICAST_FLT)) { ++ /* When updating the port count we also update all ports' ++ * promiscuous mode. ++ * A port leaving promiscuous mode normally gets the bridge's ++ * fdb synced to the unicast filter (if supported), however, ++ * `br_port_clear_promisc` does not distinguish between ++ * non-promiscuous ports and *new* ports, so we need to ++ * sync explicitly here. ++ */ ++ fdb_synced = br_fdb_sync_static(br, p) == 0; ++ if (!fdb_synced) ++ netdev_err(dev, "failed to sync bridge static fdb addresses to this port\n"); ++ } + + netdev_update_features(br->dev); + +@@ -701,6 +714,8 @@ int br_add_if(struct net_bridge *br, struct net_device *dev, + return 0; + + err7: ++ if (fdb_synced) ++ br_fdb_unsync_static(br, p); + list_del_rcu(&p->list); + br_fdb_delete_by_port(br, p, 0, 1); + nbp_update_port_count(br);