public inbox for netdev@vger.kernel.org
 help / color / mirror / Atom feed
From: "Linus Lüssing" <linus.luessing@c0d3.blue>
To: bridge@lists.linux.dev
Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
	"Nikolay Aleksandrov" <razor@blackwall.org>,
	"Ido Schimmel" <idosch@nvidia.com>,
	"Andrew Lunn" <andrew+netdev@lunn.ch>,
	"Simon Horman" <horms@kernel.org>,
	"Paolo Abeni" <pabeni@redhat.com>,
	"Jakub Kicinski" <kuba@kernel.org>,
	"Eric Dumazet" <edumazet@google.com>,
	"David S . Miller" <davem@davemloft.net>,
	"Kuniyuki Iwashima" <kuniyu@google.com>,
	"Stanislav Fomichev" <sdf@fomichev.me>,
	"Xiao Liang" <shaw.leon@gmail.com>,
	"Linus Lüssing" <linus.luessing@c0d3.blue>
Subject: [PATCH net-next v2 13/14] net: bridge: mcast: use combined active state in fast/data path
Date: Fri,  6 Feb 2026 03:52:19 +0100	[thread overview]
Message-ID: <20260206030123.5430-14-linus.luessing@c0d3.blue> (raw)
In-Reply-To: <20260206030123.5430-1-linus.luessing@c0d3.blue>

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üssing <linus.luessing@c0d3.blue>
---
 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 d9d1227d5708..ab7b54eb646e 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)
 
 		mdst = 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 1405f1061a54..c3dd8781a1b5 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 = 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 48552720bcea..8ad1b8fec3c5 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;
 }
 
+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 = false;
+		else
+			own_querier_enabled = true;
+	} else {
+		own_querier_enabled = 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 *brmctx)
 {
 	return __br_multicast_querier_exists(brmctx, &brmctx->ip4_other_query, false);
@@ -1081,6 +1101,20 @@ static bool br_ip6_multicast_querier_exists(struct net_bridge_mcast *brmctx)
 }
 #endif
 
