From: Bobby Eshleman <[email protected]>
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 <[email protected]>
---
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