Skip to content

Commit 4b30ae9

Browse files
Yong Wangdavem330
authored andcommitted
net: bridge: mcast: re-implement br_multicast_{enable, disable}_port functions
When a bridge port STP state is changed from BLOCKING/DISABLED to FORWARDING, the port's igmp query timer will NOT re-arm itself if the bridge has been configured as per-VLAN multicast snooping. Solve this by choosing the correct multicast context(s) to enable/disable port multicast based on whether per-VLAN multicast snooping is enabled or not, i.e. using per-{port, VLAN} context in case of per-VLAN multicast snooping by re-implementing br_multicast_enable_port() and br_multicast_disable_port() functions. Before the patch, the IGMP query does not happen in the last step of the following test sequence, i.e. no growth for tx counter: # ip link add name br1 up type bridge vlan_filtering 1 mcast_snooping 1 mcast_vlan_snooping 1 mcast_querier 1 mcast_stats_enabled 1 # bridge vlan global set vid 1 dev br1 mcast_snooping 1 mcast_querier 1 mcast_query_interval 100 mcast_startup_query_count 0 # ip link add name swp1 up master br1 type dummy # bridge link set dev swp1 state 0 # ip -j -p stats show dev swp1 group xstats_slave subgroup bridge suite mcast | jq '.[]["multicast"]["igmp_queries"]["tx_v2"]' 1 # sleep 1 # ip -j -p stats show dev swp1 group xstats_slave subgroup bridge suite mcast | jq '.[]["multicast"]["igmp_queries"]["tx_v2"]' 1 # bridge link set dev swp1 state 3 # sleep 2 # ip -j -p stats show dev swp1 group xstats_slave subgroup bridge suite mcast | jq '.[]["multicast"]["igmp_queries"]["tx_v2"]' 1 After the patch, the IGMP query happens in the last step of the test: # ip link add name br1 up type bridge vlan_filtering 1 mcast_snooping 1 mcast_vlan_snooping 1 mcast_querier 1 mcast_stats_enabled 1 # bridge vlan global set vid 1 dev br1 mcast_snooping 1 mcast_querier 1 mcast_query_interval 100 mcast_startup_query_count 0 # ip link add name swp1 up master br1 type dummy # bridge link set dev swp1 state 0 # ip -j -p stats show dev swp1 group xstats_slave subgroup bridge suite mcast | jq '.[]["multicast"]["igmp_queries"]["tx_v2"]' 1 # sleep 1 # ip -j -p stats show dev swp1 group xstats_slave subgroup bridge suite mcast | jq '.[]["multicast"]["igmp_queries"]["tx_v2"]' 1 # bridge link set dev swp1 state 3 # sleep 2 # ip -j -p stats show dev swp1 group xstats_slave subgroup bridge suite mcast | jq '.[]["multicast"]["igmp_queries"]["tx_v2"]' 3 Signed-off-by: Yong Wang <[email protected]> Reviewed-by: Andy Roulin <[email protected]> Reviewed-by: Ido Schimmel <[email protected]> Signed-off-by: Petr Machata <[email protected]> Acked-by: Nikolay Aleksandrov <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 0e0a7e3 commit 4b30ae9

File tree

1 file changed

+69
-8
lines changed

1 file changed

+69
-8
lines changed

net/bridge/br_multicast.c

Lines changed: 69 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2105,12 +2105,17 @@ static void __br_multicast_enable_port_ctx(struct net_bridge_mcast_port *pmctx)
21052105
}
21062106
}
21072107

2108-
void br_multicast_enable_port(struct net_bridge_port *port)
2108+
static void br_multicast_enable_port_ctx(struct net_bridge_mcast_port *pmctx)
21092109
{
2110-
struct net_bridge *br = port->br;
2110+
struct net_bridge *br = pmctx->port->br;
21112111

21122112
spin_lock_bh(&br->multicast_lock);
2113-
__br_multicast_enable_port_ctx(&port->multicast_ctx);
2113+
if (br_multicast_port_ctx_is_vlan(pmctx) &&
2114+
!(pmctx->vlan->priv_flags & BR_VLFLAG_MCAST_ENABLED)) {
2115+
spin_unlock_bh(&br->multicast_lock);
2116+
return;
2117+
}
2118+
__br_multicast_enable_port_ctx(pmctx);
21142119
spin_unlock_bh(&br->multicast_lock);
21152120
}
21162121