+static bool br_multicast_querier_exists(struct net_bridge_mcast *brmctx, int 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)
 {
@@ -5123,7 +5157,6 @@ bool br_multicast_has_querier_anywhere(struct net_device *dev, int proto)
 {
 	struct net_bridge *br;
 	struct net_bridge_port *port;
-	struct ethhdr eth;
 	bool ret = false;
 
 	rcu_read_lock();
@@ -5136,10 +5169,7 @@ bool br_multicast_has_querier_anywhere(struct net_device *dev, int proto)
 
 	br = port->br;
 
-	memset(&eth, 0, sizeof(eth));
-	eth.h_proto = htons(proto);
-
-	ret = br_multicast_querier_exists(&br->multicast_ctx, &eth, NULL);
+	ret = br_multicast_querier_exists(&br->multicast_ctx, proto);
 
 unlock:
 	rcu_read_unlock();
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 8150ecc2c919..75684f8079f2 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -1159,37 +1159,15 @@ br_multicast_is_router(struct net_bridge_mcast *brmctx, struct sk_buff *skb)
 }
 
 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_proto,
+			     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 = false;
-		else
-			own_querier_enabled = true;
-	} else {
-		own_querier_enabled = 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 *brmctx,
-					       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 READ_ONCE(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 READ_ONCE(brmctx->ip6_active);
 #endif
 	default:
 		return !!mdb && br_group_is_l2(&mdb->addr);
@@ -1448,9 +1426,9 @@ static inline bool br_multicast_is_router(struct net_bridge_mcast *brmctx,
 	return false;
 }
 
-static inline bool br_multicast_querier_exists(struct net_bridge_mcast *brmctx,
-					       struct ethhdr *eth,
-					       const struct net_bridge_mdb_entry *mdb)
+static inline bool
+br_multicast_snooping_active(struct net_bridge_mcast *brmctx, __be16 eth_proto,
+			     const struct net_bridge_mdb_entry *mdb)
 {
 	return false;
 }
-- 
2.51.0


  parent reply	other threads:[~2026-02-06  3:01 UTC|newest]

Thread overview: 35+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-02-06  2:52 [PATCH net-next v2 00/14] net: bridge: reduce multicast checks in fast path Linus Lüssing
2026-02-06  2:52 ` [PATCH net-next v2 01/14] net: bridge: mcast: export ip{4,6}_active state to netlink Linus Lüssing
2026-02-08 16:00   ` Ido Schimmel
2026-02-06  2:52 ` [PATCH net-next v2 02/14] net: bridge: mcast: track active state, adding tests Linus Lüssing
2026-02-07  4:58   ` Jakub Kicinski
2026-02-08 16:00   ` Ido Schimmel
2026-02-10 21:06     ` Linus Lüssing
2026-02-11  9:42       ` Ido Schimmel
2026-02-06  2:52 ` [PATCH net-next v2 03/14] net: bridge: mcast: avoid sleeping on bridge-down Linus Lüssing
2026-02-08 11:41   ` Ido Schimmel
2026-02-08 16:01   ` Ido Schimmel
2026-02-06  2:52 ` [PATCH net-next v2 04/14] net: bridge: mcast: track active state, IGMP/MLD querier appearance Linus Lüssing
2026-02-08 16:07   ` Ido Schimmel
2026-02-06  2:52 ` [PATCH net-next v2 05/14] net: bridge: mcast: track active state, foreign IGMP/MLD querier disappearance Linus Lüssing
2026-02-07  4:56   ` [net-next,v2,05/14] " Jakub Kicinski
2026-02-11  3:05     ` Linus Lüssing
2026-02-08 16:08   ` [PATCH net-next v2 05/14] " Ido Schimmel
2026-02-06  2:52 ` [PATCH net-next v2 06/14] net: bridge: mcast: track active state, IPv6 address availability Linus Lüssing
2026-02-08 16:08   ` Ido Schimmel
2026-02-06  2:52 ` [PATCH net-next v2 07/14] net: bridge: mcast: track active state, own MLD querier disappearance Linus Lüssing
2026-02-08 16:09   ` Ido Schimmel
2026-02-06  2:52 ` [PATCH net-next v2 08/14] net: bridge: mcast: track active state, if snooping is enabled Linus Lüssing
2026-02-08 16:09   ` Ido Schimmel
2026-02-06  2:52 ` [PATCH net-next v2 09/14] net: bridge: mcast: track active state, VLAN snooping Linus Lüssing
2026-02-08 16:10   ` Ido Schimmel
2026-02-06  2:52 ` [PATCH net-next v2 10/14] net: bridge: mcast: track active state, bridge up/down Linus Lüssing
2026-02-08 16:10   ` Ido Schimmel
2026-02-06  2:52 ` [PATCH net-next v2 11/14] net: bridge: mcast: track active state, prepare for outside lock reads Linus Lüssing
2026-02-08 16:11   ` Ido Schimmel
2026-02-06  2:52 ` [PATCH net-next v2 12/14] net: bridge: mcast: use combined active state in netlink Linus Lüssing
2026-02-08 16:11   ` Ido Schimmel
2026-02-06  2:52 ` Linus Lüssing [this message]
2026-02-08 16:12   ` [PATCH net-next v2 13/14] net: bridge: mcast: use combined active state in fast/data path Ido Schimmel
2026-02-06  2:52 ` [PATCH net-next v2 14/14] net: bridge: mcast: add inactive state assertions Linus Lüssing
2026-02-08 16:13   ` Ido Schimmel

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260206030123.5430-14-linus.luessing@c0d3.blue \
    --to=linus.luessing@c0d3.blue \
    --cc=andrew+netdev@lunn.ch \
    --cc=bridge@lists.linux.dev \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=horms@kernel.org \
    --cc=idosch@nvidia.com \
    --cc=kuba@kernel.org \
    --cc=kuniyu@google.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=razor@blackwall.org \
    --cc=sdf@fomichev.me \
    --cc=shaw.leon@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox