* [PATCH v6 0/4] RDMA/rxe: Add the support that rxe can work in net namespace
@ 2026-03-11 6:29 Zhu Yanjun
2026-03-11 6:29 ` [PATCH v6 1/4] RDMA/nldev: Add dellink function pointer Zhu Yanjun
` (3 more replies)
0 siblings, 4 replies; 6+ messages in thread
From: Zhu Yanjun @ 2026-03-11 6:29 UTC (permalink / raw)
To: jgg, leon, zyjzyj2000, yanjun.zhu, dsahern, linux-rdma,
linux-kselftest
Currently rxe does not work correctly in network namespaces.
When the rdma_rxe module is loaded, a UDP socket listening on port
4791 is created in init_net. When users run:
ip link add ... type rxe
inside another network namespace, the RXE RDMA link is created but it
cannot function properly because the underlying UDP socket belongs to
init_net. Other network namespaces cannot use that socket.
To address this issue, this series introduces net namespace support
for rxe and moves socket management to be per network namespace.
The series first introduces per-net namespace management for the IPv4
and IPv6 sockets used by rxe. The sockets are created when the network
namespace becomes active and are released when the namespace is
destroyed.
Based on this infrastructure, rxe RDMA links are then created and
destroyed within each network namespace. This ensures that both the
UDP sockets and RDMA links are correctly scoped to the namespace in
which they are used.
With these changes, rxe RDMA links can be created and used both in
init_net and in other network namespaces, and resources are properly
cleaned up during namespace teardown.
The series also includes a selftest to verify RXE functionality in
network namespaces.
"
# make -C tools/testing/selftests/ TARGETS=rdma run_tests
make: Entering directory 'tools/testing/selftests'
make[1]: Nothing to be done for 'all'.
TAP version 13
1..4
# timeout set to 45
# selftests: rdma: rxe_rping_between_netns.sh
# client DISCONNECT EVENT...
ok 1 selftests: rdma: rxe_rping_between_netns.sh
# timeout set to 45
# selftests: rdma: rxe_ipv6.sh
ok 2 selftests: rdma: rxe_ipv6.sh
# timeout set to 45
# selftests: rdma: rxe_socket_with_netns.sh
ok 3 selftests: rdma: rxe_socket_with_netns.sh
# timeout set to 45
# selftests: rdma: rxe_test_NETDEV_UNREGISTER.sh
ok 4 selftests: rdma: rxe_test_NETDEV_UNREGISTER.sh
make: Leaving directory 'tools/testing/selftests'
"
V5 -> V6: Fix some problems based on Leon's advice
V4 -> V5: Fix rcu warnings
V3 -> V4: Squash all the changes about rxe_ns.c/h into one commit.
V2 -> V3: Fix build warnings
V1 -> V2: Fix the problems based on David Ahern.
Zhu Yanjun (4):
RDMA/nldev: Add dellink function pointer
RDMA/rxe: Add net namespace support for IPv4/IPv6 sockets
RDMA/rxe: Support RDMA link creation and destruction per net namespace
RDMA/rxe: Add testcase for net namespace rxe
MAINTAINERS | 1 +
drivers/infiniband/core/nldev.c | 6 +
drivers/infiniband/sw/rxe/Makefile | 3 +-
drivers/infiniband/sw/rxe/rxe.c | 38 ++++-
drivers/infiniband/sw/rxe/rxe_net.c | 144 +++++++++++++-----
drivers/infiniband/sw/rxe/rxe_net.h | 9 +-
drivers/infiniband/sw/rxe/rxe_ns.c | 124 +++++++++++++++
drivers/infiniband/sw/rxe/rxe_ns.h | 26 ++++
include/rdma/rdma_netlink.h | 2 +
tools/testing/selftests/Makefile | 1 +
tools/testing/selftests/rdma/Makefile | 7 +
tools/testing/selftests/rdma/config | 3 +
tools/testing/selftests/rdma/rxe_ipv6.sh | 63 ++++++++
.../selftests/rdma/rxe_rping_between_netns.sh | 85 +++++++++++
.../selftests/rdma/rxe_socket_with_netns.sh | 76 +++++++++
.../rdma/rxe_test_NETDEV_UNREGISTER.sh | 63 ++++++++
16 files changed, 604 insertions(+), 47 deletions(-)
create mode 100644 drivers/infiniband/sw/rxe/rxe_ns.c
create mode 100644 drivers/infiniband/sw/rxe/rxe_ns.h
create mode 100644 tools/testing/selftests/rdma/Makefile
create mode 100644 tools/testing/selftests/rdma/config
create mode 100755 tools/testing/selftests/rdma/rxe_ipv6.sh
create mode 100755 tools/testing/selftests/rdma/rxe_rping_between_netns.sh
create mode 100755 tools/testing/selftests/rdma/rxe_socket_with_netns.sh
create mode 100755 tools/testing/selftests/rdma/rxe_test_NETDEV_UNREGISTER.sh
--
2.52.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v6 1/4] RDMA/nldev: Add dellink function pointer
2026-03-11 6:29 [PATCH v6 0/4] RDMA/rxe: Add the support that rxe can work in net namespace Zhu Yanjun
@ 2026-03-11 6:29 ` Zhu Yanjun
2026-03-11 6:29 ` [PATCH v6 2/4] RDMA/rxe: Add net namespace support for IPv4/IPv6 sockets Zhu Yanjun
` (2 subsequent siblings)
3 siblings, 0 replies; 6+ messages in thread
From: Zhu Yanjun @ 2026-03-11 6:29 UTC (permalink / raw)
To: jgg, leon, zyjzyj2000, yanjun.zhu, dsahern, linux-rdma,
linux-kselftest
The newlink function pointer is added. And the sock listening on port 4791
is added in the newlink function. So the dellink function is needed to
remove the sock.
Reviewed-by: David Ahern <dsahern@kernel.org>
Signed-off-by: Zhu Yanjun <yanjun.zhu@linux.dev>
---
drivers/infiniband/core/nldev.c | 6 ++++++
include/rdma/rdma_netlink.h | 2 ++
2 files changed, 8 insertions(+)
diff --git a/drivers/infiniband/core/nldev.c b/drivers/infiniband/core/nldev.c
index 2220a2dfab24..cdd55db8d399 100644
--- a/drivers/infiniband/core/nldev.c
+++ b/drivers/infiniband/core/nldev.c
@@ -1824,6 +1824,12 @@ static int nldev_dellink(struct sk_buff *skb, struct nlmsghdr *nlh,
return -EINVAL;
}
+ if ((device->ops.driver_id == RDMA_DRIVER_RXE) && device->link_ops) {
+ err = device->link_ops->dellink(device);
+ if (err)
+ return err;
+ }
+
ib_unregister_device_and_put(device);
return 0;
}
diff --git a/include/rdma/rdma_netlink.h b/include/rdma/rdma_netlink.h
index 326deaf56d5d..2fd1358ea57d 100644
--- a/include/rdma/rdma_netlink.h
+++ b/include/rdma/rdma_netlink.h
@@ -5,6 +5,7 @@
#include <linux/netlink.h>
#include <uapi/rdma/rdma_netlink.h>
+#include <rdma/ib_verbs.h>
struct ib_device;
@@ -126,6 +127,7 @@ struct rdma_link_ops {
struct list_head list;
const char *type;
int (*newlink)(const char *ibdev_name, struct net_device *ndev);
+ int (*dellink)(struct ib_device *dev);
};
void rdma_link_register(struct rdma_link_ops *ops);
--
2.52.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v6 2/4] RDMA/rxe: Add net namespace support for IPv4/IPv6 sockets
2026-03-11 6:29 [PATCH v6 0/4] RDMA/rxe: Add the support that rxe can work in net namespace Zhu Yanjun
2026-03-11 6:29 ` [PATCH v6 1/4] RDMA/nldev: Add dellink function pointer Zhu Yanjun
@ 2026-03-11 6:29 ` Zhu Yanjun
2026-03-11 6:29 ` [PATCH v6 3/4] RDMA/rxe: Support RDMA link creation and destruction per net namespace Zhu Yanjun
2026-03-11 6:29 ` [PATCH v6 4/4] RDMA/rxe: Add testcase for net namespace rxe Zhu Yanjun
3 siblings, 0 replies; 6+ messages in thread
From: Zhu Yanjun @ 2026-03-11 6:29 UTC (permalink / raw)
To: jgg, leon, zyjzyj2000, yanjun.zhu, dsahern, linux-rdma,
linux-kselftest
Add a net namespace implementation file to rxe to manage the
lifecycle of IPv4 and IPv6 sockets per network namespace.
This implementation handles the creation and destruction of the
sockets both for init_net and for dynamically created network
namespaces. The sockets are initialized when a namespace becomes
active and are properly released when the namespace is removed.
This change provides the infrastructure needed for rxe to operate
correctly in environments using multiple network namespaces.
Reviewed-by: David Ahern <dsahern@kernel.org>
Signed-off-by: Zhu Yanjun <yanjun.zhu@linux.dev>
---
drivers/infiniband/sw/rxe/Makefile | 3 +-
drivers/infiniband/sw/rxe/rxe_ns.c | 124 +++++++++++++++++++++++++++++
drivers/infiniband/sw/rxe/rxe_ns.h | 26 ++++++
3 files changed, 152 insertions(+), 1 deletion(-)
create mode 100644 drivers/infiniband/sw/rxe/rxe_ns.c
create mode 100644 drivers/infiniband/sw/rxe/rxe_ns.h
diff --git a/drivers/infiniband/sw/rxe/Makefile b/drivers/infiniband/sw/rxe/Makefile
index 93134f1d1d0c..3977f4f13258 100644
--- a/drivers/infiniband/sw/rxe/Makefile
+++ b/drivers/infiniband/sw/rxe/Makefile
@@ -22,6 +22,7 @@ rdma_rxe-y := \
rxe_mcast.o \
rxe_task.o \
rxe_net.o \
- rxe_hw_counters.o
+ rxe_hw_counters.o \
+ rxe_ns.o
rdma_rxe-$(CONFIG_INFINIBAND_ON_DEMAND_PAGING) += rxe_odp.o
diff --git a/drivers/infiniband/sw/rxe/rxe_ns.c b/drivers/infiniband/sw/rxe/rxe_ns.c
new file mode 100644
index 000000000000..8b9d734229b2
--- /dev/null
+++ b/drivers/infiniband/sw/rxe/rxe_ns.c
@@ -0,0 +1,124 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
+
+#include <net/sock.h>
+#include <net/netns/generic.h>
+#include <net/net_namespace.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/pid_namespace.h>
+#include <net/udp_tunnel.h>
+
+#include "rxe_ns.h"
+
+/*
+ * Per network namespace data
+ */
+struct rxe_ns_sock {
+ struct sock __rcu *rxe_sk4;
+ struct sock __rcu *rxe_sk6;
+};
+
+/*
+ * Index to store custom data for each network namespace.
+ */
+static unsigned int rxe_pernet_id;
+
+/*
+ * Called for every existing and added network namespaces
+ */
+static int rxe_ns_init(struct net *net)
+{
+ /* defer socket create in the namespace to the first
+ * device create.
+ */
+
+ return 0;
+}
+
+static void rxe_ns_exit(struct net *net)
+{
+ /* called when the network namespace is removed
+ */
+ struct rxe_ns_sock *ns_sk = net_generic(net, rxe_pernet_id);
+ struct sock *sk;
+
+ rcu_read_lock();
+ sk = rcu_dereference(ns_sk->rxe_sk4);
+ rcu_read_unlock();
+ if (sk) {
+ rcu_assign_pointer(ns_sk->rxe_sk4, NULL);
+ udp_tunnel_sock_release(sk->sk_socket);
+ }
+
+#if IS_ENABLED(CONFIG_IPV6)
+ rcu_read_lock();
+ sk = rcu_dereference(ns_sk->rxe_sk6);
+ rcu_read_unlock();
+ if (sk) {
+ rcu_assign_pointer(ns_sk->rxe_sk6, NULL);
+ udp_tunnel_sock_release(sk->sk_socket);
+ }
+#endif
+}
+
+/*
+ * callback to make the module network namespace aware
+ */
+static struct pernet_operations rxe_net_ops = {
+ .init = rxe_ns_init,
+ .exit = rxe_ns_exit,
+ .id = &rxe_pernet_id,
+ .size = sizeof(struct rxe_ns_sock),
+};
+
+struct sock *rxe_ns_pernet_sk4(struct net *net)
+{
+ struct rxe_ns_sock *ns_sk = net_generic(net, rxe_pernet_id);
+ struct sock *sk;
+
+ rcu_read_lock();
+ sk = rcu_dereference(ns_sk->rxe_sk4);
+ rcu_read_unlock();
+
+ return sk;
+}
+
+void rxe_ns_pernet_set_sk4(struct net *net, struct sock *sk)
+{
+ struct rxe_ns_sock *ns_sk = net_generic(net, rxe_pernet_id);
+
+ rcu_assign_pointer(ns_sk->rxe_sk4, sk);
+ synchronize_rcu();
+}
+
+#if IS_ENABLED(CONFIG_IPV6)
+struct sock *rxe_ns_pernet_sk6(struct net *net)
+{
+ struct rxe_ns_sock *ns_sk = net_generic(net, rxe_pernet_id);
+ struct sock *sk;
+
+ rcu_read_lock();
+ sk = rcu_dereference(ns_sk->rxe_sk6);
+ rcu_read_unlock();
+
+ return sk;
+}
+
+void rxe_ns_pernet_set_sk6(struct net *net, struct sock *sk)
+{
+ struct rxe_ns_sock *ns_sk = net_generic(net, rxe_pernet_id);
+
+ rcu_assign_pointer(ns_sk->rxe_sk6, sk);
+ synchronize_rcu();
+}
+#endif /* IPV6 */
+
+int rxe_namespace_init(void)
+{
+ return register_pernet_subsys(&rxe_net_ops);
+}
+
+void rxe_namespace_exit(void)
+{
+ unregister_pernet_subsys(&rxe_net_ops);
+}
diff --git a/drivers/infiniband/sw/rxe/rxe_ns.h b/drivers/infiniband/sw/rxe/rxe_ns.h
new file mode 100644
index 000000000000..4da2709e6b71
--- /dev/null
+++ b/drivers/infiniband/sw/rxe/rxe_ns.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
+
+#ifndef RXE_NS_H
+#define RXE_NS_H
+
+struct sock *rxe_ns_pernet_sk4(struct net *net);
+void rxe_ns_pernet_set_sk4(struct net *net, struct sock *sk);
+
+#if IS_ENABLED(CONFIG_IPV6)
+void rxe_ns_pernet_set_sk6(struct net *net, struct sock *sk);
+struct sock *rxe_ns_pernet_sk6(struct net *net);
+#else /* IPv6 */
+static inline struct sock *rxe_ns_pernet_sk6(struct net *net)
+{
+ return NULL;
+}
+
+static inline void rxe_ns_pernet_set_sk6(struct net *net, struct sock *sk)
+{
+}
+#endif /* IPv6 */
+
+int rxe_namespace_init(void);
+void rxe_namespace_exit(void);
+
+#endif /* RXE_NS_H */
--
2.52.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v6 3/4] RDMA/rxe: Support RDMA link creation and destruction per net namespace
2026-03-11 6:29 [PATCH v6 0/4] RDMA/rxe: Add the support that rxe can work in net namespace Zhu Yanjun
2026-03-11 6:29 ` [PATCH v6 1/4] RDMA/nldev: Add dellink function pointer Zhu Yanjun
2026-03-11 6:29 ` [PATCH v6 2/4] RDMA/rxe: Add net namespace support for IPv4/IPv6 sockets Zhu Yanjun
@ 2026-03-11 6:29 ` Zhu Yanjun
2026-03-11 6:29 ` [PATCH v6 4/4] RDMA/rxe: Add testcase for net namespace rxe Zhu Yanjun
3 siblings, 0 replies; 6+ messages in thread
From: Zhu Yanjun @ 2026-03-11 6:29 UTC (permalink / raw)
To: jgg, leon, zyjzyj2000, yanjun.zhu, dsahern, linux-rdma,
linux-kselftest
After introducing dellink handling and per-net namespace management
for IPv4 and IPv6 sockets, extend rxe to create and destroy RDMA links
within each network namespace.
With this change, RDMA links can be instantiated both in init_net and
in other network namespaces. The lifecycle of the RDMA link is now tied
to the corresponding namespace and is properly cleaned up when the
namespace or link is removed.
This ensures rxe behaves correctly in multi-namespace environments and
keeps socket and RDMA link resources consistent across namespace
creation and teardown.
Reviewed-by: David Ahern <dsahern@kernel.org>
Signed-off-by: Zhu Yanjun <yanjun.zhu@linux.dev>
---
drivers/infiniband/sw/rxe/rxe.c | 38 +++++++-
drivers/infiniband/sw/rxe/rxe_net.c | 144 +++++++++++++++++++++-------
drivers/infiniband/sw/rxe/rxe_net.h | 9 +-
3 files changed, 145 insertions(+), 46 deletions(-)
diff --git a/drivers/infiniband/sw/rxe/rxe.c b/drivers/infiniband/sw/rxe/rxe.c
index e891199cbdef..b0714f9abe3d 100644
--- a/drivers/infiniband/sw/rxe/rxe.c
+++ b/drivers/infiniband/sw/rxe/rxe.c
@@ -8,6 +8,8 @@
#include <net/addrconf.h>
#include "rxe.h"
#include "rxe_loc.h"
+#include "rxe_net.h"
+#include "rxe_ns.h"
MODULE_AUTHOR("Bob Pearson, Frank Zago, John Groves, Kamal Heib");
MODULE_DESCRIPTION("Soft RDMA transport");
@@ -200,6 +202,8 @@ void rxe_set_mtu(struct rxe_dev *rxe, unsigned int ndev_mtu)
port->mtu_cap = ib_mtu_enum_to_int(mtu);
}
+static struct rdma_link_ops rxe_link_ops;
+
/* called by ifc layer to create new rxe device.
* The caller should allocate memory for rxe by calling ib_alloc_device.
*/
@@ -208,6 +212,7 @@ int rxe_add(struct rxe_dev *rxe, unsigned int mtu, const char *ibdev_name,
{
rxe_init(rxe, ndev);
rxe_set_mtu(rxe, mtu);
+ rxe->ib_dev.link_ops = &rxe_link_ops;
return rxe_register_device(rxe, ibdev_name, ndev);
}
@@ -231,6 +236,10 @@ static int rxe_newlink(const char *ibdev_name, struct net_device *ndev)
goto err;
}
+ err = rxe_net_init(ndev);
+ if (err)
+ return err;
+
err = rxe_net_add(ibdev_name, ndev);
if (err) {
rxe_err("failed to add %s\n", ndev->name);
@@ -240,9 +249,17 @@ static int rxe_newlink(const char *ibdev_name, struct net_device *ndev)
return err;
}
+static int rxe_dellink(struct ib_device *dev)
+{
+ rxe_net_del(dev);
+
+ return 0;
+}
+
static struct rdma_link_ops rxe_link_ops = {
.type = "rxe",
.newlink = rxe_newlink,
+ .dellink = rxe_dellink,
};
static int __init rxe_module_init(void)
@@ -253,15 +270,24 @@ static int __init rxe_module_init(void)
if (err)
return err;
- err = rxe_net_init();
- if (err) {
- rxe_destroy_wq();
- return err;
- }
+ err = rxe_namespace_init();
+ if (err)
+ goto err_destroy_wq;
+
+ err = rxe_register_notifier();
+ if (err)
+ goto err_namespace_exit;
rdma_link_register(&rxe_link_ops);
+
pr_info("loaded\n");
return 0;
+
+err_namespace_exit:
+ rxe_namespace_exit();
+err_destroy_wq:
+ rxe_destroy_wq();
+ return err;
}
static void __exit rxe_module_exit(void)
@@ -271,6 +297,8 @@ static void __exit rxe_module_exit(void)
rxe_net_exit();
rxe_destroy_wq();
+ rxe_namespace_exit();
+
pr_info("unloaded\n");
}
diff --git a/drivers/infiniband/sw/rxe/rxe_net.c b/drivers/infiniband/sw/rxe/rxe_net.c
index 0bd0902b11f7..92b0c8d598a0 100644
--- a/drivers/infiniband/sw/rxe/rxe_net.c
+++ b/drivers/infiniband/sw/rxe/rxe_net.c
@@ -17,8 +17,7 @@
#include "rxe.h"
#include "rxe_net.h"
#include "rxe_loc.h"
-
-static struct rxe_recv_sockets recv_sockets;
+#include "rxe_ns.h"
#ifdef CONFIG_DEBUG_LOCK_ALLOC
/*
@@ -101,20 +100,20 @@ static inline void rxe_reclassify_recv_socket(struct socket *sock)
}
static struct dst_entry *rxe_find_route4(struct rxe_qp *qp,
+ struct net *net,
struct net_device *ndev,
struct in_addr *saddr,
struct in_addr *daddr)
{
struct rtable *rt;
- struct flowi4 fl = { { 0 } };
+ struct flowi4 fl = {};
- memset(&fl, 0, sizeof(fl));
fl.flowi4_oif = ndev->ifindex;
memcpy(&fl.saddr, saddr, sizeof(*saddr));
memcpy(&fl.daddr, daddr, sizeof(*daddr));
fl.flowi4_proto = IPPROTO_UDP;
- rt = ip_route_output_key(&init_net, &fl);
+ rt = ip_route_output_key(net, &fl);
if (IS_ERR(rt)) {
rxe_dbg_qp(qp, "no route to %pI4\n", &daddr->s_addr);
return NULL;
@@ -125,21 +124,21 @@ static struct dst_entry *rxe_find_route4(struct rxe_qp *qp,
#if IS_ENABLED(CONFIG_IPV6)
static struct dst_entry *rxe_find_route6(struct rxe_qp *qp,
+ struct net *net,
struct net_device *ndev,
struct in6_addr *saddr,
struct in6_addr *daddr)
{
struct dst_entry *ndst;
- struct flowi6 fl6 = { { 0 } };
+ struct flowi6 fl6 = {};
- memset(&fl6, 0, sizeof(fl6));
fl6.flowi6_oif = ndev->ifindex;
memcpy(&fl6.saddr, saddr, sizeof(*saddr));
memcpy(&fl6.daddr, daddr, sizeof(*daddr));
fl6.flowi6_proto = IPPROTO_UDP;
- ndst = ipv6_stub->ipv6_dst_lookup_flow(sock_net(recv_sockets.sk6->sk),
- recv_sockets.sk6->sk, &fl6,
+ ndst = ipv6_stub->ipv6_dst_lookup_flow(net,
+ rxe_ns_pernet_sk6(net), &fl6,
NULL);
if (IS_ERR(ndst)) {
rxe_dbg_qp(qp, "no route to %pI6\n", daddr);
@@ -160,6 +159,7 @@ static struct dst_entry *rxe_find_route6(struct rxe_qp *qp,
#else
static struct dst_entry *rxe_find_route6(struct rxe_qp *qp,
+ struct net *net,
struct net_device *ndev,
struct in6_addr *saddr,
struct in6_addr *daddr)
@@ -174,6 +174,7 @@ static struct dst_entry *rxe_find_route(struct net_device *ndev,
struct rxe_av *av)
{
struct dst_entry *dst = NULL;
+ struct net *net;
if (qp_type(qp) == IB_QPT_RC)
dst = sk_dst_get(qp->sk->sk);
@@ -182,20 +183,22 @@ static struct dst_entry *rxe_find_route(struct net_device *ndev,
if (dst)
dst_release(dst);
+ net = dev_net(ndev);
+
if (av->network_type == RXE_NETWORK_TYPE_IPV4) {
struct in_addr *saddr;
struct in_addr *daddr;
saddr = &av->sgid_addr._sockaddr_in.sin_addr;
daddr = &av->dgid_addr._sockaddr_in.sin_addr;
- dst = rxe_find_route4(qp, ndev, saddr, daddr);
+ dst = rxe_find_route4(qp, net, ndev, saddr, daddr);
} else if (av->network_type == RXE_NETWORK_TYPE_IPV6) {
struct in6_addr *saddr6;
struct in6_addr *daddr6;
saddr6 = &av->sgid_addr._sockaddr_in6.sin6_addr;
daddr6 = &av->dgid_addr._sockaddr_in6.sin6_addr;
- dst = rxe_find_route6(qp, ndev, saddr6, daddr6);
+ dst = rxe_find_route6(qp, net, ndev, saddr6, daddr6);
#if IS_ENABLED(CONFIG_IPV6)
if (dst)
qp->dst_cookie =
@@ -624,6 +627,45 @@ int rxe_net_add(const char *ibdev_name, struct net_device *ndev)
return 0;
}
+static void rxe_sock_put(struct sock *sk,
+ void (*set_sk)(struct net *, struct sock *),
+ struct net *net)
+{
+#define SK_REF_FOR_TUNNEL 2
+ if (refcount_read(&sk->sk_refcnt) > SK_REF_FOR_TUNNEL) {
+ __sock_put(sk);
+ } else {
+ rxe_release_udp_tunnel(sk->sk_socket);
+ sk = NULL;
+ set_sk(net, sk);
+ }
+#undef SK_REF_FOR_TUNNEL
+}
+
+void rxe_net_del(struct ib_device *dev)
+{
+ struct rxe_dev *rxe = container_of(dev, struct rxe_dev, ib_dev);
+ struct net_device *ndev;
+ struct sock *sk;
+ struct net *net;
+
+ ndev = rxe_ib_device_get_netdev(&rxe->ib_dev);
+ if (!ndev)
+ return;
+
+ net = dev_net(ndev);
+
+ sk = rxe_ns_pernet_sk4(net);
+ if (sk)
+ rxe_sock_put(sk, rxe_ns_pernet_set_sk4, net);
+
+ sk = rxe_ns_pernet_sk6(net);
+ if (sk)
+ rxe_sock_put(sk, rxe_ns_pernet_set_sk6, net);
+
+ dev_put(ndev);
+}
+
static void rxe_port_event(struct rxe_dev *rxe,
enum ib_event_type event)
{
@@ -680,6 +722,7 @@ static int rxe_notify(struct notifier_block *not_blk,
switch (event) {
case NETDEV_UNREGISTER:
ib_unregister_device_queued(&rxe->ib_dev);
+ rxe_net_del(&rxe->ib_dev);
break;
case NETDEV_CHANGEMTU:
rxe_dbg_dev(rxe, "%s changed mtu to %d\n", ndev->name, ndev->mtu);
@@ -709,66 +752,97 @@ static struct notifier_block rxe_net_notifier = {
.notifier_call = rxe_notify,
};
-static int rxe_net_ipv4_init(void)
+static int rxe_net_ipv4_init(struct net *net)
{
- recv_sockets.sk4 = rxe_setup_udp_tunnel(&init_net,
- htons(ROCE_V2_UDP_DPORT), false);
- if (IS_ERR(recv_sockets.sk4)) {
- recv_sockets.sk4 = NULL;
+ struct sock *sk;
+ struct socket *sock;
+
+ sk = rxe_ns_pernet_sk4(net);
+ if (sk) {
+ sock_hold(sk);
+ return 0;
+ }
+
+ sock = rxe_setup_udp_tunnel(net, htons(ROCE_V2_UDP_DPORT), false);
+ if (IS_ERR(sock)) {
pr_err("Failed to create IPv4 UDP tunnel\n");
return -1;
}
+ rxe_ns_pernet_set_sk4(net, sock->sk);
return 0;
}
-static int rxe_net_ipv6_init(void)
+static int rxe_net_ipv6_init(struct net *net)
{
#if IS_ENABLED(CONFIG_IPV6)
+ struct sock *sk;
+ struct socket *sock;
- recv_sockets.sk6 = rxe_setup_udp_tunnel(&init_net,
- htons(ROCE_V2_UDP_DPORT), true);
- if (PTR_ERR(recv_sockets.sk6) == -EAFNOSUPPORT) {
- recv_sockets.sk6 = NULL;
+ sk = rxe_ns_pernet_sk6(net);
+ if (sk) {
+ sock_hold(sk);
+ return 0;
+ }
+
+ sock = rxe_setup_udp_tunnel(net, htons(ROCE_V2_UDP_DPORT), true);
+ if (PTR_ERR(sock) == -EAFNOSUPPORT) {
pr_warn("IPv6 is not supported, can not create a UDPv6 socket\n");
return 0;
}
- if (IS_ERR(recv_sockets.sk6)) {
- recv_sockets.sk6 = NULL;
+ if (IS_ERR(sock)) {
pr_err("Failed to create IPv6 UDP tunnel\n");
return -1;
}
+
+ rxe_ns_pernet_set_sk6(net, sock->sk);
+
#endif
return 0;
}
+int rxe_register_notifier(void)
+{
+ int err;
+
+ err = register_netdevice_notifier(&rxe_net_notifier);
+ if (err) {
+ pr_err("Failed to register netdev notifier\n");
+ return -1;
+ }
+
+ return 0;
+}
+
void rxe_net_exit(void)
{
- rxe_release_udp_tunnel(recv_sockets.sk6);
- rxe_release_udp_tunnel(recv_sockets.sk4);
unregister_netdevice_notifier(&rxe_net_notifier);
}
-int rxe_net_init(void)
+int rxe_net_init(struct net_device *ndev)
{
+ struct net *net;
int err;
- recv_sockets.sk6 = NULL;
+ net = dev_net(ndev);
- err = rxe_net_ipv4_init();
+ err = rxe_net_ipv4_init(net);
if (err)
return err;
- err = rxe_net_ipv6_init();
+
+ err = rxe_net_ipv6_init(net);
if (err)
goto err_out;
- err = register_netdevice_notifier(&rxe_net_notifier);
- if (err) {
- pr_err("Failed to register netdev notifier\n");
- goto err_out;
- }
+
return 0;
+
err_out:
- rxe_net_exit();
+ /* If ipv6 error, release ipv4 resource */
+ struct sock *sk = rxe_ns_pernet_sk4(net);
+
+ if (sk)
+ rxe_sock_put(sk, rxe_ns_pernet_set_sk4, net);
+
return err;
}
diff --git a/drivers/infiniband/sw/rxe/rxe_net.h b/drivers/infiniband/sw/rxe/rxe_net.h
index 45d80d00f86b..56249677d692 100644
--- a/drivers/infiniband/sw/rxe/rxe_net.h
+++ b/drivers/infiniband/sw/rxe/rxe_net.h
@@ -11,14 +11,11 @@
#include <net/if_inet6.h>
#include <linux/module.h>
-struct rxe_recv_sockets {
- struct socket *sk4;
- struct socket *sk6;
-};
-
int rxe_net_add(const char *ibdev_name, struct net_device *ndev);
+void rxe_net_del(struct ib_device *dev);
-int rxe_net_init(void);
+int rxe_register_notifier(void);
+int rxe_net_init(struct net_device *ndev);
void rxe_net_exit(void);
#endif /* RXE_NET_H */
--
2.52.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v6 4/4] RDMA/rxe: Add testcase for net namespace rxe
2026-03-11 6:29 [PATCH v6 0/4] RDMA/rxe: Add the support that rxe can work in net namespace Zhu Yanjun
` (2 preceding siblings ...)
2026-03-11 6:29 ` [PATCH v6 3/4] RDMA/rxe: Support RDMA link creation and destruction per net namespace Zhu Yanjun
@ 2026-03-11 6:29 ` Zhu Yanjun
2026-03-11 6:35 ` Zhu Yanjun
3 siblings, 1 reply; 6+ messages in thread
From: Zhu Yanjun @ 2026-03-11 6:29 UTC (permalink / raw)
To: jgg, leon, zyjzyj2000, yanjun.zhu, dsahern, linux-rdma,
linux-kselftest
Add 4 testcases for rxe with net namespace.
Reviewed-by: David Ahern <dsahern@kernel.org>
Signed-off-by: Zhu Yanjun <yanjun.zhu@linux.dev>
---
MAINTAINERS | 1 +
tools/testing/selftests/Makefile | 1 +
tools/testing/selftests/rdma/Makefile | 7 ++
tools/testing/selftests/rdma/config | 3 +
tools/testing/selftests/rdma/rxe_ipv6.sh | 63 ++++++++++++++
.../selftests/rdma/rxe_rping_between_netns.sh | 85 +++++++++++++++++++
.../selftests/rdma/rxe_socket_with_netns.sh | 76 +++++++++++++++++
.../rdma/rxe_test_NETDEV_UNREGISTER.sh | 63 ++++++++++++++
8 files changed, 299 insertions(+)
create mode 100644 tools/testing/selftests/rdma/Makefile
create mode 100644 tools/testing/selftests/rdma/config
create mode 100755 tools/testing/selftests/rdma/rxe_ipv6.sh
create mode 100755 tools/testing/selftests/rdma/rxe_rping_between_netns.sh
create mode 100755 tools/testing/selftests/rdma/rxe_socket_with_netns.sh
create mode 100755 tools/testing/selftests/rdma/rxe_test_NETDEV_UNREGISTER.sh
diff --git a/MAINTAINERS b/MAINTAINERS
index 77fdfcb55f06..3c18bc614169 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -24492,6 +24492,7 @@ L: linux-rdma@vger.kernel.org
S: Supported
F: drivers/infiniband/sw/rxe/
F: include/uapi/rdma/rdma_user_rxe.h
+F: tools/testing/selftests/rdma/exe*
SOFTLOGIC 6x10 MPEG CODEC
M: Bluecherry Maintainers <maintainers@bluecherrydvr.com>
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index 450f13ba4cca..110e07c0d99d 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -94,6 +94,7 @@ TARGETS += proc
TARGETS += pstore
TARGETS += ptrace
TARGETS += openat2
+TARGETS += rdma
TARGETS += resctrl
TARGETS += riscv
TARGETS += rlimits
diff --git a/tools/testing/selftests/rdma/Makefile b/tools/testing/selftests/rdma/Makefile
new file mode 100644
index 000000000000..7dd7cba7a73c
--- /dev/null
+++ b/tools/testing/selftests/rdma/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0
+TEST_PROGS := rxe_rping_between_netns.sh \
+ rxe_ipv6.sh \
+ rxe_socket_with_netns.sh \
+ rxe_test_NETDEV_UNREGISTER.sh
+
+include ../lib.mk
diff --git a/tools/testing/selftests/rdma/config b/tools/testing/selftests/rdma/config
new file mode 100644
index 000000000000..4ffb814e253b
--- /dev/null
+++ b/tools/testing/selftests/rdma/config
@@ -0,0 +1,3 @@
+CONFIG_TUN
+CONFIG_VETH
+CONFIG_RDMA_RXE
diff --git a/tools/testing/selftests/rdma/rxe_ipv6.sh b/tools/testing/selftests/rdma/rxe_ipv6.sh
new file mode 100755
index 000000000000..b7059bfd6d7c
--- /dev/null
+++ b/tools/testing/selftests/rdma/rxe_ipv6.sh
@@ -0,0 +1,63 @@
+#!/bin/bash
+
+# Configuration
+NS_NAME="net6"
+VETH_HOST="veth0"
+VETH_NS="veth1"
+RXE_NAME="rxe6"
+PORT=4791
+IP6_ADDR="2001:db8::1/64"
+
+exec > /dev/null
+
+# Cleanup function to run on exit (even on failure)
+cleanup() {
+ ip netns del "$NS_NAME" 2>/dev/null
+ modprobe -r rdma_rxe 2>/dev/null
+ echo "Done."
+}
+trap cleanup EXIT
+
+# 1. Prerequisites check
+for mod in tun veth rdma_rxe; do
+ if ! modinfo "$mod" >/dev/null 2>&1; then
+ echo "Error: Kernel module '$mod' not found."
+ exit 1
+ fi
+done
+
+modprobe rdma_rxe
+
+# 2. Setup Namespace and Networking
+echo "Setting up IPv6 network namespace..."
+ip netns add "$NS_NAME"
+ip link add "$VETH_HOST" type veth peer name "$VETH_NS"
+ip link set "$VETH_NS" netns "$NS_NAME"
+ip netns exec "$NS_NAME" ip addr add "$IP6_ADDR" dev "$VETH_NS"
+ip netns exec "$NS_NAME" ip link set "$VETH_NS" up
+ip link set "$VETH_HOST" up
+
+# 3. Add RDMA Link
+echo "Adding RDMA RXE link..."
+if ! ip netns exec "$NS_NAME" rdma link add "$RXE_NAME" type rxe netdev "$VETH_NS"; then
+ echo "Error: Failed to create RXE link."
+ exit 1
+fi
+
+# 4. Verification: Port should be listening
+# Using -H to skip headers and -q for quiet exit codes
+if ! ip netns exec "$NS_NAME" ss -Hul6n sport = :$PORT | grep -q ":$PORT"; then
+ echo "Error: UDP port $PORT is NOT listening after link creation."
+ exit 1
+fi
+echo "Verified: Port $PORT is active."
+
+# 5. Removal and Verification
+echo "Deleting RDMA link..."
+ip netns exec "$NS_NAME" rdma link del "$RXE_NAME"
+
+if ip netns exec "$NS_NAME" ss -Hul6n sport = :$PORT | grep -q ":$PORT"; then
+ echo "Error: UDP port $PORT still active after link deletion."
+ exit 1
+fi
+echo "Verified: Port $PORT closed successfully."
diff --git a/tools/testing/selftests/rdma/rxe_rping_between_netns.sh b/tools/testing/selftests/rdma/rxe_rping_between_netns.sh
new file mode 100755
index 000000000000..e5b876f58c6e
--- /dev/null
+++ b/tools/testing/selftests/rdma/rxe_rping_between_netns.sh
@@ -0,0 +1,85 @@
+#!/bin/bash
+
+# Configuration
+NS="test1"
+VETH_A="veth-a"
+VETH_B="veth-b"
+IP_A="1.1.1.1"
+IP_B="1.1.1.2"
+PORT=4791
+
+exec > /dev/null
+
+# --- Cleanup Routine ---
+cleanup() {
+ echo "Cleaning up resources..."
+ rdma link del rxe1 2>/dev/null
+ ip netns exec "$NS" rdma link del rxe0 2>/dev/null
+ ip link delete "$VETH_B" 2>/dev/null
+ ip netns del "$NS" 2>/dev/null
+ modprobe -r rdma_rxe 2>/dev/null
+}
+trap cleanup EXIT
+
+# --- Prerequisite Checks ---
+if [[ $EUID -ne 0 ]]; then
+ echo "This script must be run as root"
+ exit 1
+fi
+
+modprobe rdma_rxe || { echo "Failed to load rdma_rxe"; exit 1; }
+
+# --- Setup Network Topology ---
+echo "Setting up network namespace and veth pair..."
+ip netns add "$NS"
+ip link add "$VETH_A" type veth peer name "$VETH_B"
+ip link set "$VETH_A" netns "$NS"
+
+# Configure Namespace side (test1)
+ip netns exec "$NS" ip addr add "$IP_A/24" dev "$VETH_A"
+ip netns exec "$NS" ip link set "$VETH_A" up
+ip netns exec "$NS" ip link set lo up
+
+# Configure Host side
+ip addr add "$IP_B/24" dev "$VETH_B"
+ip link set "$VETH_B" up
+
+# --- RXE Link Creation ---
+echo "Creating RDMA links..."
+ip netns exec "$NS" rdma link add rxe0 type rxe netdev "$VETH_A"
+rdma link add rxe1 type rxe netdev "$VETH_B"
+
+# Verify UDP 4791 is listening
+check_port() {
+ local target=$1 # "host" or "ns"
+ if [ "$target" == "ns" ]; then
+ ip netns exec "$NS" ss -Huln sport == :$PORT | grep -q ":$PORT"
+ else
+ ss -Huln sport == :$PORT | grep -q ":$PORT"
+ fi
+}
+
+check_port "ns" || { echo "Error: RXE port not listening in namespace"; exit 1; }
+check_port "host" || { echo "Error: RXE port not listening on host"; exit 1; }
+
+# --- Connectivity Test ---
+echo "Testing connectivity with rping..."
+ping -c 2 -W 1 "$IP_A" > /dev/null || { echo "Ping failed"; exit 1; }
+
+# Start rping server in background
+ip netns exec "$NS" rping -s -a "$IP_A" -v > /dev/null 2>&1 &
+RPING_PID=$!
+sleep 1 # Allow server to bind
+
+# Run rping client
+rping -c -a "$IP_A" -d -v -C 3
+RESULT=$?
+
+kill $RPING_PID 2>/dev/null
+
+if [ $RESULT -eq 0 ]; then
+ echo "SUCCESS: RDMA traffic verified."
+else
+ echo "FAILURE: rping failed."
+ exit 1
+fi
diff --git a/tools/testing/selftests/rdma/rxe_socket_with_netns.sh b/tools/testing/selftests/rdma/rxe_socket_with_netns.sh
new file mode 100755
index 000000000000..002e5098f751
--- /dev/null
+++ b/tools/testing/selftests/rdma/rxe_socket_with_netns.sh
@@ -0,0 +1,76 @@
+#!/bin/bash
+
+# Configuration
+PORT=4791
+MODS=("tun" "rdma_rxe")
+
+exec > /dev/null
+
+# --- Helper: Cleanup Routine ---
+cleanup() {
+ echo "Cleaning up resources..."
+ rdma link del rxe1 2>/dev/null
+ rdma link del rxe0 2>/dev/null
+ ip link del tun0 2>/dev/null
+ ip link del tun1 2>/dev/null
+ for m in "${MODS[@]}"; do modprobe -r "$m" 2>/dev/null; done
+}
+
+# Ensure cleanup runs on script exit or interrupt
+trap cleanup EXIT
+
+# --- Phase 1: Environment Check ---
+if [[ $EUID -ne 0 ]]; then
+ echo "Error: This script must be run as root."
+ exit 1
+fi
+
+for m in "${MODS[@]}"; do
+ modprobe "$m" || { echo "Error: Failed to load $m"; exit 1; }
+done
+
+# --- Phase 2: Create Interfaces & RXE Links ---
+echo "Creating tun0 (1.1.1.1) and rxe0..."
+ip tuntap add mode tun tun0
+ip addr add 1.1.1.1/24 dev tun0
+ip link set tun0 up
+rdma link add rxe0 type rxe netdev tun0
+
+# Verify port 4791 is listening
+if ! ss -Huln sport = :$PORT | grep -q ":$PORT"; then
+ echo "Error: UDP port $PORT not found after rxe0 creation"
+ exit 1
+fi
+
+echo "Creating tun1 (2.2.2.2) and rxe1..."
+ip tuntap add mode tun tun1
+ip addr add 2.2.2.2/24 dev tun1
+ip link set tun1 up
+rdma link add rxe1 type rxe netdev tun1
+
+# Verify port 4791 is still listening
+if ! ss -Huln sport = :$PORT | grep -q ":$PORT"; then
+ echo "Error: UDP port $PORT missing after rxe1 creation"
+ exit 1
+fi
+
+# --- Phase 3: Targeted Deletion ---
+echo "Deleting rxe1..."
+rdma link del rxe1
+
+# Port should still be active because rxe0 is still alive
+if ! ss -Huln sport = :$PORT | grep -q ":$PORT"; then
+ echo "Error: UDP port $PORT closed prematurely"
+ exit 1
+fi
+
+echo "Deleting rxe0..."
+rdma link del rxe0
+
+# Port should now be gone
+if ss -Huln sport = :$PORT | grep -q ":$PORT"; then
+ echo "Error: UDP port $PORT still exists after all links deleted"
+ exit 1
+fi
+
+echo "Test passed successfully."
diff --git a/tools/testing/selftests/rdma/rxe_test_NETDEV_UNREGISTER.sh b/tools/testing/selftests/rdma/rxe_test_NETDEV_UNREGISTER.sh
new file mode 100755
index 000000000000..021ca451499d
--- /dev/null
+++ b/tools/testing/selftests/rdma/rxe_test_NETDEV_UNREGISTER.sh
@@ -0,0 +1,63 @@
+#!/bin/bash
+
+# Configuration
+DEV_NAME="tun0"
+RXE_NAME="rxe0"
+RDMA_PORT=4791
+
+exec > /dev/null
+
+# --- Cleanup Routine ---
+# Ensures environment is clean even if the script hits an error
+cleanup() {
+ echo "Performing cleanup..."
+ rdma link del $RXE_NAME 2>/dev/null
+ ip link del $DEV_NAME 2>/dev/null
+ modprobe -r rdma_rxe 2>/dev/null
+}
+trap cleanup EXIT
+
+# 1. Dependency Check
+if ! modinfo rdma_rxe >/dev/null 2>&1; then
+ echo "Error: rdma_rxe module not found."
+ exit 1
+fi
+
+modprobe rdma_rxe
+
+# 2. Setup TUN Device
+echo "Creating $DEV_NAME..."
+ip tuntap add mode tun "$DEV_NAME"
+ip addr add 1.1.1.1/24 dev "$DEV_NAME"
+ip link set "$DEV_NAME" up
+
+# 3. Attach RXE Link
+echo "Attaching RXE link $RXE_NAME to $DEV_NAME..."
+rdma link add "$RXE_NAME" type rxe netdev "$DEV_NAME"
+
+# 4. Verification: Port Check
+# Use -H (no header) and -q (quiet) for cleaner scripting logic
+if ! ss -Huln sport == :$RDMA_PORT | grep -q ":$RDMA_PORT"; then
+ echo "Error: UDP port $RDMA_PORT is not listening."
+ exit 1
+fi
+echo "Verified: RXE is listening on UDP $RDMA_PORT."
+
+# 5. Trigger NETDEV_UNREGISTER
+# We delete the underlying device without deleting the RDMA link first.
+echo "Triggering NETDEV_UNREGISTER by deleting $DEV_NAME..."
+ip link del "$DEV_NAME"
+
+# 6. Final Verification
+# The RXE link and the UDP port should be automatically cleaned up by the kernel.
+if rdma link show "$RXE_NAME" 2>/dev/null; then
+ echo "Error: $RXE_NAME still exists after netdev removal."
+ exit 1
+fi
+
+if ss -Huln sport == :$RDMA_PORT | grep -q ":$RDMA_PORT"; then
+ echo "Error: UDP port $RDMA_PORT still listening after netdev removal."
+ exit 1
+fi
+
+echo "Success: NETDEV_UNREGISTER handled correctly."
--
2.52.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v6 4/4] RDMA/rxe: Add testcase for net namespace rxe
2026-03-11 6:29 ` [PATCH v6 4/4] RDMA/rxe: Add testcase for net namespace rxe Zhu Yanjun
@ 2026-03-11 6:35 ` Zhu Yanjun
0 siblings, 0 replies; 6+ messages in thread
From: Zhu Yanjun @ 2026-03-11 6:35 UTC (permalink / raw)
To: jgg, leon, zyjzyj2000, dsahern, linux-rdma, linux-kselftest,
yanjun.zhu@linux.dev
在 2026/3/10 23:29, Zhu Yanjun 写道:
> Add 4 testcases for rxe with net namespace.
>
> Reviewed-by: David Ahern <dsahern@kernel.org>
> Signed-off-by: Zhu Yanjun <yanjun.zhu@linux.dev>
> ---
> MAINTAINERS | 1 +
> tools/testing/selftests/Makefile | 1 +
> tools/testing/selftests/rdma/Makefile | 7 ++
> tools/testing/selftests/rdma/config | 3 +
> tools/testing/selftests/rdma/rxe_ipv6.sh | 63 ++++++++++++++
> .../selftests/rdma/rxe_rping_between_netns.sh | 85 +++++++++++++++++++
> .../selftests/rdma/rxe_socket_with_netns.sh | 76 +++++++++++++++++
> .../rdma/rxe_test_NETDEV_UNREGISTER.sh | 63 ++++++++++++++
> 8 files changed, 299 insertions(+)
> create mode 100644 tools/testing/selftests/rdma/Makefile
> create mode 100644 tools/testing/selftests/rdma/config
> create mode 100755 tools/testing/selftests/rdma/rxe_ipv6.sh
> create mode 100755 tools/testing/selftests/rdma/rxe_rping_between_netns.sh
> create mode 100755 tools/testing/selftests/rdma/rxe_socket_with_netns.sh
> create mode 100755 tools/testing/selftests/rdma/rxe_test_NETDEV_UNREGISTER.sh
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 77fdfcb55f06..3c18bc614169 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -24492,6 +24492,7 @@ L: linux-rdma@vger.kernel.org
> S: Supported
> F: drivers/infiniband/sw/rxe/
> F: include/uapi/rdma/rdma_user_rxe.h
> +F: tools/testing/selftests/rdma/exe*
Sorry. Should be "tools/testing/selftests/rdma/rxe*"
Zhu Yanjun
>
> SOFTLOGIC 6x10 MPEG CODEC
> M: Bluecherry Maintainers <maintainers@bluecherrydvr.com>
> diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
> index 450f13ba4cca..110e07c0d99d 100644
> --- a/tools/testing/selftests/Makefile
> +++ b/tools/testing/selftests/Makefile
> @@ -94,6 +94,7 @@ TARGETS += proc
> TARGETS += pstore
> TARGETS += ptrace
> TARGETS += openat2
> +TARGETS += rdma
> TARGETS += resctrl
> TARGETS += riscv
> TARGETS += rlimits
> diff --git a/tools/testing/selftests/rdma/Makefile b/tools/testing/selftests/rdma/Makefile
> new file mode 100644
> index 000000000000..7dd7cba7a73c
> --- /dev/null
> +++ b/tools/testing/selftests/rdma/Makefile
> @@ -0,0 +1,7 @@
> +# SPDX-License-Identifier: GPL-2.0
> +TEST_PROGS := rxe_rping_between_netns.sh \
> + rxe_ipv6.sh \
> + rxe_socket_with_netns.sh \
> + rxe_test_NETDEV_UNREGISTER.sh
> +
> +include ../lib.mk
> diff --git a/tools/testing/selftests/rdma/config b/tools/testing/selftests/rdma/config
> new file mode 100644
> index 000000000000..4ffb814e253b
> --- /dev/null
> +++ b/tools/testing/selftests/rdma/config
> @@ -0,0 +1,3 @@
> +CONFIG_TUN
> +CONFIG_VETH
> +CONFIG_RDMA_RXE
> diff --git a/tools/testing/selftests/rdma/rxe_ipv6.sh b/tools/testing/selftests/rdma/rxe_ipv6.sh
> new file mode 100755
> index 000000000000..b7059bfd6d7c
> --- /dev/null
> +++ b/tools/testing/selftests/rdma/rxe_ipv6.sh
> @@ -0,0 +1,63 @@
> +#!/bin/bash
> +
> +# Configuration
> +NS_NAME="net6"
> +VETH_HOST="veth0"
> +VETH_NS="veth1"
> +RXE_NAME="rxe6"
> +PORT=4791
> +IP6_ADDR="2001:db8::1/64"
> +
> +exec > /dev/null
> +
> +# Cleanup function to run on exit (even on failure)
> +cleanup() {
> + ip netns del "$NS_NAME" 2>/dev/null
> + modprobe -r rdma_rxe 2>/dev/null
> + echo "Done."
> +}
> +trap cleanup EXIT
> +
> +# 1. Prerequisites check
> +for mod in tun veth rdma_rxe; do
> + if ! modinfo "$mod" >/dev/null 2>&1; then
> + echo "Error: Kernel module '$mod' not found."
> + exit 1
> + fi
> +done
> +
> +modprobe rdma_rxe
> +
> +# 2. Setup Namespace and Networking
> +echo "Setting up IPv6 network namespace..."
> +ip netns add "$NS_NAME"
> +ip link add "$VETH_HOST" type veth peer name "$VETH_NS"
> +ip link set "$VETH_NS" netns "$NS_NAME"
> +ip netns exec "$NS_NAME" ip addr add "$IP6_ADDR" dev "$VETH_NS"
> +ip netns exec "$NS_NAME" ip link set "$VETH_NS" up
> +ip link set "$VETH_HOST" up
> +
> +# 3. Add RDMA Link
> +echo "Adding RDMA RXE link..."
> +if ! ip netns exec "$NS_NAME" rdma link add "$RXE_NAME" type rxe netdev "$VETH_NS"; then
> + echo "Error: Failed to create RXE link."
> + exit 1
> +fi
> +
> +# 4. Verification: Port should be listening
> +# Using -H to skip headers and -q for quiet exit codes
> +if ! ip netns exec "$NS_NAME" ss -Hul6n sport = :$PORT | grep -q ":$PORT"; then
> + echo "Error: UDP port $PORT is NOT listening after link creation."
> + exit 1
> +fi
> +echo "Verified: Port $PORT is active."
> +
> +# 5. Removal and Verification
> +echo "Deleting RDMA link..."
> +ip netns exec "$NS_NAME" rdma link del "$RXE_NAME"
> +
> +if ip netns exec "$NS_NAME" ss -Hul6n sport = :$PORT | grep -q ":$PORT"; then
> + echo "Error: UDP port $PORT still active after link deletion."
> + exit 1
> +fi
> +echo "Verified: Port $PORT closed successfully."
> diff --git a/tools/testing/selftests/rdma/rxe_rping_between_netns.sh b/tools/testing/selftests/rdma/rxe_rping_between_netns.sh
> new file mode 100755
> index 000000000000..e5b876f58c6e
> --- /dev/null
> +++ b/tools/testing/selftests/rdma/rxe_rping_between_netns.sh
> @@ -0,0 +1,85 @@
> +#!/bin/bash
> +
> +# Configuration
> +NS="test1"
> +VETH_A="veth-a"
> +VETH_B="veth-b"
> +IP_A="1.1.1.1"
> +IP_B="1.1.1.2"
> +PORT=4791
> +
> +exec > /dev/null
> +
> +# --- Cleanup Routine ---
> +cleanup() {
> + echo "Cleaning up resources..."
> + rdma link del rxe1 2>/dev/null
> + ip netns exec "$NS" rdma link del rxe0 2>/dev/null
> + ip link delete "$VETH_B" 2>/dev/null
> + ip netns del "$NS" 2>/dev/null
> + modprobe -r rdma_rxe 2>/dev/null
> +}
> +trap cleanup EXIT
> +
> +# --- Prerequisite Checks ---
> +if [[ $EUID -ne 0 ]]; then
> + echo "This script must be run as root"
> + exit 1
> +fi
> +
> +modprobe rdma_rxe || { echo "Failed to load rdma_rxe"; exit 1; }
> +
> +# --- Setup Network Topology ---
> +echo "Setting up network namespace and veth pair..."
> +ip netns add "$NS"
> +ip link add "$VETH_A" type veth peer name "$VETH_B"
> +ip link set "$VETH_A" netns "$NS"
> +
> +# Configure Namespace side (test1)
> +ip netns exec "$NS" ip addr add "$IP_A/24" dev "$VETH_A"
> +ip netns exec "$NS" ip link set "$VETH_A" up
> +ip netns exec "$NS" ip link set lo up
> +
> +# Configure Host side
> +ip addr add "$IP_B/24" dev "$VETH_B"
> +ip link set "$VETH_B" up
> +
> +# --- RXE Link Creation ---
> +echo "Creating RDMA links..."
> +ip netns exec "$NS" rdma link add rxe0 type rxe netdev "$VETH_A"
> +rdma link add rxe1 type rxe netdev "$VETH_B"
> +
> +# Verify UDP 4791 is listening
> +check_port() {
> + local target=$1 # "host" or "ns"
> + if [ "$target" == "ns" ]; then
> + ip netns exec "$NS" ss -Huln sport == :$PORT | grep -q ":$PORT"
> + else
> + ss -Huln sport == :$PORT | grep -q ":$PORT"
> + fi
> +}
> +
> +check_port "ns" || { echo "Error: RXE port not listening in namespace"; exit 1; }
> +check_port "host" || { echo "Error: RXE port not listening on host"; exit 1; }
> +
> +# --- Connectivity Test ---
> +echo "Testing connectivity with rping..."
> +ping -c 2 -W 1 "$IP_A" > /dev/null || { echo "Ping failed"; exit 1; }
> +
> +# Start rping server in background
> +ip netns exec "$NS" rping -s -a "$IP_A" -v > /dev/null 2>&1 &
> +RPING_PID=$!
> +sleep 1 # Allow server to bind
> +
> +# Run rping client
> +rping -c -a "$IP_A" -d -v -C 3
> +RESULT=$?
> +
> +kill $RPING_PID 2>/dev/null
> +
> +if [ $RESULT -eq 0 ]; then
> + echo "SUCCESS: RDMA traffic verified."
> +else
> + echo "FAILURE: rping failed."
> + exit 1
> +fi
> diff --git a/tools/testing/selftests/rdma/rxe_socket_with_netns.sh b/tools/testing/selftests/rdma/rxe_socket_with_netns.sh
> new file mode 100755
> index 000000000000..002e5098f751
> --- /dev/null
> +++ b/tools/testing/selftests/rdma/rxe_socket_with_netns.sh
> @@ -0,0 +1,76 @@
> +#!/bin/bash
> +
> +# Configuration
> +PORT=4791
> +MODS=("tun" "rdma_rxe")
> +
> +exec > /dev/null
> +
> +# --- Helper: Cleanup Routine ---
> +cleanup() {
> + echo "Cleaning up resources..."
> + rdma link del rxe1 2>/dev/null
> + rdma link del rxe0 2>/dev/null
> + ip link del tun0 2>/dev/null
> + ip link del tun1 2>/dev/null
> + for m in "${MODS[@]}"; do modprobe -r "$m" 2>/dev/null; done
> +}
> +
> +# Ensure cleanup runs on script exit or interrupt
> +trap cleanup EXIT
> +
> +# --- Phase 1: Environment Check ---
> +if [[ $EUID -ne 0 ]]; then
> + echo "Error: This script must be run as root."
> + exit 1
> +fi
> +
> +for m in "${MODS[@]}"; do
> + modprobe "$m" || { echo "Error: Failed to load $m"; exit 1; }
> +done
> +
> +# --- Phase 2: Create Interfaces & RXE Links ---
> +echo "Creating tun0 (1.1.1.1) and rxe0..."
> +ip tuntap add mode tun tun0
> +ip addr add 1.1.1.1/24 dev tun0
> +ip link set tun0 up
> +rdma link add rxe0 type rxe netdev tun0
> +
> +# Verify port 4791 is listening
> +if ! ss -Huln sport = :$PORT | grep -q ":$PORT"; then
> + echo "Error: UDP port $PORT not found after rxe0 creation"
> + exit 1
> +fi
> +
> +echo "Creating tun1 (2.2.2.2) and rxe1..."
> +ip tuntap add mode tun tun1
> +ip addr add 2.2.2.2/24 dev tun1
> +ip link set tun1 up
> +rdma link add rxe1 type rxe netdev tun1
> +
> +# Verify port 4791 is still listening
> +if ! ss -Huln sport = :$PORT | grep -q ":$PORT"; then
> + echo "Error: UDP port $PORT missing after rxe1 creation"
> + exit 1
> +fi
> +
> +# --- Phase 3: Targeted Deletion ---
> +echo "Deleting rxe1..."
> +rdma link del rxe1
> +
> +# Port should still be active because rxe0 is still alive
> +if ! ss -Huln sport = :$PORT | grep -q ":$PORT"; then
> + echo "Error: UDP port $PORT closed prematurely"
> + exit 1
> +fi
> +
> +echo "Deleting rxe0..."
> +rdma link del rxe0
> +
> +# Port should now be gone
> +if ss -Huln sport = :$PORT | grep -q ":$PORT"; then
> + echo "Error: UDP port $PORT still exists after all links deleted"
> + exit 1
> +fi
> +
> +echo "Test passed successfully."
> diff --git a/tools/testing/selftests/rdma/rxe_test_NETDEV_UNREGISTER.sh b/tools/testing/selftests/rdma/rxe_test_NETDEV_UNREGISTER.sh
> new file mode 100755
> index 000000000000..021ca451499d
> --- /dev/null
> +++ b/tools/testing/selftests/rdma/rxe_test_NETDEV_UNREGISTER.sh
> @@ -0,0 +1,63 @@
> +#!/bin/bash
> +
> +# Configuration
> +DEV_NAME="tun0"
> +RXE_NAME="rxe0"
> +RDMA_PORT=4791
> +
> +exec > /dev/null
> +
> +# --- Cleanup Routine ---
> +# Ensures environment is clean even if the script hits an error
> +cleanup() {
> + echo "Performing cleanup..."
> + rdma link del $RXE_NAME 2>/dev/null
> + ip link del $DEV_NAME 2>/dev/null
> + modprobe -r rdma_rxe 2>/dev/null
> +}
> +trap cleanup EXIT
> +
> +# 1. Dependency Check
> +if ! modinfo rdma_rxe >/dev/null 2>&1; then
> + echo "Error: rdma_rxe module not found."
> + exit 1
> +fi
> +
> +modprobe rdma_rxe
> +
> +# 2. Setup TUN Device
> +echo "Creating $DEV_NAME..."
> +ip tuntap add mode tun "$DEV_NAME"
> +ip addr add 1.1.1.1/24 dev "$DEV_NAME"
> +ip link set "$DEV_NAME" up
> +
> +# 3. Attach RXE Link
> +echo "Attaching RXE link $RXE_NAME to $DEV_NAME..."
> +rdma link add "$RXE_NAME" type rxe netdev "$DEV_NAME"
> +
> +# 4. Verification: Port Check
> +# Use -H (no header) and -q (quiet) for cleaner scripting logic
> +if ! ss -Huln sport == :$RDMA_PORT | grep -q ":$RDMA_PORT"; then
> + echo "Error: UDP port $RDMA_PORT is not listening."
> + exit 1
> +fi
> +echo "Verified: RXE is listening on UDP $RDMA_PORT."
> +
> +# 5. Trigger NETDEV_UNREGISTER
> +# We delete the underlying device without deleting the RDMA link first.
> +echo "Triggering NETDEV_UNREGISTER by deleting $DEV_NAME..."
> +ip link del "$DEV_NAME"
> +
> +# 6. Final Verification
> +# The RXE link and the UDP port should be automatically cleaned up by the kernel.
> +if rdma link show "$RXE_NAME" 2>/dev/null; then
> + echo "Error: $RXE_NAME still exists after netdev removal."
> + exit 1
> +fi
> +
> +if ss -Huln sport == :$RDMA_PORT | grep -q ":$RDMA_PORT"; then
> + echo "Error: UDP port $RDMA_PORT still listening after netdev removal."
> + exit 1
> +fi
> +
> +echo "Success: NETDEV_UNREGISTER handled correctly."
--
Best Regards,
Yanjun.Zhu
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-03-11 6:35 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-11 6:29 [PATCH v6 0/4] RDMA/rxe: Add the support that rxe can work in net namespace Zhu Yanjun
2026-03-11 6:29 ` [PATCH v6 1/4] RDMA/nldev: Add dellink function pointer Zhu Yanjun
2026-03-11 6:29 ` [PATCH v6 2/4] RDMA/rxe: Add net namespace support for IPv4/IPv6 sockets Zhu Yanjun
2026-03-11 6:29 ` [PATCH v6 3/4] RDMA/rxe: Support RDMA link creation and destruction per net namespace Zhu Yanjun
2026-03-11 6:29 ` [PATCH v6 4/4] RDMA/rxe: Add testcase for net namespace rxe Zhu Yanjun
2026-03-11 6:35 ` Zhu Yanjun
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox