Thread (12 messages) 12 messages, 4 authors, 2025-05-25
STALE413d

[PATCH net-next 4/5] net: bridge: switchdev: notify on mcast active changes

From: Linus Lüssing <hidden>
Date: 2025-05-22 20:07:10
Also in: bridge, linux-doc, lkml
Subsystem: documentation, ethernet bridge, networking [general], switchdev, the rest · Maintainers: Jonathan Corbet, Nikolay Aleksandrov, Ido Schimmel, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Jiri Pirko, Ivan Vecera, Linus Torvalds

Let the bridge notify switchdev if the multicast
active state toggles. So that switch drivers can act on it
accordingly, especially to avoid packetloss.

Signed-off-by: Linus Lüssing <redacted>
---
 Documentation/networking/switchdev.rst |  8 +++----
 include/net/switchdev.h                | 10 ++++++++
 net/bridge/br_multicast.c              | 33 ++++++++++++++++++++++++++
 3 files changed, 47 insertions(+), 4 deletions(-)
diff --git a/Documentation/networking/switchdev.rst b/Documentation/networking/switchdev.rst
index 2966b7122f05..130f7a36fc73 100644
--- a/Documentation/networking/switchdev.rst
+++ b/Documentation/networking/switchdev.rst
@@ -558,7 +558,7 @@ Because IGMP snooping can be turned on/off at runtime, the switchdev driver
 must be able to reconfigure the underlying hardware on the fly to honor the
 toggling of that option and behave appropriately.
 
-A switchdev driver can also refuse to support dynamic toggling of the multicast
-snooping knob at runtime and require the destruction of the bridge device(s)
-and creation of a new bridge device(s) with a different multicast snooping
-value.
+A switchdev driver must also be able to react to vanishing or appearing
+IGMP/MLD queriers. If no querier is present then, even if IGMP/MLD snooping
+is enabled, the switch must treat this as if IGMP/MLD snooping were disabled.
+The SWITCHDEV_ATTR_ID_BRIDGE_MC_ACTIVE notification allows to track this.
diff --git a/include/net/switchdev.h b/include/net/switchdev.h
index 8346b0d29542..abcc34a81e00 100644
--- a/include/net/switchdev.h
+++ b/include/net/switchdev.h
@@ -27,6 +27,7 @@ enum switchdev_attr_id {
 	SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING,
 	SWITCHDEV_ATTR_ID_BRIDGE_VLAN_PROTOCOL,
 	SWITCHDEV_ATTR_ID_BRIDGE_MC_DISABLED,
+	SWITCHDEV_ATTR_ID_BRIDGE_MC_ACTIVE,
 	SWITCHDEV_ATTR_ID_BRIDGE_MROUTER,
 	SWITCHDEV_ATTR_ID_BRIDGE_MST,
 	SWITCHDEV_ATTR_ID_MRP_PORT_ROLE,
@@ -43,6 +44,14 @@ struct switchdev_brport_flags {
 	unsigned long mask;
 };
 
+struct switchdev_mc_active {
+	short vid;
+	u8 ip4:1,
+	   ip6:1,
+	   ip4_changed:1,
+	   ip6_changed:1;
+};
+
 struct switchdev_vlan_msti {
 	u16 vid;
 	u16 msti;
@@ -64,6 +73,7 @@ struct switchdev_attr {
 		u16 vlan_protocol;			/* BRIDGE_VLAN_PROTOCOL */
 		bool mst;				/* BRIDGE_MST */
 		bool mc_disabled;			/* MC_DISABLED */
+		struct switchdev_mc_active mc_active;	/* MC_ACTIVE */
 		u8 mrp_port_role;			/* MRP_PORT_ROLE */
 		struct switchdev_vlan_msti vlan_msti;	/* VLAN_MSTI */
 	} u;
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 0bbaa21c1479..aec106f9c17d 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -1138,6 +1138,27 @@ static int br_ip6_multicast_check_active(struct net_bridge_mcast *brmctx,
 #endif
 }
 
+static int br_multicast_notify_active(struct net_bridge_mcast *brmctx,
+				      bool ip4_active, bool ip6_active,
+				      bool ip4_changed, bool ip6_changed,
+				      struct netlink_ext_ack *extack)
+{
+	struct switchdev_attr attr = {
+		.orig_dev = brmctx->br->dev,
+		.id = SWITCHDEV_ATTR_ID_BRIDGE_MC_ACTIVE,
+		.flags = SWITCHDEV_F_DEFER,
+		.u.mc_active = {
+			.vid = brmctx->vlan ? brmctx->vlan->vid : -1,
+			.ip4 = ip4_active,
+			.ip6 = ip6_active,
+			.ip4_changed = ip4_changed,
+			.ip6_changed = ip6_changed,
+		},
+	};
+
+	return switchdev_port_attr_set(brmctx->br->dev, &attr, extack);
+}
+
 /**
  * __br_multicast_update_active() - update mcast active state
  * @brmctx: the bridge multicast context to check
@@ -1159,6 +1180,8 @@ static int br_ip6_multicast_check_active(struct net_bridge_mcast *brmctx,
  * This function should be called by anything that changes one of the
  * above prerequisites.
  *
+ * Any multicast active state toggling is further notified to switchdev.
+ *
  * Return: 0 on success, a negative value otherwise.
  */
 static int __br_multicast_update_active(struct net_bridge_mcast *brmctx,
@@ -1182,11 +1205,21 @@ static int __br_multicast_update_active(struct net_bridge_mcast *brmctx,
 	ip4_changed = br_ip4_multicast_check_active(brmctx, &ip4_active);
 	ip6_changed = br_ip6_multicast_check_active(brmctx, &ip6_active);
 
+	if (!ip4_changed && !ip6_changed)
+		goto out;
+
+	ret = br_multicast_notify_active(brmctx, ip4_active, ip6_active,
+					 ip4_changed, ip6_changed,
+					 extack);
+	if (ret && ret != -EOPNOTSUPP)
+		goto out;
+
 	if (ip4_changed)
 		brmctx->ip4_active = ip4_active;
 	if (ip6_changed)
 		brmctx->ip6_active = ip6_active;
 
+out:
 	return ret;
 }
 
-- 
2.49.0
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help