@@ -2137,11 +2142,67 @@ static void __br_multicast_disable_port_ctx(struct net_bridge_mcast_port *pmctx)
21372142
br_multicast_rport_del_notify(pmctx, del);
21382143
}
21392144

2145+
static void br_multicast_disable_port_ctx(struct net_bridge_mcast_port *pmctx)
2146+
{
2147+
struct net_bridge *br = pmctx->port->br;
2148+
2149+
spin_lock_bh(&br->multicast_lock);
2150+
if (br_multicast_port_ctx_is_vlan(pmctx) &&
2151+
!(pmctx->vlan->priv_flags & BR_VLFLAG_MCAST_ENABLED)) {
2152+
spin_unlock_bh(&br->multicast_lock);
2153+
return;
2154+
}
2155+
2156+
__br_multicast_disable_port_ctx(pmctx);
2157+
spin_unlock_bh(&br->multicast_lock);
2158+
}
2159+
2160+
static void br_multicast_toggle_port(struct net_bridge_port *port, bool on)
2161+
{
2162+
#if IS_ENABLED(CONFIG_BRIDGE_VLAN_FILTERING)
2163+
if (br_opt_get(port->br, BROPT_MCAST_VLAN_SNOOPING_ENABLED)) {
2164+
struct net_bridge_vlan_group *vg;
2165+
struct net_bridge_vlan *vlan;
2166+
2167+
rcu_read_lock();
2168+
vg = nbp_vlan_group_rcu(port);
2169+
if (!vg) {
2170+
rcu_read_unlock();
2171+
return;
2172+
}
2173+
2174+
/* iterate each vlan, toggle vlan multicast context */
2175+
list_for_each_entry_rcu(vlan, &vg->vlan_list, vlist) {
2176+
struct net_bridge_mcast_port *pmctx =
2177+
&vlan->port_mcast_ctx;
2178+
u8 state = br_vlan_get_state(vlan);
2179+
/* enable vlan multicast context when state is
2180+
* LEARNING or FORWARDING
2181+
*/
2182+
if (on && br_vlan_state_allowed(state, true))
2183+
br_multicast_enable_port_ctx(pmctx);
2184+
else
2185+
br_multicast_disable_port_ctx(pmctx);
2186+
}
2187+
rcu_read_unlock();
2188+
return;
2189+
}
2190+
#endif
2191+
/* toggle port multicast context when vlan snooping is disabled */
2192+
if (on)
2193+
br_multicast_enable_port_ctx(&port->multicast_ctx);
2194+
else
2195+
br_multicast_disable_port_ctx(&port->multicast_ctx);
2196+
}
2197+
2198+
void br_multicast_enable_port(struct net_bridge_port *port)
2199+
{
2200+
br_multicast_toggle_port(port, true);
2201+
}
2202+
21402203
void br_multicast_disable_port(struct net_bridge_port *port)
21412204
{
2142-
spin_lock_bh(&port->br->multicast_lock);
2143-
__br_multicast_disable_port_ctx(&port->multicast_ctx);
2144-
spin_unlock_bh(&port->br->multicast_lock);
2205+
br_multicast_toggle_port(port, false);
21452206
}
21462207

21472208
static int __grp_src_delete_marked(struct net_bridge_port_group *pg)
@@ -4304,9 +4365,9 @@ int br_multicast_toggle_vlan_snooping(struct net_bridge *br, bool on,
43044365
__br_multicast_open(&br->multicast_ctx);
43054366
list_for_each_entry(p, &br->port_list, list) {
43064367
if (on)
4307-
br_multicast_disable_port(p);
4368+
br_multicast_disable_port_ctx(&p->multicast_ctx);
43084369
else
4309-
br_multicast_enable_port(p);
4370+
br_multicast_enable_port_ctx(&p->multicast_ctx);
43104371
}
43114372

43124373
list_for_each_entry(vlan, &vg->vlan_list, vlist)

0 commit comments

Comments
 (0)