From nobody Fri Oct 3 14:34:25 2025 Received: from mail.aperture-lab.de (mail.aperture-lab.de [116.203.183.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1CF7A2DCF6F; Fri, 29 Aug 2025 09:04:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=116.203.183.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756458292; cv=none; b=hNhxhmxh12zQzR3BSh+FYwW/vK9uYGaHWZm9/mv4nbwX9QylZCV5BVf4LfOwh6M5v5i5hL0FHwF7QNi2unk1+ZmNmmaSJXFrM9iWiSkM9vg1qa/0T0dQK3fnU/IR47joOa1gvf8OnpZojvwVosNSNS72qcGqYx8fRltlqd2EO3k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756458292; c=relaxed/simple; bh=aNcFr2dAW7sNkmQoscRhRn0JZ3avd2DELg+pkBK4jmE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=PolLF3n95Gy+wVTXqIS2tpW9HH406ZSvzBzl2Al/XgVNlburFUgoYhOvKCFMxvA9Ijc01GAdlE/uhFMNrcNYU8MvJDKTr1Wkpo8XCtLMvoqbTw0n6VnfU2G7m5cQGaktfp8l1K6s32In2ZkG/FbpFGGeOY6WTgz8f54SA0FGt0s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=c0d3.blue; spf=pass smtp.mailfrom=c0d3.blue; arc=none smtp.client-ip=116.203.183.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=c0d3.blue Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=c0d3.blue Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id F01AC54F66C; Fri, 29 Aug 2025 10:57:33 +0200 (CEST) From: =?UTF-8?q?Linus=20L=C3=BCssing?= To: bridge@lists.linux.dev Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Nikolay Aleksandrov , Ido Schimmel , Andrew Lunn , Simon Horman , Paolo Abeni , Jakub Kicinski , Eric Dumazet , "David S . Miller" , Kuniyuki Iwashima , Stanislav Fomichev , Xiao Liang , =?UTF-8?q?Linus=20L=C3=BCssing?= Subject: [PATCH 1/9] net: bridge: mcast: track active state, IGMP/MLD querier appearance Date: Fri, 29 Aug 2025 10:53:42 +0200 Message-ID: <20250829085724.24230-2-linus.luessing@c0d3.blue> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250829085724.24230-1-linus.luessing@c0d3.blue> References: <20250829085724.24230-1-linus.luessing@c0d3.blue> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Last-TLS-Session-Version: TLSv1.3 This is the first step to track in dedicated, per protocol family variables if we can actively and safely use multicast snooping. To later use these in the fast/data path instead of performing all these checks for every packet and to later notify DSA/switchdev about this state. This toggles these new variables to true after a Maximum Response Delay (default: 10 seconds) if a new IGMP or MLD querier has appeared. This can be triggered either through receiving an IGMP/MLD query from another host or by a user enabling our own IGMP/MLD querier. This is the first of several requirements, similar to what br_multicast_querier_exists() already checks so far, to be able to reliably receive IGMP/MLD reports, which in turn are needed to build a complete multicast database. No functional change for the fast/data path yet. Signed-off-by: Linus L=C3=BCssing --- net/bridge/br_multicast.c | 91 +++++++++++++++++++++++++++++++++++++-- net/bridge/br_private.h | 2 + 2 files changed, 90 insertions(+), 3 deletions(-) diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 22d12e545966..5cc713adcf9b 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -1069,6 +1069,65 @@ static struct sk_buff *br_ip4_multicast_alloc_query(= struct net_bridge_mcast *brm return skb; } =20 +static bool br_ip4_multicast_querier_exists(struct net_bridge_mcast *brmct= x) +{ + return __br_multicast_querier_exists(brmctx, &brmctx->ip4_other_query, fa= lse); +} + +#if IS_ENABLED(CONFIG_IPV6) +static bool br_ip6_multicast_querier_exists(struct net_bridge_mcast *brmct= x) +{ + return __br_multicast_querier_exists(brmctx, &brmctx->ip6_other_query, tr= ue); +} +#endif + +static void br_ip4_multicast_update_active(struct net_bridge_mcast *brmctx, + bool force_inactive) +{ + if (force_inactive) + brmctx->ip4_active =3D false; + else + brmctx->ip4_active =3D br_ip4_multicast_querier_exists(brmctx); +} + +static void br_ip6_multicast_update_active(struct net_bridge_mcast *brmctx, + bool force_inactive) +{ +#if IS_ENABLED(CONFIG_IPV6) + if (force_inactive) + brmctx->ip6_active =3D false; + else + brmctx->ip6_active =3D br_ip6_multicast_querier_exists(brmctx); +#endif +} + +/** + * br_multicast_update_active() - update mcast active state + * @brmctx: the bridge multicast context to check + * + * This (potentially) updates the IPv4/IPv6 multicast active state. And by + * that enables or disables snooping of multicast payload traffic in fast + * path. + * + * The multicast active state is set, per protocol family, if: + * + * - an IGMP/MLD querier is present + * + * And is unset otherwise. + * + * This function should be called by anything that changes one of the + * above prerequisites. + */ +static void br_multicast_update_active(struct net_bridge_mcast *brmctx) +{ + bool force_inactive =3D false; + + lockdep_assert_held_once(&brmctx->br->multicast_lock); + + br_ip4_multicast_update_active(brmctx, force_inactive); + br_ip6_multicast_update_active(brmctx, force_inactive); +} + #if IS_ENABLED(CONFIG_IPV6) static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge_mcas= t *brmctx, struct net_bridge_mcast_port *pmctx, @@ -1762,10 +1821,34 @@ static void br_ip6_multicast_querier_expired(struct= timer_list *t) } #endif =20 -static void br_multicast_query_delay_expired(struct timer_list *t) +static void br_ip4_multicast_query_delay_expired(struct timer_list *t) { + struct net_bridge_mcast *brmctx =3D timer_container_of(brmctx, t, + ip4_other_query.delay_timer); + + spin_lock(&brmctx->br->multicast_lock); + /* an own or other IGMP querier appeared some seconds ago and all + * reports should have arrived by now, maybe set multicast state to active + */ + br_multicast_update_active(brmctx); + spin_unlock(&brmctx->br->multicast_lock); } =20 +#if IS_ENABLED(CONFIG_IPV6) +static void br_ip6_multicast_query_delay_expired(struct timer_list *t) +{ + struct net_bridge_mcast *brmctx =3D timer_container_of(brmctx, t, + ip6_other_query.delay_timer); + + spin_lock(&brmctx->br->multicast_lock); + /* an own or other MLD querier appeared some seconds ago and all + * reports should have arrived, maybe set multicast state to active + */ + br_multicast_update_active(brmctx); + spin_unlock(&brmctx->br->multicast_lock); +} +#endif + static void br_multicast_select_own_querier(struct net_bridge_mcast *brmct= x, struct br_ip *ip, struct sk_buff *skb) @@ -4112,11 +4195,13 @@ void br_multicast_ctx_init(struct net_bridge *br, brmctx->multicast_membership_interval =3D 260 * HZ; =20 brmctx->ip4_querier.port_ifidx =3D 0; + brmctx->ip4_active =3D 0; seqcount_spinlock_init(&brmctx->ip4_querier.seq, &br->multicast_lock); brmctx->multicast_igmp_version =3D 2; #if IS_ENABLED(CONFIG_IPV6) brmctx->multicast_mld_version =3D 1; brmctx->ip6_querier.port_ifidx =3D 0; + brmctx->ip6_active =3D 0; seqcount_spinlock_init(&brmctx->ip6_querier.seq, &br->multicast_lock); #endif =20 @@ -4125,7 +4210,7 @@ void br_multicast_ctx_init(struct net_bridge *br, timer_setup(&brmctx->ip4_other_query.timer, br_ip4_multicast_querier_expired, 0); timer_setup(&brmctx->ip4_other_query.delay_timer, - br_multicast_query_delay_expired, 0); + br_ip4_multicast_query_delay_expired, 0); timer_setup(&brmctx->ip4_own_query.timer, br_ip4_multicast_query_expired, 0); #if IS_ENABLED(CONFIG_IPV6) @@ -4134,7 +4219,7 @@ void br_multicast_ctx_init(struct net_bridge *br, timer_setup(&brmctx->ip6_other_query.timer, br_ip6_multicast_querier_expired, 0); timer_setup(&brmctx->ip6_other_query.delay_timer, - br_multicast_query_delay_expired, 0); + br_ip6_multicast_query_delay_expired, 0); timer_setup(&brmctx->ip6_own_query.timer, br_ip6_multicast_query_expired, 0); #endif diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 8de0904b9627..f83c24def595 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -160,12 +160,14 @@ struct net_bridge_mcast { struct bridge_mcast_other_query ip4_other_query; struct bridge_mcast_own_query ip4_own_query; struct bridge_mcast_querier ip4_querier; + bool ip4_active; #if IS_ENABLED(CONFIG_IPV6) struct hlist_head ip6_mc_router_list; struct timer_list ip6_mc_router_timer; struct bridge_mcast_other_query ip6_other_query; struct bridge_mcast_own_query ip6_own_query; struct bridge_mcast_querier ip6_querier; + bool ip6_active; #endif /* IS_ENABLED(CONFIG_IPV6) */ #endif /* CONFIG_BRIDGE_IGMP_SNOOPING */ }; --=20 2.50.1 From nobody Fri Oct 3 14:34:25 2025 Received: from mail.aperture-lab.de (mail.aperture-lab.de [116.203.183.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BE4982E339E; Fri, 29 Aug 2025 09:04:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=116.203.183.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756458292; cv=none; b=KQ9veVWdaOro7gJDgZTb2/O5igYBnhxU2rHdIE1O0rlirIUc2latw/s9ftdJDHr3XP2ERK+882Hg2wAukfGcSoQr4IYUOHHWGcFsjTDn2ZyMuAIqhST2FAjB6UymlfKFyinptCxiZ6JUtQ0xk4aeExWlsag9BFEz5hjo5Kna10o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756458292; c=relaxed/simple; bh=fbBKMw9IBF47m/JGG1gdhqS6Y0eNHz+HO0O98UFQ5Dw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=reZG/bje34e/iWUH0/PfnxVMLCT4QrJBvlfTemoj8o3ldlYA+VVm8I9xzIr/O7srZDc2MIkasAYVyh3wetbAunWVqTdLV6V+Q6WjD/kA2cQOSmGD7QEUWiNlNIu+Sb+gG/KEVA/JMAUkQd/eCrhodKjaSVWUH1dc9kGvEWvkNIs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=c0d3.blue; spf=pass smtp.mailfrom=c0d3.blue; arc=none smtp.client-ip=116.203.183.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=c0d3.blue Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=c0d3.blue Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 5D25054F683; Fri, 29 Aug 2025 10:57:35 +0200 (CEST) From: =?UTF-8?q?Linus=20L=C3=BCssing?= To: bridge@lists.linux.dev Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Nikolay Aleksandrov , Ido Schimmel , Andrew Lunn , Simon Horman , Paolo Abeni , Jakub Kicinski , Eric Dumazet , "David S . Miller" , Kuniyuki Iwashima , Stanislav Fomichev , Xiao Liang , =?UTF-8?q?Linus=20L=C3=BCssing?= Subject: [PATCH 2/9] net: bridge: mcast: track active state, foreign IGMP/MLD querier disappearance Date: Fri, 29 Aug 2025 10:53:43 +0200 Message-ID: <20250829085724.24230-3-linus.luessing@c0d3.blue> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250829085724.24230-1-linus.luessing@c0d3.blue> References: <20250829085724.24230-1-linus.luessing@c0d3.blue> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Last-TLS-Session-Version: TLSv1.3 This change ensures that the new multicast active state variable is unset again after a foreign IGMP/MLD querier has disappeared (default: 255 seconds). If no new, other IGMP/MLD querier took over then we can't reliably receive IGMP/MLD reports anymore and in turn can't ensure the completeness of our MDB anymore either. No functional change for the fast/data path yet. Signed-off-by: Linus L=C3=BCssing --- net/bridge/br_multicast.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 5cc713adcf9b..2e5b5281e484 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -1800,6 +1800,10 @@ static void br_multicast_querier_expired(struct net_= bridge_mcast *brmctx, br_multicast_start_querier(brmctx, query); =20 out: + /* another IGMP/MLD querier disappeared, set multicast state to inactive + * if our own querier is disabled, too + */ + br_multicast_update_active(brmctx); spin_unlock(&brmctx->br->multicast_lock); } =20 --=20 2.50.1 From nobody Fri Oct 3 14:34:25 2025 Received: from mail.aperture-lab.de (mail.aperture-lab.de [116.203.183.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BE4062E337B; Fri, 29 Aug 2025 09:04:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=116.203.183.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756458292; cv=none; b=caUuhh4UCgqKAYyYYgcCpVdh+5yQkypBi67oPQ0/sJtCX4jUXsIj7O/icolSW/z3+tc2aK+aQZcMPXOrSho/7+RDToWYrvzp8toOVbIK6k3m0IFBFA/VYnkUa8KVTupDaehgXuwfUbkib/4b9akkxcClLoEnnOXHDP/l3CDQhBE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756458292; c=relaxed/simple; bh=xlFbFNeGawRnq4xxs78hLclAmH+Lzu/wNhnqs0cOCbw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=JVfXy24q0gPBX1ytNH2jUZSUuIY65RaaKw/RVqo7qKmD7jCG6j8+HU5lEVwFOsXiHrGWxVSo2OrqAYTsCv9M7sgQdemiybQhnnKiAByipT/jxwR1Af1LuV66rkjgJ2cpw19v98Fe9NglYC3Cq7W/yMW9RTfe+8sfEsKvbX7eAwU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=c0d3.blue; spf=pass smtp.mailfrom=c0d3.blue; arc=none smtp.client-ip=116.203.183.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=c0d3.blue Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=c0d3.blue Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 8B0AA54F687; Fri, 29 Aug 2025 10:57:36 +0200 (CEST) From: =?UTF-8?q?Linus=20L=C3=BCssing?= To: bridge@lists.linux.dev Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Nikolay Aleksandrov , Ido Schimmel , Andrew Lunn , Simon Horman , Paolo Abeni , Jakub Kicinski , Eric Dumazet , "David S . Miller" , Kuniyuki Iwashima , Stanislav Fomichev , Xiao Liang , =?UTF-8?q?Linus=20L=C3=BCssing?= Subject: [PATCH 3/9] net: bridge: mcast: track active state, IPv6 address availability Date: Fri, 29 Aug 2025 10:53:44 +0200 Message-ID: <20250829085724.24230-4-linus.luessing@c0d3.blue> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250829085724.24230-1-linus.luessing@c0d3.blue> References: <20250829085724.24230-1-linus.luessing@c0d3.blue> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Last-TLS-Session-Version: TLSv1.3 If we are the only potential MLD querier but don't have an IPv6 link-local address configured on our bridge interface then we can't create a valid MLD query and in turn can't reliably receive MLD reports and can't build a complete MDB. Hence disable the new multicast active state variable then. Or reenable it if an IPv6 link-local address became available. No functional change for the fast/data path yet. Signed-off-by: Linus L=C3=BCssing --- net/bridge/br_multicast.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 2e5b5281e484..b689e62b9e74 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -1112,6 +1112,7 @@ static void br_ip6_multicast_update_active(struct net= _bridge_mcast *brmctx, * The multicast active state is set, per protocol family, if: * * - an IGMP/MLD querier is present + * - for own IPv6 MLD querier: an IPv6 address is configured on the bridge * * And is unset otherwise. * @@ -1206,10 +1207,12 @@ static struct sk_buff *br_ip6_multicast_alloc_query= (struct net_bridge_mcast *brm &ip6h->daddr, 0, &ip6h->saddr)) { kfree_skb(skb); br_opt_toggle(brmctx->br, BROPT_HAS_IPV6_ADDR, false); + br_multicast_update_active(brmctx); return NULL; } =20 br_opt_toggle(brmctx->br, BROPT_HAS_IPV6_ADDR, true); + br_multicast_update_active(brmctx); ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest); =20 hopopt =3D (u8 *)(ip6h + 1); --=20 2.50.1 From nobody Fri Oct 3 14:34:25 2025 Received: from mail.aperture-lab.de (mail.aperture-lab.de [116.203.183.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E397B2E3AFE; Fri, 29 Aug 2025 09:04:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=116.203.183.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756458292; cv=none; b=inLKd2WM3zdurC/Dqgp5u/F0M2elQFi4WN8TTlPUXhqwMfEzcrnUnDjTmKpwqURSu41rtGnLRywen0lEUjxySnBxgLRmRiKFo69BVd+Vv5r5B9aI8cdJmwhg3UnOUrvUW6dG+wVmlVCkCAArwOQP53XC14pLOgqxZpRo7fFEHeY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756458292; c=relaxed/simple; bh=r+3rfB+WbGku9OYPkoNsOw1s2NBUXdF0N5hjuZ+9264=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Ti2cq9enrcGRk9/Tsz/jMsSUy2t3ToPD8hSWizd5ZbCvO6V9JtVrdjvNCc0lQE2aUD6av0jL8Xd75qS9WP30TQaj6RyCa4yUgelhudaUHz+nnXI0quqJWJyf4T5EIhM8JPAwuorGOZanjWX96dRpWawsmdv6j8I/RsS1tIl/mfA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=c0d3.blue; spf=pass smtp.mailfrom=c0d3.blue; arc=none smtp.client-ip=116.203.183.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=c0d3.blue Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=c0d3.blue Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id D18A054F6AB; Fri, 29 Aug 2025 10:57:39 +0200 (CEST) From: =?UTF-8?q?Linus=20L=C3=BCssing?= To: bridge@lists.linux.dev Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Nikolay Aleksandrov , Ido Schimmel , Andrew Lunn , Simon Horman , Paolo Abeni , Jakub Kicinski , Eric Dumazet , "David S . Miller" , Kuniyuki Iwashima , Stanislav Fomichev , Xiao Liang , =?UTF-8?q?Linus=20L=C3=BCssing?= Subject: [PATCH 4/9] net: bridge: mcast: track active state, own MLD querier disappearance Date: Fri, 29 Aug 2025 10:53:45 +0200 Message-ID: <20250829085724.24230-5-linus.luessing@c0d3.blue> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250829085724.24230-1-linus.luessing@c0d3.blue> References: <20250829085724.24230-1-linus.luessing@c0d3.blue> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Last-TLS-Session-Version: TLSv1.3 This change ensures that the new multicast active state variable is immediately unset if our internal IGMP/MLD querier was elected and now disabled. If no IGMP/MLD querier exists on the link then we can't reliably receive IGMP/MLD reports and in turn can't ensure the completeness of our MDB anymore either. No functional change for the fast/data path yet. This is the last necessary check before using the new multicast active state variable in the fast/data path, too. Signed-off-by: Linus L=C3=BCssing --- net/bridge/br_multicast.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index b689e62b9e74..13840f8f2e5f 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -4849,6 +4849,7 @@ int br_multicast_set_querier(struct net_bridge_mcast = *brmctx, unsigned long val) #endif =20 unlock: + br_multicast_update_active(brmctx); spin_unlock_bh(&brmctx->br->multicast_lock); =20 return 0; --=20 2.50.1 From nobody Fri Oct 3 14:34:25 2025 Received: from mail.aperture-lab.de (mail.aperture-lab.de [116.203.183.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BF4062BE63A; Fri, 29 Aug 2025 08:57:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=116.203.183.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756457869; cv=none; b=c0tWvP2R8av4zLT+8hdGbGg0UJY9c1+z3YOGVLF/2Wm8VT4y7hSsz+YBA8cq5qLUKz5mxODgP+N8GN4bmdBWfilRE4wMGdtTmoeeZiReGMhzE8Pa8giq2St0+ncnCLWnA7maV+BwQlyRWilvpvA34G3JQ23360H/rMRhWvVt0KE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756457869; c=relaxed/simple; bh=bQOvgOoppceBzTNV4VcTZG5BOPE1ySioEcjDqcVOOkc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=ohCtOUT1a5ZF3FgWRNXv94o5wCD+HqbscFFqRo9RpCqFcLYiVztF/EIkxxjvZZgsWSLkuvkNz2MyWyHn+wkySauiqYy2HUgq0+B+3S2R+7DLxPftgx6sd8bMTKg9UvInwgFaFWlydM5wXnjsV7S3CpCPcnddoo3zWicnPkis88I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=c0d3.blue; spf=pass smtp.mailfrom=c0d3.blue; arc=none smtp.client-ip=116.203.183.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=c0d3.blue Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=c0d3.blue Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 60F9454F6B8; Fri, 29 Aug 2025 10:57:41 +0200 (CEST) From: =?UTF-8?q?Linus=20L=C3=BCssing?= To: bridge@lists.linux.dev Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Nikolay Aleksandrov , Ido Schimmel , Andrew Lunn , Simon Horman , Paolo Abeni , Jakub Kicinski , Eric Dumazet , "David S . Miller" , Kuniyuki Iwashima , Stanislav Fomichev , Xiao Liang , =?UTF-8?q?Linus=20L=C3=BCssing?= Subject: [PATCH 5/9] net: bridge: mcast: export ip{4,6}_active state to netlink Date: Fri, 29 Aug 2025 10:53:46 +0200 Message-ID: <20250829085724.24230-6-linus.luessing@c0d3.blue> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250829085724.24230-1-linus.luessing@c0d3.blue> References: <20250829085724.24230-1-linus.luessing@c0d3.blue> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Last-TLS-Session-Version: TLSv1.3 Export the new ip{4,6}_active variables to netlink, to be able to check from userspace that they are updated as intended. Signed-off-by: Linus L=C3=BCssing --- include/uapi/linux/if_bridge.h | 2 ++ include/uapi/linux/if_link.h | 12 ++++++++++++ net/bridge/br_netlink.c | 10 +++++++++- net/bridge/br_vlan_options.c | 10 +++++++++- net/core/rtnetlink.c | 2 +- 5 files changed, 33 insertions(+), 3 deletions(-) diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h index 73876c0e2bba..c4d92df8d374 100644 --- a/include/uapi/linux/if_bridge.h +++ b/include/uapi/linux/if_bridge.h @@ -584,6 +584,8 @@ enum { BRIDGE_VLANDB_GOPTS_MCAST_ROUTER_PORTS, BRIDGE_VLANDB_GOPTS_MCAST_QUERIER_STATE, BRIDGE_VLANDB_GOPTS_MSTI, + BRIDGE_VLANDB_GOPTS_MCAST_ACTIVE_V4, + BRIDGE_VLANDB_GOPTS_MCAST_ACTIVE_V6, __BRIDGE_VLANDB_GOPTS_MAX }; #define BRIDGE_VLANDB_GOPTS_MAX (__BRIDGE_VLANDB_GOPTS_MAX - 1) diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index 784ace3a519c..fcf2c42aa6c4 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -742,6 +742,16 @@ enum in6_addr_gen_mode { * @IFLA_BR_FDB_MAX_LEARNED * Set the number of max dynamically learned FDB entries for the current * bridge. + * + * @IFLA_BR_MCAST_ACTIVE_V4 + * Bridge IPv4 mcast active state, read only. + * + * 1 if an IGMP querier is present, 0 otherwise. + * + * @IFLA_BR_MCAST_ACTIVE_V6 + * Bridge IPv6 mcast active state, read only. + * + * 1 if an MLD querier is present, 0 otherwise. */ enum { IFLA_BR_UNSPEC, @@ -794,6 +804,8 @@ enum { IFLA_BR_MCAST_QUERIER_STATE, IFLA_BR_FDB_N_LEARNED, IFLA_BR_FDB_MAX_LEARNED, + IFLA_BR_MCAST_ACTIVE_V4, + IFLA_BR_MCAST_ACTIVE_V6, __IFLA_BR_MAX, }; =20 diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index 4e2d53b27221..5aa1721830d6 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -1264,7 +1264,9 @@ static const struct nla_policy br_policy[IFLA_BR_MAX = + 1] =3D { [IFLA_BR_VLAN_STATS_ENABLED] =3D { .type =3D NLA_U8 }, [IFLA_BR_MCAST_STATS_ENABLED] =3D { .type =3D NLA_U8 }, [IFLA_BR_MCAST_IGMP_VERSION] =3D { .type =3D NLA_U8 }, + [IFLA_BR_MCAST_ACTIVE_V4] =3D { .type =3D NLA_REJECT }, [IFLA_BR_MCAST_MLD_VERSION] =3D { .type =3D NLA_U8 }, + [IFLA_BR_MCAST_ACTIVE_V6] =3D { .type =3D NLA_REJECT }, [IFLA_BR_VLAN_STATS_PER_PORT] =3D { .type =3D NLA_U8 }, [IFLA_BR_MULTI_BOOLOPT] =3D NLA_POLICY_EXACT_LEN(sizeof(struct br_boolopt_multi)), @@ -1625,7 +1627,9 @@ static size_t br_get_size(const struct net_device *br= dev) nla_total_size_64bit(sizeof(u64)) + /* IFLA_BR_MCAST_QUERY_RESPONS= E_INTVL */ nla_total_size_64bit(sizeof(u64)) + /* IFLA_BR_MCAST_STARTUP_QUERY= _INTVL */ nla_total_size(sizeof(u8)) + /* IFLA_BR_MCAST_IGMP_VERSION */ + nla_total_size(sizeof(u8)) + /* IFLA_BR_MCAST_ACTIVE_V4 */ nla_total_size(sizeof(u8)) + /* IFLA_BR_MCAST_MLD_VERSION */ + nla_total_size(sizeof(u8)) + /* IFLA_BR_MCAST_ACTIVE_V6 */ br_multicast_querier_state_size() + /* IFLA_BR_MCAST_QUERIER_STATE= */ #endif #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) @@ -1717,12 +1721,16 @@ static int br_fill_info(struct sk_buff *skb, const = struct net_device *brdev) br->multicast_ctx.multicast_startup_query_count) || nla_put_u8(skb, IFLA_BR_MCAST_IGMP_VERSION, br->multicast_ctx.multicast_igmp_version) || + nla_put_u8(skb, IFLA_BR_MCAST_ACTIVE_V4, + br->multicast_ctx.ip4_active) || br_multicast_dump_querier_state(skb, &br->multicast_ctx, IFLA_BR_MCAST_QUERIER_STATE)) return -EMSGSIZE; #if IS_ENABLED(CONFIG_IPV6) if (nla_put_u8(skb, IFLA_BR_MCAST_MLD_VERSION, - br->multicast_ctx.multicast_mld_version)) + br->multicast_ctx.multicast_mld_version) || + nla_put_u8(skb, IFLA_BR_MCAST_ACTIVE_V6, + br->multicast_ctx.ip6_active)) return -EMSGSIZE; #endif clockval =3D jiffies_to_clock_t(br->multicast_ctx.multicast_last_member_i= nterval); diff --git a/net/bridge/br_vlan_options.c b/net/bridge/br_vlan_options.c index 8fa89b04ee94..33f055d3a304 100644 --- a/net/bridge/br_vlan_options.c +++ b/net/bridge/br_vlan_options.c @@ -369,6 +369,8 @@ bool br_vlan_global_opts_fill(struct sk_buff *skb, u16 = vid, u16 vid_range, !!(v_opts->priv_flags & BR_VLFLAG_GLOBAL_MCAST_ENABLED)) || nla_put_u8(skb, BRIDGE_VLANDB_GOPTS_MCAST_IGMP_VERSION, v_opts->br_mcast_ctx.multicast_igmp_version) || + nla_put_u8(skb, BRIDGE_VLANDB_GOPTS_MCAST_ACTIVE_V4, + v_opts->br_mcast_ctx.ip4_active) || nla_put_u32(skb, BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_CNT, v_opts->br_mcast_ctx.multicast_last_member_count) || nla_put_u32(skb, BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_CNT, @@ -423,7 +425,9 @@ bool br_vlan_global_opts_fill(struct sk_buff *skb, u16 = vid, u16 vid_range, =20 #if IS_ENABLED(CONFIG_IPV6) if (nla_put_u8(skb, BRIDGE_VLANDB_GOPTS_MCAST_MLD_VERSION, - v_opts->br_mcast_ctx.multicast_mld_version)) + v_opts->br_mcast_ctx.multicast_mld_version) || + nla_put_u8(skb, BRIDGE_VLANDB_GOPTS_MCAST_ACTIVE_V6, + v_opts->br_mcast_ctx.ip4_active)) goto out_err; #endif #endif @@ -448,7 +452,9 @@ static size_t rtnl_vlan_global_opts_nlmsg_size(const st= ruct net_bridge_vlan *v) #ifdef CONFIG_BRIDGE_IGMP_SNOOPING + nla_total_size(sizeof(u8)) /* BRIDGE_VLANDB_GOPTS_MCAST_SNOOPING */ + nla_total_size(sizeof(u8)) /* BRIDGE_VLANDB_GOPTS_MCAST_IGMP_VERSION */ + + nla_total_size(sizeof(u8)) /* BRIDGE_VLANDB_GOPTS_MCAST_ACTIVE_V4 */ + nla_total_size(sizeof(u8)) /* BRIDGE_VLANDB_GOPTS_MCAST_MLD_VERSION */ + + nla_total_size(sizeof(u8)) /* BRIDGE_VLANDB_GOPTS_MCAST_ACTIVE_V6 */ + nla_total_size(sizeof(u32)) /* BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_C= NT */ + nla_total_size(sizeof(u32)) /* BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY= _CNT */ + nla_total_size(sizeof(u64)) /* BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_I= NTVL */ @@ -630,9 +636,11 @@ static const struct nla_policy br_vlan_db_gpol[BRIDGE_= VLANDB_GOPTS_MAX + 1] =3D { [BRIDGE_VLANDB_GOPTS_RANGE] =3D { .type =3D NLA_U16 }, [BRIDGE_VLANDB_GOPTS_MCAST_SNOOPING] =3D { .type =3D NLA_U8 }, [BRIDGE_VLANDB_GOPTS_MCAST_MLD_VERSION] =3D { .type =3D NLA_U8 }, + [BRIDGE_VLANDB_GOPTS_MCAST_ACTIVE_V6] =3D { .type =3D NLA_REJECT }, [BRIDGE_VLANDB_GOPTS_MCAST_QUERY_INTVL] =3D { .type =3D NLA_U64 }, [BRIDGE_VLANDB_GOPTS_MCAST_QUERIER] =3D { .type =3D NLA_U8 }, [BRIDGE_VLANDB_GOPTS_MCAST_IGMP_VERSION] =3D { .type =3D NLA_U8 }, + [BRIDGE_VLANDB_GOPTS_MCAST_ACTIVE_V4] =3D { .type =3D NLA_REJECT }, [BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_CNT] =3D { .type =3D NLA_U32 }, [BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_CNT] =3D { .type =3D NLA_U32 }, [BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_INTVL] =3D { .type =3D NLA_U64 }, diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 094b085cff20..cb24370b719f 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -62,7 +62,7 @@ =20 #include "dev.h" =20 -#define RTNL_MAX_TYPE 50 +#define RTNL_MAX_TYPE 52 #define RTNL_SLAVE_MAX_TYPE 44 =20 struct rtnl_link { --=20 2.50.1 From nobody Fri Oct 3 14:34:25 2025 Received: from mail.aperture-lab.de (mail.aperture-lab.de [116.203.183.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 06A6C2701D1; Fri, 29 Aug 2025 08:57:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=116.203.183.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756457868; cv=none; b=LHy/KifY+C32evGy3wwLcDd2qAGAXExQGLDXpdym941hn377Npks0QYntuUScZY1FGeuxA9YPXuU7OdOfcgtj2Ua1svvLimQBg1Jri/w7PsFO7J5MPWwUBjbcEKMyRBtw26fp/y2Ki4q+VyxPqN/rheXI/zD0MgKyNp3Ssnn91c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756457868; c=relaxed/simple; bh=5k0gEYVhfBeLd8xxoqdFRX8s4nSQjtv+QkQ6CPrvUAA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=vAHrfKnv658SBRlNubgeIm9kmn/Ap7LGpPdpN3NxIKM0QfVKdLRGVm11DCmhi0d7VJB76EXzKs4DdQXD/KDV3jtNMZ3sqlt8KK9s7yAVspt/nhthBNGPSSI/zLMB41RXoVTy5OirVJzotSFLSaL7bfMDty0EJ0YvJyBjEPjZoq4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=c0d3.blue; spf=pass smtp.mailfrom=c0d3.blue; arc=none smtp.client-ip=116.203.183.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=c0d3.blue Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=c0d3.blue Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id A5D6A54F6C2; Fri, 29 Aug 2025 10:57:42 +0200 (CEST) From: =?UTF-8?q?Linus=20L=C3=BCssing?= To: bridge@lists.linux.dev Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Nikolay Aleksandrov , Ido Schimmel , Andrew Lunn , Simon Horman , Paolo Abeni , Jakub Kicinski , Eric Dumazet , "David S . Miller" , Kuniyuki Iwashima , Stanislav Fomichev , Xiao Liang , =?UTF-8?q?Linus=20L=C3=BCssing?= Subject: [PATCH 6/9] net: bridge: mcast: use combined active state in fast/data path Date: Fri, 29 Aug 2025 10:53:47 +0200 Message-ID: <20250829085724.24230-7-linus.luessing@c0d3.blue> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250829085724.24230-1-linus.luessing@c0d3.blue> References: <20250829085724.24230-1-linus.luessing@c0d3.blue> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Last-TLS-Session-Version: TLSv1.3 As the multicast active state variable is now always up to date and functionally equivalent to our manual, extensive checks in fast path we can just use this state variable in fast path, too. This allows to save some CPU cycles for every multicast packet in the fast/data path. Next to using brmctx->ip4_active / brmctx->ip6_active in fast path this mostly just moves some code around to not expose it via br_private.h anymore. While at it now also passing the ethernet protocol number directly, instead of a pointer into the ethernet header. Signed-off-by: Linus L=C3=BCssing --- net/bridge/br_device.c | 2 +- net/bridge/br_input.c | 2 +- net/bridge/br_multicast.c | 40 ++++++++++++++++++++++++++++++++++----- net/bridge/br_private.h | 38 ++++++++----------------------------- 4 files changed, 45 insertions(+), 37 deletions(-) diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index a818fdc22da9..3cdf1c17108b 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -102,7 +102,7 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net= _device *dev) =20 mdst =3D br_mdb_entry_skb_get(brmctx, skb, vid); if ((mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) && - br_multicast_querier_exists(brmctx, eth_hdr(skb), mdst)) + br_multicast_snooping_active(brmctx, eth_hdr(skb)->h_proto, mdst)) br_multicast_flood(mdst, skb, brmctx, false, true); else br_flood(br, skb, BR_PKT_MULTICAST, false, true, vid); diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index 5f6ac9bf1527..dfd49b309683 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@ -187,7 +187,7 @@ int br_handle_frame_finish(struct net *net, struct sock= *sk, struct sk_buff *skb case BR_PKT_MULTICAST: mdst =3D br_mdb_entry_skb_get(brmctx, skb, vid); if ((mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) && - br_multicast_querier_exists(brmctx, eth_hdr(skb), mdst)) { + br_multicast_snooping_active(brmctx, eth_hdr(skb)->h_proto, mdst)) { if ((mdst && mdst->host_joined) || br_multicast_is_router(brmctx, skb) || br->dev->flags & IFF_ALLMULTI) { diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 13840f8f2e5f..54163c74b9a9 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -1069,6 +1069,26 @@ static struct sk_buff *br_ip4_multicast_alloc_query(= struct net_bridge_mcast *brm return skb; } =20 +static bool +__br_multicast_querier_exists(struct net_bridge_mcast *brmctx, + struct bridge_mcast_other_query *querier, + bool is_ipv6) +{ + bool own_querier_enabled; + + if (brmctx->multicast_querier) { + if (is_ipv6 && !br_opt_get(brmctx->br, BROPT_HAS_IPV6_ADDR)) + own_querier_enabled =3D false; + else + own_querier_enabled =3D true; + } else { + own_querier_enabled =3D false; + } + + return !timer_pending(&querier->delay_timer) && + (own_querier_enabled || timer_pending(&querier->timer)); +} + static bool br_ip4_multicast_querier_exists(struct net_bridge_mcast *brmct= x) { return __br_multicast_querier_exists(brmctx, &brmctx->ip4_other_query, fa= lse); @@ -1081,6 +1101,20 @@ static bool br_ip6_multicast_querier_exists(struct n= et_bridge_mcast *brmctx) } #endif =20 +static bool br_multicast_querier_exists(struct net_bridge_mcast *brmctx, i= nt proto) +{ + switch (proto) { + case (ETH_P_IP): + return br_ip4_multicast_querier_exists(brmctx); +#if IS_ENABLED(CONFIG_IPV6) + case (ETH_P_IPV6): + return br_ip6_multicast_querier_exists(brmctx); +#endif + default: + return false; + } +} + static void br_ip4_multicast_update_active(struct net_bridge_mcast *brmctx, bool force_inactive) { @@ -5013,7 +5047,6 @@ bool br_multicast_has_querier_anywhere(struct net_dev= ice *dev, int proto) { struct net_bridge *br; struct net_bridge_port *port; - struct ethhdr eth; bool ret =3D false; =20 rcu_read_lock(); @@ -5026,10 +5059,7 @@ bool br_multicast_has_querier_anywhere(struct net_de= vice *dev, int proto) =20 br =3D port->br; =20 - memset(ð, 0, sizeof(eth)); - eth.h_proto =3D htons(proto); - - ret =3D br_multicast_querier_exists(&br->multicast_ctx, ð, NULL); + ret =3D br_multicast_querier_exists(&br->multicast_ctx, proto); =20 unlock: rcu_read_unlock(); diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index f83c24def595..05650af596ab 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -1154,37 +1154,15 @@ br_multicast_is_router(struct net_bridge_mcast *brm= ctx, struct sk_buff *skb) } =20 static inline bool -__br_multicast_querier_exists(struct net_bridge_mcast *brmctx, - struct bridge_mcast_other_query *querier, - const bool is_ipv6) +br_multicast_snooping_active(struct net_bridge_mcast *brmctx, __be16 eth_p= roto, + const struct net_bridge_mdb_entry *mdb) { - bool own_querier_enabled; - - if (brmctx->multicast_querier) { - if (is_ipv6 && !br_opt_get(brmctx->br, BROPT_HAS_IPV6_ADDR)) - own_querier_enabled =3D false; - else - own_querier_enabled =3D true; - } else { - own_querier_enabled =3D false; - } - - return !timer_pending(&querier->delay_timer) && - (own_querier_enabled || timer_pending(&querier->timer)); -} - -static inline bool br_multicast_querier_exists(struct net_bridge_mcast *br= mctx, - struct ethhdr *eth, - const struct net_bridge_mdb_entry *mdb) -{ - switch (eth->h_proto) { + switch (eth_proto) { case (htons(ETH_P_IP)): - return __br_multicast_querier_exists(brmctx, - &brmctx->ip4_other_query, false); + return brmctx->ip4_active; #if IS_ENABLED(CONFIG_IPV6) case (htons(ETH_P_IPV6)): - return __br_multicast_querier_exists(brmctx, - &brmctx->ip6_other_query, true); + return brmctx->ip6_active; #endif default: return !!mdb && br_group_is_l2(&mdb->addr); @@ -1439,9 +1417,9 @@ static inline bool br_multicast_is_router(struct net_= bridge_mcast *brmctx, return false; } =20 -static inline bool br_multicast_querier_exists(struct net_bridge_mcast *br= mctx, - struct ethhdr *eth, - const struct net_bridge_mdb_entry *mdb) +static inline bool +br_multicast_snooping_active(struct net_bridge_mcast *brmctx, __be16 eth_p= roto, + const struct net_bridge_mdb_entry *mdb) { return false; } --=20 2.50.1 From nobody Fri Oct 3 14:34:25 2025 Received: from mail.aperture-lab.de (mail.aperture-lab.de [116.203.183.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 984941EEA40; Fri, 29 Aug 2025 08:57:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=116.203.183.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756457869; cv=none; b=ewAVqvYA+JrlydjjMLrPi/a22+LgdzGR34BSfBivWTg5/iUMHTjV2hhy5qHgYzSkKtNyTNjvSeh7xpBdrV9DNjFIPudoO4AavhlM8yjGqzFxzI3/U/RZVH0OQVYM5FejyzXLMOgKwb5v3fLTaAk+jIQ9nq7M/WH/Dv5Q/uSnJpc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756457869; c=relaxed/simple; bh=hIcmWdt6oCUpiVjncW8Q9KsvVg1CUjk/pioAO7KtjR4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=K2aJgM1F65IxHx9YZ7LxGJzP3+Cm4YynXO3CArz9q1M7avH2hYCsD2N0iMYahmm+hw+xg8xCx2K+eYokKkNBSQZMTVOVNaKiijprwXf9VOsymC+7uudLM4OKAy0xVaBvTpE2Y7w3tcZs2AI/GEke4mtmlmVd+wWONiDxyaar9qA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=c0d3.blue; spf=pass smtp.mailfrom=c0d3.blue; arc=none smtp.client-ip=116.203.183.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=c0d3.blue Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=c0d3.blue Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id EC37A54F6CA; Fri, 29 Aug 2025 10:57:43 +0200 (CEST) From: =?UTF-8?q?Linus=20L=C3=BCssing?= To: bridge@lists.linux.dev Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Nikolay Aleksandrov , Ido Schimmel , Andrew Lunn , Simon Horman , Paolo Abeni , Jakub Kicinski , Eric Dumazet , "David S . Miller" , Kuniyuki Iwashima , Stanislav Fomichev , Xiao Liang , =?UTF-8?q?Linus=20L=C3=BCssing?= Subject: [PATCH 7/9] net: bridge: mcast: active state, if snooping is enabled Date: Fri, 29 Aug 2025 10:53:48 +0200 Message-ID: <20250829085724.24230-8-linus.luessing@c0d3.blue> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250829085724.24230-1-linus.luessing@c0d3.blue> References: <20250829085724.24230-1-linus.luessing@c0d3.blue> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Last-TLS-Session-Version: TLSv1.3 To be able to use the upcoming SWITCHDEV_ATTR_ID_BRIDGE_MC_ACTIVE as a potential replacement for SWITCHDEV_ATTR_ID_BRIDGE_MC_DISABLED also check and toggle the active state if multicast snooping is enabled or disabled. So that MC_ACTIVE not only checks the querier state, but also if multicast snooping is enabled in general. No functional change for the fast/data path yet. Signed-off-by: Linus L=C3=BCssing --- include/uapi/linux/if_link.h | 6 ++++-- net/bridge/br_multicast.c | 21 +++++++++++++++++++-- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index fcf2c42aa6c4..ef686ea17afe 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -746,12 +746,14 @@ enum in6_addr_gen_mode { * @IFLA_BR_MCAST_ACTIVE_V4 * Bridge IPv4 mcast active state, read only. * - * 1 if an IGMP querier is present, 0 otherwise. + * 1 if *IFLA_BR_MCAST_SNOOPING* is enabled and an IGMP querier is prese= nt, + * 0 otherwise. * * @IFLA_BR_MCAST_ACTIVE_V6 * Bridge IPv6 mcast active state, read only. * - * 1 if an MLD querier is present, 0 otherwise. + * 1 if *IFLA_BR_MCAST_SNOOPING* is enabled and an MLD querier is presen= t, + * 0 otherwise. */ enum { IFLA_BR_UNSPEC, diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 54163c74b9a9..53720337a1e3 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -1145,6 +1145,7 @@ static void br_ip6_multicast_update_active(struct net= _bridge_mcast *brmctx, * * The multicast active state is set, per protocol family, if: * + * - multicast snooping is enabled * - an IGMP/MLD querier is present * - for own IPv6 MLD querier: an IPv6 address is configured on the bridge * @@ -1159,6 +1160,13 @@ static void br_multicast_update_active(struct net_br= idge_mcast *brmctx) =20 lockdep_assert_held_once(&brmctx->br->multicast_lock); =20 + if (!br_opt_get(brmctx->br, BROPT_MULTICAST_ENABLED)) + force_inactive =3D true; + + if (br_opt_get(brmctx->br, BROPT_MCAST_VLAN_SNOOPING_ENABLED) && + br_multicast_ctx_vlan_disabled(brmctx)) + force_inactive =3D true; + br_ip4_multicast_update_active(brmctx, force_inactive); br_ip6_multicast_update_active(brmctx, force_inactive); } @@ -1371,6 +1379,12 @@ static struct sk_buff *br_multicast_alloc_query(stru= ct net_bridge_mcast *brmctx, return NULL; } =20 +static void br_multicast_toggle_enabled(struct net_bridge *br, bool on) +{ + br_opt_toggle(br, BROPT_MULTICAST_ENABLED, on); + br_multicast_update_active(&br->multicast_ctx); +} + struct net_bridge_mdb_entry *br_multicast_new_group(struct net_bridge *br, struct br_ip *group) { @@ -1384,7 +1398,7 @@ struct net_bridge_mdb_entry *br_multicast_new_group(s= truct net_bridge *br, if (atomic_read(&br->mdb_hash_tbl.nelems) >=3D br->hash_max) { trace_br_mdb_full(br->dev, group); br_mc_disabled_update(br->dev, false, NULL); - br_opt_toggle(br, BROPT_MULTICAST_ENABLED, false); + br_multicast_toggle_enabled(br, false); return ERR_PTR(-E2BIG); } =20 @@ -4452,6 +4466,7 @@ void br_multicast_toggle_one_vlan(struct net_bridge_v= lan *vlan, bool on) =20 spin_lock_bh(&br->multicast_lock); vlan->priv_flags ^=3D BR_VLFLAG_MCAST_ENABLED; + br_multicast_update_active(&vlan->br_mcast_ctx); spin_unlock_bh(&br->multicast_lock); =20 if (on) @@ -4472,6 +4487,7 @@ void br_multicast_toggle_one_vlan(struct net_bridge_v= lan *vlan, bool on) __br_multicast_enable_port_ctx(&vlan->port_mcast_ctx); else __br_multicast_disable_port_ctx(&vlan->port_mcast_ctx); + br_multicast_update_active(brmctx); spin_unlock_bh(&br->multicast_lock); } } @@ -4792,7 +4808,8 @@ int br_multicast_toggle(struct net_bridge *br, unsign= ed long val, if (err) goto unlock; =20 - br_opt_toggle(br, BROPT_MULTICAST_ENABLED, !!val); + br_multicast_toggle_enabled(br, !!val); + if (!br_opt_get(br, BROPT_MULTICAST_ENABLED)) { change_snoopers =3D true; goto unlock; --=20 2.50.1 From nobody Fri Oct 3 14:34:25 2025 Received: from mail.aperture-lab.de (mail.aperture-lab.de [116.203.183.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E7A202BE7AD; Fri, 29 Aug 2025 08:57:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=116.203.183.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756457870; cv=none; b=C4b1JReCoxdeJPumdBAd+XBxs/ggPF6Gno7RoEa2R3435soSeZlW3Vp7TTlQi5Wsc1YNx8ewiBbmh+gLAEyVJqryZ0LFWx4qUukEvRJtWoDUxbaQbSFKBZdbbuTQbHpfTRrBIfZ0Iu7/Imo5DfqkS3cdxbMJm9zZunDg3n8Kqbw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756457870; c=relaxed/simple; bh=5tBY9R2qfz2tgyChHYNEpEVjcvXKbQ/eJbvbCi6oHOc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=SW+5cyUMdibaGImcli4W6UNd6CdnD67U3hvyYvqsJUmrFhD4QuiHtpuzdcftEoWEgLxY9t3v3ND4yCVYXZG+AZn5KmKkrrjVSURCqgG5VLk+tfarePnY7ubXISn7Mdyh9EFAtfQSM8R2BSnY9Yh5uRMqOKTBBnctcqKVzfiowX0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=c0d3.blue; spf=pass smtp.mailfrom=c0d3.blue; arc=none smtp.client-ip=116.203.183.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=c0d3.blue Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=c0d3.blue Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 3BEDE54F6D1; Fri, 29 Aug 2025 10:57:45 +0200 (CEST) From: =?UTF-8?q?Linus=20L=C3=BCssing?= To: bridge@lists.linux.dev Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Nikolay Aleksandrov , Ido Schimmel , Andrew Lunn , Simon Horman , Paolo Abeni , Jakub Kicinski , Eric Dumazet , "David S . Miller" , Kuniyuki Iwashima , Stanislav Fomichev , Xiao Liang , =?UTF-8?q?Linus=20L=C3=BCssing?= Subject: [PATCH 8/9] net: bridge: mcast: track active state, bridge up/down Date: Fri, 29 Aug 2025 10:53:49 +0200 Message-ID: <20250829085724.24230-9-linus.luessing@c0d3.blue> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250829085724.24230-1-linus.luessing@c0d3.blue> References: <20250829085724.24230-1-linus.luessing@c0d3.blue> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Last-TLS-Session-Version: TLSv1.3 This is mainly for switchdev and DSA later: To ensure that we switch to inactive before destroying a bridge interface. A switchdev/DSA driver might have allocated resources after we switched to an enabled multicast active state. This gives switchdev/DSA drivers a chance to free these resources again when we destroy the bridge (later). Putting it into the ndo_stop / bridge interface down part instead of the ndo_uninit / bridge destroy part though for a better semantic match. If the bridge interface is down / stopped then it is also inactive. No functional change for the fast/data path. Signed-off-by: Linus L=C3=BCssing --- include/uapi/linux/if_link.h | 8 ++++---- net/bridge/br_device.c | 3 +++ net/bridge/br_multicast.c | 26 ++++++++++++++++++++++---- 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index ef686ea17afe..76d15a07344d 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -746,14 +746,14 @@ enum in6_addr_gen_mode { * @IFLA_BR_MCAST_ACTIVE_V4 * Bridge IPv4 mcast active state, read only. * - * 1 if *IFLA_BR_MCAST_SNOOPING* is enabled and an IGMP querier is prese= nt, - * 0 otherwise. + * 1 if *IFLA_BR_MCAST_SNOOPING* is enabled, an IGMP querier is present + * and the bridge interface is up, 0 otherwise. * * @IFLA_BR_MCAST_ACTIVE_V6 * Bridge IPv6 mcast active state, read only. * - * 1 if *IFLA_BR_MCAST_SNOOPING* is enabled and an MLD querier is presen= t, - * 0 otherwise. + * 1 if *IFLA_BR_MCAST_SNOOPING* is enabled, an MLD querier is present + * and the bridge interface is up, 0 otherwise. */ enum { IFLA_BR_UNSPEC, diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 3cdf1c17108b..efb5d35c2dd4 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -168,7 +168,10 @@ static int br_dev_open(struct net_device *dev) netdev_update_features(dev); netif_start_queue(dev); br_stp_enable_bridge(br); + + spin_lock_bh(&br->multicast_lock); br_multicast_open(br); + spin_unlock_bh(&br->multicast_lock); =20 if (br_opt_get(br, BROPT_MULTICAST_ENABLED)) br_multicast_join_snoopers(br); diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 53720337a1e3..09e23e4d8b74 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -1145,6 +1145,7 @@ static void br_ip6_multicast_update_active(struct net= _bridge_mcast *brmctx, * * The multicast active state is set, per protocol family, if: * + * - the bridge interface is up * - multicast snooping is enabled * - an IGMP/MLD querier is present * - for own IPv6 MLD querier: an IPv6 address is configured on the bridge @@ -1160,6 +1161,9 @@ static void br_multicast_update_active(struct net_bri= dge_mcast *brmctx) =20 lockdep_assert_held_once(&brmctx->br->multicast_lock); =20 + if (!netif_running(brmctx->br->dev)) + force_inactive =3D true; + if (!br_opt_get(brmctx->br, BROPT_MULTICAST_ENABLED)) force_inactive =3D true; =20 @@ -4379,6 +4383,9 @@ static void __br_multicast_open(struct net_bridge_mca= st *brmctx) #if IS_ENABLED(CONFIG_IPV6) __br_multicast_open_query(brmctx->br, &brmctx->ip6_own_query); #endif + + /* bridge interface is up, maybe set multicast state to active */ + br_multicast_update_active(brmctx); } =20 void br_multicast_open(struct net_bridge *br) @@ -4417,6 +4424,11 @@ static void __br_multicast_stop(struct net_bridge_mc= ast *brmctx) timer_delete_sync(&brmctx->ip6_other_query.delay_timer); timer_delete_sync(&brmctx->ip6_own_query.timer); #endif + + spin_lock_bh(&brmctx->br->multicast_lock); + /* bridge interface is down, set multicast state to inactive */ + br_multicast_update_active(brmctx); + spin_unlock_bh(&brmctx->br->multicast_lock); } =20 void br_multicast_update_vlan_mcast_ctx(struct net_bridge_vlan *v, u8 stat= e) @@ -4469,10 +4481,13 @@ void br_multicast_toggle_one_vlan(struct net_bridge= _vlan *vlan, bool on) br_multicast_update_active(&vlan->br_mcast_ctx); spin_unlock_bh(&br->multicast_lock); =20 - if (on) + if (on) { + spin_lock_bh(&br->multicast_lock); __br_multicast_open(&vlan->br_mcast_ctx); - else + spin_unlock_bh(&br->multicast_lock); + } else { __br_multicast_stop(&vlan->br_mcast_ctx); + } } else { struct net_bridge_mcast *brmctx; =20 @@ -4534,10 +4549,13 @@ int br_multicast_toggle_vlan_snooping(struct net_br= idge *br, bool on, br_opt_toggle(br, BROPT_MCAST_VLAN_SNOOPING_ENABLED, on); =20 /* disable/enable non-vlan mcast contexts based on vlan snooping */ - if (on) + if (on) { __br_multicast_stop(&br->multicast_ctx); - else + } else { + spin_lock_bh(&br->multicast_lock); __br_multicast_open(&br->multicast_ctx); + spin_unlock_bh(&br->multicast_lock); + } list_for_each_entry(p, &br->port_list, list) { if (on) br_multicast_disable_port_ctx(&p->multicast_ctx); --=20 2.50.1 From nobody Fri Oct 3 14:34:25 2025 Received: from mail.aperture-lab.de (mail.aperture-lab.de [116.203.183.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 86F362C3271; Fri, 29 Aug 2025 08:57:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=116.203.183.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756457872; cv=none; b=e00g3JBAeKQgtOapD97/XBGaLWPxDOeUKYveVRBQ61qlWgUd/LZyZ/gwBSHrpptpmV3S/ZeEc9Ncp+G8Xjd8WA9+EgKC7gtkf/af4IfsLAYGTuVUryWjA5YnE/MCT6CYfUvnlGKWiTm4FkKj1UmBt2yypDSQoKhygxDZN+3IEV4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756457872; c=relaxed/simple; bh=XF9aiog0YNLpl5STE1KJ16Lm0Irt3eXp+klTmcIRsnI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Ujs0YAIAHjaGS8aUhQqQyAAArATn9RkC/DprV5a5ocxJjvo7Dje3Y8ALoIMs2fbY9cHxQsf6mXQVXSb8CG77Z0KrYVPxJNYb3WpYBWjbm7AU/YEuX9G1vscQqUBdpYm/lkQK25EHqEKz/WrKsCR3MDsbSMwyR8yn1Am5YEldACg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=c0d3.blue; spf=pass smtp.mailfrom=c0d3.blue; arc=none smtp.client-ip=116.203.183.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=c0d3.blue Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=c0d3.blue Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 8120054F65B; Fri, 29 Aug 2025 10:57:46 +0200 (CEST) From: =?UTF-8?q?Linus=20L=C3=BCssing?= To: bridge@lists.linux.dev Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Nikolay Aleksandrov , Ido Schimmel , Andrew Lunn , Simon Horman , Paolo Abeni , Jakub Kicinski , Eric Dumazet , "David S . Miller" , Kuniyuki Iwashima , Stanislav Fomichev , Xiao Liang , =?UTF-8?q?Linus=20L=C3=BCssing?= Subject: [PATCH 9/9] net: bridge: mcast: add inactive state assertions Date: Fri, 29 Aug 2025 10:53:50 +0200 Message-ID: <20250829085724.24230-10-linus.luessing@c0d3.blue> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250829085724.24230-1-linus.luessing@c0d3.blue> References: <20250829085724.24230-1-linus.luessing@c0d3.blue> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Last-TLS-Session-Version: TLSv1.3 To avoid packetloss and as it is very hard from a user's perspective to debug multicast snooping related issues it is even more crucial to properly switch from an active to an inactive multicast snooping state than the other way around. Therefore adding a few kernel warnings if any of our assertions to be in an inactive state would fail. Signed-off-by: Linus L=C3=BCssing --- net/bridge/br_multicast.c | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 09e23e4d8b74..46161e707fc5 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -1383,10 +1383,29 @@ static struct sk_buff *br_multicast_alloc_query(str= uct net_bridge_mcast *brmctx, return NULL; } =20 +static void br_ip4_multicast_assert_inactive(struct net_bridge_mcast *brmc= tx) +{ + WARN_ON(br_multicast_snooping_active(brmctx, htons(ETH_P_IP), NULL)); +} + +static void br_ip6_multicast_assert_inactive(struct net_bridge_mcast *brmc= tx) +{ + WARN_ON(br_multicast_snooping_active(brmctx, htons(ETH_P_IPV6), NULL)); +} + +static void br_multicast_assert_inactive(struct net_bridge_mcast *brmctx) +{ + br_ip4_multicast_assert_inactive(brmctx); + br_ip6_multicast_assert_inactive(brmctx); +} + static void br_multicast_toggle_enabled(struct net_bridge *br, bool on) { br_opt_toggle(br, BROPT_MULTICAST_ENABLED, on); br_multicast_update_active(&br->multicast_ctx); + + if (!on) + br_multicast_assert_inactive(&br->multicast_ctx); } =20 struct net_bridge_mdb_entry *br_multicast_new_group(struct net_bridge *br, @@ -1846,7 +1865,6 @@ static void br_ip6_multicast_local_router_expired(str= uct timer_list *t) static void br_multicast_querier_expired(struct net_bridge_mcast *brmctx, struct bridge_mcast_own_query *query) { - spin_lock(&brmctx->br->multicast_lock); if (!netif_running(brmctx->br->dev) || br_multicast_ctx_vlan_global_disabled(brmctx) || !br_opt_get(brmctx->br, BROPT_MULTICAST_ENABLED)) @@ -1859,7 +1877,6 @@ static void br_multicast_querier_expired(struct net_b= ridge_mcast *brmctx, * if our own querier is disabled, too */ br_multicast_update_active(brmctx); - spin_unlock(&brmctx->br->multicast_lock); } =20 static void br_ip4_multicast_querier_expired(struct timer_list *t) @@ -1867,7 +1884,12 @@ static void br_ip4_multicast_querier_expired(struct = timer_list *t) struct net_bridge_mcast *brmctx =3D timer_container_of(brmctx, t, ip4_other_query.timer); =20 + spin_lock(&brmctx->br->multicast_lock); br_multicast_querier_expired(brmctx, &brmctx->ip4_own_query); + + if (!brmctx->multicast_querier) + br_ip4_multicast_assert_inactive(brmctx); + spin_unlock(&brmctx->br->multicast_lock); } =20 #if IS_ENABLED(CONFIG_IPV6) @@ -1876,7 +1898,12 @@ static void br_ip6_multicast_querier_expired(struct = timer_list *t) struct net_bridge_mcast *brmctx =3D timer_container_of(brmctx, t, ip6_other_query.timer); =20 + spin_lock(&brmctx->br->multicast_lock); br_multicast_querier_expired(brmctx, &brmctx->ip6_own_query); + + if (!brmctx->multicast_querier) + br_ip6_multicast_assert_inactive(brmctx); + spin_unlock(&brmctx->br->multicast_lock); } #endif =20 @@ -4428,6 +4455,7 @@ static void __br_multicast_stop(struct net_bridge_mca= st *brmctx) spin_lock_bh(&brmctx->br->multicast_lock); /* bridge interface is down, set multicast state to inactive */ br_multicast_update_active(brmctx); + br_multicast_assert_inactive(brmctx); spin_unlock_bh(&brmctx->br->multicast_lock); } =20 @@ -4479,6 +4507,8 @@ void br_multicast_toggle_one_vlan(struct net_bridge_v= lan *vlan, bool on) spin_lock_bh(&br->multicast_lock); vlan->priv_flags ^=3D BR_VLFLAG_MCAST_ENABLED; br_multicast_update_active(&vlan->br_mcast_ctx); + if (!on) + br_multicast_assert_inactive(&vlan->br_mcast_ctx); spin_unlock_bh(&br->multicast_lock); =20 if (on) { @@ -4503,6 +4533,8 @@ void br_multicast_toggle_one_vlan(struct net_bridge_v= lan *vlan, bool on) else __br_multicast_disable_port_ctx(&vlan->port_mcast_ctx); br_multicast_update_active(brmctx); + if (!on) + br_multicast_assert_inactive(brmctx); spin_unlock_bh(&br->multicast_lock); } } --=20 2.50.1