Skip to content

Commit 4498c33

Browse files
committed
net: bridge: mcast: update multicast contex when vlan state is changed
JIRA: https://issues.redhat.com/browse/RHEL-75594 commit 6c13104 Author: Yong Wang <yongwang@nvidia.com> Date: Thu Apr 17 15:43:13 2025 +0200 net: bridge: mcast: update multicast contex when vlan state is changed When the vlan STP state is changed, which could be manipulated by "bridge vlan" commands, similar to port STP state, this also impacts multicast behaviors such as igmp query. In the scenario of per-VLAN snooping, there's a need to update the corresponding multicast context to re-arm the port query timer when vlan state becomes "forwarding" etc. Update br_vlan_set_state() function to enable vlan multicast context in such scenario. 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 # sleep 1 # bridge vlan set vid 1 dev swp1 state 4 # 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 vlan set vid 1 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 # sleep 1 # bridge vlan set vid 1 dev swp1 state 4 # 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 vlan set vid 1 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 <yongwang@nvidia.com> Reviewed-by: Andy Roulin <aroulin@nvidia.com> Reviewed-by: Ido Schimmel <idosch@nvidia.com> Signed-off-by: Petr Machata <petrm@nvidia.com> Acked-by: Nikolay Aleksandrov <razor@blackwall.org> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Mohammad Heib <mheib@redhat.com>
1 parent c443c7b commit 4498c33

File tree

3 files changed

+38
-3
lines changed

3 files changed

+38
-3
lines changed

net/bridge/br_mst.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,10 @@ static void br_mst_vlan_set_state(struct net_bridge_vlan_group *vg,
8080
if (br_vlan_get_state(v) == state)
8181
return;
8282

83-
br_vlan_set_state(v, state);
84-
8583
if (v->vid == vg->pvid)
8684
br_vlan_set_pvid_state(vg, state);
85+
86+
br_vlan_set_state(v, state);
8787
}
8888

8989
int br_mst_set_state(struct net_bridge_port *p, u16 msti, u8 state,

net/bridge/br_multicast.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4272,6 +4272,32 @@ static void __br_multicast_stop(struct net_bridge_mcast *brmctx)
42724272
#endif
42734273
}
42744274

4275+
void br_multicast_update_vlan_mcast_ctx(struct net_bridge_vlan *v, u8 state)
4276+
{
4277+
#if IS_ENABLED(CONFIG_BRIDGE_VLAN_FILTERING)
4278+
struct net_bridge *br;
4279+
4280+
if (!br_vlan_should_use(v))
4281+
return;
4282+
4283+
if (br_vlan_is_master(v))
4284+
return;
4285+
4286+
br = v->port->br;
4287+
4288+
if (!br_opt_get(br, BROPT_MCAST_VLAN_SNOOPING_ENABLED))
4289+
return;
4290+
4291+
if (br_vlan_state_allowed(state, true))
4292+
br_multicast_enable_port_ctx(&v->port_mcast_ctx);
4293+
4294+
/* Multicast is not disabled for the vlan when it goes in
4295+
* blocking state because the timers will expire and stop by
4296+
* themselves without sending more queries.
4297+
*/
4298+
#endif
4299+
}
4300+
42754301
void br_multicast_toggle_one_vlan(struct net_bridge_vlan *vlan, bool on)
42764302
{
42774303
struct net_bridge *br;

net/bridge/br_private.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1055,6 +1055,7 @@ void br_multicast_port_ctx_init(struct net_bridge_port *port,
10551055
struct net_bridge_vlan *vlan,
10561056
struct net_bridge_mcast_port *pmctx);
10571057
void br_multicast_port_ctx_deinit(struct net_bridge_mcast_port *pmctx);
1058+
void br_multicast_update_vlan_mcast_ctx(struct net_bridge_vlan *v, u8 state);
10581059
void br_multicast_toggle_one_vlan(struct net_bridge_vlan *vlan, bool on);
10591060
int br_multicast_toggle_vlan_snooping(struct net_bridge *br, bool on,
10601061
struct netlink_ext_ack *extack);
@@ -1521,6 +1522,11 @@ static inline void br_multicast_port_ctx_deinit(struct net_bridge_mcast_port *pm
15211522
{
15221523
}
15231524

1525+
static inline void br_multicast_update_vlan_mcast_ctx(struct net_bridge_vlan *v,
1526+
u8 state)
1527+
{
1528+
}
1529+
15241530
static inline void br_multicast_toggle_one_vlan(struct net_bridge_vlan *vlan,
15251531
bool on)
15261532
{
@@ -1881,7 +1887,9 @@ bool br_vlan_global_opts_can_enter_range(const struct net_bridge_vlan *v_curr,
18811887
bool br_vlan_global_opts_fill(struct sk_buff *skb, u16 vid, u16 vid_range,
18821888
const struct net_bridge_vlan *v_opts);
18831889

1884-
/* vlan state manipulation helpers using *_ONCE to annotate lock-free access */
1890+
/* vlan state manipulation helpers using *_ONCE to annotate lock-free access,
1891+
* while br_vlan_set_state() may access data protected by multicast_lock.
1892+
*/
18851893
static inline u8 br_vlan_get_state(const struct net_bridge_vlan *v)
18861894
{
18871895
return READ_ONCE(v->state);
@@ -1890,6 +1898,7 @@ static inline u8 br_vlan_get_state(const struct net_bridge_vlan *v)
18901898
static inline void br_vlan_set_state(struct net_bridge_vlan *v, u8 state)
18911899
{
18921900
WRITE_ONCE(v->state, state);
1901+
br_multicast_update_vlan_mcast_ctx(v, state);
18931902
}
18941903

18951904
static inline u8 br_vlan_get_pvid_state(const struct net_bridge_vlan_group *vg)

0 commit comments

Comments
 (0)