* [PATCH rdma-next 00/13] RDMA: Make device names unique per net namespace
@ 2026-07-09 9:55 Jiri Pirko
2026-07-09 9:55 ` [PATCH rdma-next 01/13] RDMA/core: Pass the net namespace to the device name lookups Jiri Pirko
` (12 more replies)
0 siblings, 13 replies; 18+ messages in thread
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 [flat|nested] 18+ messages in thread
* [PATCH rdma-next 01/13] RDMA/core: Pass the net namespace to the device name lookups
2026-07-09 9:55 [PATCH rdma-next 00/13] RDMA: Make device names unique per net namespace Jiri Pirko
@ 2026-07-09 9:55 ` Jiri Pirko
2026-07-09 9:55 ` [PATCH rdma-next 02/13] RDMA/core: Handle device name conflicts when changing net namespace Jiri Pirko
` (11 subsequent siblings)
12 siblings, 0 replies; 18+ messages in thread
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>
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 [flat|nested] 18+ messages in thread
* [PATCH rdma-next 02/13] RDMA/core: Handle device name conflicts when changing net namespace
2026-07-09 9:55 [PATCH rdma-next 00/13] RDMA: Make device names unique per net namespace Jiri Pirko
2026-07-09 9:55 ` [PATCH rdma-next 01/13] RDMA/core: Pass the net namespace to the device name lookups Jiri Pirko
@ 2026-07-09 9:55 ` Jiri Pirko
2026-07-09 9:55 ` [PATCH rdma-next 03/13] RDMA/core: Support renaming a device when changing its " Jiri Pirko
` (10 subsequent siblings)
12 siblings, 0 replies; 18+ messages in thread
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>
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 [flat|nested] 18+ messages in thread
* [PATCH rdma-next 03/13] RDMA/core: Support renaming a device when changing its net namespace
2026-07-09 9:55 [PATCH rdma-next 00/13] RDMA: Make device names unique per net namespace Jiri Pirko
2026-07-09 9:55 ` [PATCH rdma-next 01/13] RDMA/core: Pass the net namespace to the device name lookups Jiri Pirko
2026-07-09 9:55 ` [PATCH rdma-next 02/13] RDMA/core: Handle device name conflicts when changing net namespace Jiri Pirko
@ 2026-07-09 9:55 ` Jiri Pirko
2026-07-09 9:55 ` [PATCH rdma-next 04/13] RDMA/nldev: Report net namespace move errors through extack Jiri Pirko
` (9 subsequent siblings)
12 siblings, 0 replies; 18+ messages in thread
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>
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 [flat|nested] 18+ messages in thread
* [PATCH rdma-next 04/13] RDMA/nldev: Report net namespace move errors through extack
2026-07-09 9:55 [PATCH rdma-next 00/13] RDMA: Make device names unique per net namespace Jiri Pirko
` (2 preceding siblings ...)
2026-07-09 9:55 ` [PATCH rdma-next 03/13] RDMA/core: Support renaming a device when changing its " Jiri Pirko
@ 2026-07-09 9:55 ` Jiri Pirko
2026-07-09 9:55 ` [PATCH rdma-next 05/13] RDMA/nldev: Allow setting the device name while changing net namespace Jiri Pirko
` (8 subsequent siblings)
12 siblings, 0 replies; 18+ messages in thread
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>
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 [flat|nested] 18+ messages in thread
* [PATCH rdma-next 05/13] RDMA/nldev: Allow setting the device name while changing net namespace
2026-07-09 9:55 [PATCH rdma-next 00/13] RDMA: Make device names unique per net namespace Jiri Pirko
` (3 preceding siblings ...)
2026-07-09 9:55 ` [PATCH rdma-next 04/13] RDMA/nldev: Report net namespace move errors through extack Jiri Pirko
@ 2026-07-09 9:55 ` Jiri Pirko
2026-07-09 9:55 ` [PATCH rdma-next 06/13] net/smc: Look up the pnetid ib device within the " Jiri Pirko
` (7 subsequent siblings)
12 siblings, 0 replies; 18+ messages in thread
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>
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 [flat|nested] 18+ messages in thread
* [PATCH rdma-next 06/13] net/smc: Look up the pnetid ib device within the net namespace
2026-07-09 9:55 [PATCH rdma-next 00/13] RDMA: Make device names unique per net namespace Jiri Pirko
` (4 preceding siblings ...)
2026-07-09 9:55 ` [PATCH rdma-next 05/13] RDMA/nldev: Allow setting the device name while changing net namespace Jiri Pirko
@ 2026-07-09 9:55 ` Jiri Pirko
2026-07-09 9:55 ` [PATCH rdma-next 07/13] RDMA/srp: Make the SRP sysfs class net namespace aware Jiri Pirko
` (6 subsequent siblings)
12 siblings, 0 replies; 18+ messages in thread
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>
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 [flat|nested] 18+ messages in thread
* [PATCH rdma-next 07/13] RDMA/srp: Make the SRP sysfs class net namespace aware
2026-07-09 9:55 [PATCH rdma-next 00/13] RDMA: Make device names unique per net namespace Jiri Pirko
` (5 preceding siblings ...)
2026-07-09 9:55 ` [PATCH rdma-next 06/13] net/smc: Look up the pnetid ib device within the " Jiri Pirko
@ 2026-07-09 9:55 ` Jiri Pirko
2026-07-09 9:55 ` [PATCH rdma-next 08/13] RDMA/cgroup: Scope rdma cgroup device visibility to the net namespace Jiri Pirko
` (5 subsequent siblings)
12 siblings, 0 replies; 18+ messages in thread
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>
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 [flat|nested] 18+ messages in thread
* [PATCH rdma-next 08/13] RDMA/cgroup: Scope rdma cgroup device visibility to the net namespace
2026-07-09 9:55 [PATCH rdma-next 00/13] RDMA: Make device names unique per net namespace Jiri Pirko
` (6 preceding siblings ...)
2026-07-09 9:55 ` [PATCH rdma-next 07/13] RDMA/srp: Make the SRP sysfs class net namespace aware Jiri Pirko
@ 2026-07-09 9:55 ` Jiri Pirko
2026-07-09 13:04 ` Michal Koutný
2026-07-09 9:55 ` [PATCH rdma-next 09/13] RDMA/cma: Document that CM configfs cannot be net namespace scoped Jiri Pirko
` (4 subsequent siblings)
12 siblings, 1 reply; 18+ messages in thread
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>
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 [flat|nested] 18+ messages in thread
* [PATCH rdma-next 09/13] RDMA/cma: Document that CM configfs cannot be net namespace scoped
2026-07-09 9:55 [PATCH rdma-next 00/13] RDMA: Make device names unique per net namespace Jiri Pirko
` (7 preceding siblings ...)
2026-07-09 9:55 ` [PATCH rdma-next 08/13] RDMA/cgroup: Scope rdma cgroup device visibility to the net namespace Jiri Pirko
@ 2026-07-09 9:55 ` Jiri Pirko
2026-07-09 9:55 ` [PATCH rdma-next 10/13] RDMA/core: Document the SELinux ibendport net namespace limitation Jiri Pirko
` (3 subsequent siblings)
12 siblings, 0 replies; 18+ messages in thread
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>
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 [flat|nested] 18+ messages in thread
* [PATCH rdma-next 10/13] RDMA/core: Document the SELinux ibendport net namespace limitation
2026-07-09 9:55 [PATCH rdma-next 00/13] RDMA: Make device names unique per net namespace Jiri Pirko
` (8 preceding siblings ...)
2026-07-09 9:55 ` [PATCH rdma-next 09/13] RDMA/cma: Document that CM configfs cannot be net namespace scoped Jiri Pirko
@ 2026-07-09 9:55 ` Jiri Pirko
2026-07-09 9:55 ` [PATCH rdma-next 11/13] RDMA/core: Make device names unique per net namespace Jiri Pirko
` (2 subsequent siblings)
12 siblings, 0 replies; 18+ messages in thread
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>
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 [flat|nested] 18+ messages in thread
* [PATCH rdma-next 11/13] RDMA/core: Make device names unique per net namespace
2026-07-09 9:55 [PATCH rdma-next 00/13] RDMA: Make device names unique per net namespace Jiri Pirko
` (9 preceding siblings ...)
2026-07-09 9:55 ` [PATCH rdma-next 10/13] RDMA/core: Document the SELinux ibendport net namespace limitation Jiri Pirko
@ 2026-07-09 9:55 ` Jiri Pirko
2026-07-09 9:55 ` [PATCH rdma-next 12/13] RDMA/rxe: Implement disassociate_ucontext callback Jiri Pirko
2026-07-09 9:55 ` [PATCH rdma-next 13/13] RDMA/selftests: Add rxe_netns_names test Jiri Pirko
12 siblings, 0 replies; 18+ messages in thread
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>
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 [flat|nested] 18+ messages in thread
* [PATCH rdma-next 12/13] RDMA/rxe: Implement disassociate_ucontext callback
2026-07-09 9:55 [PATCH rdma-next 00/13] RDMA: Make device names unique per net namespace Jiri Pirko
` (10 preceding siblings ...)
2026-07-09 9:55 ` [PATCH rdma-next 11/13] RDMA/core: Make device names unique per net namespace Jiri Pirko
@ 2026-07-09 9:55 ` Jiri Pirko
2026-07-10 4:21 ` Zhu Yanjun
2026-07-09 9:55 ` [PATCH rdma-next 13/13] RDMA/selftests: Add rxe_netns_names test Jiri Pirko
12 siblings, 1 reply; 18+ messages in thread
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>
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 [flat|nested] 18+ messages in thread
* [PATCH rdma-next 13/13] RDMA/selftests: Add rxe_netns_names test
2026-07-09 9:55 [PATCH rdma-next 00/13] RDMA: Make device names unique per net namespace Jiri Pirko
` (11 preceding siblings ...)
2026-07-09 9:55 ` [PATCH rdma-next 12/13] RDMA/rxe: Implement disassociate_ucontext callback Jiri Pirko
@ 2026-07-09 9:55 ` Jiri Pirko
2026-07-10 4:24 ` Zhu Yanjun
2026-07-10 23:51 ` yanjun.zhu
12 siblings, 2 replies; 18+ messages in thread
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>
Add a kselftest script that exercises per-netns RDMA device naming
with RXE. Cover duplicate names across namespaces, move conflict
handling, move-with-rename, and same-namespace rename requests.
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
tools/testing/selftests/rdma/Makefile | 3 +-
tools/testing/selftests/rdma/config | 2 +
.../testing/selftests/rdma/rxe_netns_names.sh | 282 ++++++++++++++++++
3 files changed, 286 insertions(+), 1 deletion(-)
create mode 100755 tools/testing/selftests/rdma/rxe_netns_names.sh
diff --git a/tools/testing/selftests/rdma/Makefile b/tools/testing/selftests/rdma/Makefile
index 07af7f15c1bf..a91c14c45006 100644
--- a/tools/testing/selftests/rdma/Makefile
+++ b/tools/testing/selftests/rdma/Makefile
@@ -3,6 +3,7 @@ TEST_PROGS := rxe_rping_between_netns.sh \
rxe_ipv6.sh \
rxe_socket_with_netns.sh \
rxe_test_NETDEV_UNREGISTER.sh \
- rxe_sent_rcvd_bytes.sh
+ rxe_sent_rcvd_bytes.sh \
+ rxe_netns_names.sh
include ../lib.mk
diff --git a/tools/testing/selftests/rdma/config b/tools/testing/selftests/rdma/config
index 4ffb814e253b..e1ff54ec0f57 100644
--- a/tools/testing/selftests/rdma/config
+++ b/tools/testing/selftests/rdma/config
@@ -1,3 +1,5 @@
CONFIG_TUN
CONFIG_VETH
+CONFIG_DUMMY
+CONFIG_NET_NS
CONFIG_RDMA_RXE
diff --git a/tools/testing/selftests/rdma/rxe_netns_names.sh b/tools/testing/selftests/rdma/rxe_netns_names.sh
new file mode 100755
index 000000000000..a7e57706fdff
--- /dev/null
+++ b/tools/testing/selftests/rdma/rxe_netns_names.sh
@@ -0,0 +1,282 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# Exercise RDMA device name handling across network namespaces.
+
+source "$(dirname "$0")/../kselftest/ktap_helpers.sh"
+
+NAME_PREFIX="rxe_netns_names_$$"
+NETDEV_PREFIX="rxn$$"
+NS1="${NAME_PREFIX}ns1"
+NS2="${NAME_PREFIX}ns2"
+RXE_A="${NAME_PREFIX}rxe_a"
+RXE_B="${NAME_PREFIX}rxe_b"
+RXE_SAME="${NAME_PREFIX}rxe_same"
+RXE_NEW="${NAME_PREFIX}rxe_new"
+DUMMY_A="${NETDEV_PREFIX}a"
+DUMMY_B="${NETDEV_PREFIX}b"
+OLD_MODE=""
+MODE_CHANGED=0
+MODS=("dummy" "rdma_rxe")
+TEST_SAME_NAMES="same RDMA device name can exist in two net namespaces"
+TEST_MOVE_CONFLICT="move without rename fails on destination name conflict"
+TEST_MOVE_RENAME="move then rename succeeds"
+TEST_COMBINED_MOVE_RENAME="move with requested destination name succeeds"
+TEST_SAME_NETNS_DUP_RENAME="same-netns rename rejects duplicate name"
+TEST_TEARDOWN_RETURN="netns delete returns device to init_net and renames on conflict"
+
+ksft_skip()
+{
+ ktap_skip_all "$*"
+ exit "$KSFT_SKIP"
+}
+
+fail()
+{
+ ktap_exit_fail_msg "$*"
+}
+
+need_cmd()
+{
+ command -v "$1" >/dev/null 2>&1 || ksft_skip "missing command: $1"
+}
+
+rdma_ns()
+{
+ local ns=$1
+
+ shift
+ ip netns exec "$ns" rdma "$@"
+}
+
+rdma_dev_exists()
+{
+ local ns=$1
+ local dev=$2
+
+ if [ -n "$ns" ]; then
+ rdma_ns "$ns" dev show "$dev" >/dev/null 2>&1
+ else
+ rdma dev show "$dev" >/dev/null 2>&1
+ fi
+}
+
+add_dummy()
+{
+ local netdev=$1
+
+ ip link add "$netdev" type dummy || return 1
+ ip link set "$netdev" up || return 1
+}
+
+add_rxe()
+{
+ local dev=$1
+ local netdev=$2
+
+ rdma link add "$dev" type rxe netdev "$netdev"
+}
+
+rdma_dev_on_netdev()
+{
+ local netdev=$1
+
+ rdma link show 2>/dev/null | awk -v want="$netdev" '
+ {
+ for (i = 1; i < NF; i++)
+ if ($i == "netdev" && $(i + 1) == want) {
+ dev = $2
+ sub(/\/.*/, "", dev)
+ print dev
+ exit
+ }
+ }'
+}
+
+wait_rdma_dev_on_netdev()
+{
+ local netdev=$1
+ local dev
+ local i
+
+ for i in $(seq 1 50); do
+ dev=$(rdma_dev_on_netdev "$netdev")
+ if [ -n "$dev" ]; then
+ echo "$dev"
+ return 0
+ fi
+ sleep 0.1
+ done
+
+ return 1
+}
+
+setup_devs()
+{
+ cleanup_devs
+
+ add_dummy "$DUMMY_A" || return 1
+ add_dummy "$DUMMY_B" || return 1
+
+ add_rxe "$RXE_A" "$DUMMY_A" || return 1
+ add_rxe "$RXE_B" "$DUMMY_B" || return 1
+}
+
+cleanup_devs()
+{
+ ip link del "$DUMMY_A" 2>/dev/null
+ ip link del "$DUMMY_B" 2>/dev/null
+}
+
+setup()
+{
+ OLD_MODE=$(rdma system show 2>/dev/null |
+ sed -n 's/.*netns \([^ ]*\).*/\1/p')
+ [ -n "$OLD_MODE" ] || ksft_skip "failed to read RDMA netns mode"
+
+ rdma system set netns exclusive >/dev/null 2>&1 ||
+ ksft_skip "rdma netns exclusive mode is not supported"
+ MODE_CHANGED=1
+
+ ip netns add "$NS1" || return 1
+ ip netns add "$NS2" || return 1
+}
+
+cleanup()
+{
+ cleanup_devs
+
+ ip netns del "$NS1" 2>/dev/null
+ ip netns del "$NS2" 2>/dev/null
+
+ if [ "$MODE_CHANGED" -eq 1 ]; then
+ rdma system set netns "$OLD_MODE" 2>/dev/null
+ fi
+
+ for m in "${MODS[@]}"; do
+ modprobe -r "$m" 2>/dev/null
+ done
+}
+
+rdma_supports_combined_move_rename()
+{
+ rdma dev help 2>&1 | grep -Eq 'netns .*name|name .*netns'
+}
+
+[ "$(id -u)" -eq 0 ] || ksft_skip "must be run as root"
+need_cmd ip
+need_cmd rdma
+need_cmd modprobe
+
+trap cleanup EXIT
+
+for m in "${MODS[@]}"; do
+ modinfo "$m" >/dev/null 2>&1 || ksft_skip "module $m not found"
+ modprobe "$m" || fail "failed to load $m"
+done
+
+setup || fail "failed to create net namespaces"
+
+ktap_print_header
+ktap_set_plan 7
+
+if setup_devs &&
+ rdma dev set "$RXE_A" netns "$NS1" &&
+ rdma_ns "$NS1" dev set "$RXE_A" name "$RXE_SAME" &&
+ rdma dev set "$RXE_B" netns "$NS2" &&
+ rdma_ns "$NS2" dev set "$RXE_B" name "$RXE_SAME" &&
+ rdma_dev_exists "$NS1" "$RXE_SAME" &&
+ rdma_dev_exists "$NS2" "$RXE_SAME"; then
+ ktap_test_pass "$TEST_SAME_NAMES"
+else
+ ktap_test_fail "$TEST_SAME_NAMES"
+fi
+cleanup_devs
+
+if ! setup_devs ||
+ ! rdma dev set "$RXE_A" netns "$NS1" ||
+ ! rdma_ns "$NS1" dev set "$RXE_A" name "$RXE_SAME" ||
+ ! rdma dev set "$RXE_B" netns "$NS2" ||
+ ! rdma_ns "$NS2" dev set "$RXE_B" name "$RXE_SAME"; then
+ ktap_test_fail "$TEST_MOVE_CONFLICT"
+elif rdma_ns "$NS1" dev set "$RXE_SAME" netns "$NS2" >/dev/null 2>&1; then
+ ktap_test_fail "$TEST_MOVE_CONFLICT"
+elif rdma_dev_exists "$NS1" "$RXE_SAME" &&
+ rdma_dev_exists "$NS2" "$RXE_SAME"; then
+ ktap_test_pass "$TEST_MOVE_CONFLICT"
+else
+ ktap_test_fail "$TEST_MOVE_CONFLICT"
+fi
+cleanup_devs
+
+if ! setup_devs; then
+ ktap_test_fail "$TEST_MOVE_RENAME"
+elif rdma dev set "$RXE_A" netns "$NS2" &&
+ rdma_ns "$NS2" dev set "$RXE_A" name "$RXE_NEW"; then
+ if rdma_dev_exists "$NS2" "$RXE_NEW" &&
+ ! rdma_dev_exists "" "$RXE_A"; then
+ ktap_test_pass "$TEST_MOVE_RENAME"
+ else
+ ktap_test_fail "$TEST_MOVE_RENAME"
+ fi
+else
+ ktap_test_fail "$TEST_MOVE_RENAME"
+fi
+cleanup_devs
+
+if ! rdma_supports_combined_move_rename; then
+ ktap_test_skip "$TEST_COMBINED_MOVE_RENAME"
+elif ! setup_devs; then
+ ktap_test_fail "$TEST_COMBINED_MOVE_RENAME"
+elif rdma dev set "$RXE_A" netns "$NS2" name "$RXE_NEW"; then
+ if rdma_dev_exists "$NS2" "$RXE_NEW" &&
+ ! rdma_dev_exists "" "$RXE_A"; then
+ ktap_test_pass "$TEST_COMBINED_MOVE_RENAME"
+ else
+ ktap_test_fail "$TEST_COMBINED_MOVE_RENAME"
+ fi
+else
+ ktap_test_fail "$TEST_COMBINED_MOVE_RENAME"
+fi
+cleanup_devs
+
+if ! setup_devs; then
+ ktap_test_fail "$TEST_SAME_NETNS_DUP_RENAME"
+elif rdma dev set "$RXE_A" name "$RXE_SAME" &&
+ rdma dev set "$RXE_B" name "$RXE_NEW"; then
+ if rdma dev set "$RXE_A" name "$RXE_NEW" >/dev/null 2>&1; then
+ ktap_test_fail "$TEST_SAME_NETNS_DUP_RENAME"
+ elif rdma_dev_exists "" "$RXE_SAME" &&
+ rdma_dev_exists "" "$RXE_NEW"; then
+ ktap_test_pass "$TEST_SAME_NETNS_DUP_RENAME"
+ else
+ ktap_test_fail "$TEST_SAME_NETNS_DUP_RENAME"
+ fi
+else
+ ktap_test_fail "$TEST_SAME_NETNS_DUP_RENAME"
+fi
+cleanup_devs
+
+if ! setup_devs; then
+ ktap_test_fail "$TEST_TEARDOWN_RETURN"
+elif ! rdma dev set "$RXE_A" name "$RXE_SAME" ||
+ ! rdma dev set "$RXE_B" netns "$NS2" ||
+ ! rdma_ns "$NS2" dev set "$RXE_B" name "$RXE_SAME" ||
+ ! rdma_dev_exists "$NS2" "$RXE_SAME"; then
+ ktap_test_fail "$TEST_TEARDOWN_RETURN"
+else
+ ip netns del "$NS2"
+ returned=$(wait_rdma_dev_on_netdev "$DUMMY_B")
+ ktap_print_msg "device returned to init_net as '${returned:-<missing>}'"
+ if rdma_dev_exists "" "$RXE_SAME" &&
+ [ -n "$returned" ] &&
+ [ "$returned" != "$RXE_SAME" ] &&
+ [ "${returned#ibdev}" != "$returned" ]; then
+ ktap_test_pass "$TEST_TEARDOWN_RETURN"
+ else
+ ktap_test_fail "$TEST_TEARDOWN_RETURN"
+ fi
+fi
+cleanup_devs
+
+ktap_finished
--
2.54.0
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH rdma-next 08/13] RDMA/cgroup: Scope rdma cgroup device visibility to the net namespace
2026-07-09 9:55 ` [PATCH rdma-next 08/13] RDMA/cgroup: Scope rdma cgroup device visibility to the net namespace Jiri Pirko
@ 2026-07-09 13:04 ` Michal Koutný
0 siblings, 0 replies; 18+ messages in thread
From: Michal Koutný @ 2026-07-09 13:04 UTC (permalink / raw)
To: Jiri Pirko
Cc: linux-rdma, cgroups, netdev, linux-s390, linux-kselftest, jgg,
leon, parav, mbloch, cmeiohas, roman.gushchin, bvanassche,
zyjzyj2000, shuah, tj, hannes, alibuda, dust.li, sidraya, wenjia
[-- Attachment #1: Type: text/plain, Size: 1734 bytes --]
Hi.
On Thu, Jul 09, 2026 at 11:55:27AM +0200, Jiri Pirko <jiri@resnulli.us> wrote:
> 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.
OK.
> --- 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;
Any reason to store the netns_shared split per device? (IIUC, it's a
global parameter.)
Thanks,
Michal
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 265 bytes --]
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH rdma-next 12/13] RDMA/rxe: Implement disassociate_ucontext callback
2026-07-09 9:55 ` [PATCH rdma-next 12/13] RDMA/rxe: Implement disassociate_ucontext callback Jiri Pirko
@ 2026-07-10 4:21 ` Zhu Yanjun
0 siblings, 0 replies; 18+ messages in thread
From: Zhu Yanjun @ 2026-07-10 4:21 UTC (permalink / raw)
To: Jiri Pirko, linux-rdma, yanjun.zhu@linux.dev
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
在 2026/7/9 2:55, Jiri Pirko 写道:
> 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.
The logic here is correct for enabling netns migration. Since RXE's
user-mapped
queues rely on reference-counted vmalloc memory, this empty stub is safe
enough
to prevent kernel panics or Use-After-Free (UAF) during device movement.
However, as a note for future improvement: keeping this callback
entirely empty
means userspace won't be immediately notified (via SIGBUS or page table
zapping)
when the underlying device is moved out of its netns. For now, this
serves well as
a functional enabler, but we might want to introduce proper PTE
tearing/zap_vma_ptes()
down the road if applications require strict, immediate disconnection
semantics.
Thanks Jiri.
Reviewed-by: Yanjun Zhu <yanjun.zhu@linux.dev>
Zhu Yanjun
> 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,
--
Best Regards,
Yanjun.Zhu
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH rdma-next 13/13] RDMA/selftests: Add rxe_netns_names test
2026-07-09 9:55 ` [PATCH rdma-next 13/13] RDMA/selftests: Add rxe_netns_names test Jiri Pirko
@ 2026-07-10 4:24 ` Zhu Yanjun
2026-07-10 23:51 ` yanjun.zhu
1 sibling, 0 replies; 18+ messages in thread
From: Zhu Yanjun @ 2026-07-10 4:24 UTC (permalink / raw)
To: Jiri Pirko, linux-rdma, yanjun.zhu@linux.dev
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
在 2026/7/9 2:55, Jiri Pirko 写道:
> From: Jiri Pirko <jiri@nvidia.com>
>
> Add a kselftest script that exercises per-netns RDMA device naming
> with RXE. Cover duplicate names across namespaces, move conflict
> handling, move-with-rename, and same-namespace rename requests.
This is a very comprehensive test suite for the per-netns RDMA device
naming infra.
I especially appreciate the inclusion of the 'TEST_TEARDOWN_RETURN'
case—ensuring
that the kernel's automatic renaming and fallback mechanics work
seamlessly during
netns deletion is crucial for long-term stability.
One minor thing to clean up before pushing to the tree: the script
declares 'ktap_set_plan 7'
but actually defines 6 distinct test cases in the execution block. I
will fix this plan count to 6
to avoid any "bad plan" warnings in automated CI frameworks (like KernelCI).
Aside from that, the cleanup paths and setup tracking are solid.
Thanks for adding this.
Reviewed-by: Zhu Yanjun <yanjun.zhu@linux.dev>
Zhu Yanjun
>
> Signed-off-by: Jiri Pirko <jiri@nvidia.com>
> ---
> tools/testing/selftests/rdma/Makefile | 3 +-
> tools/testing/selftests/rdma/config | 2 +
> .../testing/selftests/rdma/rxe_netns_names.sh | 282 ++++++++++++++++++
> 3 files changed, 286 insertions(+), 1 deletion(-)
> create mode 100755 tools/testing/selftests/rdma/rxe_netns_names.sh
>
> diff --git a/tools/testing/selftests/rdma/Makefile b/tools/testing/selftests/rdma/Makefile
> index 07af7f15c1bf..a91c14c45006 100644
> --- a/tools/testing/selftests/rdma/Makefile
> +++ b/tools/testing/selftests/rdma/Makefile
> @@ -3,6 +3,7 @@ TEST_PROGS := rxe_rping_between_netns.sh \
> rxe_ipv6.sh \
> rxe_socket_with_netns.sh \
> rxe_test_NETDEV_UNREGISTER.sh \
> - rxe_sent_rcvd_bytes.sh
> + rxe_sent_rcvd_bytes.sh \
> + rxe_netns_names.sh
>
> include ../lib.mk
> diff --git a/tools/testing/selftests/rdma/config b/tools/testing/selftests/rdma/config
> index 4ffb814e253b..e1ff54ec0f57 100644
> --- a/tools/testing/selftests/rdma/config
> +++ b/tools/testing/selftests/rdma/config
> @@ -1,3 +1,5 @@
> CONFIG_TUN
> CONFIG_VETH
> +CONFIG_DUMMY
> +CONFIG_NET_NS
> CONFIG_RDMA_RXE
> diff --git a/tools/testing/selftests/rdma/rxe_netns_names.sh b/tools/testing/selftests/rdma/rxe_netns_names.sh
> new file mode 100755
> index 000000000000..a7e57706fdff
> --- /dev/null
> +++ b/tools/testing/selftests/rdma/rxe_netns_names.sh
> @@ -0,0 +1,282 @@
> +#!/bin/bash
> +# SPDX-License-Identifier: GPL-2.0
> +#
> +# Exercise RDMA device name handling across network namespaces.
> +
> +source "$(dirname "$0")/../kselftest/ktap_helpers.sh"
> +
> +NAME_PREFIX="rxe_netns_names_$$"
> +NETDEV_PREFIX="rxn$$"
> +NS1="${NAME_PREFIX}ns1"
> +NS2="${NAME_PREFIX}ns2"
> +RXE_A="${NAME_PREFIX}rxe_a"
> +RXE_B="${NAME_PREFIX}rxe_b"
> +RXE_SAME="${NAME_PREFIX}rxe_same"
> +RXE_NEW="${NAME_PREFIX}rxe_new"
> +DUMMY_A="${NETDEV_PREFIX}a"
> +DUMMY_B="${NETDEV_PREFIX}b"
> +OLD_MODE=""
> +MODE_CHANGED=0
> +MODS=("dummy" "rdma_rxe")
> +TEST_SAME_NAMES="same RDMA device name can exist in two net namespaces"
> +TEST_MOVE_CONFLICT="move without rename fails on destination name conflict"
> +TEST_MOVE_RENAME="move then rename succeeds"
> +TEST_COMBINED_MOVE_RENAME="move with requested destination name succeeds"
> +TEST_SAME_NETNS_DUP_RENAME="same-netns rename rejects duplicate name"
> +TEST_TEARDOWN_RETURN="netns delete returns device to init_net and renames on conflict"
> +
> +ksft_skip()
> +{
> + ktap_skip_all "$*"
> + exit "$KSFT_SKIP"
> +}
> +
> +fail()
> +{
> + ktap_exit_fail_msg "$*"
> +}
> +
> +need_cmd()
> +{
> + command -v "$1" >/dev/null 2>&1 || ksft_skip "missing command: $1"
> +}
> +
> +rdma_ns()
> +{
> + local ns=$1
> +
> + shift
> + ip netns exec "$ns" rdma "$@"
> +}
> +
> +rdma_dev_exists()
> +{
> + local ns=$1
> + local dev=$2
> +
> + if [ -n "$ns" ]; then
> + rdma_ns "$ns" dev show "$dev" >/dev/null 2>&1
> + else
> + rdma dev show "$dev" >/dev/null 2>&1
> + fi
> +}
> +
> +add_dummy()
> +{
> + local netdev=$1
> +
> + ip link add "$netdev" type dummy || return 1
> + ip link set "$netdev" up || return 1
> +}
> +
> +add_rxe()
> +{
> + local dev=$1
> + local netdev=$2
> +
> + rdma link add "$dev" type rxe netdev "$netdev"
> +}
> +
> +rdma_dev_on_netdev()
> +{
> + local netdev=$1
> +
> + rdma link show 2>/dev/null | awk -v want="$netdev" '
> + {
> + for (i = 1; i < NF; i++)
> + if ($i == "netdev" && $(i + 1) == want) {
> + dev = $2
> + sub(/\/.*/, "", dev)
> + print dev
> + exit
> + }
> + }'
> +}
> +
> +wait_rdma_dev_on_netdev()
> +{
> + local netdev=$1
> + local dev
> + local i
> +
> + for i in $(seq 1 50); do
> + dev=$(rdma_dev_on_netdev "$netdev")
> + if [ -n "$dev" ]; then
> + echo "$dev"
> + return 0
> + fi
> + sleep 0.1
> + done
> +
> + return 1
> +}
> +
> +setup_devs()
> +{
> + cleanup_devs
> +
> + add_dummy "$DUMMY_A" || return 1
> + add_dummy "$DUMMY_B" || return 1
> +
> + add_rxe "$RXE_A" "$DUMMY_A" || return 1
> + add_rxe "$RXE_B" "$DUMMY_B" || return 1
> +}
> +
> +cleanup_devs()
> +{
> + ip link del "$DUMMY_A" 2>/dev/null
> + ip link del "$DUMMY_B" 2>/dev/null
> +}
> +
> +setup()
> +{
> + OLD_MODE=$(rdma system show 2>/dev/null |
> + sed -n 's/.*netns \([^ ]*\).*/\1/p')
> + [ -n "$OLD_MODE" ] || ksft_skip "failed to read RDMA netns mode"
> +
> + rdma system set netns exclusive >/dev/null 2>&1 ||
> + ksft_skip "rdma netns exclusive mode is not supported"
> + MODE_CHANGED=1
> +
> + ip netns add "$NS1" || return 1
> + ip netns add "$NS2" || return 1
> +}
> +
> +cleanup()
> +{
> + cleanup_devs
> +
> + ip netns del "$NS1" 2>/dev/null
> + ip netns del "$NS2" 2>/dev/null
> +
> + if [ "$MODE_CHANGED" -eq 1 ]; then
> + rdma system set netns "$OLD_MODE" 2>/dev/null
> + fi
> +
> + for m in "${MODS[@]}"; do
> + modprobe -r "$m" 2>/dev/null
> + done
> +}
> +
> +rdma_supports_combined_move_rename()
> +{
> + rdma dev help 2>&1 | grep -Eq 'netns .*name|name .*netns'
> +}
> +
> +[ "$(id -u)" -eq 0 ] || ksft_skip "must be run as root"
> +need_cmd ip
> +need_cmd rdma
> +need_cmd modprobe
> +
> +trap cleanup EXIT
> +
> +for m in "${MODS[@]}"; do
> + modinfo "$m" >/dev/null 2>&1 || ksft_skip "module $m not found"
> + modprobe "$m" || fail "failed to load $m"
> +done
> +
> +setup || fail "failed to create net namespaces"
> +
> +ktap_print_header
> +ktap_set_plan 7
> +
> +if setup_devs &&
> + rdma dev set "$RXE_A" netns "$NS1" &&
> + rdma_ns "$NS1" dev set "$RXE_A" name "$RXE_SAME" &&
> + rdma dev set "$RXE_B" netns "$NS2" &&
> + rdma_ns "$NS2" dev set "$RXE_B" name "$RXE_SAME" &&
> + rdma_dev_exists "$NS1" "$RXE_SAME" &&
> + rdma_dev_exists "$NS2" "$RXE_SAME"; then
> + ktap_test_pass "$TEST_SAME_NAMES"
> +else
> + ktap_test_fail "$TEST_SAME_NAMES"
> +fi
> +cleanup_devs
> +
> +if ! setup_devs ||
> + ! rdma dev set "$RXE_A" netns "$NS1" ||
> + ! rdma_ns "$NS1" dev set "$RXE_A" name "$RXE_SAME" ||
> + ! rdma dev set "$RXE_B" netns "$NS2" ||
> + ! rdma_ns "$NS2" dev set "$RXE_B" name "$RXE_SAME"; then
> + ktap_test_fail "$TEST_MOVE_CONFLICT"
> +elif rdma_ns "$NS1" dev set "$RXE_SAME" netns "$NS2" >/dev/null 2>&1; then
> + ktap_test_fail "$TEST_MOVE_CONFLICT"
> +elif rdma_dev_exists "$NS1" "$RXE_SAME" &&
> + rdma_dev_exists "$NS2" "$RXE_SAME"; then
> + ktap_test_pass "$TEST_MOVE_CONFLICT"
> +else
> + ktap_test_fail "$TEST_MOVE_CONFLICT"
> +fi
> +cleanup_devs
> +
> +if ! setup_devs; then
> + ktap_test_fail "$TEST_MOVE_RENAME"
> +elif rdma dev set "$RXE_A" netns "$NS2" &&
> + rdma_ns "$NS2" dev set "$RXE_A" name "$RXE_NEW"; then
> + if rdma_dev_exists "$NS2" "$RXE_NEW" &&
> + ! rdma_dev_exists "" "$RXE_A"; then
> + ktap_test_pass "$TEST_MOVE_RENAME"
> + else
> + ktap_test_fail "$TEST_MOVE_RENAME"
> + fi
> +else
> + ktap_test_fail "$TEST_MOVE_RENAME"
> +fi
> +cleanup_devs
> +
> +if ! rdma_supports_combined_move_rename; then
> + ktap_test_skip "$TEST_COMBINED_MOVE_RENAME"
> +elif ! setup_devs; then
> + ktap_test_fail "$TEST_COMBINED_MOVE_RENAME"
> +elif rdma dev set "$RXE_A" netns "$NS2" name "$RXE_NEW"; then
> + if rdma_dev_exists "$NS2" "$RXE_NEW" &&
> + ! rdma_dev_exists "" "$RXE_A"; then
> + ktap_test_pass "$TEST_COMBINED_MOVE_RENAME"
> + else
> + ktap_test_fail "$TEST_COMBINED_MOVE_RENAME"
> + fi
> +else
> + ktap_test_fail "$TEST_COMBINED_MOVE_RENAME"
> +fi
> +cleanup_devs
> +
> +if ! setup_devs; then
> + ktap_test_fail "$TEST_SAME_NETNS_DUP_RENAME"
> +elif rdma dev set "$RXE_A" name "$RXE_SAME" &&
> + rdma dev set "$RXE_B" name "$RXE_NEW"; then
> + if rdma dev set "$RXE_A" name "$RXE_NEW" >/dev/null 2>&1; then
> + ktap_test_fail "$TEST_SAME_NETNS_DUP_RENAME"
> + elif rdma_dev_exists "" "$RXE_SAME" &&
> + rdma_dev_exists "" "$RXE_NEW"; then
> + ktap_test_pass "$TEST_SAME_NETNS_DUP_RENAME"
> + else
> + ktap_test_fail "$TEST_SAME_NETNS_DUP_RENAME"
> + fi
> +else
> + ktap_test_fail "$TEST_SAME_NETNS_DUP_RENAME"
> +fi
> +cleanup_devs
> +
> +if ! setup_devs; then
> + ktap_test_fail "$TEST_TEARDOWN_RETURN"
> +elif ! rdma dev set "$RXE_A" name "$RXE_SAME" ||
> + ! rdma dev set "$RXE_B" netns "$NS2" ||
> + ! rdma_ns "$NS2" dev set "$RXE_B" name "$RXE_SAME" ||
> + ! rdma_dev_exists "$NS2" "$RXE_SAME"; then
> + ktap_test_fail "$TEST_TEARDOWN_RETURN"
> +else
> + ip netns del "$NS2"
> + returned=$(wait_rdma_dev_on_netdev "$DUMMY_B")
> + ktap_print_msg "device returned to init_net as '${returned:-<missing>}'"
> + if rdma_dev_exists "" "$RXE_SAME" &&
> + [ -n "$returned" ] &&
> + [ "$returned" != "$RXE_SAME" ] &&
> + [ "${returned#ibdev}" != "$returned" ]; then
> + ktap_test_pass "$TEST_TEARDOWN_RETURN"
> + else
> + ktap_test_fail "$TEST_TEARDOWN_RETURN"
> + fi
> +fi
> +cleanup_devs
> +
> +ktap_finished
--
Best Regards,
Yanjun.Zhu
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH rdma-next 13/13] RDMA/selftests: Add rxe_netns_names test
2026-07-09 9:55 ` [PATCH rdma-next 13/13] RDMA/selftests: Add rxe_netns_names test Jiri Pirko
2026-07-10 4:24 ` Zhu Yanjun
@ 2026-07-10 23:51 ` yanjun.zhu
1 sibling, 0 replies; 18+ messages in thread
From: yanjun.zhu @ 2026-07-10 23:51 UTC (permalink / raw)
To: Jiri Pirko, linux-rdma, Zhu Yanjun
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
On 7/9/26 2:55 AM, Jiri Pirko wrote:
> From: Jiri Pirko <jiri@nvidia.com>
>
> Add a kselftest script that exercises per-netns RDMA device naming
> with RXE. Cover duplicate names across namespaces, move conflict
> handling, move-with-rename, and same-namespace rename requests.
# timeout set to 45
# selftests: rdma: rxe_netns_names.sh
# TAP version 13
# 1..6
# ok 1 same RDMA device name can exist in two net namespaces
# ok 2 move without rename fails on destination name conflict
# ok 3 move then rename succeeds
# ok 4 move with requested destination name succeeds # SKIP < ---
This testcase skip
# ok 5 same-netns rename rejects duplicate name
# # device returned to init_net as 'ibdev35'
# ok 6 netns delete returns device to init_net and renames on conflict
# # 1 skipped test(s) detected. Consider enabling relevant config
options to improve coverage.
# # Totals: pass:5 fail:0 xfail:0 xpass:0 skip:1 error:0
ok 6 selftests: rdma: rxe_netns_names.sh
The above are my test results. But one testcase is skipped.
Zhu Yanjun
>
> Signed-off-by: Jiri Pirko <jiri@nvidia.com>
> ---
> tools/testing/selftests/rdma/Makefile | 3 +-
> tools/testing/selftests/rdma/config | 2 +
> .../testing/selftests/rdma/rxe_netns_names.sh | 282 ++++++++++++++++++
> 3 files changed, 286 insertions(+), 1 deletion(-)
> create mode 100755 tools/testing/selftests/rdma/rxe_netns_names.sh
>
> diff --git a/tools/testing/selftests/rdma/Makefile b/tools/testing/selftests/rdma/Makefile
> index 07af7f15c1bf..a91c14c45006 100644
> --- a/tools/testing/selftests/rdma/Makefile
> +++ b/tools/testing/selftests/rdma/Makefile
> @@ -3,6 +3,7 @@ TEST_PROGS := rxe_rping_between_netns.sh \
> rxe_ipv6.sh \
> rxe_socket_with_netns.sh \
> rxe_test_NETDEV_UNREGISTER.sh \
> - rxe_sent_rcvd_bytes.sh
> + rxe_sent_rcvd_bytes.sh \
> + rxe_netns_names.sh
>
> include ../lib.mk
> diff --git a/tools/testing/selftests/rdma/config b/tools/testing/selftests/rdma/config
> index 4ffb814e253b..e1ff54ec0f57 100644
> --- a/tools/testing/selftests/rdma/config
> +++ b/tools/testing/selftests/rdma/config
> @@ -1,3 +1,5 @@
> CONFIG_TUN
> CONFIG_VETH
> +CONFIG_DUMMY
> +CONFIG_NET_NS
> CONFIG_RDMA_RXE
> diff --git a/tools/testing/selftests/rdma/rxe_netns_names.sh b/tools/testing/selftests/rdma/rxe_netns_names.sh
> new file mode 100755
> index 000000000000..a7e57706fdff
> --- /dev/null
> +++ b/tools/testing/selftests/rdma/rxe_netns_names.sh
> @@ -0,0 +1,282 @@
> +#!/bin/bash
> +# SPDX-License-Identifier: GPL-2.0
> +#
> +# Exercise RDMA device name handling across network namespaces.
> +
> +source "$(dirname "$0")/../kselftest/ktap_helpers.sh"
> +
> +NAME_PREFIX="rxe_netns_names_$$"
> +NETDEV_PREFIX="rxn$$"
> +NS1="${NAME_PREFIX}ns1"
> +NS2="${NAME_PREFIX}ns2"
> +RXE_A="${NAME_PREFIX}rxe_a"
> +RXE_B="${NAME_PREFIX}rxe_b"
> +RXE_SAME="${NAME_PREFIX}rxe_same"
> +RXE_NEW="${NAME_PREFIX}rxe_new"
> +DUMMY_A="${NETDEV_PREFIX}a"
> +DUMMY_B="${NETDEV_PREFIX}b"
> +OLD_MODE=""
> +MODE_CHANGED=0
> +MODS=("dummy" "rdma_rxe")
> +TEST_SAME_NAMES="same RDMA device name can exist in two net namespaces"
> +TEST_MOVE_CONFLICT="move without rename fails on destination name conflict"
> +TEST_MOVE_RENAME="move then rename succeeds"
> +TEST_COMBINED_MOVE_RENAME="move with requested destination name succeeds"
> +TEST_SAME_NETNS_DUP_RENAME="same-netns rename rejects duplicate name"
> +TEST_TEARDOWN_RETURN="netns delete returns device to init_net and renames on conflict"
> +
> +ksft_skip()
> +{
> + ktap_skip_all "$*"
> + exit "$KSFT_SKIP"
> +}
> +
> +fail()
> +{
> + ktap_exit_fail_msg "$*"
> +}
> +
> +need_cmd()
> +{
> + command -v "$1" >/dev/null 2>&1 || ksft_skip "missing command: $1"
> +}
> +
> +rdma_ns()
> +{
> + local ns=$1
> +
> + shift
> + ip netns exec "$ns" rdma "$@"
> +}
> +
> +rdma_dev_exists()
> +{
> + local ns=$1
> + local dev=$2
> +
> + if [ -n "$ns" ]; then
> + rdma_ns "$ns" dev show "$dev" >/dev/null 2>&1
> + else
> + rdma dev show "$dev" >/dev/null 2>&1
> + fi
> +}
> +
> +add_dummy()
> +{
> + local netdev=$1
> +
> + ip link add "$netdev" type dummy || return 1
> + ip link set "$netdev" up || return 1
> +}
> +
> +add_rxe()
> +{
> + local dev=$1
> + local netdev=$2
> +
> + rdma link add "$dev" type rxe netdev "$netdev"
> +}
> +
> +rdma_dev_on_netdev()
> +{
> + local netdev=$1
> +
> + rdma link show 2>/dev/null | awk -v want="$netdev" '
> + {
> + for (i = 1; i < NF; i++)
> + if ($i == "netdev" && $(i + 1) == want) {
> + dev = $2
> + sub(/\/.*/, "", dev)
> + print dev
> + exit
> + }
> + }'
> +}
> +
> +wait_rdma_dev_on_netdev()
> +{
> + local netdev=$1
> + local dev
> + local i
> +
> + for i in $(seq 1 50); do
> + dev=$(rdma_dev_on_netdev "$netdev")
> + if [ -n "$dev" ]; then
> + echo "$dev"
> + return 0
> + fi
> + sleep 0.1
> + done
> +
> + return 1
> +}
> +
> +setup_devs()
> +{
> + cleanup_devs
> +
> + add_dummy "$DUMMY_A" || return 1
> + add_dummy "$DUMMY_B" || return 1
> +
> + add_rxe "$RXE_A" "$DUMMY_A" || return 1
> + add_rxe "$RXE_B" "$DUMMY_B" || return 1
> +}
> +
> +cleanup_devs()
> +{
> + ip link del "$DUMMY_A" 2>/dev/null
> + ip link del "$DUMMY_B" 2>/dev/null
> +}
> +
> +setup()
> +{
> + OLD_MODE=$(rdma system show 2>/dev/null |
> + sed -n 's/.*netns \([^ ]*\).*/\1/p')
> + [ -n "$OLD_MODE" ] || ksft_skip "failed to read RDMA netns mode"
> +
> + rdma system set netns exclusive >/dev/null 2>&1 ||
> + ksft_skip "rdma netns exclusive mode is not supported"
> + MODE_CHANGED=1
> +
> + ip netns add "$NS1" || return 1
> + ip netns add "$NS2" || return 1
> +}
> +
> +cleanup()
> +{
> + cleanup_devs
> +
> + ip netns del "$NS1" 2>/dev/null
> + ip netns del "$NS2" 2>/dev/null
> +
> + if [ "$MODE_CHANGED" -eq 1 ]; then
> + rdma system set netns "$OLD_MODE" 2>/dev/null
> + fi
> +
> + for m in "${MODS[@]}"; do
> + modprobe -r "$m" 2>/dev/null
> + done
> +}
> +
> +rdma_supports_combined_move_rename()
> +{
> + rdma dev help 2>&1 | grep -Eq 'netns .*name|name .*netns'
> +}
> +
> +[ "$(id -u)" -eq 0 ] || ksft_skip "must be run as root"
> +need_cmd ip
> +need_cmd rdma
> +need_cmd modprobe
> +
> +trap cleanup EXIT
> +
> +for m in "${MODS[@]}"; do
> + modinfo "$m" >/dev/null 2>&1 || ksft_skip "module $m not found"
> + modprobe "$m" || fail "failed to load $m"
> +done
> +
> +setup || fail "failed to create net namespaces"
> +
> +ktap_print_header
> +ktap_set_plan 7
> +
> +if setup_devs &&
> + rdma dev set "$RXE_A" netns "$NS1" &&
> + rdma_ns "$NS1" dev set "$RXE_A" name "$RXE_SAME" &&
> + rdma dev set "$RXE_B" netns "$NS2" &&
> + rdma_ns "$NS2" dev set "$RXE_B" name "$RXE_SAME" &&
> + rdma_dev_exists "$NS1" "$RXE_SAME" &&
> + rdma_dev_exists "$NS2" "$RXE_SAME"; then
> + ktap_test_pass "$TEST_SAME_NAMES"
> +else
> + ktap_test_fail "$TEST_SAME_NAMES"
> +fi
> +cleanup_devs
> +
> +if ! setup_devs ||
> + ! rdma dev set "$RXE_A" netns "$NS1" ||
> + ! rdma_ns "$NS1" dev set "$RXE_A" name "$RXE_SAME" ||
> + ! rdma dev set "$RXE_B" netns "$NS2" ||
> + ! rdma_ns "$NS2" dev set "$RXE_B" name "$RXE_SAME"; then
> + ktap_test_fail "$TEST_MOVE_CONFLICT"
> +elif rdma_ns "$NS1" dev set "$RXE_SAME" netns "$NS2" >/dev/null 2>&1; then
> + ktap_test_fail "$TEST_MOVE_CONFLICT"
> +elif rdma_dev_exists "$NS1" "$RXE_SAME" &&
> + rdma_dev_exists "$NS2" "$RXE_SAME"; then
> + ktap_test_pass "$TEST_MOVE_CONFLICT"
> +else
> + ktap_test_fail "$TEST_MOVE_CONFLICT"
> +fi
> +cleanup_devs
> +
> +if ! setup_devs; then
> + ktap_test_fail "$TEST_MOVE_RENAME"
> +elif rdma dev set "$RXE_A" netns "$NS2" &&
> + rdma_ns "$NS2" dev set "$RXE_A" name "$RXE_NEW"; then
> + if rdma_dev_exists "$NS2" "$RXE_NEW" &&
> + ! rdma_dev_exists "" "$RXE_A"; then
> + ktap_test_pass "$TEST_MOVE_RENAME"
> + else
> + ktap_test_fail "$TEST_MOVE_RENAME"
> + fi
> +else
> + ktap_test_fail "$TEST_MOVE_RENAME"
> +fi
> +cleanup_devs
> +
> +if ! rdma_supports_combined_move_rename; then
> + ktap_test_skip "$TEST_COMBINED_MOVE_RENAME"
> +elif ! setup_devs; then
> + ktap_test_fail "$TEST_COMBINED_MOVE_RENAME"
> +elif rdma dev set "$RXE_A" netns "$NS2" name "$RXE_NEW"; then
> + if rdma_dev_exists "$NS2" "$RXE_NEW" &&
> + ! rdma_dev_exists "" "$RXE_A"; then
> + ktap_test_pass "$TEST_COMBINED_MOVE_RENAME"
> + else
> + ktap_test_fail "$TEST_COMBINED_MOVE_RENAME"
> + fi
> +else
> + ktap_test_fail "$TEST_COMBINED_MOVE_RENAME"
> +fi
> +cleanup_devs
> +
> +if ! setup_devs; then
> + ktap_test_fail "$TEST_SAME_NETNS_DUP_RENAME"
> +elif rdma dev set "$RXE_A" name "$RXE_SAME" &&
> + rdma dev set "$RXE_B" name "$RXE_NEW"; then
> + if rdma dev set "$RXE_A" name "$RXE_NEW" >/dev/null 2>&1; then
> + ktap_test_fail "$TEST_SAME_NETNS_DUP_RENAME"
> + elif rdma_dev_exists "" "$RXE_SAME" &&
> + rdma_dev_exists "" "$RXE_NEW"; then
> + ktap_test_pass "$TEST_SAME_NETNS_DUP_RENAME"
> + else
> + ktap_test_fail "$TEST_SAME_NETNS_DUP_RENAME"
> + fi
> +else
> + ktap_test_fail "$TEST_SAME_NETNS_DUP_RENAME"
> +fi
> +cleanup_devs
> +
> +if ! setup_devs; then
> + ktap_test_fail "$TEST_TEARDOWN_RETURN"
> +elif ! rdma dev set "$RXE_A" name "$RXE_SAME" ||
> + ! rdma dev set "$RXE_B" netns "$NS2" ||
> + ! rdma_ns "$NS2" dev set "$RXE_B" name "$RXE_SAME" ||
> + ! rdma_dev_exists "$NS2" "$RXE_SAME"; then
> + ktap_test_fail "$TEST_TEARDOWN_RETURN"
> +else
> + ip netns del "$NS2"
> + returned=$(wait_rdma_dev_on_netdev "$DUMMY_B")
> + ktap_print_msg "device returned to init_net as '${returned:-<missing>}'"
> + if rdma_dev_exists "" "$RXE_SAME" &&
> + [ -n "$returned" ] &&
> + [ "$returned" != "$RXE_SAME" ] &&
> + [ "${returned#ibdev}" != "$returned" ]; then
> + ktap_test_pass "$TEST_TEARDOWN_RETURN"
> + else
> + ktap_test_fail "$TEST_TEARDOWN_RETURN"
> + fi
> +fi
> +cleanup_devs
> +
> +ktap_finished
^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2026-07-10 23:52 UTC | newest]
Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-09 9:55 [PATCH rdma-next 00/13] RDMA: Make device names unique per net namespace Jiri Pirko
2026-07-09 9:55 ` [PATCH rdma-next 01/13] RDMA/core: Pass the net namespace to the device name lookups Jiri Pirko
2026-07-09 9:55 ` [PATCH rdma-next 02/13] RDMA/core: Handle device name conflicts when changing net namespace Jiri Pirko
2026-07-09 9:55 ` [PATCH rdma-next 03/13] RDMA/core: Support renaming a device when changing its " Jiri Pirko
2026-07-09 9:55 ` [PATCH rdma-next 04/13] RDMA/nldev: Report net namespace move errors through extack Jiri Pirko
2026-07-09 9:55 ` [PATCH rdma-next 05/13] RDMA/nldev: Allow setting the device name while changing net namespace Jiri Pirko
2026-07-09 9:55 ` [PATCH rdma-next 06/13] net/smc: Look up the pnetid ib device within the " Jiri Pirko
2026-07-09 9:55 ` [PATCH rdma-next 07/13] RDMA/srp: Make the SRP sysfs class net namespace aware Jiri Pirko
2026-07-09 9:55 ` [PATCH rdma-next 08/13] RDMA/cgroup: Scope rdma cgroup device visibility to the net namespace Jiri Pirko
2026-07-09 13:04 ` Michal Koutný
2026-07-09 9:55 ` [PATCH rdma-next 09/13] RDMA/cma: Document that CM configfs cannot be net namespace scoped Jiri Pirko
2026-07-09 9:55 ` [PATCH rdma-next 10/13] RDMA/core: Document the SELinux ibendport net namespace limitation Jiri Pirko
2026-07-09 9:55 ` [PATCH rdma-next 11/13] RDMA/core: Make device names unique per net namespace Jiri Pirko
2026-07-09 9:55 ` [PATCH rdma-next 12/13] RDMA/rxe: Implement disassociate_ucontext callback Jiri Pirko
2026-07-10 4:21 ` Zhu Yanjun
2026-07-09 9:55 ` [PATCH rdma-next 13/13] RDMA/selftests: Add rxe_netns_names test Jiri Pirko
2026-07-10 4:24 ` Zhu Yanjun
2026-07-10 23:51 ` yanjun.zhu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox