[PATCH net-next v4 09/14] net: bridge: mcast: track active state, VLAN snooping

Linus Lüssing posted 14 patches 3 weeks, 6 days ago
[PATCH net-next v4 09/14] net: bridge: mcast: track active state, VLAN snooping
Posted by Linus Lüssing 3 weeks, 6 days ago
If VLAN aware multicast snooping is enabled then we need to perform a
few extra checks to figure out if multicast snooping is actually enabled
for a specific VLAN, as there is then an additional per VLAN multicast
snooping toggle.

Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue>
---
 net/bridge/br_multicast.c | 25 ++++++++++++++++++++++++-
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index cdc921b97243..1059984d8147 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -1142,9 +1142,31 @@ static void br_multicast_update_active(struct net_bridge_mcast *brmctx)
 
 	lockdep_assert_held_once(&brmctx->br->multicast_lock);
 
-	if (!br_opt_get(brmctx->br, BROPT_MULTICAST_ENABLED))
+	if (!br_opt_get(brmctx->br, BROPT_MULTICAST_ENABLED)) {
 		force_inactive = true;
+		goto update;
+	}
 
+	if (br_opt_get(brmctx->br, BROPT_MCAST_VLAN_SNOOPING_ENABLED)) {
+		/* with per-vlan snooping enabled there is an extra per-vlan
+		 * toggle to enable/disable snooping which we must check
+		 */
+		if (br_multicast_ctx_vlan_global_disabled(brmctx))
+			force_inactive = true;
+		/* with per-vlan snooping enabled the non-vlan multicast
+		 * snooping context is inactive
+		 */
+		else if (!br_multicast_ctx_is_vlan(brmctx))
+			force_inactive = true;
+	} else {
+		/* with per-vlan snooping disabled a vlan multicast
+		 * snooping context is inactive
+		 */
+		if (br_multicast_ctx_is_vlan(brmctx))
+			force_inactive = true;
+	}
+
+update:
 	br_ip4_multicast_update_active(brmctx, force_inactive);
 	br_ip6_multicast_update_active(brmctx, force_inactive);
 
@@ -4505,6 +4527,7 @@ void br_multicast_toggle_one_vlan(struct net_bridge_vlan *vlan, bool on)
 
 		spin_lock_bh(&br->multicast_lock);
 		vlan->priv_flags ^= BR_VLFLAG_MCAST_ENABLED;
+		br_multicast_update_active(&vlan->br_mcast_ctx);
 
 		if (on)
 			__br_multicast_open(&vlan->br_mcast_ctx);
-- 
2.53.0

Re: [PATCH net-next v4 09/14] net: bridge: mcast: track active state, VLAN snooping
Posted by Ido Schimmel 3 weeks, 5 days ago
On Sat, Mar 07, 2026 at 05:45:43AM +0100, Linus Lüssing wrote:
> If VLAN aware multicast snooping is enabled then we need to perform a
> few extra checks to figure out if multicast snooping is actually enabled
> for a specific VLAN, as there is then an additional per VLAN multicast
> snooping toggle.
> 
> Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue>
> ---
>  net/bridge/br_multicast.c | 25 ++++++++++++++++++++++++-
>  1 file changed, 24 insertions(+), 1 deletion(-)
> 
> diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
> index cdc921b97243..1059984d8147 100644
> --- a/net/bridge/br_multicast.c
> +++ b/net/bridge/br_multicast.c
> @@ -1142,9 +1142,31 @@ static void br_multicast_update_active(struct net_bridge_mcast *brmctx)
>  
>  	lockdep_assert_held_once(&brmctx->br->multicast_lock);
>  
> -	if (!br_opt_get(brmctx->br, BROPT_MULTICAST_ENABLED))
> +	if (!br_opt_get(brmctx->br, BROPT_MULTICAST_ENABLED)) {
>  		force_inactive = true;
> +		goto update;
> +	}
>  
> +	if (br_opt_get(brmctx->br, BROPT_MCAST_VLAN_SNOOPING_ENABLED)) {
> +		/* with per-vlan snooping enabled there is an extra per-vlan
> +		 * toggle to enable/disable snooping which we must check
> +		 */
> +		if (br_multicast_ctx_vlan_global_disabled(brmctx))
> +			force_inactive = true;
> +		/* with per-vlan snooping enabled the non-vlan multicast
> +		 * snooping context is inactive
> +		 */
> +		else if (!br_multicast_ctx_is_vlan(brmctx))
> +			force_inactive = true;
> +	} else {
> +		/* with per-vlan snooping disabled a vlan multicast
> +		 * snooping context is inactive
> +		 */
> +		if (br_multicast_ctx_is_vlan(brmctx))
> +			force_inactive = true;
> +	}
> +
> +update:
>  	br_ip4_multicast_update_active(brmctx, force_inactive);
>  	br_ip6_multicast_update_active(brmctx, force_inactive);
>  
> @@ -4505,6 +4527,7 @@ void br_multicast_toggle_one_vlan(struct net_bridge_vlan *vlan, bool on)
>  
>  		spin_lock_bh(&br->multicast_lock);
>  		vlan->priv_flags ^= BR_VLFLAG_MCAST_ENABLED;
> +		br_multicast_update_active(&vlan->br_mcast_ctx);
>  
>  		if (on)
>  			__br_multicast_open(&vlan->br_mcast_ctx);

I believe the active state is not disabled when snooping is disabled on
a specific VLAN. AFAICT that's because br_multicast_update_active() is
only called when the VLAN is actually used by the bridge (i.e.,
"brentry"). Can be reproduced with [1]. Please add it as a test case in
patch #2.

Will continue tomorrow.

[1]
#!/bin/bash

for ns in ns0 ns1; do
	ip netns del $ns &> /dev/null
	ip netns add $ns
	ip -n $ns link set dev lo up
done

ip -n ns0 link add name veth0 type veth peer name veth1 netns ns1

ip -n ns0 link add name br0 up type bridge vlan_filtering 1 mcast_snooping 1 mcast_vlan_snooping 1
ip -n ns1 link add name br1 up type bridge vlan_filtering 1 mcast_snooping 1 mcast_vlan_snooping 1

ip -n ns0 link set dev veth0 up master br0
ip -n ns1 link set dev veth1 up master br1

bridge -n ns0 vlan add vid 10 dev veth0 master
bridge -n ns1 vlan add vid 10 dev veth1 master

sleep 1

bridge -n ns0 vlan global set vid 10 dev br0 mcast_snooping 1 mcast_query_response_interval 100 mcast_querier 1
bridge -n ns1 vlan global set vid 10 dev br1 mcast_snooping 1 mcast_query_response_interval 100 mcast_querier 0

sleep 1

bridge -n ns1 -j -p vlan global show dev br1 vid 10 | jq '.[]["vlans"][]["mcast_active_v4"]'

bridge -n ns1 vlan global set vid 10 dev br1 mcast_snooping 0
sleep 1
bridge -n ns1 -j -p vlan global show dev br1 vid 10 | jq '.[]["vlans"][]["mcast_active_v4"]'