public inbox for netdev@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next 0/6] net: devmem: support devmem with netkit devices
@ 2026-03-16 22:29 Bobby Eshleman
  2026-03-16 22:29 ` [PATCH net-next 1/6] net: devmem: support TX through netkit leased queues Bobby Eshleman
                   ` (5 more replies)
  0 siblings, 6 replies; 13+ messages in thread
From: Bobby Eshleman @ 2026-03-16 22:29 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Andrew Lunn, Shuah Khan
  Cc: Stanislav Fomichev, Mina Almasry, Wei Wang, David Wei, netdev,
	linux-kernel, linux-kselftest, bpf, Bobby Eshleman

This series introduces support for TCP devmem with netkit devices.

When a physical device leases a queue to a netkit device, the netkit
device is free to bind-rx on that queue. This works out-of-the-box and
for this RX path this series only introduces tests. The tx path, via
bind-tx, is less forgiving. Before the skb ever encounters the netkit
forwarding policy or BPF redirection verdict, the skb is dropped
because the upper devmem TX path deems the underlying netkit device
unsuitable for DMA and netmem TX.

This patch series introduces netkit and queue leasing awareness to
bind-tx and the devmem TX path, so that devmem packets do not
prematurely drop even when destined for a suitable netkit device.

When bind-tx is called on a netkit device that has been leased a queue
from a physical device, the binding looks up and remembers the physical
device if it supports netmem tx. This physical device is then used in
bind-tx and TX skb validation where the checks for netmem_tx are
performed on the physical device instead of the virtual device. If no
queue has been leased or the physical device doesn't support netmem TX,
then as usual these checks will fail.

If BPF redirect or ip forwarding lands the skb in the TX path of a
device that does not support netmem, then validate_xmit_unreadable_skb()
will fail and the pkt dropped.

This series depends on the queue leasing series:
https://lore.kernel.org/all/20260129222830.439687-1-daniel@iogearbox.net/

Signed-off-by: Bobby Eshleman <bobbyeshleman@meta.com>
---
Bobby Eshleman (6):
      net: devmem: support TX through netkit leased queues
      selftests: drv-net: extract _find_bss_map_id helper in NetDrvContEnv
      selftests: drv-net: add skip-config flag to ncdevmem
      selftests: drv-net: add primary RX redirect support to NetDrvContEnv
      selftests: drv-net: add netkit devmem RX test
      selftests: drv-net: add netkit devmem TX test

 net/core/dev.c                                     |  26 +++--
 net/core/devmem.c                                  |  16 ++-
 net/core/devmem.h                                  |   6 +-
 net/core/netdev-genl.c                             |  38 ++++++-
 tools/testing/selftests/drivers/net/hw/.gitignore  |   1 +
 tools/testing/selftests/drivers/net/hw/Makefile    |   1 +
 tools/testing/selftests/drivers/net/hw/ncdevmem.c  |  58 ++++++----
 .../testing/selftests/drivers/net/hw/nk_devmem.py  | 123 +++++++++++++++++++++
 .../drivers/net/hw/nk_primary_rx_redirect.bpf.c    |  41 +++++++
 tools/testing/selftests/drivers/net/lib/py/env.py  |  60 ++++++++--
 10 files changed, 314 insertions(+), 56 deletions(-)
---
base-commit: 6c80a1ec8984e01a4d92225ecaba66ab74063d2c
change-id: 20260313-scratch-bobbyeshleman-tcp-dm-netkit5-fb85f437568c

Best regards,
-- 
Bobby Eshleman <bobbyeshleman@meta.com>


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH net-next 1/6] net: devmem: support TX through netkit leased queues
  2026-03-16 22:29 [PATCH net-next 0/6] net: devmem: support devmem with netkit devices Bobby Eshleman
@ 2026-03-16 22:29 ` Bobby Eshleman
  2026-03-16 22:29 ` [PATCH net-next 2/6] selftests: drv-net: extract _find_bss_map_id helper in NetDrvContEnv Bobby Eshleman
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 13+ messages in thread
From: Bobby Eshleman @ 2026-03-16 22:29 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Andrew Lunn, Shuah Khan
  Cc: Stanislav Fomichev, Mina Almasry, Wei Wang, David Wei, netdev,
	linux-kernel, linux-kselftest, bpf, Bobby Eshleman

From: Bobby Eshleman <bobbyeshleman@meta.com>

When a netkit virtual device leases queues from a physical NIC, devmem
TX bindings created on the netkit device should use the physical NIC
for DMA operations rather than the virtual device, which has no DMA
capability.

In bind_tx_doit, walk the device's leased rx queues to discover the
underlying physical device that supports netmem_tx. Use this device
for DMA device lookup and pass it as the real_tx_dev in the binding.
When real_tx_dev is set, it is also used for NUMA-local allocations.

Extend validate_xmit_unreadable_skb() to support the netkit case, where
the skb is validated twice: once on the netkit guest device and again on
the physical NIC after BPF redirect or ip forwarding. Both invocations
must pass for the skb to be transmitted.

Signed-off-by: Bobby Eshleman <bobbyeshleman@meta.com>
---
 net/core/dev.c         | 26 +++++++++++++++++++-------
 net/core/devmem.c      | 16 ++++++++++------
 net/core/devmem.h      |  6 ++++--
 net/core/netdev-genl.c | 38 +++++++++++++++++++++++++++++++++-----
 4 files changed, 66 insertions(+), 20 deletions(-)

diff --git a/net/core/dev.c b/net/core/dev.c
index ca4b26dfb1bd..105bd27be024 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3981,24 +3981,36 @@ static struct sk_buff *sk_validate_xmit_skb(struct sk_buff *skb,
 static struct sk_buff *validate_xmit_unreadable_skb(struct sk_buff *skb,
 						    struct net_device *dev)
 {
+	struct net_devmem_dmabuf_binding *binding;
 	struct skb_shared_info *shinfo;
+	struct net_device *real_tx_dev;
 	struct net_iov *niov;
 
 	if (likely(skb_frags_readable(skb)))
 		goto out;
 
-	if (!dev->netmem_tx)
-		goto out_free;
-
 	shinfo = skb_shinfo(skb);
+	if (shinfo->nr_frags == 0)
+		goto out;
 
-	if (shinfo->nr_frags > 0) {
-		niov = netmem_to_net_iov(skb_frag_netmem(&shinfo->frags[0]));
-		if (net_is_devmem_iov(niov) &&
-		    READ_ONCE(net_devmem_iov_binding(niov)->dev) != dev)
+	niov = netmem_to_net_iov(skb_frag_netmem(&shinfo->frags[0]));
+	if (!net_is_devmem_iov(niov))
+		goto out;
+
+	binding = net_devmem_iov_binding(niov);
+	real_tx_dev = READ_ONCE(binding->real_tx_dev);
+
+	if (real_tx_dev) {
+		if (!real_tx_dev->netmem_tx)
+			goto out_free;
+		if (READ_ONCE(binding->dev) != dev && real_tx_dev != dev)
 			goto out_free;
+		goto out;
 	}
 
+	if (READ_ONCE(binding->dev) != dev || !dev->netmem_tx)
+		goto out_free;
+
 out:
 	return skb;
 
diff --git a/net/core/devmem.c b/net/core/devmem.c
index 7ede81509968..a4148cba5b5f 100644
--- a/net/core/devmem.c
+++ b/net/core/devmem.c
@@ -181,12 +181,13 @@ int net_devmem_bind_dmabuf_to_queue(struct net_device *dev, u32 rxq_idx,
 }
 
 struct net_devmem_dmabuf_binding *
-net_devmem_bind_dmabuf(struct net_device *dev,
+net_devmem_bind_dmabuf(struct net_device *dev, struct net_device *real_tx_dev,
 		       struct device *dma_dev,
 		       enum dma_data_direction direction,
 		       unsigned int dmabuf_fd, struct netdev_nl_sock *priv,
 		       struct netlink_ext_ack *extack)
 {
+	struct net_device *node_dev = real_tx_dev ?: dev;
 	struct net_devmem_dmabuf_binding *binding;
 	static u32 id_alloc_next;
 	struct scatterlist *sg;
@@ -205,13 +206,14 @@ net_devmem_bind_dmabuf(struct net_device *dev,
 		return ERR_CAST(dmabuf);
 
 	binding = kzalloc_node(sizeof(*binding), GFP_KERNEL,
-			       dev_to_node(&dev->dev));
+			       dev_to_node(&node_dev->dev));
 	if (!binding) {
 		err = -ENOMEM;
 		goto err_put_dmabuf;
 	}
 
 	binding->dev = dev;
+	binding->real_tx_dev = real_tx_dev;
 	xa_init_flags(&binding->bound_rxqs, XA_FLAGS_ALLOC);
 
 	err = percpu_ref_init(&binding->ref,
@@ -254,7 +256,7 @@ net_devmem_bind_dmabuf(struct net_device *dev,
 	 * allocate MTU sized chunks here. Leave that for future work...
 	 */
 	binding->chunk_pool = gen_pool_create(PAGE_SHIFT,
-					      dev_to_node(&dev->dev));
+					      dev_to_node(&node_dev->dev));
 	if (!binding->chunk_pool) {
 		err = -ENOMEM;
 		goto err_tx_vec;
@@ -268,7 +270,7 @@ net_devmem_bind_dmabuf(struct net_device *dev,
 		struct net_iov *niov;
 
 		owner = kzalloc_node(sizeof(*owner), GFP_KERNEL,
-				     dev_to_node(&dev->dev));
+				     dev_to_node(&node_dev->dev));
 		if (!owner) {
 			err = -ENOMEM;
 			goto err_free_chunks;
@@ -280,7 +282,8 @@ net_devmem_bind_dmabuf(struct net_device *dev,
 		owner->binding = binding;
 
 		err = gen_pool_add_owner(binding->chunk_pool, dma_addr,
-					 dma_addr, len, dev_to_node(&dev->dev),
+					 dma_addr, len,
+					 dev_to_node(&node_dev->dev),
 					 owner);
 		if (err) {
 			kfree(owner);
@@ -397,7 +400,8 @@ struct net_devmem_dmabuf_binding *net_devmem_get_binding(struct sock *sk,
 	 */
 	dst_dev = dst_dev_rcu(dst);
 	if (unlikely(!dst_dev) ||
-	    unlikely(dst_dev != READ_ONCE(binding->dev))) {
+	    unlikely(dst_dev != READ_ONCE(binding->dev) &&
+		     dst_dev != READ_ONCE(binding->real_tx_dev))) {
 		err = -ENODEV;
 		goto out_unlock;
 	}
diff --git a/net/core/devmem.h b/net/core/devmem.h
index 1c5c18581fcb..ffcf97a33633 100644
--- a/net/core/devmem.h
+++ b/net/core/devmem.h
@@ -20,6 +20,8 @@ struct net_devmem_dmabuf_binding {
 	struct dma_buf_attachment *attachment;
 	struct sg_table *sgt;
 	struct net_device *dev;
+	/* Phys dev behind a virtual dev (e.g. netkit) with a queue lease. */
+	struct net_device *real_tx_dev;
 	struct gen_pool *chunk_pool;
 	/* Protect dev */
 	struct mutex lock;
@@ -84,7 +86,7 @@ struct dmabuf_genpool_chunk_owner {
 
 void __net_devmem_dmabuf_binding_free(struct work_struct *wq);
 struct net_devmem_dmabuf_binding *
-net_devmem_bind_dmabuf(struct net_device *dev,
+net_devmem_bind_dmabuf(struct net_device *dev, struct net_device *real_tx_dev,
 		       struct device *dma_dev,
 		       enum dma_data_direction direction,
 		       unsigned int dmabuf_fd, struct netdev_nl_sock *priv,
@@ -165,7 +167,7 @@ static inline void net_devmem_put_net_iov(struct net_iov *niov)
 }
 
 static inline struct net_devmem_dmabuf_binding *
-net_devmem_bind_dmabuf(struct net_device *dev,
+net_devmem_bind_dmabuf(struct net_device *dev, struct net_device *real_tx_dev,
 		       struct device *dma_dev,
 		       enum dma_data_direction direction,
 		       unsigned int dmabuf_fd,
diff --git a/net/core/netdev-genl.c b/net/core/netdev-genl.c
index 7d073894ca74..2b34924dc30f 100644
--- a/net/core/netdev-genl.c
+++ b/net/core/netdev-genl.c
@@ -1037,7 +1037,7 @@ int netdev_nl_bind_rx_doit(struct sk_buff *skb, struct genl_info *info)
 		goto err_rxq_bitmap;
 	}
 
-	binding = net_devmem_bind_dmabuf(netdev, dma_dev, DMA_FROM_DEVICE,
+	binding = net_devmem_bind_dmabuf(netdev, NULL, dma_dev, DMA_FROM_DEVICE,
 					 dmabuf_fd, priv, info->extack);
 	if (IS_ERR(binding)) {
 		err = PTR_ERR(binding);
@@ -1082,6 +1082,8 @@ int netdev_nl_bind_rx_doit(struct sk_buff *skb, struct genl_info *info)
 int netdev_nl_bind_tx_doit(struct sk_buff *skb, struct genl_info *info)
 {
 	struct net_devmem_dmabuf_binding *binding;
+	struct net_device *real_tx_dev = NULL;
+	struct netdev_rx_queue *lease_rxq;
 	struct netdev_nl_sock *priv;
 	struct net_device *netdev;
 	struct device *dma_dev;
@@ -1089,6 +1091,7 @@ int netdev_nl_bind_tx_doit(struct sk_buff *skb, struct genl_info *info)
 	struct sk_buff *rsp;
 	int err = 0;
 	void *hdr;
+	int i;
 
 	if (GENL_REQ_ATTR_CHECK(info, NETDEV_A_DEV_IFINDEX) ||
 	    GENL_REQ_ATTR_CHECK(info, NETDEV_A_DMABUF_FD))
@@ -1124,16 +1127,41 @@ int netdev_nl_bind_tx_doit(struct sk_buff *skb, struct genl_info *info)
 		goto err_unlock_netdev;
 	}
 
-	if (!netdev->netmem_tx) {
+	for (i = 0; i < netdev->real_num_rx_queues; i++) {
+		lease_rxq = READ_ONCE(__netif_get_rx_queue(netdev, i)->lease);
+
+		if (!lease_rxq)
+			continue;
+
+		real_tx_dev = lease_rxq->dev;
+		break;
+	}
+
+	if (real_tx_dev) {
+		if (!netif_device_present(real_tx_dev)) {
+			err = -ENODEV;
+			goto err_unlock_netdev;
+		}
+
+		if (!real_tx_dev->netmem_tx) {
+			err = -EOPNOTSUPP;
+			NL_SET_ERR_MSG(info->extack,
+				       "Driver for queue lease device does not support netmem TX");
+			goto err_unlock_netdev;
+		}
+	}
+
+	if (!real_tx_dev && !netdev->netmem_tx) {
 		err = -EOPNOTSUPP;
 		NL_SET_ERR_MSG(info->extack,
 			       "Driver does not support netmem TX");
 		goto err_unlock_netdev;
 	}
 
-	dma_dev = netdev_queue_get_dma_dev(netdev, 0);
-	binding = net_devmem_bind_dmabuf(netdev, dma_dev, DMA_TO_DEVICE,
-					 dmabuf_fd, priv, info->extack);
+	dma_dev = netdev_queue_get_dma_dev(real_tx_dev ?: netdev, 0);
+	binding = net_devmem_bind_dmabuf(netdev, real_tx_dev, dma_dev,
+					 DMA_TO_DEVICE, dmabuf_fd, priv,
+					 info->extack);
 	if (IS_ERR(binding)) {
 		err = PTR_ERR(binding);
 		goto err_unlock_netdev;

-- 
2.52.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH net-next 2/6] selftests: drv-net: extract _find_bss_map_id helper in NetDrvContEnv
  2026-03-16 22:29 [PATCH net-next 0/6] net: devmem: support devmem with netkit devices Bobby Eshleman
  2026-03-16 22:29 ` [PATCH net-next 1/6] net: devmem: support TX through netkit leased queues Bobby Eshleman
@ 2026-03-16 22:29 ` Bobby Eshleman
  2026-03-16 22:29 ` [PATCH net-next 3/6] selftests: drv-net: add skip-config flag to ncdevmem Bobby Eshleman
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 13+ messages in thread
From: Bobby Eshleman @ 2026-03-16 22:29 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Andrew Lunn, Shuah Khan
  Cc: Stanislav Fomichev, Mina Almasry, Wei Wang, David Wei, netdev,
	linux-kernel, linux-kselftest, bpf, Bobby Eshleman

From: Bobby Eshleman <bobbyeshleman@meta.com>

Factor out a _find_bss_map_id() helper from _attach_bpf() so it can be
reused by other BPF attachment methods. This will be used by subsequent
patches in this series that add support for netkit devmem TX testing.

No functional change to existing tests.

Signed-off-by: Bobby Eshleman <bobbyeshleman@meta.com>
---
 tools/testing/selftests/drivers/net/lib/py/env.py | 21 ++++++++++-----------
 1 file changed, 10 insertions(+), 11 deletions(-)

diff --git a/tools/testing/selftests/drivers/net/lib/py/env.py b/tools/testing/selftests/drivers/net/lib/py/env.py
index ccff345fe1c1..08e90448f48d 100644
--- a/tools/testing/selftests/drivers/net/lib/py/env.py
+++ b/tools/testing/selftests/drivers/net/lib/py/env.py
@@ -467,6 +467,15 @@ class NetDrvContEnv(NetDrvEpEnv):
                 return (bpf['pref'], bpf['options']['prog']['id'])
         raise Exception("Failed to get BPF prog ID")
 
+    def _find_bss_map_id(self, prog_id):
+        """Find the .bss map ID for a loaded BPF program."""
+        prog_info = bpftool(f"prog show id {prog_id}", json=True)
+        for map_id in prog_info.get("map_ids", []):
+            map_info = bpftool(f"map show id {map_id}", json=True)
+            if map_info.get("name", "").endswith("bss"):
+                return map_id
+        raise Exception(f"Failed to find .bss map for prog {prog_id}")
+
     def _attach_bpf(self):
         bpf_obj = self.test_dir / "nk_forward.bpf.o"
         if not bpf_obj.exists():
@@ -478,17 +487,7 @@ class NetDrvContEnv(NetDrvEpEnv):
         self._tc_attached = True
 
         (self._bpf_prog_pref, self._bpf_prog_id) = self._get_bpf_prog_ids()
-        prog_info = bpftool(f"prog show id {self._bpf_prog_id}", json=True)
-        map_ids = prog_info.get("map_ids", [])
-
-        bss_map_id = None
-        for map_id in map_ids:
-            map_info = bpftool(f"map show id {map_id}", json=True)
-            if map_info.get("name").endswith("bss"):
-                bss_map_id = map_id
-
-        if bss_map_id is None:
-            raise Exception("Failed to find .bss map")
+        bss_map_id = self._find_bss_map_id(self._bpf_prog_id)
 
         ipv6_addr = ipaddress.IPv6Address(self.ipv6_prefix)
         ipv6_bytes = ipv6_addr.packed

-- 
2.52.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH net-next 3/6] selftests: drv-net: add skip-config flag to ncdevmem
  2026-03-16 22:29 [PATCH net-next 0/6] net: devmem: support devmem with netkit devices Bobby Eshleman
  2026-03-16 22:29 ` [PATCH net-next 1/6] net: devmem: support TX through netkit leased queues Bobby Eshleman
  2026-03-16 22:29 ` [PATCH net-next 2/6] selftests: drv-net: extract _find_bss_map_id helper in NetDrvContEnv Bobby Eshleman
@ 2026-03-16 22:29 ` Bobby Eshleman
  2026-03-16 22:29 ` [PATCH net-next 4/6] selftests: drv-net: add primary RX redirect support to NetDrvContEnv Bobby Eshleman
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 13+ messages in thread
From: Bobby Eshleman @ 2026-03-16 22:29 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Andrew Lunn, Shuah Khan
  Cc: Stanislav Fomichev, Mina Almasry, Wei Wang, David Wei, netdev,
	linux-kernel, linux-kselftest, bpf, Bobby Eshleman

From: Bobby Eshleman <bobbyeshleman@meta.com>

Add a -n flag to ncdevmem that skips hardware configuration (header
split, RSS, flow steering). This is needed when ncdevmem is run inside a
netkit namespace where hardware configuration is managed externally by
the test harness.

When -n is set, ncdevmem skips configure_headersplit(), configure_rss(),
and configure_flow_steering(). The calling environment is expected to
perform this setup prior to invoking ncdevmem.

This is used in subsequent patches of this series that bring up netkit
devmem TX testing. ncdevmem will only have access to the netkit inside
the namespace, and not the physical device. Therefore, in those tests,
the test harness itself does the physical device setup.

Signed-off-by: Bobby Eshleman <bobbyeshleman@meta.com>
---
 tools/testing/selftests/drivers/net/hw/ncdevmem.c | 58 +++++++++++++----------
 1 file changed, 34 insertions(+), 24 deletions(-)

diff --git a/tools/testing/selftests/drivers/net/hw/ncdevmem.c b/tools/testing/selftests/drivers/net/hw/ncdevmem.c
index e098d6534c3c..d96e8a3b5a65 100644
--- a/tools/testing/selftests/drivers/net/hw/ncdevmem.c
+++ b/tools/testing/selftests/drivers/net/hw/ncdevmem.c
@@ -93,6 +93,7 @@ static char *port;
 static size_t do_validation;
 static int start_queue = -1;
 static int num_queues = -1;
+static int skip_config;
 static char *ifname;
 static unsigned int ifindex;
 static unsigned int dmabuf_id;
@@ -828,7 +829,7 @@ static struct netdev_queue_id *create_queues(void)
 
 static int do_server(struct memory_buffer *mem)
 {
-	struct ethtool_rings_get_rsp *ring_config;
+	struct ethtool_rings_get_rsp *ring_config = NULL;
 	char ctrl_data[sizeof(int) * 20000];
 	size_t non_page_aligned_frags = 0;
 	struct sockaddr_in6 client_addr;
@@ -851,27 +852,29 @@ static int do_server(struct memory_buffer *mem)
 		return -1;
 	}
 
-	ring_config = get_ring_config();
-	if (!ring_config) {
-		pr_err("Failed to get current ring configuration");
-		return -1;
-	}
+	if (!skip_config) {
+		ring_config = get_ring_config();
+		if (!ring_config) {
+			pr_err("Failed to get current ring configuration");
+			return -1;
+		}
 
-	if (configure_headersplit(ring_config, 1)) {
-		pr_err("Failed to enable TCP header split");
-		goto err_free_ring_config;
-	}
+		if (configure_headersplit(ring_config, 1)) {
+			pr_err("Failed to enable TCP header split");
+			goto err_free_ring_config;
+		}
 
-	/* Configure RSS to divert all traffic from our devmem queues */
-	if (configure_rss()) {
-		pr_err("Failed to configure rss");
-		goto err_reset_headersplit;
-	}
+		/* Configure RSS to divert all traffic from our devmem queues */
+		if (configure_rss()) {
+			pr_err("Failed to configure rss");
+			goto err_reset_headersplit;
+		}
 
-	/* Flow steer our devmem flows to start_queue */
-	if (configure_flow_steering(&server_sin)) {
-		pr_err("Failed to configure flow steering");
-		goto err_reset_rss;
+		/* Flow steer our devmem flows to start_queue */
+		if (configure_flow_steering(&server_sin)) {
+			pr_err("Failed to configure flow steering");
+			goto err_reset_rss;
+		}
 	}
 
 	if (bind_rx_queue(ifindex, mem->fd, create_queues(), num_queues, &ys)) {
@@ -1052,13 +1055,17 @@ static int do_server(struct memory_buffer *mem)
 err_unbind:
 	ynl_sock_destroy(ys);
 err_reset_flow_steering:
-	reset_flow_steering();
+	if (!skip_config)
+		reset_flow_steering();
 err_reset_rss:
-	reset_rss();
+	if (!skip_config)
+		reset_rss();
 err_reset_headersplit:
-	restore_ring_config(ring_config);
+	if (!skip_config)
+		restore_ring_config(ring_config);
 err_free_ring_config:
-	ethtool_rings_get_rsp_free(ring_config);
+	if (!skip_config)
+		ethtool_rings_get_rsp_free(ring_config);
 	return err;
 }
 
@@ -1404,7 +1411,7 @@ int main(int argc, char *argv[])
 	int is_server = 0, opt;
 	int ret, err = 1;
 
-	while ((opt = getopt(argc, argv, "Lls:c:p:v:q:t:f:z:")) != -1) {
+	while ((opt = getopt(argc, argv, "Lls:c:p:v:q:t:f:z:n")) != -1) {
 		switch (opt) {
 		case 'L':
 			fail_on_linear = true;
@@ -1436,6 +1443,9 @@ int main(int argc, char *argv[])
 		case 'z':
 			max_chunk = atoi(optarg);
 			break;
+		case 'n':
+			skip_config = 1;
+			break;
 		case '?':
 			fprintf(stderr, "unknown option: %c\n", optopt);
 			break;

-- 
2.52.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH net-next 4/6] selftests: drv-net: add primary RX redirect support to NetDrvContEnv
  2026-03-16 22:29 [PATCH net-next 0/6] net: devmem: support devmem with netkit devices Bobby Eshleman
                   ` (2 preceding siblings ...)
  2026-03-16 22:29 ` [PATCH net-next 3/6] selftests: drv-net: add skip-config flag to ncdevmem Bobby Eshleman
@ 2026-03-16 22:29 ` Bobby Eshleman
  2026-03-16 22:29 ` [PATCH net-next 5/6] selftests: drv-net: add netkit devmem RX test Bobby Eshleman
  2026-03-16 22:29 ` [PATCH net-next 6/6] selftests: drv-net: add netkit devmem TX test Bobby Eshleman
  5 siblings, 0 replies; 13+ messages in thread
From: Bobby Eshleman @ 2026-03-16 22:29 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Andrew Lunn, Shuah Khan
  Cc: Stanislav Fomichev, Mina Almasry, Wei Wang, David Wei, netdev,
	linux-kernel, linux-kselftest, bpf, Bobby Eshleman

From: Bobby Eshleman <bobbyeshleman@meta.com>

Add a primary_rx_redirect parameter to NetDrvContEnv that enables a BPF
tc program (nk_primary_rx_redirect.bpf.c) on the primary netkit ingress.
This program redirects traffic to the physical NIC via
bpf_redirect_neigh(), while letting ICMPv6 through for neighbor
discovery.

This will be used by the devmem netkit TX tests where the nk peer is
sending to the nk primary for redirection to the physical NIC.

Signed-off-by: Bobby Eshleman <bobbyeshleman@meta.com>
---
 tools/testing/selftests/drivers/net/hw/.gitignore  |  1 +
 .../drivers/net/hw/nk_primary_rx_redirect.bpf.c    | 41 ++++++++++++++++++++++
 tools/testing/selftests/drivers/net/lib/py/env.py  | 39 +++++++++++++++++++-
 3 files changed, 80 insertions(+), 1 deletion(-)

diff --git a/tools/testing/selftests/drivers/net/hw/.gitignore b/tools/testing/selftests/drivers/net/hw/.gitignore
index 46540468a775..3e5c51f8e1c7 100644
--- a/tools/testing/selftests/drivers/net/hw/.gitignore
+++ b/tools/testing/selftests/drivers/net/hw/.gitignore
@@ -1,4 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0-only
 iou-zcrx
 ncdevmem
+nk_primary_rx_redirect
 toeplitz
diff --git a/tools/testing/selftests/drivers/net/hw/nk_primary_rx_redirect.bpf.c b/tools/testing/selftests/drivers/net/hw/nk_primary_rx_redirect.bpf.c
new file mode 100644
index 000000000000..fe3c127a4fd0
--- /dev/null
+++ b/tools/testing/selftests/drivers/net/hw/nk_primary_rx_redirect.bpf.c
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/bpf.h>
+#include <linux/if_ether.h>
+#include <linux/ipv6.h>
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_endian.h>
+
+#define TC_ACT_OK 0
+#define ETH_P_IPV6 0x86DD
+#define IPPROTO_ICMPV6 58
+
+#define ctx_ptr(field)		((void *)(long)(field))
+
+volatile __u32 phys_ifindex;
+
+SEC("tc/ingress")
+int nk_primary_rx_redirect(struct __sk_buff *skb)
+{
+	void *data_end = ctx_ptr(skb->data_end);
+	void *data = ctx_ptr(skb->data);
+	struct ethhdr *eth;
+	struct ipv6hdr *ip6h;
+
+	eth = data;
+	if ((void *)(eth + 1) > data_end)
+		return TC_ACT_OK;
+
+	if (eth->h_proto != bpf_htons(ETH_P_IPV6))
+		return TC_ACT_OK;
+
+	ip6h = data + sizeof(struct ethhdr);
+	if ((void *)(ip6h + 1) > data_end)
+		return TC_ACT_OK;
+
+	if (ip6h->nexthdr == IPPROTO_ICMPV6)
+		return TC_ACT_OK;
+
+	return bpf_redirect_neigh(phys_ifindex, NULL, 0, 0);
+}
+
+char __license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/drivers/net/lib/py/env.py b/tools/testing/selftests/drivers/net/lib/py/env.py
index 08e90448f48d..e124b9c7c95c 100644
--- a/tools/testing/selftests/drivers/net/lib/py/env.py
+++ b/tools/testing/selftests/drivers/net/lib/py/env.py
@@ -327,12 +327,13 @@ class NetDrvContEnv(NetDrvEpEnv):
               +---------------+
     """
 
-    def __init__(self, src_path, rxqueues=1, **kwargs):
+    def __init__(self, src_path, rxqueues=1, primary_rx_redirect=False, **kwargs):
         self.netns = None
         self._nk_host_ifname = None
         self._nk_guest_ifname = None
         self._tc_clsact_added = False
         self._tc_attached = False
+        self._primary_rx_redirect_attached = False
         self._bpf_prog_pref = None
         self._bpf_prog_id = None
         self._init_ns_attached = False
@@ -387,8 +388,14 @@ class NetDrvContEnv(NetDrvEpEnv):
 
         self._setup_ns()
         self._attach_bpf()
+        if primary_rx_redirect:
+            self._attach_primary_rx_redirect_bpf()
 
     def __del__(self):
+        if self._primary_rx_redirect_attached:
+            cmd(f"tc qdisc del dev {self._nk_host_ifname} clsact", fail=False)
+            self._primary_rx_redirect_attached = False
+
         if self._tc_attached:
             cmd(f"tc filter del dev {self.ifname} ingress pref {self._bpf_prog_pref}")
             self._tc_attached = False
@@ -450,6 +457,8 @@ class NetDrvContEnv(NetDrvEpEnv):
         ip(f"-6 addr add {self.nk_guest_ipv6}/64 dev {self._nk_guest_ifname} nodad", ns=self.netns)
         ip(f"-6 route add default via fe80::1 dev {self._nk_guest_ifname}", ns=self.netns)
 
+        ip(f"-6 route add {self.nk_guest_ipv6}/128 via {self.addr_v['6']}", host=self.remote)
+
     def _tc_ensure_clsact(self):
         qdisc = json.loads(cmd(f"tc -j qdisc show dev {self.ifname}").stdout)
         for q in qdisc:
@@ -495,3 +504,31 @@ class NetDrvContEnv(NetDrvEpEnv):
         value = ipv6_bytes + ifindex_bytes
         value_hex = ' '.join(f'{b:02x}' for b in value)
         bpftool(f"map update id {bss_map_id} key hex 00 00 00 00 value hex {value_hex}")
+
+    def _attach_primary_rx_redirect_bpf(self):
+        """Attach BPF redirect program on the primary netkit ingress."""
+        bpf_obj = self.test_dir / "nk_primary_rx_redirect.bpf.o"
+        if not bpf_obj.exists():
+            raise KsftSkipEx("Primary RX redirect BPF prog not found")
+
+        cmd(f"tc qdisc add dev {self._nk_host_ifname} clsact")
+        cmd(f"tc filter add dev {self._nk_host_ifname} ingress"
+            f" bpf obj {bpf_obj} sec tc/ingress direct-action")
+        self._primary_rx_redirect_attached = True
+
+        filters = json.loads(
+            cmd(f"tc -j filter show dev {self._nk_host_ifname} ingress").stdout)
+        redirect_prog_id = None
+        for bpf in filters:
+            if 'options' not in bpf:
+                continue
+            if bpf['options']['bpf_name'].startswith('nk_primary_rx_redirect'):
+                redirect_prog_id = bpf['options']['prog']['id']
+                break
+        if redirect_prog_id is None:
+            raise Exception("Failed to get primary RX redirect BPF prog ID")
+
+        bss_map_id = self._find_bss_map_id(redirect_prog_id)
+        phys_ifindex_bytes = self.ifindex.to_bytes(4, byteorder='little')
+        value_hex = ' '.join(f'{b:02x}' for b in phys_ifindex_bytes)
+        bpftool(f"map update id {bss_map_id} key hex 00 00 00 00 value hex {value_hex}")

-- 
2.52.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH net-next 5/6] selftests: drv-net: add netkit devmem RX test
  2026-03-16 22:29 [PATCH net-next 0/6] net: devmem: support devmem with netkit devices Bobby Eshleman
                   ` (3 preceding siblings ...)
  2026-03-16 22:29 ` [PATCH net-next 4/6] selftests: drv-net: add primary RX redirect support to NetDrvContEnv Bobby Eshleman
@ 2026-03-16 22:29 ` Bobby Eshleman
  2026-03-18  0:08   ` Stanislav Fomichev
  2026-03-16 22:29 ` [PATCH net-next 6/6] selftests: drv-net: add netkit devmem TX test Bobby Eshleman
  5 siblings, 1 reply; 13+ messages in thread
From: Bobby Eshleman @ 2026-03-16 22:29 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Andrew Lunn, Shuah Khan
  Cc: Stanislav Fomichev, Mina Almasry, Wei Wang, David Wei, netdev,
	linux-kernel, linux-kselftest, bpf, Bobby Eshleman

From: Bobby Eshleman <bobbyeshleman@meta.com>

Add tests for devmem RX over a netkit device with a leased queue. This
is the same as the other devmem RX test except for ncdevmem executes in
a namespace, binds to a netkit, and skips the ethtool NIC configuration
steps (relying on the test runner for that setup).

The RX path is setup as the following:

 RX Path
 -------

 Remote            Physical NIC          Netkit Host        Netkit Guest (netns)
   |                    |                     |                    |
   |--- TCP send ------>|                     |                    |
                        |-------------------->|                    |
                      dmabuf                  |--- BPF redirect -->|

Signed-off-by: Bobby Eshleman <bobbyeshleman@meta.com>
---
 tools/testing/selftests/drivers/net/hw/Makefile    |   1 +
 .../testing/selftests/drivers/net/hw/nk_devmem.py  | 104 +++++++++++++++++++++
 2 files changed, 105 insertions(+)

diff --git a/tools/testing/selftests/drivers/net/hw/Makefile b/tools/testing/selftests/drivers/net/hw/Makefile
index 91df028abfc0..3cd68e06f592 100644
--- a/tools/testing/selftests/drivers/net/hw/Makefile
+++ b/tools/testing/selftests/drivers/net/hw/Makefile
@@ -32,6 +32,7 @@ TEST_PROGS = \
 	irq.py \
 	loopback.sh \
 	nic_timestamp.py \
+	nk_devmem.py \
 	nk_netns.py \
 	pp_alloc_fail.py \
 	rss_api.py \
diff --git a/tools/testing/selftests/drivers/net/hw/nk_devmem.py b/tools/testing/selftests/drivers/net/hw/nk_devmem.py
new file mode 100755
index 000000000000..0a66ff85db9d
--- /dev/null
+++ b/tools/testing/selftests/drivers/net/hw/nk_devmem.py
@@ -0,0 +1,104 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0
+"""Test devmem TCP through netkit with queue leasing."""
+
+import re
+from os import path
+from lib.py import ksft_run, ksft_exit, ksft_eq, KsftSkipEx
+from lib.py import NetDrvContEnv, NetNSEnter, EthtoolFamily, NetdevFamily
+from lib.py import bkg, cmd, defer, ethtool, rand_port, wait_port_listen
+
+
+def set_flow_rule(cfg):
+    """Insert an ethtool flow rule steering traffic to the leased queue."""
+    output = ethtool(
+        f"-N {cfg.ifname} flow-type tcp6 dst-port {cfg.port}"
+        f" action {cfg.src_queue}"
+    ).stdout
+    values = re.search(r'ID (\d+)', output).group(1)
+    return int(values)
+
+
+def configure_nic(cfg):
+    """Common setup for devmem tests: channels, rings, RSS, queue lease."""
+    cfg.require_ipver('6')
+    ethnl = EthtoolFamily()
+
+    channels = ethnl.channels_get({'header': {'dev-index': cfg.ifindex}})
+    channels = channels['combined-count']
+    if channels < 2:
+        raise KsftSkipEx(
+            'Test requires NETIF with at least 2 combined channels'
+        )
+
+    rings = ethnl.rings_get({'header': {'dev-index': cfg.ifindex}})
+    rx_rings = rings['rx']
+    hds_thresh = rings.get('hds-thresh', 0)
+    orig_data_split = rings.get('tcp-data-split', 'unknown')
+
+    ethnl.rings_set({'header': {'dev-index': cfg.ifindex},
+                         'tcp-data-split': 'enabled',
+                         'hds-thresh': 0,
+                         'rx': min(64, rx_rings)})
+    defer(ethnl.rings_set, {'header': {'dev-index': cfg.ifindex},
+                                'tcp-data-split': orig_data_split,
+                                'hds-thresh': hds_thresh,
+                                'rx': rx_rings})
+
+    cfg.src_queue = channels - 1
+    ethtool(f"-X {cfg.ifname} equal {cfg.src_queue}")
+    defer(ethtool, f"-X {cfg.ifname} default")
+
+    if hasattr(cfg, 'nk_queue'):
+        return
+
+    with NetNSEnter(str(cfg.netns)):
+        netdevnl = NetdevFamily()
+        lease_result = netdevnl.queue_create(
+            {
+                "ifindex": cfg.nk_guest_ifindex,
+                "type": "rx",
+                "lease": {
+                    "ifindex": cfg.ifindex,
+                    "queue": {"id": cfg.src_queue, "type": "rx"},
+                    "netns-id": 0,
+                },
+            }
+        )
+        cfg.nk_queue = lease_result['id']
+
+
+def test_devmem(cfg) -> None:
+    """Test devmem RX: send from remote, receive on netkit guest."""
+    configure_nic(cfg)
+
+    flow_rule_id = set_flow_rule(cfg)
+    defer(ethtool, f"-N {cfg.ifname} delete {flow_rule_id}")
+
+    rx_cmd = (f"ip netns exec {cfg.netns.name} {cfg.bin_local}"
+              f" -l -f {cfg._nk_guest_ifname} -s {cfg.nk_guest_ipv6}"
+              f" -p {cfg.port} -t {cfg.nk_queue} -q 1 -v 7 -n")
+    socat = f"socat -u - TCP6:[{cfg.nk_guest_ipv6}]:{cfg.port}"
+
+    with bkg(rx_cmd, exit_wait=True) as ncdevmem_rx:
+        wait_port_listen(cfg.port, proto="tcp", ns=cfg.netns)
+        cmd(f"yes $(echo -e \x01\x02\x03\x04\x05\x06) | head -c 1K"
+            f" | {socat}",
+            host=cfg.remote, shell=True)
+
+    ksft_eq(ncdevmem_rx.ret, 0)
+
+
+def main() -> None:
+    """Run netkit devmem tests."""
+    with NetDrvContEnv(__file__, rxqueues=2) as cfg:
+        cfg.bin_local = path.abspath(
+            path.dirname(__file__) + "/ncdevmem"
+        )
+        cfg.port = rand_port()
+        ksft_run([test_devmem], args=(cfg,))
+    ksft_exit()
+
+
+if __name__ == "__main__":
+    main()

-- 
2.52.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH net-next 6/6] selftests: drv-net: add netkit devmem TX test
  2026-03-16 22:29 [PATCH net-next 0/6] net: devmem: support devmem with netkit devices Bobby Eshleman
                   ` (4 preceding siblings ...)
  2026-03-16 22:29 ` [PATCH net-next 5/6] selftests: drv-net: add netkit devmem RX test Bobby Eshleman
@ 2026-03-16 22:29 ` Bobby Eshleman
  5 siblings, 0 replies; 13+ messages in thread
From: Bobby Eshleman @ 2026-03-16 22:29 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Andrew Lunn, Shuah Khan
  Cc: Stanislav Fomichev, Mina Almasry, Wei Wang, David Wei, netdev,
	linux-kernel, linux-kselftest, bpf, Bobby Eshleman

From: Bobby Eshleman <bobbyeshleman@meta.com>

Extend the netkit devmem selftest with a TX test case. The TX path uses
the primary RX redirect BPF program to redirect traffic from the primary
netkit ingress to the physical NIC via bpf_redirect_neigh().

The actual TX path looks like the following:

 TX Path
 -------

 Netkit Guest (netns)     Netkit Host          Physical NIC          Remote
      |                       |                     |                    |
      |--- TCP send --------->|                     |                    |
                              |--- BPF redirect --->|                    |
                                                    |---- transmit ----->|
						   dmabuf

Signed-off-by: Bobby Eshleman <bobbyeshleman@meta.com>
---
 .../testing/selftests/drivers/net/hw/nk_devmem.py  | 23 ++++++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/tools/testing/selftests/drivers/net/hw/nk_devmem.py b/tools/testing/selftests/drivers/net/hw/nk_devmem.py
index 0a66ff85db9d..0e3c5aab6423 100755
--- a/tools/testing/selftests/drivers/net/hw/nk_devmem.py
+++ b/tools/testing/selftests/drivers/net/hw/nk_devmem.py
@@ -89,14 +89,33 @@ def test_devmem(cfg) -> None:
     ksft_eq(ncdevmem_rx.ret, 0)
 
 
+def test_devmem_tx(cfg) -> None:
+    """Test devmem TX: send from netkit guest, receive on remote."""
+    configure_nic(cfg)
+
+    socat = f"socat -U - TCP6-LISTEN:{cfg.port},reuseaddr"
+    tx_cmd = (f"ip netns exec {cfg.netns.name} bash -c"
+              f" 'echo test_devmem_tx | {cfg.bin_local}"
+              f" -f {cfg._nk_guest_ifname} -s {cfg.remote_addr_v['6']}"
+              f" -p {cfg.port} -t 0 -q 1 -n'")
+
+    with bkg(socat, host=cfg.remote, exit_wait=True) as receiver:
+        wait_port_listen(cfg.port, proto="tcp", host=cfg.remote)
+        cmd(tx_cmd, shell=True)
+
+    ksft_eq(receiver.ret, 0)
+    ksft_eq(receiver.stdout.strip(), "test_devmem_tx")
+
+
 def main() -> None:
     """Run netkit devmem tests."""
-    with NetDrvContEnv(__file__, rxqueues=2) as cfg:
+    with NetDrvContEnv(__file__, rxqueues=2,
+                       primary_rx_redirect=True) as cfg:
         cfg.bin_local = path.abspath(
             path.dirname(__file__) + "/ncdevmem"
         )
         cfg.port = rand_port()
-        ksft_run([test_devmem], args=(cfg,))
+        ksft_run([test_devmem, test_devmem_tx], args=(cfg,))
     ksft_exit()
 
 

-- 
2.52.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH net-next 5/6] selftests: drv-net: add netkit devmem RX test
  2026-03-16 22:29 ` [PATCH net-next 5/6] selftests: drv-net: add netkit devmem RX test Bobby Eshleman
@ 2026-03-18  0:08   ` Stanislav Fomichev
  2026-03-18  0:54     ` Bobby Eshleman
  0 siblings, 1 reply; 13+ messages in thread
From: Stanislav Fomichev @ 2026-03-18  0:08 UTC (permalink / raw)
  To: Bobby Eshleman
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Andrew Lunn, Shuah Khan, Stanislav Fomichev,
	Mina Almasry, Wei Wang, David Wei, netdev, linux-kernel,
	linux-kselftest, bpf, Bobby Eshleman

On 03/16, Bobby Eshleman wrote:
> From: Bobby Eshleman <bobbyeshleman@meta.com>
> 
> Add tests for devmem RX over a netkit device with a leased queue. This
> is the same as the other devmem RX test except for ncdevmem executes in
> a namespace, binds to a netkit, and skips the ethtool NIC configuration
> steps (relying on the test runner for that setup).
> 
> The RX path is setup as the following:
> 
>  RX Path
>  -------
> 
>  Remote            Physical NIC          Netkit Host        Netkit Guest (netns)
>    |                    |                     |                    |
>    |--- TCP send ------>|                     |                    |
>                         |-------------------->|                    |
>                       dmabuf                  |--- BPF redirect -->|
> 

Is it too messy to parametrize the existing test to run both with and
without the namespaces? Feels like should be somewhat doable in python?

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH net-next 5/6] selftests: drv-net: add netkit devmem RX test
  2026-03-18  0:08   ` Stanislav Fomichev
@ 2026-03-18  0:54     ` Bobby Eshleman
  2026-03-18 14:59       ` Stanislav Fomichev
  0 siblings, 1 reply; 13+ messages in thread
From: Bobby Eshleman @ 2026-03-18  0:54 UTC (permalink / raw)
  To: Stanislav Fomichev
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Andrew Lunn, Shuah Khan, Stanislav Fomichev,
	Mina Almasry, Wei Wang, David Wei, netdev, linux-kernel,
	linux-kselftest, bpf, Bobby Eshleman

On Tue, Mar 17, 2026 at 05:08:20PM -0700, Stanislav Fomichev wrote:
> On 03/16, Bobby Eshleman wrote:
> > From: Bobby Eshleman <bobbyeshleman@meta.com>
> > 
> > Add tests for devmem RX over a netkit device with a leased queue. This
> > is the same as the other devmem RX test except for ncdevmem executes in
> > a namespace, binds to a netkit, and skips the ethtool NIC configuration
> > steps (relying on the test runner for that setup).
> > 
> > The RX path is setup as the following:
> > 
> >  RX Path
> >  -------
> > 
> >  Remote            Physical NIC          Netkit Host        Netkit Guest (netns)
> >    |                    |                     |                    |
> >    |--- TCP send ------>|                     |                    |
> >                         |-------------------->|                    |
> >                       dmabuf                  |--- BPF redirect -->|
> > 
> 
> Is it too messy to parametrize the existing test to run both with and
> without the namespaces? Feels like should be somewhat doable in python?

IIUC, we could have main() do something like:

for env [NetDrvContEnv, NetDrvEpEnv]:
    with env as cfg:
        [...]
        ksft_run(tests, args=(cfg,))


And then the tests could call helpers that check cfg.netns to use the
nk_{guest,host}_ip6 addresses when true, otherwise use the regular
addresses?

It should be doable if I'm following your drift.

Best,
Bobby

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH net-next 5/6] selftests: drv-net: add netkit devmem RX test
  2026-03-18  0:54     ` Bobby Eshleman
@ 2026-03-18 14:59       ` Stanislav Fomichev
  2026-03-18 16:21         ` Bobby Eshleman
  0 siblings, 1 reply; 13+ messages in thread
From: Stanislav Fomichev @ 2026-03-18 14:59 UTC (permalink / raw)
  To: Bobby Eshleman
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Andrew Lunn, Shuah Khan, Stanislav Fomichev,
	Mina Almasry, Wei Wang, David Wei, netdev, linux-kernel,
	linux-kselftest, bpf, Bobby Eshleman

On 03/17, Bobby Eshleman wrote:
> On Tue, Mar 17, 2026 at 05:08:20PM -0700, Stanislav Fomichev wrote:
> > On 03/16, Bobby Eshleman wrote:
> > > From: Bobby Eshleman <bobbyeshleman@meta.com>
> > > 
> > > Add tests for devmem RX over a netkit device with a leased queue. This
> > > is the same as the other devmem RX test except for ncdevmem executes in
> > > a namespace, binds to a netkit, and skips the ethtool NIC configuration
> > > steps (relying on the test runner for that setup).
> > > 
> > > The RX path is setup as the following:
> > > 
> > >  RX Path
> > >  -------
> > > 
> > >  Remote            Physical NIC          Netkit Host        Netkit Guest (netns)
> > >    |                    |                     |                    |
> > >    |--- TCP send ------>|                     |                    |
> > >                         |-------------------->|                    |
> > >                       dmabuf                  |--- BPF redirect -->|
> > > 
> > 
> > Is it too messy to parametrize the existing test to run both with and
> > without the namespaces? Feels like should be somewhat doable in python?
> 
> IIUC, we could have main() do something like:
> 
> for env [NetDrvContEnv, NetDrvEpEnv]:
>     with env as cfg:
>         [...]
>         ksft_run(tests, args=(cfg,))
> 
> 
> And then the tests could call helpers that check cfg.netns to use the
> nk_{guest,host}_ip6 addresses when true, otherwise use the regular
> addresses?
> 
> It should be doable if I'm following your drift.

Yeah, yeah, this plus some small changes here and there (to pass your
new -n in the netns mode for example).

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH net-next 5/6] selftests: drv-net: add netkit devmem RX test
  2026-03-18 14:59       ` Stanislav Fomichev
@ 2026-03-18 16:21         ` Bobby Eshleman
  2026-03-18 23:10           ` Jakub Kicinski
  0 siblings, 1 reply; 13+ messages in thread
From: Bobby Eshleman @ 2026-03-18 16:21 UTC (permalink / raw)
  To: Stanislav Fomichev
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Andrew Lunn, Shuah Khan, Stanislav Fomichev,
	Mina Almasry, Wei Wang, David Wei, netdev, linux-kernel,
	linux-kselftest, bpf, Bobby Eshleman

On Wed, Mar 18, 2026 at 07:59:57AM -0700, Stanislav Fomichev wrote:
> On 03/17, Bobby Eshleman wrote:
> > On Tue, Mar 17, 2026 at 05:08:20PM -0700, Stanislav Fomichev wrote:
> > > On 03/16, Bobby Eshleman wrote:
> > > > From: Bobby Eshleman <bobbyeshleman@meta.com>
> > > > 
> > > > Add tests for devmem RX over a netkit device with a leased queue. This
> > > > is the same as the other devmem RX test except for ncdevmem executes in
> > > > a namespace, binds to a netkit, and skips the ethtool NIC configuration
> > > > steps (relying on the test runner for that setup).
> > > > 
> > > > The RX path is setup as the following:
> > > > 
> > > >  RX Path
> > > >  -------
> > > > 
> > > >  Remote            Physical NIC          Netkit Host        Netkit Guest (netns)
> > > >    |                    |                     |                    |
> > > >    |--- TCP send ------>|                     |                    |
> > > >                         |-------------------->|                    |
> > > >                       dmabuf                  |--- BPF redirect -->|
> > > > 
> > > 
> > > Is it too messy to parametrize the existing test to run both with and
> > > without the namespaces? Feels like should be somewhat doable in python?
> > 
> > IIUC, we could have main() do something like:
> > 
> > for env [NetDrvContEnv, NetDrvEpEnv]:
> >     with env as cfg:
> >         [...]
> >         ksft_run(tests, args=(cfg,))
> > 
> > 
> > And then the tests could call helpers that check cfg.netns to use the
> > nk_{guest,host}_ip6 addresses when true, otherwise use the regular
> > addresses?
> > 
> > It should be doable if I'm following your drift.
> 
> Yeah, yeah, this plus some small changes here and there (to pass your
> new -n in the netns mode for example).

Sounds good, I'll give it a look.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH net-next 5/6] selftests: drv-net: add netkit devmem RX test
  2026-03-18 16:21         ` Bobby Eshleman
@ 2026-03-18 23:10           ` Jakub Kicinski
  2026-03-19  0:01             ` Bobby Eshleman
  0 siblings, 1 reply; 13+ messages in thread
From: Jakub Kicinski @ 2026-03-18 23:10 UTC (permalink / raw)
  To: Bobby Eshleman
  Cc: Stanislav Fomichev, David S. Miller, Eric Dumazet, Paolo Abeni,
	Simon Horman, Andrew Lunn, Shuah Khan, Stanislav Fomichev,
	Mina Almasry, Wei Wang, David Wei, netdev, linux-kernel,
	linux-kselftest, bpf, Bobby Eshleman

On Wed, 18 Mar 2026 09:21:32 -0700 Bobby Eshleman wrote:
> > > IIUC, we could have main() do something like:
> > > 
> > > for env [NetDrvContEnv, NetDrvEpEnv]:
> > >     with env as cfg:
> > >         [...]
> > >         ksft_run(tests, args=(cfg,))
> > > 
> > > 
> > > And then the tests could call helpers that check cfg.netns to use the
> > > nk_{guest,host}_ip6 addresses when true, otherwise use the regular
> > > addresses?
> > > 
> > > It should be doable if I'm following your drift.  
> > 
> > Yeah, yeah, this plus some small changes here and there (to pass your
> > new -n in the netns mode for example).  
> 
> Sounds good, I'll give it a look.

I haven't actually looked but double check ksft_run can actually 
be called multiple times. We may have some global state :S

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH net-next 5/6] selftests: drv-net: add netkit devmem RX test
  2026-03-18 23:10           ` Jakub Kicinski
@ 2026-03-19  0:01             ` Bobby Eshleman
  0 siblings, 0 replies; 13+ messages in thread
From: Bobby Eshleman @ 2026-03-19  0:01 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: Stanislav Fomichev, David S. Miller, Eric Dumazet, Paolo Abeni,
	Simon Horman, Andrew Lunn, Shuah Khan, Stanislav Fomichev,
	Mina Almasry, Wei Wang, David Wei, netdev, linux-kernel,
	linux-kselftest, bpf, Bobby Eshleman

On Wed, Mar 18, 2026 at 04:10:10PM -0700, Jakub Kicinski wrote:
> On Wed, 18 Mar 2026 09:21:32 -0700 Bobby Eshleman wrote:
> > > > IIUC, we could have main() do something like:
> > > > 
> > > > for env [NetDrvContEnv, NetDrvEpEnv]:
> > > >     with env as cfg:
> > > >         [...]
> > > >         ksft_run(tests, args=(cfg,))
> > > > 
> > > > 
> > > > And then the tests could call helpers that check cfg.netns to use the
> > > > nk_{guest,host}_ip6 addresses when true, otherwise use the regular
> > > > addresses?
> > > > 
> > > > It should be doable if I'm following your drift.  
> > > 
> > > Yeah, yeah, this plus some small changes here and there (to pass your
> > > new -n in the netns mode for example).  
> > 
> > Sounds good, I'll give it a look.
> 
> I haven't actually looked but double check ksft_run can actually 
> be called multiple times. We may have some global state :S

The result is global, but accumulates correctly.

But the tap output doubles:

TAP version 13
1..2
ok 1 devmem.check_nk_rx
ok 2 devmem.check_nk_tx
# Totals: pass:2 ...
TAP version 13
1..4
ok 1 devmem.check_rx
ok 2 devmem.check_tx
ok 3 devmem.check_tx_chunks
ok 4 devmem.check_rx_hds
# Totals: pass:4 ...

Not sure what outside parsing expects yet...

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2026-03-19  0:01 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-16 22:29 [PATCH net-next 0/6] net: devmem: support devmem with netkit devices Bobby Eshleman
2026-03-16 22:29 ` [PATCH net-next 1/6] net: devmem: support TX through netkit leased queues Bobby Eshleman
2026-03-16 22:29 ` [PATCH net-next 2/6] selftests: drv-net: extract _find_bss_map_id helper in NetDrvContEnv Bobby Eshleman
2026-03-16 22:29 ` [PATCH net-next 3/6] selftests: drv-net: add skip-config flag to ncdevmem Bobby Eshleman
2026-03-16 22:29 ` [PATCH net-next 4/6] selftests: drv-net: add primary RX redirect support to NetDrvContEnv Bobby Eshleman
2026-03-16 22:29 ` [PATCH net-next 5/6] selftests: drv-net: add netkit devmem RX test Bobby Eshleman
2026-03-18  0:08   ` Stanislav Fomichev
2026-03-18  0:54     ` Bobby Eshleman
2026-03-18 14:59       ` Stanislav Fomichev
2026-03-18 16:21         ` Bobby Eshleman
2026-03-18 23:10           ` Jakub Kicinski
2026-03-19  0:01             ` Bobby Eshleman
2026-03-16 22:29 ` [PATCH net-next 6/6] selftests: drv-net: add netkit devmem TX test Bobby Eshleman

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