lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250522195952.29265-6-linus.luessing@c0d3.blue>
Date: Thu, 22 May 2025 21:17:07 +0200
From: Linus Lüssing <linus.luessing@...3.blue>
To: bridge@...ts.linux.dev
Cc: netdev@...r.kernel.org,
	openwrt-devel@...ts.openwrt.org,
	linux-kernel@...r.kernel.org,
	linux-doc@...r.kernel.org,
	Nikolay Aleksandrov <razor@...ckwall.org>,
	Ido Schimmel <idosch@...dia.com>,
	Ivan Vecera <ivecera@...hat.com>,
	Jiri Pirko <jiri@...nulli.us>,
	Vladimir Oltean <olteanv@...il.com>,
	Andrew Lunn <andrew@...n.ch>,
	Jonathan Corbet <corbet@....net>,
	Simon Horman <horms@...nel.org>,
	Paolo Abeni <pabeni@...hat.com>,
	Jakub Kicinski <kuba@...nel.org>,
	Eric Dumazet <edumazet@...gle.com>,
	"David S . Miller" <davem@...emloft.net>,
	Kuniyuki Iwashima <kuniyu@...zon.com>,
	Stanislav Fomichev <sdf@...ichev.me>,
	Xiao Liang <shaw.leon@...il.com>,
	Markus Stockhausen <markus.stockhausen@....de>,
	Jan Hoffmann <jan.christian.hoffmann@...il.com>,
	Birger Koblitz <git@...ger-koblitz.de>,
	Bjørn Mork <bjorn@...k.no>,
	Linus Lüssing <linus.luessing@...3.blue>
Subject: [PATCH net-next 5/5] net: dsa: forward bridge/switchdev mcast active notification

Add a new "port_mdb_active()" handler to the DSA API. This allows DSA
drivers to receive the multicast active notification from the
bridge. So that switch drivers can act on it accordingly, especially
to avoid packetloss.

The switchdev notifier "handled" attribute is propagated, too, so that a
DSA based switch driver can decide whether it wants to act on the event
for each port individually or only on the first one, on behalf of all
others.

Signed-off-by: Linus Lüssing <linus.luessing@...3.blue>
---
 Documentation/networking/dsa/dsa.rst |  9 +++++++++
 include/net/dsa.h                    |  5 +++++
 net/dsa/port.c                       | 19 +++++++++++++++++++
 net/dsa/port.h                       |  3 +++
 net/dsa/switch.c                     | 13 +++++++++++++
 net/dsa/switch.h                     | 11 ++++++++++-
 net/dsa/user.c                       | 21 ++++++++++++++++++++-
 7 files changed, 79 insertions(+), 2 deletions(-)

diff --git a/Documentation/networking/dsa/dsa.rst b/Documentation/networking/dsa/dsa.rst
index 7b2e69cd7ef0..0b0be619be04 100644
--- a/Documentation/networking/dsa/dsa.rst
+++ b/Documentation/networking/dsa/dsa.rst
@@ -1025,6 +1025,15 @@ Bridge VLAN filtering
   the specified MAC address from the specified VLAN ID if it was mapped into
   this port forwarding database.
 
+- ``port_mdb_active``: bridge layer function invoked when the bridge starts (or
+  stops) to actively apply multicast snooping to multicast payload, i.e. when
+  multicast snooping is enabled and a multicast querier is present on the link
+  for a particular protocol family (or not). A switch should (by default) ensure:
+  To flood multicast packets for the given protocol family if multicast snooping
+  is inactive - to avoid multicast (and consequently also IPv6 unicast, which
+  depends on multicast for NDP) packet loss. And should (by default) avoid
+  forwarding to an active port if there is no listener or multicast router on it.
+
 Link aggregation
 ----------------
 
diff --git a/include/net/dsa.h b/include/net/dsa.h
index a0a9481c52c2..edc0e6821ba2 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -1080,6 +1080,11 @@ struct dsa_switch_ops {
 	int	(*port_mdb_del)(struct dsa_switch *ds, int port,
 				const struct switchdev_obj_port_mdb *mdb,
 				struct dsa_db db);
+	int	(*port_mdb_active)(struct dsa_switch *ds, int port,
+				   const struct switchdev_mc_active mc_active,
+				   struct netlink_ext_ack *extack,
+				   bool handled);
+
 	/*
 	 * RXNFC
 	 */
diff --git a/net/dsa/port.c b/net/dsa/port.c
index 5c9d1798e830..a1e692d9122e 100644
--- a/net/dsa/port.c
+++ b/net/dsa/port.c
@@ -1290,6 +1290,25 @@ int dsa_port_bridge_host_mdb_del(const struct dsa_port *dp,
 	return dsa_port_host_mdb_del(dp, mdb, db);
 }
 
+int dsa_port_bridge_mdb_active(const struct dsa_port *dp,
+			       const struct switchdev_mc_active mc_active,
+			       struct netlink_ext_ack *extack,
+			       bool handled)
+{
+	struct dsa_switch *ds = dp->ds;
+	struct dsa_notifier_mdb_active_info info = {
+		.dp = dp,
+		.mc_active = mc_active,
+		.extack = extack,
+		.handled = handled,
+	};
+
+	if (!ds->ops->port_mdb_active)
+		return -EOPNOTSUPP;
+
+	return dsa_port_notify(dp, DSA_NOTIFIER_MDB_ACTIVE, &info);
+}
+
 int dsa_port_vlan_add(struct dsa_port *dp,
 		      const struct switchdev_obj_port_vlan *vlan,
 		      struct netlink_ext_ack *extack)
diff --git a/net/dsa/port.h b/net/dsa/port.h
index 6bc3291573c0..0e92815e7de2 100644
--- a/net/dsa/port.h
+++ b/net/dsa/port.h
@@ -75,6 +75,9 @@ int dsa_port_bridge_host_mdb_add(const struct dsa_port *dp,
 				 const struct switchdev_obj_port_mdb *mdb);
 int dsa_port_bridge_host_mdb_del(const struct dsa_port *dp,
 				 const struct switchdev_obj_port_mdb *mdb);
+int dsa_port_bridge_mdb_active(const struct dsa_port *dp,
+			       const struct switchdev_mc_active mc_active,
+			       struct netlink_ext_ack *extack, bool handled);
 int dsa_port_pre_bridge_flags(const struct dsa_port *dp,
 			      struct switchdev_brport_flags flags,
 			      struct netlink_ext_ack *extack);
diff --git a/net/dsa/switch.c b/net/dsa/switch.c
index 3d2feeea897b..5b30dfe4bebd 100644
--- a/net/dsa/switch.c
+++ b/net/dsa/switch.c
@@ -652,6 +652,16 @@ static int dsa_switch_host_mdb_del(struct dsa_switch *ds,
 	return err;
 }
 
+static int dsa_switch_mdb_active(struct dsa_switch *ds,
+				 struct dsa_notifier_mdb_active_info *info)
+{
+	if (!ds->ops->port_mdb_active)
+		return -EOPNOTSUPP;
+
+	return ds->ops->port_mdb_active(ds, info->dp->index, info->mc_active,
+					info->extack, info->handled);
+}
+
 /* Port VLANs match on the targeted port and on all DSA ports */
 static bool dsa_port_vlan_match(struct dsa_port *dp,
 				struct dsa_notifier_vlan_info *info)
@@ -1026,6 +1036,9 @@ static int dsa_switch_event(struct notifier_block *nb,
 	case DSA_NOTIFIER_HOST_MDB_DEL:
 		err = dsa_switch_host_mdb_del(ds, info);
 		break;
+	case DSA_NOTIFIER_MDB_ACTIVE:
+		err = dsa_switch_mdb_active(ds, info);
+		break;
 	case DSA_NOTIFIER_VLAN_ADD:
 		err = dsa_switch_vlan_add(ds, info);
 		break;
diff --git a/net/dsa/switch.h b/net/dsa/switch.h
index be0a2749cd97..69a5004e48c8 100644
--- a/net/dsa/switch.h
+++ b/net/dsa/switch.h
@@ -24,6 +24,7 @@ enum {
 	DSA_NOTIFIER_MDB_DEL,
 	DSA_NOTIFIER_HOST_MDB_ADD,
 	DSA_NOTIFIER_HOST_MDB_DEL,
+	DSA_NOTIFIER_MDB_ACTIVE,
 	DSA_NOTIFIER_VLAN_ADD,
 	DSA_NOTIFIER_VLAN_DEL,
 	DSA_NOTIFIER_HOST_VLAN_ADD,
@@ -66,13 +67,21 @@ struct dsa_notifier_lag_fdb_info {
 	struct dsa_db db;
 };
 
-/* DSA_NOTIFIER_MDB_* */
+/* DSA_NOTIFIER_MDB_{ADD,DEL} */
 struct dsa_notifier_mdb_info {
 	const struct dsa_port *dp;
 	const struct switchdev_obj_port_mdb *mdb;
 	struct dsa_db db;
 };
 
+/* DSA_NOTIFIER_MDB_ACTIVE */
+struct dsa_notifier_mdb_active_info {
+	const struct dsa_port *dp;
+	const struct switchdev_mc_active mc_active;
+	struct netlink_ext_ack *extack;
+	int handled;
+};
+
 /* DSA_NOTIFIER_LAG_* */
 struct dsa_notifier_lag_info {
 	const struct dsa_port *dp;
diff --git a/net/dsa/user.c b/net/dsa/user.c
index 804dc7dac4f2..231b92d6e7b9 100644
--- a/net/dsa/user.c
+++ b/net/dsa/user.c
@@ -603,7 +603,7 @@ static int dsa_user_port_attr_set(struct net_device *dev, const void *ctx,
 	struct dsa_port *dp = dsa_user_to_port(dev);
 	int ret;
 
-	if (ctx && ctx != dp)
+	if (ctx && ctx != dp && attr->id != SWITCHDEV_ATTR_ID_BRIDGE_MC_ACTIVE)
 		return 0;
 
 	switch (attr->id) {
@@ -657,6 +657,15 @@ static int dsa_user_port_attr_set(struct net_device *dev, const void *ctx,
 
 		ret = dsa_port_vlan_msti(dp, &attr->u.vlan_msti);
 		break;
+	case SWITCHDEV_ATTR_ID_BRIDGE_MC_ACTIVE:
+		const bool *handled = ctx;
+
+		if (!dsa_port_offloads_bridge_dev(dp, attr->orig_dev))
+			return -EOPNOTSUPP;
+
+		ret = dsa_port_bridge_mdb_active(dp, attr->u.mc_active, extack,
+						 *handled);
+		break;
 	default:
 		ret = -EOPNOTSUPP;
 		break;
@@ -3758,6 +3767,11 @@ static int dsa_user_switchdev_event(struct notifier_block *unused,
 
 	switch (event) {
 	case SWITCHDEV_PORT_ATTR_SET:
+		struct switchdev_notifier_port_attr_info *item = ptr;
+
+		if (item && item->attr->id == SWITCHDEV_ATTR_ID_BRIDGE_MC_ACTIVE)
+			item->info.ctx = &item->handled;
+
 		err = switchdev_handle_port_attr_set(dev, ptr,
 						     dsa_user_dev_check,
 						     dsa_user_port_attr_set);
@@ -3796,6 +3810,11 @@ static int dsa_user_switchdev_blocking_event(struct notifier_block *unused,
 							    dsa_user_port_obj_del);
 		return notifier_from_errno(err);
 	case SWITCHDEV_PORT_ATTR_SET:
+		struct switchdev_notifier_port_attr_info *item = ptr;
+
+		if (item && item->attr->id == SWITCHDEV_ATTR_ID_BRIDGE_MC_ACTIVE)
+			item->info.ctx = &item->handled;
+
 		err = switchdev_handle_port_attr_set(dev, ptr,
 						     dsa_user_dev_check,
 						     dsa_user_port_attr_set);
-- 
2.49.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