net: bridge: sync fdb to new unicast-filtering ports
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
This commit is contained in:
parent
3cd48d75bf
commit
53dd604743
@ -0,0 +1,68 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
|
||||||
|
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 <w.bumiller@proxmox.com>
|
||||||
|
---
|
||||||
|
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);
|
Loading…
Reference in New Issue
Block a user