summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorWolfgang Bumiller <w.bumiller@proxmox.com>2021-07-02 14:07:36 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-07-28 11:12:15 +0200
commit8ebf5391323486624b6f9e1f4ac48bec5fabbe1c (patch)
tree7ab09c0d5a75855de07cef876c8a1033a8069596 /net
parentc1f486e1a9046b858d6c8571745c9e786a0cca96 (diff)
downloadlinux-stable-8ebf5391323486624b6f9e1f4ac48bec5fabbe1c.tar.gz
linux-stable-8ebf5391323486624b6f9e1f4ac48bec5fabbe1c.tar.bz2
linux-stable-8ebf5391323486624b6f9e1f4ac48bec5fabbe1c.zip
net: bridge: sync fdb to new unicast-filtering ports
commit a019abd8022061b917da767cd1a66ed823724eab upstream. 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> Acked-by: Nikolay Aleksandrov <nikolay@nvidia.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'net')
-rw-r--r--net/bridge/br_if.c17
1 files changed, 16 insertions, 1 deletions
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index d9156eabddb8..9a36592cf20f 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -485,7 +485,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, or DSA-enabled
* master network devices since the bridge layer rx_handler prevents
@@ -555,6 +555,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);
@@ -595,6 +608,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);