Netdev List
 help / color / mirror / Atom feed
* [PATCH rdma-next 12/13] RDMA/rxe: Implement disassociate_ucontext callback
From: Jiri Pirko @ 2026-07-09  9:55 UTC (permalink / raw)
  To: linux-rdma
  Cc: cgroups, netdev, linux-s390, linux-kselftest, jgg, leon, parav,
	mbloch, cmeiohas, roman.gushchin, bvanassche, zyjzyj2000, shuah,
	tj, mkoutny, hannes, alibuda, dust.li, sidraya, wenjia
In-Reply-To: <20260709095532.855647-1-jiri@resnulli.us>

From: Jiri Pirko <jiri@nvidia.com>

Implement an empty disassociate_ucontext() callback so the RDMA core
can move rxe devices between net namespaces. The core requires this
callback to reset user contexts without waiting for userspace.

rxe needs no teardown here: its user-mapped queues live in
reference-counted vmalloc memory (see rxe_mmap.c) that stays valid
while userspace holds the mappings.

Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
 drivers/infiniband/sw/rxe/rxe_verbs.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.c b/drivers/infiniband/sw/rxe/rxe_verbs.c
index 1ec130fee8ea..6eb10d2f0653 100644
--- a/drivers/infiniband/sw/rxe/rxe_verbs.c
+++ b/drivers/infiniband/sw/rxe/rxe_verbs.c
@@ -240,6 +240,10 @@ static void rxe_dealloc_ucontext(struct ib_ucontext *ibuc)
 		rxe_err_uc(uc, "cleanup failed, err = %d\n", err);
 }
 
