]>
Commit | Line | Data |
---|---|---|
53dd6047 TL |
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
2 | From: Wolfgang Bumiller <w.bumiller@proxmox.com> | |
3 | Date: Fri, 2 Jul 2021 14:07:36 +0200 | |
4 | Subject: [PATCH] net: bridge: sync fdb to new unicast-filtering ports | |
5 | ||
6 | Since commit 2796d0c648c9 ("bridge: Automatically manage | |
7 | port promiscuous mode.") | |
8 | bridges with `vlan_filtering 1` and only 1 auto-port don't | |
9 | set IFF_PROMISC for unicast-filtering-capable ports. | |
10 | ||
11 | Normally on port changes `br_manage_promisc` is called to | |
12 | update the promisc flags and unicast filters if necessary, | |
13 | but it cannot distinguish between *new* ports and ones | |
14 | losing their promisc flag, and new ports end up not | |
15 | receiving the MAC address list. | |
16 | ||
17 | Fix this by calling `br_fdb_sync_static` in `br_add_if` | |
18 | after the port promisc flags are updated and the unicast | |
19 | filter was supposed to have been filled. | |
20 | ||
21 | Fixes: 2796d0c648c9 ("bridge: Automatically manage port promiscuous mode.") | |
22 | Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com> | |
23 | --- | |
24 | net/bridge/br_if.c | 17 ++++++++++++++++- | |
25 | 1 file changed, 16 insertions(+), 1 deletion(-) | |
26 | ||
27 | diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c | |
28 | index f7d2f472ae24..6e4a32354a13 100644 | |
29 | --- a/net/bridge/br_if.c | |
30 | +++ b/net/bridge/br_if.c | |
31 | @@ -562,7 +562,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev, | |
32 | struct net_bridge_port *p; | |
33 | int err = 0; | |
34 | unsigned br_hr, dev_hr; | |
35 | - bool changed_addr; | |
36 | + bool changed_addr, fdb_synced = false; | |
37 | ||
38 | /* Don't allow bridging non-ethernet like devices. */ | |
39 | if ((dev->flags & IFF_LOOPBACK) || | |
40 | @@ -652,6 +652,19 @@ int br_add_if(struct net_bridge *br, struct net_device *dev, | |
41 | list_add_rcu(&p->list, &br->port_list); | |
42 | ||
43 | nbp_update_port_count(br); | |
44 | + if (!br_promisc_port(p) && (p->dev->priv_flags & IFF_UNICAST_FLT)) { | |
45 | + /* When updating the port count we also update all ports' | |
46 | + * promiscuous mode. | |
47 | + * A port leaving promiscuous mode normally gets the bridge's | |
48 | + * fdb synced to the unicast filter (if supported), however, | |
49 | + * `br_port_clear_promisc` does not distinguish between | |
50 | + * non-promiscuous ports and *new* ports, so we need to | |
51 | + * sync explicitly here. | |
52 | + */ | |
53 | + fdb_synced = br_fdb_sync_static(br, p) == 0; | |
54 | + if (!fdb_synced) | |
55 | + netdev_err(dev, "failed to sync bridge static fdb addresses to this port\n"); | |
56 | + } | |
57 | ||
58 | netdev_update_features(br->dev); | |
59 | ||
60 | @@ -701,6 +714,8 @@ int br_add_if(struct net_bridge *br, struct net_device *dev, | |
61 | return 0; | |
62 | ||
63 | err7: | |
64 | + if (fdb_synced) | |
65 | + br_fdb_unsync_static(br, p); | |
66 | list_del_rcu(&p->list); | |
67 | br_fdb_delete_by_port(br, p, 0, 1); | |
68 | nbp_update_port_count(br); |