+static void rxe_disassociate_ucontext(struct ib_ucontext *ibuc)
+{
+}
+
 /* pd */
 static int rxe_alloc_pd(struct ib_pd *ibpd, struct ib_udata *udata)
 {
@@ -1478,6 +1482,7 @@ static const struct ib_device_ops rxe_dev_ops = {
 	.destroy_srq = rxe_destroy_srq,
 	.detach_mcast = rxe_detach_mcast,
 	.device_group = &rxe_attr_group,
+	.disassociate_ucontext = rxe_disassociate_ucontext,
 	.enable_driver = rxe_enable_driver,
 	.get_dma_mr = rxe_get_dma_mr,
 	.get_hw_stats = rxe_ib_get_hw_stats,
-- 
2.54.0


^ permalink raw reply related

* [PATCH rdma-next 11/13] RDMA/core: Make device names unique per net namespace
From: Jiri Pirko @ 2026-07-09  9:55 UTC (permalink / raw)
  To: linux-rdma
  Cc: cgroups, netdev, linux-s390, linux-kselftest, jgg, leon, parav,
	mbloch, cmeiohas, roman.gushchin, bvanassche, zyjzyj2000, shuah,
	tj, mkoutny, hannes, alibuda, dust.li, sidraya, wenjia
In-Reply-To: <20260709095532.855647-1-jiri@resnulli.us>

From: Jiri Pirko <jiri@nvidia.com>

Use rdma_dev_access_netns() to scope RDMA device name lookup and "%d" name
allocation to the relevant net namespace. Keep shared mode and
CONFIG_NET_NS=n behaviour system-wide.

Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
 drivers/infiniband/core/device.c | 22 +++++++++++++++-------
 1 file changed, 15 insertions(+), 7 deletions(-)

diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index 3ccf4731154a..cffb0de1c001 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -129,7 +129,7 @@ static DECLARE_RWSEM(rdma_nets_rwsem);
 bool ib_devices_shared_netns = true;
 module_param_named(netns_mode, ib_devices_shared_netns, bool, 0444);
 MODULE_PARM_DESC(netns_mode,
-		 "Share device among net namespaces; default=1 (shared)");
+		 "Share device among net namespaces; default=1 (shared). In exclusive mode device names are unique per net namespace");
 /**
  * rdma_dev_access_netns() - Return whether an rdma device can be accessed
  *			     from a specified net namespace or not.
@@ -359,7 +359,8 @@ static struct ib_device *__ib_device_get_by_name(const char *name,
 	unsigned long index;
 
 	xa_for_each (&devices, index, device)
-		if (!strcmp(name, dev_name(&device->dev)))
+		if (rdma_dev_access_netns(device, net) &&
+		    !strcmp(name, dev_name(&device->dev)))
 			return device;
 
 	return NULL;
@@ -437,7 +438,11 @@ int ib_device_set_dim(struct ib_device *ibdev, u8 use_dim)
 	return 0;
 }
 
-/* Pick a free index for the '%d' style @name pattern. */
+/*
+ * Pick a free index for the '%d' style @name pattern within net namespace
+ * @net. Returns the index on success or a negative errno. The caller builds
+ * the final unique device name from the returned index.
+ */
 static int __alloc_name_id(struct net *net, const char *name,
 			   const struct ib_device *skip)
 {
@@ -452,7 +457,7 @@ static int __alloc_name_id(struct net *net, const char *name,
 	xa_for_each (&devices, index, device) {
 		char buf[IB_DEVICE_NAME_MAX];
 
-		if (device == skip)
+		if (device == skip || !rdma_dev_access_netns(device, net))
 			continue;
 		if (sscanf(dev_name(&device->dev), name, &i) != 1)
 			continue;
@@ -1240,7 +1245,8 @@ static __net_init int rdma_dev_init_net(struct net *net)
 }
 
 /*
- * Assign the unique string device name and the unique device index. This is
+ * Assign the unique string device name and the unique device index. The device
+ * name is unique within the net namespace the device is assigned to. This is
  * undone by ib_dealloc_device.
  */
 static int assign_name(struct ib_device *device, const char *name)
@@ -1424,8 +1430,9 @@ static void ib_device_notify_register(struct ib_device *device)
 /**
  * ib_register_device - Register an IB device with IB core
  * @device: Device to register
- * @name: unique string device name. This may include a '%' which will
- * 	  cause a unique index to be added to the passed device name.
+ * @name: device name, unique within the device's net namespace. This may
+ *	  include a '%' which will cause a unique index to be added to the
+ *	  passed device name.
  * @dma_device: pointer to a DMA-capable device. If %NULL, then the IB
  *	        device will be used. In this case the caller should fully
  *		setup the ibdev for DMA. This usually means using dma_virt_ops.
@@ -1716,6 +1723,7 @@ static bool rdma_dev_name_in_netns(struct ib_device *skip, struct net *net,
 
 	xa_for_each(&devices, index, device)
 		if (device != skip &&
+		    rdma_dev_access_netns(device, net) &&
 		    !strcmp(name, dev_name(&device->dev)))
 			return true;
 
-- 
2.54.0


^ permalink raw reply related

* [PATCH rdma-next 10/13] RDMA/core: Document the SELinux ibendport net namespace limitation
From: Jiri Pirko @ 2026-07-09  9:55 UTC (permalink / raw)
  To: linux-rdma
  Cc: cgroups, netdev, linux-s390, linux-kselftest, jgg, leon, parav,
	mbloch, cmeiohas, roman.gushchin, bvanassche, zyjzyj2000, shuah,
	tj, mkoutny, hannes, alibuda, dust.li, sidraya, wenjia
In-Reply-To: <20260709095532.855647-1-jiri@resnulli.us>

From: Jiri Pirko <jiri@nvidia.com>

Document that SELinux ibendport labels use a global (device name, port)
key, so same-named RDMA devices in different net namespaces share a label.

Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
 drivers/infiniband/core/security.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/infiniband/core/security.c b/drivers/infiniband/core/security.c
index 9af31d1d9d70..a82c46965416 100644
--- a/drivers/infiniband/core/security.c
+++ b/drivers/infiniband/core/security.c
@@ -700,6 +700,12 @@ int ib_mad_agent_security_setup(struct ib_mad_agent *agent,
 	if (qp_type != IB_QPT_SMI)
 		return 0;
 
+	/*
+	 * SELinux labels an endport by (device name, port) from a global
+	 * policy. If devices in different net namespaces share a name, they get
+	 * the same label; distinguishing them would need net namespace support
+	 * in the policy language and tooling.
+	 */
 	spin_lock(&mad_agent_list_lock);
 	ret = security_ib_endport_manage_subnet(agent->security,
 						dev_name(&agent->device->dev),
-- 
2.54.0


^ permalink raw reply related

* [PATCH rdma-next 09/13] RDMA/cma: Document that CM configfs cannot be net namespace scoped
From: Jiri Pirko @ 2026-07-09  9:55 UTC (permalink / raw)
  To: linux-rdma
  Cc: cgroups, netdev, linux-s390, linux-kselftest, jgg, leon, parav,
	mbloch, cmeiohas, roman.gushchin, bvanassche, zyjzyj2000, shuah,
	tj, mkoutny, hannes, alibuda, dust.li, sidraya, wenjia
In-Reply-To: <20260709095532.855647-1-jiri@resnulli.us>

From: Jiri Pirko <jiri@nvidia.com>

Document the rdma_cm configfs limitation: configfs is global, so same-named
RDMA devices in different net namespaces cannot both be represented there.

Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
 Documentation/ABI/testing/configfs-rdma_cm | 4 ++++
 drivers/infiniband/core/cma_configfs.c     | 4 ++++
 2 files changed, 8 insertions(+)

diff --git a/Documentation/ABI/testing/configfs-rdma_cm b/Documentation/ABI/testing/configfs-rdma_cm
index 74f9506f42e7..739f7b6a1259 100644
--- a/Documentation/ABI/testing/configfs-rdma_cm
+++ b/Documentation/ABI/testing/configfs-rdma_cm
@@ -12,6 +12,10 @@ Description: 	Interface is used to configure RDMA-cable HCAs in respect to
 		for this HCA has to be created:
 		mkdir -p /config/rdma_cm/<hca>
 
+		Note: configfs has no network namespace support, so this
+		interface cannot represent two devices that share a name in
+		different network namespaces (possible in exclusive netns mode).
+
 
 What: 		/config/rdma_cm/<hca>/ports/<port-num>/default_roce_mode
 Date: 		November 29, 2015
diff --git a/drivers/infiniband/core/cma_configfs.c b/drivers/infiniband/core/cma_configfs.c
index 891e52afb8f4..c389d4e37b6b 100644
--- a/drivers/infiniband/core/cma_configfs.c
+++ b/drivers/infiniband/core/cma_configfs.c
@@ -65,6 +65,10 @@ static struct cma_dev_port_group *to_dev_port_group(struct config_item *item)
 	return container_of(group, struct cma_dev_port_group, group);
 }
 
+/*
+ * configfs is not net namespace aware, so a name shared by devices in
+ * different namespaces resolves to the first match here.
+ */
 static bool filter_by_name(struct ib_device *ib_dev, void *cookie)
 {
 	return !strcmp(dev_name(&ib_dev->dev), cookie);
-- 
2.54.0


^ permalink raw reply related

* [PATCH rdma-next 08/13] RDMA/cgroup: Scope rdma cgroup device visibility to the net namespace
From: Jiri Pirko @ 2026-07-09  9:55 UTC (permalink / raw)
  To: linux-rdma
  Cc: cgroups, netdev, linux-s390, linux-kselftest, jgg, leon, parav,
	mbloch, cmeiohas, roman.gushchin, bvanassche, zyjzyj2000, shuah,
	tj, mkoutny, hannes, alibuda, dust.li, sidraya, wenjia
In-Reply-To: <20260709095532.855647-1-jiri@resnulli.us>

From: Jiri Pirko <jiri@nvidia.com>

Track each rdma cgroup device's net namespace and sharing mode, then filter
name lookups and cgroupfs enumeration to devices visible from the caller's
namespace. Keep the cached sharing mode synchronized across registration,
netns moves, and runtime mode changes.

Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
 Documentation/admin-guide/cgroup-v2.rst |  7 +++++++
 drivers/infiniband/core/cgroup.c        | 12 ++++++++++++
 drivers/infiniband/core/core_priv.h     | 12 ++++++++++++
 drivers/infiniband/core/device.c        | 11 +++++++++++
 include/linux/cgroup_rdma.h             | 10 ++++++++++
 kernel/cgroup/rdma.c                    | 20 +++++++++++++++++++-
 6 files changed, 71 insertions(+), 1 deletion(-)

diff --git a/Documentation/admin-guide/cgroup-v2.rst b/Documentation/admin-guide/cgroup-v2.rst
index 993446ab66d0..4523c1884d67 100644
--- a/Documentation/admin-guide/cgroup-v2.rst
+++ b/Documentation/admin-guide/cgroup-v2.rst
@@ -2752,6 +2752,13 @@ RDMA
 The "rdma" controller regulates the distribution and accounting of
 RDMA resources.
 
+When RDMA devices are isolated per network namespace (exclusive mode),
+device names are unique only within a network namespace. The device lines
+below are therefore scoped to the reading or writing process's network
+namespace: only devices accessible from that namespace are listed, and a
+limit is applied to the device of that name in that namespace. Configure
+limits from the same network namespace as the workloads.
+
 RDMA Interface Files
 ~~~~~~~~~~~~~~~~~~~~
 
diff --git a/drivers/infiniband/core/cgroup.c b/drivers/infiniband/core/cgroup.c
index 1f037fe01450..7a216ed45199 100644
--- a/drivers/infiniband/core/cgroup.c
+++ b/drivers/infiniband/core/cgroup.c
@@ -17,6 +17,8 @@
 void ib_device_register_rdmacg(struct ib_device *device)
 {
 	device->cg_device.name = device->name;
+	device->cg_device.netns_shared = ib_devices_shared_netns;
+	write_pnet(&device->cg_device.net, rdma_dev_net(device));
 	rdmacg_register_device(&device->cg_device);
 }
 
@@ -34,6 +36,16 @@ void ib_device_unregister_rdmacg(struct ib_device *device)
 	rdmacg_unregister_device(&device->cg_device);
 }
 
+void ib_device_rdmacg_change_netns(struct ib_device *device, struct net *net)
+{
+	write_pnet(&device->cg_device.net, net);
+}
+
+void ib_device_rdmacg_set_netns_shared(struct ib_device *device, bool shared)
+{
+	WRITE_ONCE(device->cg_device.netns_shared, shared);
+}
+
 int ib_rdmacg_try_charge(struct ib_rdmacg_object *cg_obj,
 			 struct ib_device *device,
 			 enum rdmacg_resource_type resource_index)
diff --git a/drivers/infiniband/core/core_priv.h b/drivers/infiniband/core/core_priv.h
index aaf330b0d333..9cd671e2db20 100644
--- a/drivers/infiniband/core/core_priv.h
+++ b/drivers/infiniband/core/core_priv.h
@@ -156,6 +156,8 @@ void ib_dispatch_event_clients(struct ib_event *event);
 #ifdef CONFIG_CGROUP_RDMA
 void ib_device_register_rdmacg(struct ib_device *device);
 void ib_device_unregister_rdmacg(struct ib_device *device);
+void ib_device_rdmacg_change_netns(struct ib_device *device, struct net *net);
+void ib_device_rdmacg_set_netns_shared(struct ib_device *device, bool shared);
 
 int ib_rdmacg_try_charge(struct ib_rdmacg_object *cg_obj,
 			 struct ib_device *device,
@@ -173,6 +175,16 @@ static inline void ib_device_unregister_rdmacg(struct ib_device *device)
 {
 }
 
+static inline void ib_device_rdmacg_change_netns(struct ib_device *device,
+						 struct net *net)
+{
+}
+
+static inline void ib_device_rdmacg_set_netns_shared(struct ib_device *device,
+						     bool shared)
+{
+}
+
 static inline int ib_rdmacg_try_charge(struct ib_rdmacg_object *cg_obj,
 				       struct ib_device *device,
 				       enum rdmacg_resource_type resource_index)
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index 8705011fab66..3ccf4731154a 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -1112,6 +1112,7 @@ static int add_all_compat_devs(void)
 int rdma_compatdev_set(u8 enable)
 {
 	struct rdma_dev_net *rnet;
+	struct ib_device *dev;
 	unsigned long index;
 	int ret = 0;
 
@@ -1134,6 +1135,12 @@ int rdma_compatdev_set(u8 enable)
 	if (ret)
 		return -EBUSY;
 
+	/* Keep each registered device's rdma cgroup visibility in sync. */
+	down_read(&devices_rwsem);
+	xa_for_each_marked(&devices, index, dev, DEVICE_REGISTERED)
+		ib_device_rdmacg_set_netns_shared(dev, enable);
+	up_read(&devices_rwsem);
+
 	if (enable)
 		ret = add_all_compat_devs();
 	else
@@ -1350,6 +1357,7 @@ static int enable_device_and_get(struct ib_device *device)
 	 */
 	refcount_set(&device->refcount, 2);
 	down_write(&devices_rwsem);
+	ib_device_rdmacg_set_netns_shared(device, ib_devices_shared_netns);
 	xa_set_mark(&devices, device->index, DEVICE_REGISTERED);
 
 	/*
@@ -1823,12 +1831,14 @@ static int rdma_dev_change_netns(struct ib_device *device, struct net *cur_net,
 			     "%s: failed to pick device name during namespace teardown: %d\n",
 			     __func__, ret);
 			write_pnet(&device->coredev.rdma_net, net);
+			ib_device_rdmacg_change_netns(device, net);
 			ret = 0;
 		}
 		goto rename_done;
 	}
 
 	write_pnet(&device->coredev.rdma_net, net);
+	ib_device_rdmacg_change_netns(device, net);
 	ret = device_rename(&device->dev, new_name);
 	if (ret) {
 		if (fallback_pattern) {
@@ -1842,6 +1852,7 @@ static int rdma_dev_change_netns(struct ib_device *device, struct net *cur_net,
 				 __func__);
 			/* Try and put things back and re-enable the device */
 			write_pnet(&device->coredev.rdma_net, cur_net);
+			ib_device_rdmacg_change_netns(device, cur_net);
 		}
 	} else {
 		strscpy(device->name, dev_name(&device->dev),
diff --git a/include/linux/cgroup_rdma.h b/include/linux/cgroup_rdma.h
index 404e746552ca..71170cb0e19e 100644
--- a/include/linux/cgroup_rdma.h
+++ b/include/linux/cgroup_rdma.h
@@ -7,6 +7,7 @@
 #define _CGROUP_RDMA_H
 
 #include <linux/cgroup.h>
+#include <net/net_namespace.h>
 
 enum rdmacg_resource_type {
 	RDMACG_RESOURCE_HCA_HANDLE,
@@ -34,6 +35,15 @@ struct rdmacg_device {
 	struct list_head	dev_node;
 	struct list_head	rpools;
 	char			*name;
+	/*
+	 * Net namespace the device belongs to. @netns_shared mirrors
+	 * ib_devices_shared_netns: when true the device is visible from every
+	 * net namespace (shared mode); otherwise @net is the only namespace
+	 * that may see and configure it. @netns_shared is updated when the
+	 * sharing mode changes, so use {READ,WRITE}_ONCE() to access it.
+	 */
+	possible_net_t		net;
+	bool			netns_shared;
 };
 
 /*
diff --git a/kernel/cgroup/rdma.c b/kernel/cgroup/rdma.c
index 5e82a03b3270..c8b4e3de7630 100644
--- a/kernel/cgroup/rdma.c
+++ b/kernel/cgroup/rdma.c
@@ -15,6 +15,7 @@
 #include <linux/cgroup.h>
 #include <linux/parser.h>
 #include <linux/cgroup_rdma.h>
+#include <linux/nsproxy.h>
 
 #define RDMACG_MAX_STR "max"
 
@@ -464,6 +465,13 @@ void rdmacg_unregister_device(struct rdmacg_device *device)
 }
 EXPORT_SYMBOL(rdmacg_unregister_device);
 
+/* netns_shared is toggled without rdmacg_mutex, hence READ_ONCE(). */
+static bool rdmacg_device_visible(const struct rdmacg_device *device)
+{
+	return READ_ONCE(device->netns_shared) ||
+	       net_eq(read_pnet(&device->net), current->nsproxy->net_ns);
+}
+
 static struct rdmacg_device *rdmacg_get_device_locked(const char *name)
 {
 	struct rdmacg_device *device;
@@ -471,7 +479,8 @@ static struct rdmacg_device *rdmacg_get_device_locked(const char *name)
 	lockdep_assert_held(&rdmacg_mutex);
 
 	list_for_each_entry(device, &rdmacg_devices, dev_node)
-		if (!strcmp(name, device->name))
+		if (rdmacg_device_visible(device) &&
+		    !strcmp(name, device->name))
 			return device;
 
 	return NULL;
@@ -626,6 +635,9 @@ static int rdmacg_resource_read(struct seq_file *sf, void *v)
 	mutex_lock(&rdmacg_mutex);
 
 	list_for_each_entry(device, &rdmacg_devices, dev_node) {
+		if (!rdmacg_device_visible(device))
+			continue;
+
 		seq_printf(sf, "%s ", device->name);
 
 		rpool = find_cg_rpool_locked(cg, device);
@@ -648,6 +660,9 @@ static int rdmacg_events_show(struct seq_file *sf, void *v)
 	mutex_lock(&rdmacg_mutex);
 
 	list_for_each_entry(device, &rdmacg_devices, dev_node) {
+		if (!rdmacg_device_visible(device))
+			continue;
+
 		rpool = find_cg_rpool_locked(cg, device);
 
 		seq_printf(sf, "%s ", device->name);
@@ -677,6 +692,9 @@ static int rdmacg_events_local_show(struct seq_file *sf, void *v)
 	mutex_lock(&rdmacg_mutex);
 
 	list_for_each_entry(device, &rdmacg_devices, dev_node) {
+		if (!rdmacg_device_visible(device))
+			continue;
+
 		rpool = find_cg_rpool_locked(cg, device);
 
 		seq_printf(sf, "%s ", device->name);
-- 
2.54.0


^ permalink raw reply related

* [PATCH rdma-next 07/13] RDMA/srp: Make the SRP sysfs class net namespace aware
From: Jiri Pirko @ 2026-07-09  9:55 UTC (permalink / raw)
  To: linux-rdma
  Cc: cgroups, netdev, linux-s390, linux-kselftest, jgg, leon, parav,
	mbloch, cmeiohas, roman.gushchin, bvanassche, zyjzyj2000, shuah,
	tj, mkoutny, hannes, alibuda, dust.li, sidraya, wenjia
In-Reply-To: <20260709095532.855647-1-jiri@resnulli.us>

From: Jiri Pirko <jiri@nvidia.com>

Tag srp_class by the RDMA device's net namespace so SRP hosts derived from
same-named RDMA devices can coexist across namespaces.

Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
 drivers/infiniband/ulp/srp/ib_srp.c | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index acbd787de265..a070fcf86e8a 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -3189,10 +3189,24 @@ static struct attribute *srp_class_attrs[];
 
 ATTRIBUTE_GROUPS(srp_class);
 
+/*
+ * SRP hosts are named after their ib device, so tag the class by the ib
+ * device's net namespace.
+ */
+static const struct ns_common *srp_net_namespace(const struct device *dev)
+{
+	struct srp_host *host = container_of(dev, struct srp_host, dev);
+	struct net *net = rdma_dev_net(host->srp_dev->dev);
+
+	return net ? to_ns_common(net) : NULL;
+}
+
 static struct class srp_class = {
 	.name    = "infiniband_srp",
 	.dev_groups = srp_class_groups,
-	.dev_release = srp_release_dev
+	.dev_release = srp_release_dev,
+	.ns_type = &net_ns_type_operations,
+	.namespace = srp_net_namespace,
 };
 
 /**
-- 
2.54.0


^ permalink raw reply related

* [PATCH rdma-next 06/13] net/smc: Look up the pnetid ib device within the net namespace
From: Jiri Pirko @ 2026-07-09  9:55 UTC (permalink / raw)
  To: linux-rdma
  Cc: cgroups, netdev, linux-s390, linux-kselftest, jgg, leon, parav,
	mbloch, cmeiohas, roman.gushchin, bvanassche, zyjzyj2000, shuah,
	tj, mkoutny, hannes, alibuda, dust.li, sidraya, wenjia
In-Reply-To: <20260709095532.855647-1-jiri@resnulli.us>

From: Jiri Pirko <jiri@nvidia.com>

Scope smc_pnet_find_ib() to the caller's net namespace so pnetid setup
cannot bind to a same-named RDMA device from another namespace once names
become per-netns.

Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
 net/smc/smc_pnet.c | 20 ++++++++++++++------
 1 file changed, 14 insertions(+), 6 deletions(-)

diff --git a/net/smc/smc_pnet.c b/net/smc/smc_pnet.c
index 63e286e2dfaa..ff9c9c35cc2f 100644
--- a/net/smc/smc_pnet.c
+++ b/net/smc/smc_pnet.c
@@ -304,13 +304,18 @@ static bool smc_pnetid_valid(const char *pnet_name, char *pnetid)
 	return true;
 }
 
-/* Find an infiniband device by a given name. The device might not exist. */
-static struct smc_ib_device *smc_pnet_find_ib(char *ib_name)
+/*
+ * Find an infiniband device by a given name, restricted to the devices
+ * accessible from @net. The device might not exist.
+ */
+static struct smc_ib_device *smc_pnet_find_ib(struct net *net, char *ib_name)
 {
 	struct smc_ib_device *ibdev;
 
 	mutex_lock(&smc_ib_devices.mutex);
 	list_for_each_entry(ibdev, &smc_ib_devices.list, list) {
+		if (!rdma_dev_access_netns(ibdev->ibdev, net))
+			continue;
 		if (!strncmp(ibdev->ibdev->name, ib_name,
 			     sizeof(ibdev->ibdev->name)) ||
 		    (ibdev->ibdev->dev.parent &&
@@ -408,8 +413,8 @@ static int smc_pnet_add_eth(struct smc_pnettable *pnettable, struct net *net,
 	return rc;
 }
 
-static int smc_pnet_add_ib(struct smc_pnettable *pnettable, char *ib_name,
-			   u8 ib_port, char *pnet_name)
+static int smc_pnet_add_ib(struct smc_pnettable *pnettable, struct net *net,
+			   char *ib_name, u8 ib_port, char *pnet_name)
 {
 	struct smc_pnetentry *tmp_pe, *new_pe;
 	struct smc_ib_device *ib_dev;
@@ -419,7 +424,7 @@ static int smc_pnet_add_ib(struct smc_pnettable *pnettable, char *ib_name,
 	bool new_ibdev;
 
 	/* try to apply the pnetid to active devices */
-	ib_dev = smc_pnet_find_ib(ib_name);
+	ib_dev = smc_pnet_find_ib(net, ib_name);
 	if (ib_dev) {
 		ibdev_applied = smc_pnet_apply_ib(ib_dev, ib_port, pnet_name);
 		if (ibdev_applied)
@@ -518,7 +523,7 @@ static int smc_pnet_enter(struct net *net, struct nlattr *tb[])
 			if (ibport < 1 || ibport > SMC_MAX_PORTS)
 				goto error;
 		}
-		rc = smc_pnet_add_ib(pnettable, string, ibport, pnet_name);
+		rc = smc_pnet_add_ib(pnettable, net, string, ibport, pnet_name);
 		if (!rc)
 			new_ibdev = true;
 		else if (rc != -EEXIST)
@@ -1170,6 +1175,9 @@ int smc_pnetid_by_table_ib(struct smc_ib_device *smcibdev, u8 ib_port)
 	struct smc_net *sn;
 	int rc = -ENOENT;
 
+	if (!rdma_dev_access_netns(smcibdev->ibdev, &init_net))
+		return -ENOENT;
+
 	/* get pnettable for init namespace */
 	sn = net_generic(&init_net, smc_net_id);
 	pnettable = &sn->pnettable;
-- 
2.54.0


^ permalink raw reply related

* [PATCH rdma-next 05/13] RDMA/nldev: Allow setting the device name while changing net namespace
From: Jiri Pirko @ 2026-07-09  9:55 UTC (permalink / raw)
  To: linux-rdma
  Cc: cgroups, netdev, linux-s390, linux-kselftest, jgg, leon, parav,
	mbloch, cmeiohas, roman.gushchin, bvanassche, zyjzyj2000, shuah,
	tj, mkoutny, hannes, alibuda, dust.li, sidraya, wenjia
In-Reply-To: <20260709095532.855647-1-jiri@resnulli.us>

From: Jiri Pirko <jiri@nvidia.com>

Accept RDMA_NLDEV_ATTR_DEV_NAME together with RDMA_NLDEV_NET_NS_FD so a
netlink move can rename the device in the destination namespace. Keep the
name semantics aligned with the existing RDMA rename path.

Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
 drivers/infiniband/core/device.c |  6 ++++++
 drivers/infiniband/core/nldev.c  | 27 ++++++++++++++++++---------
 include/uapi/rdma/rdma_netlink.h |  5 ++++-
 3 files changed, 28 insertions(+), 10 deletions(-)

diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index 2391bc7c8d23..8705011fab66 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -1901,6 +1901,9 @@ int ib_device_set_netns_put(struct sk_buff *skb,
 		if (ret == -EEXIST)
 			NL_SET_ERR_MSG(extack,
 				       "Device name already exists in the target net namespace");
+		else if (ret == -EINVAL && name)
+			NL_SET_ERR_MSG(extack,
+				       "Unable to use requested device name in the target net namespace");
 		goto ns_err;
 	}
 
@@ -1931,6 +1934,9 @@ int ib_device_set_netns_put(struct sk_buff *skb,
 	if (ret == -EEXIST)
 		NL_SET_ERR_MSG(extack,
 			       "Device name already exists in the target net namespace");
+	else if (ret == -EINVAL && name)
+		NL_SET_ERR_MSG(extack,
+			       "Unable to use requested device name in the target net namespace");
 
 	put_net(net);
 	return ret;
diff --git a/drivers/infiniband/core/nldev.c b/drivers/infiniband/core/nldev.c
index 5fd1ef2c5050..473bf9667f83 100644
--- a/drivers/infiniband/core/nldev.c
+++ b/drivers/infiniband/core/nldev.c
@@ -1177,6 +1177,24 @@ static int nldev_set_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
 	if (!device)
 		return -EINVAL;
 
+	if (tb[RDMA_NLDEV_NET_NS_FD]) {
+		char name[IB_DEVICE_NAME_MAX] = {};
+		u32 ns_fd;
+
+		if (tb[RDMA_NLDEV_ATTR_DEV_NAME]) {
+			nla_strscpy(name, tb[RDMA_NLDEV_ATTR_DEV_NAME],
+				    IB_DEVICE_NAME_MAX);
+			if (strlen(name) == 0) {
+				err = -EINVAL;
+				goto done;
+			}
+		}
+		ns_fd = nla_get_u32(tb[RDMA_NLDEV_NET_NS_FD]);
+		err = ib_device_set_netns_put(skb, device, ns_fd,
+					      name[0] ? name : NULL, extack);
+		goto put_done;
+	}
+
 	if (tb[RDMA_NLDEV_ATTR_DEV_NAME]) {
 		char name[IB_DEVICE_NAME_MAX] = {};
 
@@ -1190,15 +1208,6 @@ static int nldev_set_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
 		goto done;
 	}
 
-	if (tb[RDMA_NLDEV_NET_NS_FD]) {
-		u32 ns_fd;
-
-		ns_fd = nla_get_u32(tb[RDMA_NLDEV_NET_NS_FD]);
-		err = ib_device_set_netns_put(skb, device, ns_fd, NULL,
-					      extack);
-		goto put_done;
-	}
-
 	if (tb[RDMA_NLDEV_ATTR_DEV_DIM]) {
 		u8 use_dim;
 
diff --git a/include/uapi/rdma/rdma_netlink.h b/include/uapi/rdma/rdma_netlink.h
index 3af946ecbac3..ee11c3bbbae2 100644
--- a/include/uapi/rdma/rdma_netlink.h
+++ b/include/uapi/rdma/rdma_netlink.h
@@ -516,7 +516,10 @@ enum rdma_nldev_attr {
 	RDMA_NLDEV_ATTR_DEV_PROTOCOL,		/* string */
 
 	/*
-	 * File descriptor handle of the net namespace object
+	 * File descriptor handle of the net namespace object. May be combined
+	 * with RDMA_NLDEV_ATTR_DEV_NAME (a literal device name) to also rename
+	 * the device in the destination namespace; the move fails with -EEXIST
+	 * if that name is already taken there.
 	 */
 	RDMA_NLDEV_NET_NS_FD,			/* u32 */
 	/*
-- 
2.54.0


^ permalink raw reply related

* [PATCH rdma-next 04/13] RDMA/nldev: Report net namespace move errors through extack
From: Jiri Pirko @ 2026-07-09  9:55 UTC (permalink / raw)
  To: linux-rdma
  Cc: cgroups, netdev, linux-s390, linux-kselftest, jgg, leon, parav,
	mbloch, cmeiohas, roman.gushchin, bvanassche, zyjzyj2000, shuah,
	tj, mkoutny, hannes, alibuda, dust.li, sidraya, wenjia
In-Reply-To: <20260709095532.855647-1-jiri@resnulli.us>

From: Jiri Pirko <jiri@nvidia.com>

Thread extack through the existing net namespace move helper and report the
main failure reasons from the core path. Keep the existing move UAPI shape
unchanged.

Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
 drivers/infiniband/core/core_priv.h |  3 ++-
 drivers/infiniband/core/device.c    | 24 ++++++++++++++++++++++--
 drivers/infiniband/core/nldev.c     |  6 ++----
 3 files changed, 26 insertions(+), 7 deletions(-)

diff --git a/drivers/infiniband/core/core_priv.h b/drivers/infiniband/core/core_priv.h
index 3bd5bb7135a3..aaf330b0d333 100644
--- a/drivers/infiniband/core/core_priv.h
+++ b/drivers/infiniband/core/core_priv.h
@@ -356,7 +356,8 @@ void ib_port_unregister_client_groups(struct ib_device *ibdev, u32 port_num,
 				     const struct attribute_group **groups);
 
 int ib_device_set_netns_put(struct sk_buff *skb,
-			    struct ib_device *dev, u32 ns_fd, const char *name);
+			    struct ib_device *dev, u32 ns_fd, const char *name,
+			    struct netlink_ext_ack *extack);
 
 int rdma_nl_net_init(struct rdma_dev_net *rnet);
 void rdma_nl_net_exit(struct rdma_dev_net *rnet);
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index 191f05898bae..2391bc7c8d23 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -1871,18 +1871,22 @@ static int rdma_dev_change_netns(struct ib_device *device, struct net *cur_net,
 }
 
 int ib_device_set_netns_put(struct sk_buff *skb,
-			    struct ib_device *dev, u32 ns_fd, const char *name)
+			    struct ib_device *dev, u32 ns_fd, const char *name,
+			    struct netlink_ext_ack *extack)
 {
 	struct net *net;
 	int ret;
 
 	net = get_net_ns_by_fd(ns_fd);
 	if (IS_ERR(net)) {
+		NL_SET_ERR_MSG(extack, "Invalid target net namespace fd");
 		ret = PTR_ERR(net);
 		goto net_err;
 	}
 
 	if (!netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN)) {
+		NL_SET_ERR_MSG(extack,
+			       "Missing CAP_NET_ADMIN in the target net namespace");
 		ret = -EPERM;
 		goto ns_err;
 	}
@@ -1893,6 +1897,10 @@ int ib_device_set_netns_put(struct sk_buff *skb,
 	 */
 	if (net_eq(net, read_pnet(&dev->coredev.rdma_net))) {
 		ret = name ? ib_device_rename(dev, name) : 0;
+
+		if (ret == -EEXIST)
+			NL_SET_ERR_MSG(extack,
+				       "Device name already exists in the target net namespace");
 		goto ns_err;
 	}
 
@@ -1901,7 +1909,16 @@ int ib_device_set_netns_put(struct sk_buff *skb,
 	 * changed and this cannot be blocked waiting for userspace to do
 	 * something, so disassociation is mandatory.
 	 */
-	if (!dev->ops.disassociate_ucontext || ib_devices_shared_netns) {
+	if (ib_devices_shared_netns) {
+		NL_SET_ERR_MSG(extack,
+			       "Cannot change net namespace of RDMA device in shared netns mode");
+		ret = -EOPNOTSUPP;
+		goto ns_err;
+	}
+
+	if (!dev->ops.disassociate_ucontext) {
+		NL_SET_ERR_MSG(extack,
+			       "Device does not support namespace changes (no disassociate support)");
 		ret = -EOPNOTSUPP;
 		goto ns_err;
 	}
@@ -1911,6 +1928,9 @@ int ib_device_set_netns_put(struct sk_buff *skb,
 	ret = rdma_dev_change_netns(dev, current->nsproxy->net_ns, net, name,
 				    NULL);
 	put_device(&dev->dev);
+	if (ret == -EEXIST)
+		NL_SET_ERR_MSG(extack,
+			       "Device name already exists in the target net namespace");
 
 	put_net(net);
 	return ret;
diff --git a/drivers/infiniband/core/nldev.c b/drivers/infiniband/core/nldev.c
index 3540cb0b9d4f..5fd1ef2c5050 100644
--- a/drivers/infiniband/core/nldev.c
+++ b/drivers/infiniband/core/nldev.c
@@ -1194,10 +1194,8 @@ static int nldev_set_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
 		u32 ns_fd;
 
 		ns_fd = nla_get_u32(tb[RDMA_NLDEV_NET_NS_FD]);
-		err = ib_device_set_netns_put(skb, device, ns_fd, NULL);
-		if (err == -EEXIST)
-			NL_SET_ERR_MSG(extack,
-				       "Device name already exists in the target net namespace");
+		err = ib_device_set_netns_put(skb, device, ns_fd, NULL,
+					      extack);
 		goto put_done;
 	}
 
-- 
2.54.0


^ permalink raw reply related

* [PATCH rdma-next 03/13] RDMA/core: Support renaming a device when changing its net namespace
From: Jiri Pirko @ 2026-07-09  9:55 UTC (permalink / raw)
  To: linux-rdma
  Cc: cgroups, netdev, linux-s390, linux-kselftest, jgg, leon, parav,
	mbloch, cmeiohas, roman.gushchin, bvanassche, zyjzyj2000, shuah,
	tj, mkoutny, hannes, alibuda, dust.li, sidraya, wenjia
In-Reply-To: <20260709095532.855647-1-jiri@resnulli.us>

From: Jiri Pirko <jiri@nvidia.com>

Allow namespace moves to request a destination device name. Keep requested
names on the same literal-name path as the existing RDMA rename operation,
and keep teardown fallback naming on the trusted kernel-controlled path.

Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
 drivers/infiniband/core/core_priv.h |  2 +-
 drivers/infiniband/core/device.c    | 48 ++++++++++++++++++++---------
 drivers/infiniband/core/nldev.c     |  2 +-
 3 files changed, 35 insertions(+), 17 deletions(-)

diff --git a/drivers/infiniband/core/core_priv.h b/drivers/infiniband/core/core_priv.h
index 19104c542b27..3bd5bb7135a3 100644
--- a/drivers/infiniband/core/core_priv.h
+++ b/drivers/infiniband/core/core_priv.h
@@ -356,7 +356,7 @@ void ib_port_unregister_client_groups(struct ib_device *ibdev, u32 port_num,
 				     const struct attribute_group **groups);
 
 int ib_device_set_netns_put(struct sk_buff *skb,
-			    struct ib_device *dev, u32 ns_fd);
+			    struct ib_device *dev, u32 ns_fd, const char *name);
 
 int rdma_nl_net_init(struct rdma_dev_net *rnet);
 void rdma_nl_net_exit(struct rdma_dev_net *rnet);
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index 8d169658e312..191f05898bae 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -268,7 +268,8 @@ static struct notifier_block ibdev_lsm_nb = {
 };
 
 static int rdma_dev_change_netns(struct ib_device *device, struct net *cur_net,
-				 struct net *net, const char *fallback_pattern);
+				 struct net *net, const char *requested_name,
+				 const char *fallback_pattern);
 
 /* Pointer to the RCU head at the start of the ib_port_data array */
 struct ib_port_data_rcu {
@@ -1173,7 +1174,7 @@ static void rdma_dev_exit_net(struct net *net)
 		 */
 		if (net_eq(net, read_pnet(&dev->coredev.rdma_net))) {
 			ret = rdma_dev_change_netns(dev, net, &init_net,
-						    "ibdev%d");
+						    NULL, "ibdev%d");
 			if (ret)
 				WARN(1,
 				     "Failed to move RDMA device %s to init_net on netns exit: %d\n",
@@ -1714,12 +1715,13 @@ static bool rdma_dev_name_in_netns(struct ib_device *skip, struct net *net,
 }
 
 /*
- * Choose the name @device should use in net namespace @net: keep the current
- * name when it is free, otherwise use a trusted '%d' @fallback_pattern
- * (namespace teardown) to pick a free index. The caller must hold the write
- * side of devices_rwsem.
+ * Choose the name @device should use in net namespace @net. @requested_name
+ * is used as a literal device name when set. Otherwise keep the current name
+ * when it is free, or use a trusted '%d' @fallback_pattern for teardown. The
+ * caller must hold the write side of devices_rwsem.
  */
 static int rdma_dev_pick_netns_name(struct ib_device *device, struct net *net,
+				    const char *requested_name,
 				    const char *fallback_pattern,
 				    char *buf, size_t buf_len,
 				    const char **new_name)
@@ -1728,6 +1730,15 @@ static int rdma_dev_pick_netns_name(struct ib_device *device, struct net *net,
 
 	lockdep_assert_held_write(&devices_rwsem);
 
+	if (requested_name) {
+		if (!rdma_dev_name_in_netns(device, net, requested_name)) {
+			*new_name = requested_name;
+			return 0;
+		}
+
+		return -EEXIST;
+	}
+
 	if (!rdma_dev_name_in_netns(device, net, dev_name(&device->dev))) {
 		*new_name = dev_name(&device->dev);
 		return 0;
@@ -1758,7 +1769,8 @@ static int rdma_dev_pick_netns_name(struct ib_device *device, struct net *net,
  * Naming rules are handled by rdma_dev_pick_netns_name().
  */
 static int rdma_dev_change_netns(struct ib_device *device, struct net *cur_net,
-				 struct net *net, const char *fallback_pattern)
+				 struct net *net, const char *requested_name,
+				 const char *fallback_pattern)
 {
 	char buf[IB_DEVICE_NAME_MAX];
 	const char *new_name;
@@ -1784,8 +1796,9 @@ static int rdma_dev_change_netns(struct ib_device *device, struct net *cur_net,
 		 * down, so a doomed user move does not disable a live device.
 		 */
 		down_write(&devices_rwsem);
-		ret = rdma_dev_pick_netns_name(device, net, fallback_pattern,
-					       buf, sizeof(buf), &new_name);
+		ret = rdma_dev_pick_netns_name(device, net, requested_name,
+					       fallback_pattern, buf,
+					       sizeof(buf), &new_name);
 		up_write(&devices_rwsem);
 		if (ret)
 			goto out;
@@ -1801,8 +1814,9 @@ static int rdma_dev_change_netns(struct ib_device *device, struct net *cur_net,
 	 * level.
 	 */
 	down_write(&devices_rwsem);
-	ret = rdma_dev_pick_netns_name(device, net, fallback_pattern, buf,
-				       sizeof(buf), &new_name);
+	ret = rdma_dev_pick_netns_name(device, net, requested_name,
+				       fallback_pattern, buf, sizeof(buf),
+				       &new_name);
 	if (ret) {
 		if (fallback_pattern) {
 			WARN(1,
@@ -1857,7 +1871,7 @@ static int rdma_dev_change_netns(struct ib_device *device, struct net *cur_net,
 }
 
 int ib_device_set_netns_put(struct sk_buff *skb,
-			    struct ib_device *dev, u32 ns_fd)
+			    struct ib_device *dev, u32 ns_fd, const char *name)
 {
 	struct net *net;
 	int ret;
@@ -1873,9 +1887,12 @@ int ib_device_set_netns_put(struct sk_buff *skb,
 		goto ns_err;
 	}
 
-	/* Moving a device to the namespace it already lives in is a no-op. */
+	/*
+	 * Moving a device to the namespace it already lives in is a no-op; a
+	 * supplied name still renames it in place.
+	 */
 	if (net_eq(net, read_pnet(&dev->coredev.rdma_net))) {
-		ret = 0;
+		ret = name ? ib_device_rename(dev, name) : 0;
 		goto ns_err;
 	}
 
@@ -1891,7 +1908,8 @@ int ib_device_set_netns_put(struct sk_buff *skb,
 
 	get_device(&dev->dev);
 	ib_device_put(dev);
-	ret = rdma_dev_change_netns(dev, current->nsproxy->net_ns, net, NULL);
+	ret = rdma_dev_change_netns(dev, current->nsproxy->net_ns, net, name,
+				    NULL);
 	put_device(&dev->dev);
 
 	put_net(net);
diff --git a/drivers/infiniband/core/nldev.c b/drivers/infiniband/core/nldev.c
index 3a9ec43a16f1..3540cb0b9d4f 100644
--- a/drivers/infiniband/core/nldev.c
+++ b/drivers/infiniband/core/nldev.c
@@ -1194,7 +1194,7 @@ static int nldev_set_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
 		u32 ns_fd;
 
 		ns_fd = nla_get_u32(tb[RDMA_NLDEV_NET_NS_FD]);
-		err = ib_device_set_netns_put(skb, device, ns_fd);
+		err = ib_device_set_netns_put(skb, device, ns_fd, NULL);
 		if (err == -EEXIST)
 			NL_SET_ERR_MSG(extack,
 				       "Device name already exists in the target net namespace");
-- 
2.54.0


^ permalink raw reply related

* [PATCH rdma-next 02/13] RDMA/core: Handle device name conflicts when changing net namespace
From: Jiri Pirko @ 2026-07-09  9:55 UTC (permalink / raw)
  To: linux-rdma
  Cc: cgroups, netdev, linux-s390, linux-kselftest, jgg, leon, parav,
	mbloch, cmeiohas, roman.gushchin, bvanassche, zyjzyj2000, shuah,
	tj, mkoutny, hannes, alibuda, dust.li, sidraya, wenjia
In-Reply-To: <20260709095532.855647-1-jiri@resnulli.us>

From: Jiri Pirko <jiri@nvidia.com>

Prepare namespace moves for per-netns names. Check user-initiated moves for
destination-name conflicts before disabling the device, keep same-netns
moves as no-ops, and make teardown moves detach from the exiting namespace
even if fallback naming fails.

Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
 drivers/infiniband/core/device.c | 155 ++++++++++++++++++++++++++-----
 drivers/infiniband/core/nldev.c  |   3 +
 2 files changed, 137 insertions(+), 21 deletions(-)

diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index de610f52c9b2..8d169658e312 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -268,7 +268,7 @@ static struct notifier_block ibdev_lsm_nb = {
 };
 
 static int rdma_dev_change_netns(struct ib_device *device, struct net *cur_net,
-				 struct net *net);
+				 struct net *net, const char *fallback_pattern);
 
 /* Pointer to the RCU head at the start of the ib_port_data array */
 struct ib_port_data_rcu {
@@ -437,7 +437,8 @@ int ib_device_set_dim(struct ib_device *ibdev, u8 use_dim)
 }
 
 /* Pick a free index for the '%d' style @name pattern. */
-static int alloc_name_id(struct net *net, const char *name)
+static int __alloc_name_id(struct net *net, const char *name,
+			   const struct ib_device *skip)
 {
 	struct ib_device *device;
 	unsigned long index;
@@ -450,6 +451,8 @@ static int alloc_name_id(struct net *net, const char *name)
 	xa_for_each (&devices, index, device) {
 		char buf[IB_DEVICE_NAME_MAX];
 
+		if (device == skip)
+			continue;
 		if (sscanf(dev_name(&device->dev), name, &i) != 1)
 			continue;
 		if (i < 0 || i >= INT_MAX)
@@ -469,6 +472,11 @@ static int alloc_name_id(struct net *net, const char *name)
 	return rc;
 }
 
+static int alloc_name_id(struct net *net, const char *name)
+{
+	return __alloc_name_id(net, name, NULL);
+}
+
 static int alloc_name(struct ib_device *ibdev, const char *name)
 {
 	int id;
@@ -1160,8 +1168,17 @@ static void rdma_dev_exit_net(struct net *net)
 
 		/*
 		 * If the real device is in the NS then move it back to init.
+		 * Provide a fallback pattern so a name conflict in init_net
+		 * cannot make the teardown move fail.
 		 */
-		rdma_dev_change_netns(dev, net, &init_net);
+		if (net_eq(net, read_pnet(&dev->coredev.rdma_net))) {
+			ret = rdma_dev_change_netns(dev, net, &init_net,
+						    "ibdev%d");
+			if (ret)
+				WARN(1,
+				     "Failed to move RDMA device %s to init_net on netns exit: %d\n",
+				     dev_name(&dev->dev), ret);
+		}
 
 		put_device(&dev->dev);
 		down_read(&devices_rwsem);
@@ -1680,14 +1697,71 @@ void ib_unregister_device_queued(struct ib_device *ib_dev)
 }
 EXPORT_SYMBOL(ib_unregister_device_queued);
 
+static bool rdma_dev_name_in_netns(struct ib_device *skip, struct net *net,
+				   const char *name)
+{
+	struct ib_device *device;
+	unsigned long index;
+
+	lockdep_assert_held_write(&devices_rwsem);
+
+	xa_for_each(&devices, index, device)
+		if (device != skip &&
+		    !strcmp(name, dev_name(&device->dev)))
+			return true;
+
+	return false;
+}
+
+/*
+ * Choose the name @device should use in net namespace @net: keep the current
+ * name when it is free, otherwise use a trusted '%d' @fallback_pattern
+ * (namespace teardown) to pick a free index. The caller must hold the write
+ * side of devices_rwsem.
+ */
+static int rdma_dev_pick_netns_name(struct ib_device *device, struct net *net,
+				    const char *fallback_pattern,
+				    char *buf, size_t buf_len,
+				    const char **new_name)
+{
+	int id;
+
+	lockdep_assert_held_write(&devices_rwsem);
+
+	if (!rdma_dev_name_in_netns(device, net, dev_name(&device->dev))) {
+		*new_name = dev_name(&device->dev);
+		return 0;
+	}
+
+	if (!fallback_pattern)
+		return -EEXIST;
+
+	snprintf(buf, buf_len, "ibdev%u", device->index);
+	if (!rdma_dev_name_in_netns(device, net, buf)) {
+		*new_name = buf;
+		return 0;
+	}
+
+	id = __alloc_name_id(net, fallback_pattern, device);
+	if (id < 0)
+		return id;
+	snprintf(buf, buf_len, fallback_pattern, id);
+	*new_name = buf;
+	return 0;
+}
+
 /*
  * The caller must pass in a device that has the kref held and the refcount
  * released. If the device is in cur_net and still registered then it is moved
  * into net.
+ *
+ * Naming rules are handled by rdma_dev_pick_netns_name().
  */
 static int rdma_dev_change_netns(struct ib_device *device, struct net *cur_net,
-				 struct net *net)
+				 struct net *net, const char *fallback_pattern)
 {
+	char buf[IB_DEVICE_NAME_MAX];
+	const char *new_name;
 	int ret2 = -EINVAL;
 	int ret;
 
@@ -1704,30 +1778,63 @@ static int rdma_dev_change_netns(struct ib_device *device, struct net *cur_net,
 		goto out;
 	}
 
+	if (!fallback_pattern) {
+		/*
+		 * Reject a predictable name conflict before tearing anything
+		 * down, so a doomed user move does not disable a live device.
+		 */
+		down_write(&devices_rwsem);
+		ret = rdma_dev_pick_netns_name(device, net, fallback_pattern,
+					       buf, sizeof(buf), &new_name);
+		up_write(&devices_rwsem);
+		if (ret)
+			goto out;
+	}
+
 	kobject_uevent(&device->dev.kobj, KOBJ_REMOVE);
 	disable_device(device);
 
 	/*
-	 * At this point no one can be using the device, so it is safe to
-	 * change the namespace.
+	 * Recompute the destination name under the write side of devices_rwsem
+	 * now that the device is disabled, closing races with a concurrent
+	 * registration or rename, then publish the new namespace at the sysfs
+	 * level.
 	 */
-	write_pnet(&device->coredev.rdma_net, net);
+	down_write(&devices_rwsem);
+	ret = rdma_dev_pick_netns_name(device, net, fallback_pattern, buf,
+				       sizeof(buf), &new_name);
+	if (ret) {
+		if (fallback_pattern) {
+			WARN(1,
+			     "%s: failed to pick device name during namespace teardown: %d\n",
+			     __func__, ret);
+			write_pnet(&device->coredev.rdma_net, net);
+			ret = 0;
+		}
+		goto rename_done;
+	}
 
-	down_read(&devices_rwsem);
-	/*
-	 * Currently rdma devices are system wide unique. So the device name
-	 * is guaranteed free in the new namespace. Publish the new namespace
-	 * at the sysfs level.
-	 */
-	ret = device_rename(&device->dev, dev_name(&device->dev));
-	up_read(&devices_rwsem);
+	write_pnet(&device->coredev.rdma_net, net);
+	ret = device_rename(&device->dev, new_name);
 	if (ret) {
-		dev_warn(&device->dev,
-			 "%s: Couldn't rename device after namespace change\n",
-			 __func__);
-		/* Try and put things back and re-enable the device */
-		write_pnet(&device->coredev.rdma_net, cur_net);
+		if (fallback_pattern) {
+			WARN(1,
+			     "%s: failed to rename device during namespace teardown: %d\n",
+			     __func__, ret);
+			ret = 0;
+		} else {
+			dev_warn(&device->dev,
+				 "%s: Couldn't rename device after namespace change\n",
+				 __func__);
+			/* Try and put things back and re-enable the device */
+			write_pnet(&device->coredev.rdma_net, cur_net);
+		}
+	} else {
+		strscpy(device->name, dev_name(&device->dev),
+			IB_DEVICE_NAME_MAX);
 	}
+rename_done:
+	up_write(&devices_rwsem);
 
 	ret2 = enable_device_and_get(device);
 	if (ret2) {
@@ -1766,6 +1873,12 @@ int ib_device_set_netns_put(struct sk_buff *skb,
 		goto ns_err;
 	}
 
+	/* Moving a device to the namespace it already lives in is a no-op. */
+	if (net_eq(net, read_pnet(&dev->coredev.rdma_net))) {
+		ret = 0;
+		goto ns_err;
+	}
+
 	/*
 	 * All the ib_clients, including uverbs, are reset when the namespace is
 	 * changed and this cannot be blocked waiting for userspace to do
@@ -1778,7 +1891,7 @@ int ib_device_set_netns_put(struct sk_buff *skb,
 
 	get_device(&dev->dev);
 	ib_device_put(dev);
-	ret = rdma_dev_change_netns(dev, current->nsproxy->net_ns, net);
+	ret = rdma_dev_change_netns(dev, current->nsproxy->net_ns, net, NULL);
 	put_device(&dev->dev);
 
 	put_net(net);
diff --git a/drivers/infiniband/core/nldev.c b/drivers/infiniband/core/nldev.c
index f599c24b34e8..3a9ec43a16f1 100644
--- a/drivers/infiniband/core/nldev.c
+++ b/drivers/infiniband/core/nldev.c
@@ -1195,6 +1195,9 @@ static int nldev_set_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
 
 		ns_fd = nla_get_u32(tb[RDMA_NLDEV_NET_NS_FD]);
 		err = ib_device_set_netns_put(skb, device, ns_fd);
+		if (err == -EEXIST)
+			NL_SET_ERR_MSG(extack,
+				       "Device name already exists in the target net namespace");
 		goto put_done;
 	}
 
-- 
2.54.0


^ permalink raw reply related

* [PATCH rdma-next 01/13] RDMA/core: Pass the net namespace to the device name lookups
From: Jiri Pirko @ 2026-07-09  9:55 UTC (permalink / raw)
  To: linux-rdma
  Cc: cgroups, netdev, linux-s390, linux-kselftest, jgg, leon, parav,
	mbloch, cmeiohas, roman.gushchin, bvanassche, zyjzyj2000, shuah,
	tj, mkoutny, hannes, alibuda, dust.li, sidraya, wenjia
In-Reply-To: <20260709095532.855647-1-jiri@resnulli.us>

From: Jiri Pirko <jiri@nvidia.com>

Prepare for per-netns RDMA device names by passing the target net
namespace through the name lookup and allocation helpers. Keep current
global uniqueness behaviour.

Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
 drivers/infiniband/core/device.c | 26 ++++++++++++++++++--------
 1 file changed, 18 insertions(+), 8 deletions(-)

diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index b8193e077a74..de610f52c9b2 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -351,7 +351,8 @@ void ib_device_put(struct ib_device *device)
 }
 EXPORT_SYMBOL(ib_device_put);
 
-static struct ib_device *__ib_device_get_by_name(const char *name)
+static struct ib_device *__ib_device_get_by_name(const char *name,
+						 const struct net *net)
 {
 	struct ib_device *device;
 	unsigned long index;
@@ -395,7 +396,7 @@ int ib_device_rename(struct ib_device *ibdev, const char *name)
 		return 0;
 	}
 
-	if (__ib_device_get_by_name(name)) {
+	if (__ib_device_get_by_name(name, rdma_dev_net(ibdev))) {
 		up_write(&devices_rwsem);
 		return -EEXIST;
 	}
@@ -435,7 +436,8 @@ int ib_device_set_dim(struct ib_device *ibdev, u8 use_dim)
 	return 0;
 }
 
-static int alloc_name(struct ib_device *ibdev, const char *name)
+/* Pick a free index for the '%d' style @name pattern. */
+static int alloc_name_id(struct net *net, const char *name)
 {
 	struct ib_device *device;
 	unsigned long index;
@@ -462,15 +464,22 @@ static int alloc_name(struct ib_device *ibdev, const char *name)
 	}
 
 	rc = ida_alloc(&inuse, GFP_KERNEL);
-	if (rc < 0)
-		goto out;
-
-	rc = dev_set_name(&ibdev->dev, name, rc);
 out:
 	ida_destroy(&inuse);
 	return rc;
 }
 
+static int alloc_name(struct ib_device *ibdev, const char *name)
+{
+	int id;
+
+	id = alloc_name_id(rdma_dev_net(ibdev), name);
+	if (id < 0)
+		return id;
+
+	return dev_set_name(&ibdev->dev, name, id);
+}
+
 static void ib_device_release(struct device *device)
 {
 	struct ib_device *dev = container_of(device, struct ib_device, dev);
@@ -1223,7 +1232,8 @@ static int assign_name(struct ib_device *device, const char *name)
 	if (ret)
 		goto out;
 
-	if (__ib_device_get_by_name(dev_name(&device->dev))) {
+	if (__ib_device_get_by_name(dev_name(&device->dev),
+				    rdma_dev_net(device))) {
 		ret = -ENFILE;
 		goto out;
 	}
-- 
2.54.0


^ permalink raw reply related

* [PATCH rdma-next 00/13] RDMA: Make device names unique per net namespace
From: Jiri Pirko @ 2026-07-09  9:55 UTC (permalink / raw)
  To: linux-rdma
  Cc: cgroups, netdev, linux-s390, linux-kselftest, jgg, leon, parav,
	mbloch, cmeiohas, roman.gushchin, bvanassche, zyjzyj2000, shuah,
	tj, mkoutny, hannes, alibuda, dust.li, sidraya, wenjia

From: Jiri Pirko <jiri@nvidia.com>

RDMA device names are unique system-wide today:
__ib_device_get_by_name() checks a requested name against every
registered device regardless of the network namespace it lives in.
A device in one network namespace therefore cannot use a name already
taken in another, even in exclusive netns mode (netns_mode=0) where
the two are otherwise isolated. Net devices have no such restriction -
their names only need to be unique within a network namespace.

This series makes RDMA device names unique per network namespace,
matching net device semantics, and adapts the users that assumed
system-wide unique names.

Scoping reuses the existing rdma_dev_access_netns() predicate, so
behavior only changes in exclusive mode:
  - shared mode (default): names stay unique system-wide, no change;
  - exclusive mode: names only need to be unique within a namespace;
  - CONFIG_NET_NS=n: everything is init_net, names stay system-wide
    unique.

There are two users that cannot be made per-namespace and are
documented as known limitations instead of changed:
  - the rdma_cm configfs tree: configfs has no network namespace
    support, so it cannot represent two same-named devices;
  - SELinux ibendport labelling: endports are labelled by (device
    name, port) from a global policy; distinguishing same-named
    devices would need net namespace support in the SELinux policy
    language and tooling.

Tested with the new rxe_netns_names kselftest added in the last patch.

Jiri Pirko (13):
  RDMA/core: Pass the net namespace to the device name lookups
  RDMA/core: Handle device name conflicts when changing net namespace
  RDMA/core: Support renaming a device when changing its net namespace
  RDMA/nldev: Report net namespace move errors through extack
  RDMA/nldev: Allow setting the device name while changing net namespace
  net/smc: Look up the pnetid ib device within the net namespace
  RDMA/srp: Make the SRP sysfs class net namespace aware
  RDMA/cgroup: Scope rdma cgroup device visibility to the net namespace
  RDMA/cma: Document that CM configfs cannot be net namespace scoped
  RDMA/core: Document the SELinux ibendport net namespace limitation
  RDMA/core: Make device names unique per net namespace
  RDMA/rxe: Implement disassociate_ucontext callback
  RDMA/selftests: Add rxe_netns_names test

 Documentation/ABI/testing/configfs-rdma_cm    |   4 +
 Documentation/admin-guide/cgroup-v2.rst       |   7 +
 drivers/infiniband/core/cgroup.c              |  12 +
 drivers/infiniband/core/cma_configfs.c        |   4 +
 drivers/infiniband/core/core_priv.h           |  15 +-
 drivers/infiniband/core/device.c              | 256 +++++++++++++---
 drivers/infiniband/core/nldev.c               |  26 +-
 drivers/infiniband/core/security.c            |   6 +
 drivers/infiniband/sw/rxe/rxe_verbs.c         |   5 +
 drivers/infiniband/ulp/srp/ib_srp.c           |  16 +-
 include/linux/cgroup_rdma.h                   |  10 +
 include/uapi/rdma/rdma_netlink.h              |   5 +-
 kernel/cgroup/rdma.c                          |  20 +-
 net/smc/smc_pnet.c                            |  20 +-
 tools/testing/selftests/rdma/Makefile         |   3 +-
 tools/testing/selftests/rdma/config           |   2 +
 .../testing/selftests/rdma/rxe_netns_names.sh | 282 ++++++++++++++++++
 17 files changed, 639 insertions(+), 54 deletions(-)
 create mode 100755 tools/testing/selftests/rdma/rxe_netns_names.sh

-- 
2.54.0


^ permalink raw reply

* Re: [PATCH net-next V5 6/6] net/mlx5: Apply devlink eswitch mode boot default on probe
From: Jiri Pirko @ 2026-07-09  9:52 UTC (permalink / raw)
  To: Mark Bloch
  Cc: Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
	Saeed Mahameed, Leon Romanovsky, Tariq Toukan, Andrew Lunn,
	Jonathan Corbet, Shuah Khan, netdev, linux-rdma, linux-doc
In-Reply-To: <7309e57a-89bc-4e4a-97e9-d843b02efa42@nvidia.com>

Thu, Jul 09, 2026 at 08:00:19AM +0200, mbloch@nvidia.com wrote:
>
>
>On 08/07/2026 11:34, Jiri Pirko wrote:
>> Tue, Jul 07, 2026 at 07:45:27PM +0200, mbloch@nvidia.com wrote:
>>> Apply devlink_eswitch_mode= boot defaults for mlx5 after the initial
>>> probe finishes device initialization while holding the devlink instance
>>> lock.
>>>
>>> At this point the devlink instance is registered and mlx5 can perform an
>>> eswitch mode change. Calling devl_apply_default_esw_mode() also clears
>>> any pending default apply work queued by devl_register(), so the queued
>>> work will not apply the same default again.
>>>
>>> Keep this call in mlx5_init_one() rather than the lower-level
>>> devl-locked init helper. That helper is also used by devlink reload, and
>>> devlink core already applies the boot default after a successful
>>> DRIVER_REINIT reload.
>>>
>>> Signed-off-by: Mark Bloch <mbloch@nvidia.com>
>>> ---
>>> drivers/net/ethernet/mellanox/mlx5/core/main.c | 13 +++++++++++++
>>> 1 file changed, 13 insertions(+)
>>>
>>> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c
>>> index 643b4aac2033..0712efea74cc 100644
>>> --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
>>> +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
>>> @@ -1392,6 +1392,17 @@ static void mlx5_unload(struct mlx5_core_dev *dev)
>>> 	mlx5_free_bfreg(dev, &dev->priv.bfreg);
>>> }
>>>
>>> +static void mlx5_devl_apply_default_esw_mode(struct mlx5_core_dev *dev)
>>> +{
>>> +	struct devlink *devlink = priv_to_devlink(dev);
>>> +
>>> +	if (!MLX5_ESWITCH_MANAGER(dev))
>>> +		return;
>>> +
>>> +	devl_assert_locked(devlink);
>>> +	devl_apply_default_esw_mode(devlink);
>>> +}
>>> +
>>> int mlx5_init_one_devl_locked(struct mlx5_core_dev *dev)
>>> {
>>> 	bool light_probe = mlx5_dev_is_lightweight(dev);
>>> @@ -1471,6 +1482,8 @@ int mlx5_init_one(struct mlx5_core_dev *dev)
>>> 	err = mlx5_init_one_devl_locked(dev);
>>> 	if (err)
>>> 		devl_unregister(devlink);
>>> +	else
>>> +		mlx5_devl_apply_default_esw_mode(dev);
>> 
>> I don't understand why this patch is needed at all. Just leave the job
>> to the devlink core, no? That was the point to not pollute drivers with
>> code like this. Is it some kind of leftover?
>
>It was discussed with Jakub here:
>https://lore.kernel.org/all/20260611085440.4fe36bf2@kernel.org/
>
>The main reason is timing. If the default is applied only by devlink
>core, it has to wait until the driver drops the devlink lock.

I don't follow.

<quote>
	devl_lock(devlink);
	if (dev->shd) {
		err = devl_nested_devlink_set(dev->shd, devlink);
		if (err)
			goto unlock;
	}
	devl_register(devlink);
	err = mlx5_init_one_devl_locked(dev);
	if (err)
		devl_unregister(devlink);
unlock:
	devl_unlock(devlink);
</quote>

devlink lock is droped right after.



>For mlx5, that usually happens very late in the init sequence. I
>wanted drivers to be able to apply the default as soon as the driver
>is ready for it, because on NICs with a DPU the host PF can remain
>stuck until the ECPF moves to switchdev.
>
>This API is also useful beyond the initial devlink registration path.
>Follow-up patches will use it for driver controlled paths that are
>not covered by the devlink core, such as recovery and FW reset.
>
>There is also a race window where userspace may take the devlink lock
>before the core gets a chance to apply the default. Letting the driver
>explicitly apply the default at the right point avoids that scenario.
>
>Thinking about this again, maybe the simpler approach is to apply the
>default from devl_unlock(). That would avoid the whole workqueue
>infra.
>
>I avoided doing that earlier because applying a default mode as a
>side effect of devl_unlock() feels a bit odd. But compared to adding
>dedicated workqueue handling maybe it is the lesser evil here.
>
>What do you think?

I was under impression that you need the work to resolve nested locking.
If not, drop it, sure.


>
>About the extra API, I still think it's useful and would like to keep
>it if possible.
>
>Mark
>
>
>> 
>> 
>> 
>>> unlock:
>>> 	devl_unlock(devlink);
>>> 	return err;
>>> -- 
>>> 2.43.0
>>>
>

^ permalink raw reply

* Re: [PATCH net 01/17] netfilter: nf_conntrack_reasm: guard mac_header adjustment after IPv6 defrag
From: patchwork-bot+netdevbpf @ 2026-07-09  9:50 UTC (permalink / raw)
  To: Florian Westphal
  Cc: netdev, pabeni, davem, edumazet, kuba, netfilter-devel, pablo
In-Reply-To: <20260708140309.19633-2-fw@strlen.de>

Hello:

This series was applied to netdev/net.git (main)
by Florian Westphal <fw@strlen.de>:

On Wed,  8 Jul 2026 16:02:53 +0200 you wrote:
> From: Xiang Mei <xmei5@asu.edu>
> 
> nf_ct_frag6_reasm() slides the packet head forward to drop the IPv6
> fragment header and then unconditionally advances skb->mac_header:
> 
> 	skb->mac_header += sizeof(struct frag_hdr);
> 
> [...]

Here is the summary with links:
  - [net,01/17] netfilter: nf_conntrack_reasm: guard mac_header adjustment after IPv6 defrag
    https://git.kernel.org/netdev/net/c/3b08fed5b7e0
  - [net,02/17] netfilter: ebtables: terminate table name before find_table_lock()
    https://git.kernel.org/netdev/net/c/a622d2e9608c
  - [net,03/17] netfilter: ebtables: zero chainstack array
    https://git.kernel.org/netdev/net/c/cbfe53599eeb
  - [net,04/17] netfilter: ebtables: module names must be null-terminated
    https://git.kernel.org/netdev/net/c/084d23f81832
  - [net,05/17] netfilter: nft_lookup: fix catchall element handling with inverted lookups
    https://git.kernel.org/netdev/net/c/e6107a4c74b5
  - [net,06/17] netfilter: ipset: mark the rcu locked areas properly
    https://git.kernel.org/netdev/net/c/5d0c22e73656
  - [net,07/17] netfilter: ipset: exclude gc when resize is in progress
    https://git.kernel.org/netdev/net/c/cffcf57bf03c
  - [net,08/17] netfilter: ipset: cleanup the add/del backlog when resize failed
    https://git.kernel.org/netdev/net/c/672321302ed6
  - [net,09/17] netfilter: ipset: allocate the proper memory for the generic hash structure
    https://git.kernel.org/netdev/net/c/724f32699aea
  - [net,10/17] netfilter: flowtable: use dst in this direction when pushing IPIP header
    https://git.kernel.org/netdev/net/c/c328b90c17fc
  - [net,11/17] netfilter: flowtable: IPIP tunnel hardware offload is not yet support
    https://git.kernel.org/netdev/net/c/6c5dcab95f4c
  - [net,12/17] netfilter: flowtable: support IPIP tunnel with direct xmit
    https://git.kernel.org/netdev/net/c/fa7395c02d95
  - [net,13/17] netfilter: handle unreadable frags
    https://git.kernel.org/netdev/net/c/da5b58478a9c
  - [net,14/17] ipvs: pass parsed transport offset to state handlers
    https://git.kernel.org/netdev/net/c/bae7ce7bafb5
  - [net,15/17] ipvs: use parsed transport offset in TCP state lookup
    https://git.kernel.org/netdev/net/c/2500fa3958b1
  - [net,16/17] ipvs: use parsed transport offset in SCTP state lookup
    https://git.kernel.org/netdev/net/c/2f75c0faa336
  - [net,17/17] ipvs: ensure inner headers in ICMP errors are in headroom
    https://git.kernel.org/netdev/net/c/3f7a535ff0fa

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply

* Re: [PATCH net] ethtool: rss: Fix hfunc and input_xfrm parsing on big endian
From: patchwork-bot+netdevbpf @ 2026-07-09  9:50 UTC (permalink / raw)
  To: Gal Pressman
  Cc: davem, edumazet, kuba, pabeni, andrew+netdev, netdev, andrew,
	horms, dtatulea, noren
In-Reply-To: <20260706055017.3355806-1-gal@nvidia.com>

Hello:

This patch was applied to netdev/net.git (main)
by Paolo Abeni <pabeni@redhat.com>:

On Mon, 6 Jul 2026 08:50:17 +0300 you wrote:
> ETHTOOL_A_RSS_HFUNC and ETHTOOL_A_RSS_INPUT_XFRM are NLA_U32 attributes,
> but ethnl_rss_set() and ethnl_rss_create_doit() parse them with
> ethnl_update_u8(), which reads a single byte.
> 
> On little endian this happens to read the least significant byte and
> works as long as the value fits in a byte. On big endian it reads the
> most significant byte, so the requested value is parsed incorrectly.
> 
> [...]

Here is the summary with links:
  - [net] ethtool: rss: Fix hfunc and input_xfrm parsing on big endian
    https://git.kernel.org/netdev/net/c/b62869a81a7c

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply

* [PATCH net] amd-xgbe: fix MAC_AUTO_SW handling in CL37 AN
From: Prashanth Kumar KR @ 2026-07-09  9:50 UTC (permalink / raw)
  To: Andrew Lunn, David S . Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, netdev, linux-kernel, stable, Shyam Sundar S K
  Cc: Patrick Oppenlander, Thorsten Leemhuis, Prashanth Kumar KR

From: Prashanth Kumar KR <PrashanthKumar.K.R@amd.com>

MAC_AUTO_SW (VR_MII_DIG_CTRL1 bit 9) enables automatic XPCS speed
mode switching after CL37 auto-negotiation and is only meaningful in
SGMII MAC mode. The original code unconditionally set this bit on
every call to xgbe_an37_set(), including when called from
xgbe_an37_disable() with enable=false. This left MAC_AUTO_SW=1 after
AN was disabled, causing the XPCS to autonomously switch speed from
stale AN state during subsequent mode changes, breaking SGMII speed
negotiation on 1G copper SFP modules.

Fixes: 42fd432fe6d3 ("amd-xgbe: align CL37 AN sequence as per databook")
Reported-by: Patrick Oppenlander <patrick.oppenlander@gmail.com>
Link: https://lore.kernel.org/netdev/CAEg67GmFS0Q4oSZkz8zWdOzckSth9_vBPiOy6a7-d697C2w2Xg@mail.gmail.com
Signed-off-by: Prashanth Kumar KR <PrashanthKumar.K.R@amd.com>
---
 drivers/net/ethernet/amd/xgbe/xgbe-mdio.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
index fa0df6181207..12770af031eb 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
@@ -267,9 +267,14 @@ static void xgbe_an37_set(struct xgbe_prv_data *pdata, bool enable,
 
 	XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_CTRL1, reg);
 
-	reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_PCS_DIG_CTRL);
-	reg |= XGBE_VEND2_MAC_AUTO_SW;
-	XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_PCS_DIG_CTRL, reg);
+	if (pdata->an_mode == XGBE_AN_MODE_CL37_SGMII) {
+		reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_PCS_DIG_CTRL);
+		if (enable)
+			reg |= XGBE_VEND2_MAC_AUTO_SW;
+		else
+			reg &= ~XGBE_VEND2_MAC_AUTO_SW;
+		XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_PCS_DIG_CTRL, reg);
+	}
 }
 
 static void xgbe_an37_restart(struct xgbe_prv_data *pdata)
-- 
2.34.1


^ permalink raw reply related

* Re: [PATCH 1/2] umh, treewide: Explicitly include linux/umh.h where needed
From: Petr Pavlu @ 2026-07-09  9:49 UTC (permalink / raw)
  To: Michal Koutný
  Cc: Tony Luck, Borislav Petkov, Thomas Gleixner, Ingo Molnar,
	Dave Hansen, x86, H. Peter Anvin, Philipp Reisner, Lars Ellenberg,
	Christoph Böhmwalder, Jens Axboe, Johan Hovold, Alex Elder,
	Greg Kroah-Hartman, Rafael J. Wysocki, Michal Januszewski,
	Helge Deller, Alexander Viro, Christian Brauner, Jan Kara,
	Trond Myklebust, Anna Schumaker, Chuck Lever, Jeff Layton,
	NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey, Mark Fasheh,
	Joel Becker, Joseph Qi, Tejun Heo, Johannes Weiner,
	Luis Chamberlain, Daniel Gomez, Sami Tolvanen, Aaron Tomlin,
	Pavel Machek, Len Brown, Andrew Morton, Danilo Krummrich,
	Nikolay Aleksandrov, Ido Schimmel, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Simon Horman, David Howells,
	Jarkko Sakkinen, Paul Moore, James Morris, Serge E. Hallyn,
	Kentaro Takeda, Tetsuo Handa, linux-edac, linux-kernel, drbd-dev,
	linux-block, greybus-dev, linuxppc-dev, linux-acpi, linux-fbdev,
	dri-devel, linux-fsdevel, linux-nfs, ocfs2-devel, cgroups,
	linux-modules, linux-pm, driver-core, bridge, netdev, keyrings,
	linux-security-module
In-Reply-To: <ak6STbqZd-Q-c56v@localhost.localdomain>

On 7/8/26 8:13 PM, Michal Koutný wrote:
> Hi Petr.
> 
> On Wed, Jul 08, 2026 at 05:44:29PM +0200, Petr Pavlu <petr.pavlu@suse.com> wrote:
>> diff --git a/kernel/cgroup/cgroup-v1.c b/kernel/cgroup/cgroup-v1.c
>> index a4337c9b5287..60eb994c32ae 100644
>> --- a/kernel/cgroup/cgroup-v1.c
>> +++ b/kernel/cgroup/cgroup-v1.c
>> @@ -16,6 +16,7 @@
>>  #include <linux/pid_namespace.h>
>>  #include <linux/cgroupstats.h>
>>  #include <linux/fs_parser.h>
>> +#include <linux/umh.h>
>>  
>>  #include <trace/events/cgroup.h>
> 
> There is kmod.h in here too but it's unnecessary, no module lazy loading
> in this code.

You're right. I'll remove the kmod.h include from
kernel/cgroup/cgroup-v1.c. I went through all the files again and it
seems this was the only place I missed.

-- 
Thanks,
Petr

^ permalink raw reply

* Re: [PATCH net v2] cxgb4: flower: fix 802.1ad VLAN TPID matching in tc flower filters
From: Paolo Abeni @ 2026-07-09  9:48 UTC (permalink / raw)
  To: h.mahadeva; +Cc: netdev, davem, kuba, edumazet, pabeni, andrew+netdev, bharat
In-Reply-To: <20260702044955.20119-1-h.mahadeva@chelsio.com>

From: AI Reviewer <ai@example.com>

This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
Full review at: https://netdev-ai.bots.linux.dev/sashiko/
---
cxgb4: flower: fix 802.1ad VLAN TPID matching in tc flower filters

This patch adds an 802.1ad branch to cxgb4_process_flow_match() that
programs a port-specific OVLAN register with ETH_P_8021AD, sets bit 0
of the RX control register, clears bit 9 of TP_INGRESS_CONFIG, and
populates the filter's outer-VLAN match fields.

A few questions about the new code follow inline.

> diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
> index 3307e5042681..8c5cfa6982e7 100644
> --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
> +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
> @@ -266,24 +267,48 @@ static void cxgb4_process_flow_match(struct net_device *dev,
>  					       VLAN_PRIO_SHIFT);
>  		vlan_tci_mask = match.mask->vlan_id | (match.mask->vlan_priority <<
>  						     VLAN_PRIO_SHIFT);
> -		fs->val.ivlan = vlan_tci;
> -		fs->mask.ivlan = vlan_tci_mask;
> -
> -		fs->val.ivlan_vld = 1;
> -		fs->mask.ivlan_vld = 1;
> -
> -		/* Chelsio adapters use ivlan_vld bit to match vlan packets
> [ ... ]
> -		if (fs->val.ethtype == ETH_P_8021Q) {
> -			fs->val.ethtype = 0;
> -			fs->mask.ethtype = 0;
> +
> +		if (match.key->vlan_tpid == cpu_to_be16(ETH_P_8021AD)) {

[Medium]
The gating condition consults only match.key->vlan_tpid and does not
look at match.mask->vlan_tpid.  In tc-flower semantics a key value is
only significant to the extent the mask covers it.

If a rule sets key=0x88a8 with mask=0 (don't care about TPID), this
branch is still entered and the adapter registers are still
reprogrammed.  Should this test be gated on the mask as well, similar
to how mlx5 and nfp consult the mask before honoring the key?

> +			struct adapter *adap = netdev2adap(dev);
> +			u32 ovlan_reg, ctl_reg, val, port_id;
> +
> +			if (!adap) {
> +				netdev_err(dev, "%s: adap not found\n", __func__);
> +				return;
> +			}

[Low]
netdev2adap() expands to netdev2pinfo(dev)->adapter and is not expected
to return NULL for a netdev that tc-flower can bind to.  If the check
ever did fire, cxgb4_process_flow_match() is void, so this early return
also skips the trailing:

    fs->val.iport = netdev2pinfo(dev)->port_id;
    fs->mask.iport = ~0;

and cxgb4_flow_rule_replace() would proceed to install a filter with
iport=0 / iport_mask=0.  Should the check either be removed, or the
function refactored to propagate an error?

> +
> +			val = (0xffff << 16) | ETH_P_8021AD;

[Low]
The literal 0xffff has type int (signed), so 0xffff << 16 evaluates to
a value that is not representable in a signed int.  Per C11 6.5.7 this
is undefined behavior and UBSAN's shift sanitizer flags it.  Would
0xffffU << 16 (or a symbolic _V()/_M() macro) be preferable?

The layout of MPS_PORT_RX_OVLAN0_A ([31:16]=mask, [15:0]=value) is also
not expressed through the driver's usual _S/_V/_F/_M helpers used by
neighboring registers.  Could symbolic field macros be added?

> +			port_id = netdev2pinfo(dev)->port_id;
> +			fs->val.ovlan = vlan_tci;
> +			fs->mask.ovlan = vlan_tci_mask;
> +			fs->val.ovlan_vld = 1;
> +			fs->mask.ovlan_vld = 1;

[High]
Does this ovlan programming survive on adapters that have VNIC_F set in
the cached ingress_config?  In cxgb4_filter.c, both __cxgb4_set_filter()
and cxgb4_set_hash_filter() unconditionally do:

    if (adap->params.tp.ingress_config & VNIC_F) {
        fs->val.ovlan = (fs->val.pf << 13) | fs->val.vf;
        fs->val.ovlan_vld = fs->val.pfvf_vld;
        ...
    }

which overwrites the fs->val.ovlan / fs->val.ovlan_vld set here.
validate_filter() also rejects with -EOPNOTSUPP when ovlan_vld is set
together with VNIC_F, or when the filter mode does not include
VNIC_ID_F.

On adapters where VNIC_F is enabled, does this branch actually restore
matching, or does it silently lose the VID (and, per the next comment,
still mutate hardware before failing validation)?

> +			ovlan_reg = PORT_REG(port_id, MPS_PORT_RX_OVLAN0_A);
> +			ctl_reg = PORT_REG(port_id, MPS_PORT_RX_CTL_A);
> +			t4_write_reg(adap, ovlan_reg, val);

[High]
cxgb4_process_flow_match() is called from cxgb4_flow_rule_replace()
before __cxgb4_set_filter() runs validate_filter() and the mailbox/L2T
install.  Do these three writes need to be deferred until after
validation and successful install, so that a filter rejected by
validate_filter(), or one that fails allocation/mailbox/L2T setup,
does not leave the port and adapter in a reconfigured state with no
installed filter to justify it?

Additionally, clear_filter() (cxgb4_filter.c) only tears down L2T/SMT/
CLIP and memsets the filter entry.  It does not undo MPS_PORT_RX_OVLAN0,
MPS_PORT_RX_CTL bit 0, or TP_INGRESS_CONFIG bit 9.  Is a corresponding
teardown expected on filter delete/replace so that 'tc filter add' +
'tc filter del' does not leave OVLAN matching permanently enabled and
TP_INGRESS_CONFIG bit 9 permanently cleared?

MPS_PORT_RX_OVLAN0_A is also hardcoded to slot 0 with ETH_P_8021AD as
the TPID.  How is a second concurrent flow rule requesting a different
outer TPID intended to be represented, given that installing it would
clobber slot 0?

> +			val = t4_read_reg(adap, ctl_reg);
> +			t4_write_reg(adap, ctl_reg, val | 1);

[High]
This RMW on MPS_PORT_RX_CTL_A is unserialized.  If another context
modifies other bits of the same register between the read and the
write, that update is lost.  Is there a lock that should be held here
(win0_lock or similar)?

> +			t4_tp_wr_bits_indirect(adap, TP_INGRESS_CONFIG_A, 1U << 9, 0);

[High, Medium, Medium]
t4_tp_wr_bits_indirect() drives the TP_PIO_ADDR_A / TP_PIO_DATA_A
indirect-register pair:

    void t4_tp_wr_bits_indirect(struct adapter *adap, unsigned int addr,
                                unsigned int mask, unsigned int val)
    {
        t4_write_reg(adap, TP_PIO_ADDR_A, addr);
        val |= t4_read_reg(adap, TP_PIO_DATA_A) & ~mask;
        t4_write_reg(adap, TP_PIO_DATA_A, val);
    }

Before this patch the only in-tree caller was probe-time
adap_init0_tweaks().  This patch adds a runtime, user-triggerable
caller.

Can a concurrent TP_PIO user (t4_tp_pio_read/t4_tp_pio_write when LDST
is unavailable, register-dump code, or another tc-flower install on a
different netdev of the same adapter) interleave between the ADDR
write and the DATA read/write and cause the wrong TP register to be
read or written?  What serializes the TP_PIO_ADDR_A/TP_PIO_DATA_A pair
here?

Separately, the hardware bit is toggled but adap->params.tp.ingress_config
is not updated.  That shadow is consulted throughout cxgb4_filter.c
(validate_filter, __cxgb4_set_filter, cxgb4_set_hash_filter) and l2t.c
to make VNIC_F / USE_ENC_IDX_F / ovlan-vs-pfvf decisions.  Should the
shadow be kept in sync with the hardware write?

Also, bit 9 of TP_INGRESS_CONFIG_A is written as the bare literal
1U << 9, while neighboring bits of the same register are exposed as
_S/_V/_F macros in t4_regs.h (CSUM_HAS_PSEUDO_HDR_S=10, VNIC_S=11,
USE_ENC_IDX_S=13).  What feature does bit 9 control, and could a
symbolic name be introduced?  The commit message enumerates three
actions (OVLAN register, RX control enable, filter fields) but does
not mention this fourth adapter-wide write.

> +		} else {
> +			fs->val.ivlan = vlan_tci;
> +			fs->mask.ivlan = vlan_tci_mask;
> +			fs->val.ivlan_vld = 1;
> +			fs->mask.ivlan_vld = 1;
> +
> +			/* Chelsio adapters use ivlan_vld bit to match vlan packets
> +			 * as 802.1Q. Also, when vlan tag is present in packets,
> +			 * ethtype match is used then to match on ethtype of inner
> +			 * header ie. the header following the vlan header.
> +			 * So, set the ivlan_vld based on ethtype info supplied by
> +			 * TC for vlan packets if its 802.1Q. And then reset the
> +			 * ethtype value else, hw will try to match the supplied
> +			 * ethtype value with ethtype of inner header.
> +			 */
> +
> +			if (fs->val.ethtype == ETH_P_8021Q) {
> +				fs->val.ethtype = 0;
> +				fs->mask.ethtype = 0;
> +			}

[High]
The preserved comment states that the hardware ethtype field matches
the ethtype after the outer VLAN tag (the inner header), and the
802.1Q branch resets fs->val.ethtype/fs->mask.ethtype to avoid a
mismatch.

The new 802.1ad branch above does not perform the equivalent reset.
For a common rule such as:

    tc filter add ... flower \
        vlan_ethtype 0x88a8 vlan_id X ...

FLOW_DISSECTOR_KEY_BASIC processing earlier in the same function has
already set fs->val.ethtype = 0x88a8, but the ethtype field is matched
against the inner header (which for real 802.1ad traffic is 0x8100 or
an L3 protocol, never 0x88a8).  Should the 802.1ad branch clear
fs->val.ethtype / fs->mask.ethtype the same way the 802.1Q branch
does?

>  		}
>  	}
>  
> diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
> index 695916ba0405..38c585f3b1ad 100644
> --- a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
> +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
> @@ -1921,6 +1921,9 @@
>  #define MAC_PORT_PTP_SUM_LO_A 0x990
>  #define MAC_PORT_PTP_SUM_HI_A 0x994
>  
> +#define MPS_PORT_RX_OVLAN0_A 0x120
> +#define MPS_PORT_RX_CTL_A    0X100

[Low]
This isn't a bug, but the hex prefix on 0X100 is uppercase while the
line above (and every neighboring macro) uses lowercase 0x.  Was that
intentional?

> +
>  #define MPS_CMN_CTL_A	0x9000
-- 
This is an AI-generated review.


^ permalink raw reply

* Re: [PATCH net-next V5 4/6] devlink: Apply eswitch mode boot defaults
From: Jiri Pirko @ 2026-07-09  9:46 UTC (permalink / raw)
  To: Mark Bloch
  Cc: Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
	Saeed Mahameed, Leon Romanovsky, Tariq Toukan, Andrew Lunn,
	Jonathan Corbet, Shuah Khan, netdev, linux-rdma, linux-doc
In-Reply-To: <e9445ff1-87b5-4111-8264-74016634d3bb@nvidia.com>

Thu, Jul 09, 2026 at 07:45:20AM +0200, mbloch@nvidia.com wrote:
>
>
>On 08/07/2026 11:59, Jiri Pirko wrote:
>> Tue, Jul 07, 2026 at 07:45:25PM +0200, mbloch@nvidia.com wrote:
>>> Apply parsed devlink_eswitch_mode= defaults after devlink registration
>>> and after successful reload.
>>>
>>> devl_register() may still be called before the device is ready for an
>>> eswitch mode change. Keep the registration path passive and let the
>>> regular devl_unlock() path queue the async apply work once the instance
>>> is registered and the default is still pending.
>>>
>>> The queueing path runs while the devlink instance lock is held, so the
>>> queued work gets its devlink reference before the caller drops the lock.
>>> The worker then takes the devlink instance lock normally and applies the
>>> default only if the instance is still registered and the default is still
>>> pending.
>> 
>> This is very code-descriptive. What's the benefit of that?
>
>The point is that there is still a window before the queued work
>runs where the user can explicitly set the eswitch mode. If they 
>do, the default will no longer be pending, so the worker will skip
>applying it.
>
>I'll reword.
>
>> 
>> 
>>>
>>> For successful reloads that performed DRIVER_REINIT, devlink_reload()
>>> already holds the devlink instance lock and the driver has completed
>>> reload_up(). Clear pending work and apply the default directly from the
>>> reload path instead of queueing work.
>>>
>>> Preserve the user configured mode when it is set before devlink applies
>>> the default.
>>>
>> 
>> [..]
>> 
>> 
>>> +void devlink_default_esw_mode_apply_locked(struct devlink *devlink)
>>> +{
>>> +	const struct devlink_ops *ops = devlink->ops;
>>> +	int err;
>>> +
>>> +	devl_assert_locked(devlink);
>>> +
>>> +	if (!devlink_default_esw_mode_match(devlink))
>>> +		return;
>>> +
>>> +	if (!ops->eswitch_mode_set) {
>>> +		if (!devlink_default_esw_mode_match_all)
>>> +			devl_warn(devlink,
>>> +				  "devlink_eswitch_mode= selected this device but eswitch mode setting is not supported\n");
>>> +		return;
>>> +	}
>>> +
>>> +	err = devlink_eswitch_mode_set(devlink, devlink_default_esw_mode, NULL);
>>> +	if (err)
>>> +		devl_warn(devlink,
>>> +			  "Couldn't apply default eswitch mode, err %d\n",
>>> +			  err);
>>> +}
>>> +
>>> +void devlink_default_esw_mode_queue_apply_work(struct devlink *devlink)
>> 
>> eswitch/esw - we call it "eswitch" consistently everywhere. Why "esw"
>> here?
>
>Ack
>
>> 
>> 
>> 
>>> +{
>>> +	devl_assert_locked(devlink);
>>> +
>>> +	if (!devlink_default_esw_mode_enabled || !devlink_default_esw_mode_wq)
>>> +		return;
>>> +	if (!devlink->default_esw_mode_apply_pending ||
>>> +	    !__devl_is_registered(devlink))
>>> +		return;
>>> +	if (!devlink_try_get(devlink))
>>> +		return;
>>> +	if (!queue_work(devlink_default_esw_mode_wq,
>>> +			&devlink->default_esw_mode_apply_work))
>>> +		devlink_put(devlink);
>>> +}
>>> +
>>> +static void devlink_default_esw_mode_apply_work(struct work_struct *work)
>>> +{
>>> +	struct devlink *devlink;
>>> +
>>> +	devlink = container_of(work, struct devlink,
>>> +			       default_esw_mode_apply_work);
>>> +
>> 
>> What happens if userspace eswitch mode set happens now? Any userspace
>> attempt should cancel the default apply. I don't see such mechanism in
>> your patches, did I miss it?
>
>devlink_nl_eswitch_set_doit() calls
>devlink_default_esw_mode_apply_pending_clear(), which clears the
>pending bit.
>
>So if a user sets the eswitch mode before the queued default
>work applies it, the worker will see that the default is no longer
>pending and will do nothing

Okay.


>
>> 
>> 
>> 
>>> +	devl_lock(devlink);
>>> +
>>> +	if (devl_is_registered(devlink) &&
>>> +	    devlink->default_esw_mode_apply_pending) {
>>> +		devlink_default_esw_mode_apply_locked(devlink);
>>> +		devlink->default_esw_mode_apply_pending = false;
>>> +	}
>>> +
>>> +	devl_unlock(devlink);
>>> +	devlink_put(devlink);
>>> +}
>>> +
>>> +void devlink_default_esw_mode_instance_init(struct devlink *devlink)
>> 
>> Why "_instance_"? Care to drop?
>
>Ack
>
>> 
>> 
>>> +{
>>> +	INIT_WORK(&devlink->default_esw_mode_apply_work,
>>> +		  devlink_default_esw_mode_apply_work);
>>> +	devlink->default_esw_mode_apply_pending = true;
>>> +}
>>> +
>>> +void devlink_default_esw_mode_apply_pending_clear(struct devlink *devlink)
>>> +{
>>> +	devl_assert_locked(devlink);
>>> +
>>> +	devlink->default_esw_mode_apply_pending = false;
>>> +}
>>> +
>>> +void devlink_default_esw_mode_instance_cleanup(struct devlink *devlink)
>> 
>> Why "_instance_"? Care to drop?
>
>Ack
>
>> 
>> 
>>> +{
>>> +	if (cancel_work_sync(&devlink->default_esw_mode_apply_work))
>>> +		devlink_put(devlink);
>>> +}
>>> +
>>> static int __init devlink_default_esw_mode_setup(char *str)
>>> {
>>> 	devlink_default_esw_mode_param = str;
>>> @@ -228,10 +325,21 @@ int __init devlink_default_esw_mode_init(void)
>>> 		return err;
>>> 	}
>>>
>>> +	devlink_default_esw_mode_wq = alloc_workqueue("devlink_default_esw_mode",
>>> +						      WQ_UNBOUND | WQ_MEM_RECLAIM,
>>> +						      0);
>>> +	if (!devlink_default_esw_mode_wq) {
>>> +		devlink_default_esw_mode_param = NULL;
>>> +		devlink_default_esw_mode_nodes_clear();
>>> +		pr_warn("devlink: devlink_eswitch_mode parameter ignored, failed to allocate workqueue\n");
>> 
>> Why you don't "return"  here? I think that we don't need to allow the
>> case wq is not allocated.
>
>The function returns right after this block. It is not treated

What I ment was "return error".


>as a valid “workqueue unavailable” mode, the parsed defaults are
>cleared, the parameter is ignored, and no default eswitch mode will
>be applied.
>
>I kept it as a non critical failure so we do not abort the whole
>devlink init just because the default-mode workqueue could not be
>allocated.

Why to treat it like this? Is there any other example of such flow in
devlink? I don't see the benefit, only potential confusion in very
unlikely case the alloc_workqueue fails. Am I wrong? If not, just bail
out here.



>
>That said, I can make this more explicit by returning 0 directly
>from this error path.
>
>Mark
>
>> 
>> 
>>> +	}
>>> +
>>> 	return 0;
>>> }
>>>
>>> void __init devlink_default_esw_mode_cleanup(void)
>>> {
>>> +	if (devlink_default_esw_mode_wq)
>>> +		destroy_workqueue(devlink_default_esw_mode_wq);
>>> 	devlink_default_esw_mode_nodes_clear();
>>> }
>> 
>> [..]
>

^ permalink raw reply

* Re: [PATCH RFC net-next 2/3] net: dsa: mxl862xx: add SMDIO clause-22 register access
From: Daniel Golle @ 2026-07-09  9:44 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Vladimir Oltean, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Simon Horman, linux-kernel, netdev
In-Reply-To: <98505e14-d684-4225-9415-f4d872113998@lunn.ch>

On Thu, Jul 09, 2026 at 01:15:34AM +0200, Andrew Lunn wrote:
> On Wed, Jul 08, 2026 at 09:45:48PM +0200, Daniel Golle wrote:
> > On Wed, Jul 08, 2026 at 07:22:49PM +0200, Andrew Lunn wrote:
> > > On Tue, Jul 07, 2026 at 04:16:07PM +0200, Daniel Golle wrote:
> > > > Add mxl862xx_smdio_read() and mxl862xx_smdio_write() for clause-22
> > > > SMDIO register access. MCUboot rescue mode only exposes clause-22
> > > > registers; the existing clause-45 MMD interface is unavailable during
> > > > firmware transfer. The MDIO bus lock is held per-transaction (not
> > > > across polls) so that SB PDI polling during flash erase does not
> > > > starve other MDIO users.
> > > 
> > > What other MDIO users are there? It sounds like once the switch is in
> > > rescue mode, switch management is dead. So how can there be users?
> > 
> > The MDIO bus lock refers to the host bus which is used to connect
> > the switch management interface. The same bus can also be used to
> > connect other unrelated PHYs (eg. to provide a WAN or management
> > interface independent of the switch).
> 
> Thanks for the explanation. Maybe 'does not starve other non-switch
> MDIO users'?
> 
> I've not got to the rest of the patch yet, but i wondered if phylib
> might still be trying to poll the switches PHYs.

The driver takes down the CPU ports and thereby implicitely also puts
all user-ports into admin-down state, effectively disabling PHY polling
until the switch comes back and reprobe has happened.

^ permalink raw reply

* Re: [PATCH RFC net-next 3/3] net: dsa: mxl862xx: add devlink flash_update and info_get
From: Daniel Golle @ 2026-07-09  9:43 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Vladimir Oltean, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Simon Horman, linux-kernel, netdev
In-Reply-To: <b3fc69ba-9139-4933-9a4f-455393a7cfaa@lunn.ch>

On Thu, Jul 09, 2026 at 01:24:49AM +0200, Andrew Lunn wrote:
> On Wed, Jul 08, 2026 at 10:02:39PM +0200, Daniel Golle wrote:
> > On Wed, Jul 08, 2026 at 07:27:21PM +0200, Andrew Lunn wrote:
> > > > + * The flash process takes approximately 15 minutes. Progress is
> > > > + * reported via devlink status notifications. After a successful (or
> > > > + * failed) flash the driver reprobes the device automatically.
> > > 
> > > Have you tested the failed use case?
> > > 
> > > I assume if the firmware in the flash is invalid, the bootloader does
> > > not boot it, and it remains in the bootloader waiting for another
> > > attempt. Does this DSA driver still load, so devlink can be used to
> > > try again?
> > 
> > No. Without a running the firmware the driver doesn't probe and only
> > a special rescue tool allows to recover the hardware.
> > Having the DSA driver detect the presence of the switch stuck in
> > mcuboot mode and probe without registering any user or CPU ports
> > also isn't straight forward.
> 
> And that special rescue tool exists?

Yes, but it's basically a custom bootable Linux image, based on a
patched/old Linux Kernel and vendor SDK driver.
It cannot just run from userspace because (apart from the out-of-tree
mdio-netlink API) there isn't any standard way to access the MDIO bus
from userspace.

> Why not wrap it in a script which unloads the DSA driver, let it do
> its thing, and then reload the DSA driver?

It would need to be yet another driver binding the device on the
MDIO bus, check if the mcuboot C22 MDIO interface responds and if not
fire the firmware API request to put reset the device into mcuboot mode.
And this, issueing a firmware API command, is why it is easier to make
it part of the existing DSA driver which already got a robust and
endian-safe implementation of the firmware API protocol.

> All the other users of devlink flash that i know of can operate while
> the device is still running. So it makes sense for it to be part of
> the driver, it is something just going on in the background. This
> device is different, so i don't really see the advantage of making it
> part of the driver.

The controlled teardown/reprobe/reconfigure as well as the ability to
issue the reboot-into-mcuboot firmware API command are good arguments
imho.

^ permalink raw reply

* Re: [PATCH v12 nf-next 1/7] bridge: Add filling forward path from port to port
From: Nikolay Aleksandrov @ 2026-07-09  9:41 UTC (permalink / raw)
  To: Eric Woudstra, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Simon Horman, Pablo Neira Ayuso,
	Florian Westphal, Phil Sutter, Ido Schimmel, Kuniyuki Iwashima,
	Stanislav Fomichev, Samiullah Khawaja, Hangbin Liu, Krishna Kumar,
	Martin Karsten
  Cc: netdev, netfilter-devel, bridge
In-Reply-To: <20260707091045.967678-2-ericwouds@gmail.com>

On 07/07/2026 12:10, Eric Woudstra wrote:
> If a port is passed as argument instead of the master, then:
> 
> At br_fill_forward_path(): find the master and use it to fill the
> forward path.
> 
> At br_vlan_fill_forward_path_pvid(): lookup vlan group from port
> instead.
> 
> Acked-by: Nikolay Aleksandrov <razor@blackwall.org>
> Signed-off-by: Eric Woudstra <ericwouds@gmail.com>
> ---
>   net/bridge/br_device.c  | 19 ++++++++++++++-----
>   net/bridge/br_private.h |  2 ++
>   net/bridge/br_vlan.c    |  6 +++++-
>   3 files changed, 21 insertions(+), 6 deletions(-)
> 

Just FYI please see my reply [1] to Pablo's email about this patch. I think
there might be a problem that needs to be fixed.

Cheers,
  Nik

[1] https://lore.kernel.org/netdev/b0774436-bc41-462f-820b-6a037b6082bb@blackwall.org/T/#mfbfb071107713d420bf26c060b1b980b270ab172



^ permalink raw reply

* RE: [PATCH iwl-next v1 6/6] ixgbe: take rtnl lock before ixgbe_reset() is called
From: Jagielski, Jedrzej @ 2026-07-09  9:38 UTC (permalink / raw)
  To: Simon Horman
  Cc: intel-wired-lan@lists.osuosl.org, Nguyen, Anthony L,
	netdev@vger.kernel.org
In-Reply-To: <20260708170235.1514479-1-horms@kernel.org>

From: Simon Horman <horms@kernel.org> 
Sent: Wednesday, July 8, 2026 7:03 PM

>This is an AI-generated review of your patch. The human sending this
>email has considered the AI review valid, or at least plausible.
>Full review at: https://sashiko.dev
>---
>ixgbe: take rtnl lock before ixgbe_reset() is called
>
>Previous commit introduced ixgbe_mac_addr_refresh which touches netdev
>struct by updating mac addr. It should operate after taking rtnl lock.
>One of the callers is ixgbe_reset(). Most of scenarios when ixgbe_reset()
>is called met taking lock requirement, but there is a ixgbe_resume() path
>which calls ixgbe_reset() -> ixgbe_mac_addr_refresh() without taking
>the lock. So there is a risk of race.
>
>Move rtnl_lock() before ixgbe_reset() is called.
>
>> diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
>> index eb05c2f982e8e..aa5a61f95d883 100644
>> --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
>> +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
>> @@ -7535,11 +7535,11 @@ static int ixgbe_resume(struct device *dev_d)
>>  
>>  	device_wakeup_disable(dev_d);
>>  
>> +	rtnl_lock();
>>  	ixgbe_reset(adapter);
>
>[Severity: High]
>This patch fixes the missing rtnl_lock() in ixgbe_resume(), but is this fix 
>incomplete? 

That;s the only missing path that really matters

>
>It looks like there are still other paths that call ixgbe_reset() without 
>acquiring rtnl_lock(), which would trigger the same race condition and 
>ASSERT_RTNL() warning on the MAC address update. 
>
>For example, the PCI error recovery handler calls it directly:
>
>ixgbe_io_slot_reset() {
>	...
>	ixgbe_reset(adapter);
>	...
>}
>
>And the service task can also call it without rtnl_lock():
>
>ixgbe_handle_fw_event() {
>	...
>	ixgbe_down(adapter); /* calls ixgbe_reset() */
>	...
>}

With un-attached netdev i believe there in rather no chance to race even
if mac addr refresh would be conducted during pci error recovery

>
>[Severity: High]
>This isn't a bug introduced by this patch, but does ixgbe_reset() also modify 
>the unicast address list without the required lock?
>
>ixgbe_reset() directly calls __dev_uc_unsync(netdev, NULL) which iterates 
>over and modifies the dev->uc address list. However, __dev_uc_unsync() is a 
>lockless helper that expects the caller to hold netif_addr_lock_bh(netdev). 
>
>Since the callers of ixgbe_reset() only hold rtnl_lock() (or no lock), 
>could this cause list corruption or use-after-free if the device resets 
>concurrently with unicast address modifications?
>
>[Severity: High]
>This is a pre-existing issue, but does ixgbe_reset() use an ad-hoc 
>synchronization mechanism instead of standard primitives?
>
>Inside ixgbe_reset():
>
>	/* lock SFP init bit to prevent race conditions with the watchdog */
>	while (test_and_set_bit(__IXGBE_IN_SFP_INIT, &adapter->state))
>		usleep_range(1000, 2000);
>
>Reimplementing a lock with test_and_set_bit() and usleep_range() lacks 
>deadlock detection (lockdep visibility), priority inheritance, and fairness. 
>
>Should this use a proper mutex or spinlock instead of spinning on a bit flag?
>
>>  
>>  	IXGBE_WRITE_REG(&adapter->hw, IXGBE_WUS, ~0);
>>  
>> -	rtnl_lock();
>>  	err = ixgbe_init_interrupt_scheme(adapter);


Both above notes relate to the already existing findings which i believe should
not block this series since it touches different side of the driver. Addresing
these notes would require service task refactor

^ permalink raw reply

* RE: [Intel-wired-lan] [PATCH iwl-next v1 5/6] ixgbe: E610: add MAC address runtime refresh
From: Jagielski, Jedrzej @ 2026-07-09  9:37 UTC (permalink / raw)
  To: Simon Horman
  Cc: intel-wired-lan@lists.osuosl.org, Nguyen, Anthony L,
	netdev@vger.kernel.org
In-Reply-To: <20260708170223.1514429-1-horms@kernel.org>

From: Simon Horman <horms@kernel.org> 
Sent: Wednesday, July 8, 2026 7:02 PM

>This is an AI-generated review of your patch. The human sending this
>email has considered the AI review valid, or at least plausible.
>Full review at: https://netdev-ai.bots.linux.dev/sashiko/
>---
>ixgbe: E610: add MAC address runtime refresh
>
>This change polls RAR0 each service-task cycle on E610 and updates
>netdev->dev_addr, hw->mac.addr and mac_table[0].addr when firmware has
>altered the MAC.  A refresh is also invoked from ixgbe_reset() so the
>address survives RAR0 clearing during init_hw().
>
>> diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
>> index df698ddd08be..eb05c2f982e8 100644
>> --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
>> +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
>> @@ -6464,6 +6464,36 @@ void ixgbe_disable_tx(struct ixgbe_adapter *adapter)
>>  	}
>>  }
>>
>> +static void ixgbe_mac_addr_refresh(struct ixgbe_adapter *adapter)
>> +{
>> +	struct net_device *netdev = adapter->netdev;
>> +	struct ixgbe_hw *hw = &adapter->hw;
>> +	int err;
>> +
>> +	if (hw->mac.type != ixgbe_mac_e610)
>> +		return;
>> +
>> +	/* fetch address stored currently in RAR0 in case the addr has been
>> +	 * altered by FW; if so, use it as the default one
>> +	 */
>> +	err = hw->mac.ops.get_mac_addr(hw, hw->mac.addr);
>> +	if (err) {
>> +		e_dev_warn("Cannot get MAC address\n");
>> +		return;
>> +	}
>
>[High]
>Can this overwrite hw->mac.addr with transient/garbage RAR0 contents
>before validation?  ixgbe_get_mac_addr_generic() unconditionally copies
>the raw IXGBE_RAH(0)/IXGBE_RAL(0) values into the buffer passed by the
>caller and always returns 0.  Here the caller passes hw->mac.addr
>itself as the destination:
>
>    err = hw->mac.ops.get_mac_addr(hw, hw->mac.addr);
>
>so any transient RAR0 value (all zeros while firmware is rewriting the
>register, garbage during the PCI slot-reset/resume window, a
>multicast/zero pattern in flight) silently clobbers hw->mac.addr.
>
>The is_valid_ether_addr() check below prevents publishing to netdev,
>but it does not restore the previous hw->mac.addr.

Looking this way mac.addr ca be treated as a sort of transient buf.
It is not propagated further without addr check, what was noticed in that
report.
Then if transient value would be really fetched from the drvice register,
it is instantly overwritten in next service task run with correct addr once
register is written with it

>
>Consider reading into a local u8 buf[ETH_ALEN], validating that, and
>only then copying into hw->mac.addr.
>
>Compounding that, ixgbe_get_mac_addr_generic()'s own comment states "A
>reset of the adapter must be performed prior to calling this function
>in order for the MAC address to have been loaded from the EEPROM into
>RAR0", but in ixgbe_reset() the refresh runs before init_hw().  Can
>this ordering yield a stale/invalid RAR0 read on the reset path?

This comment is not longer valid as previous families did not support
mac addr runtime change from the mgmt side. In such case content of the
register is established.

>
>The corruption is then observable: after the refresh returns,
>ixgbe_reset() proceeds through init_hw() and ixgbe_mac_set_default_filter()
>memcpy()s hw->mac.addr into mac_table[0].addr and programs it via
>set_rar() — a corrupted hw->mac.addr can therefore end up written to
>hardware.

It was already in the HW - that's where the mac addr is taken from.

>
>> +
>> +	if (ether_addr_equal(netdev->dev_addr, hw->mac.addr) ||
>> +	    !is_valid_ether_addr(hw->mac.addr))
>> +		return;
>> +
>> +	ASSERT_RTNL();
>> +
>> +	eth_hw_addr_set(netdev, hw->mac.addr);
>> +	ether_addr_copy(adapter->mac_table[0].addr, hw->mac.addr);
>> +
>> +	call_netdevice_notifiers(NETDEV_CHANGEADDR, netdev);
>> +}
>
>[Medium]
>Does this leave hw->mac.perm_addr, netdev->perm_addr and
>netdev->addr_assign_type inconsistent with the newly published
>address?  Every other MAC-handling site in ixgbe (probe,
>ixgbe_reset_hw_e610, and the equivalent flows on 82598/82599/X540/X550)
>writes RAR0 into hw->mac.perm_addr.  After firmware alters the MAC at
>runtime, perm_addr will keep reporting the pre-change value, so
>consumers such as ethtool -P, bonding and netlink perm-address
>attributes will report the stale address while NET_ADDR_PERM is still
>advertised for what is now effectively a runtime-assigned MAC.

IMHO perm_address should not be changed as the name states; it can be
still restored if needed
Even after mac addr change using some mgmt tool, the fabric mac addr
still stays the same

>
>[Medium]
>This unconditionally treats RAR0 (owned by firmware/MGMT) as
>authoritative and, on the next service-task tick, silently overwrites
>any MAC previously configured via "ip link set dev X address ...":
>
>    eth_hw_addr_set(netdev, hw->mac.addr);
>    ether_addr_copy(adapter->mac_table[0].addr, hw->mac.addr);
>    call_netdevice_notifiers(NETDEV_CHANGEADDR, netdev);
>
>No log line, no arbitration with an admin-set address, no opt-out.
>NETDEV_CHANGEADDR is also emitted from a polling context, which means
>userspace (udev, NetworkManager, bridging, bonding) can receive
>spontaneous address-change events on E610 with no correlating
>administrative action.  Should the commit message describe this uAPI
>behavior change ("ip link" no longer produces a persistent MAC on
>E610), and should there be some form of arbitration or logging when
>firmware overrides an admin-configured address?

mac addr assigned by the mgmt is indeed authoritative
arbitration in that case is not applicable 

>
>> +
>>  void ixgbe_reset(struct ixgbe_adapter *adapter)
>>  {
>>  	struct ixgbe_hw *hw = &adapter->hw;
>> @@ -6481,6 +6511,8 @@ void ixgbe_reset(struct ixgbe_adapter *adapter)
>>  			     IXGBE_FLAG2_SFP_NEEDS_RESET);
>>  	adapter->flags &= ~IXGBE_FLAG_NEED_LINK_CONFIG;
>>
>> +	ixgbe_mac_addr_refresh(adapter);
>> +
>
>[High]
>Is ixgbe_reset() always called with RTNL held?  ixgbe_mac_addr_refresh()
>uses ASSERT_RTNL() and then dispatches eth_hw_addr_set() and
>call_netdevice_notifiers(NETDEV_CHANGEADDR, netdev), both of which
>require RTNL.
>
>The follow-up commit "ixgbe: take rtnl lock before ixgbe_reset() is
>called" only converts the ixgbe_resume() path.  The PCI error-recovery
>callback ixgbe_io_slot_reset() still calls ixgbe_reset() without
>acquiring rtnl_lock(), and .slot_reset callbacks are not guaranteed to
>run under RTNL.

i believe ixgbe_resume() path covers all real scenarios
ixgbe_io_slot_reset() path is something purely theoretical imho 

>
>On that path, if RAR0 differs from netdev->dev_addr on an E610,
>ASSERT_RTNL() will WARN and the subsequent netdev address publication
>and notifier-chain traversal race with concurrent RTNL-protected
>users (SIOCSIFHWADDR, notifier chain (un)registration, etc).  Should
>ixgbe_io_slot_reset() also take rtnl_lock() around ixgbe_reset(), or
>should the refresh be moved to a caller-side location that guarantees
>RTNL?

i do not see such necessity; all race potential paths are coverd
despite the one which imho is possible to happen almost only
in theoretical thinking - netdev such be detached in that path so
any potentially racing second side should not be able to operate

>
>>  	err = hw->mac.ops.init_hw(hw);
>>  	switch (err) {
>>  	case 0:
>> @@ -8651,6 +8683,11 @@ static void ixgbe_service_task(struct work_struct *work)
>>  			ixgbe_handle_fw_event(adapter);
>>  		ixgbe_check_media_subtask(adapter);
>>  	}
>> +
>> +	rtnl_lock();
>> +	ixgbe_mac_addr_refresh(adapter);
>> +	rtnl_unlock();
>> +
>
>[Medium]
>Would it make sense to hoist the E610 gating out of
>ixgbe_mac_addr_refresh() and skip the rtnl_lock()/rtnl_unlock()
>entirely for non-E610 devices?
>
>The type check lives inside the helper:
>
>    static void ixgbe_mac_addr_refresh(struct ixgbe_adapter *adapter)
>    {
>        ...
>        if (hw->mac.type != ixgbe_mac_e610)
>            return;
>        ...
>    }
>
>so 82598, 82599, X540 and X550 adapters (which comprise most of the
>ixgbe device family) acquire the global rtnl_mutex every service-task
>cycle only to return immediately.  Something like:
>
>    if (adapter->hw.mac.type == ixgbe_mac_e610) {
>        rtnl_lock();
>        ixgbe_mac_addr_refresh(adapter);
>        rtnl_unlock();
>    }

Cannot introduce rtnl locking into ixgbe_mac_addr_refresh() as this
can be already called within rtnl-locked path

>
>would avoid the rtnl_mutex contention on non-E610 hardware.
>
>>  	ixgbe_reset_subtask(adapter);
>>  	ixgbe_phy_interrupt_subtask(adapter);
>>  	ixgbe_sfp_detection_subtask(adapter);

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox