On 2026-08-13 18:23, Juanlu Herrero wrote:
Add a rss_multiqueue Python test variant that exercises multi-queue
zero-copy receive on a single listening socket.
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Juanlu Herrero <[email protected]>
---
.../selftests/drivers/net/hw/iou-zcrx.py | 50 ++++++++++++++++++-
1 file changed, 48 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/drivers/net/hw/iou-zcrx.py
b/tools/testing/selftests/drivers/net/hw/iou-zcrx.py
index b7a225fe4beae..c833535d8a03c 100755
--- a/tools/testing/selftests/drivers/net/hw/iou-zcrx.py
+++ b/tools/testing/selftests/drivers/net/hw/iou-zcrx.py
@@ -30,6 +30,13 @@ def create_rss_ctx(cfg):
return int(values)
+def create_rss_ctx_multi(cfg, start, count):
+ """Create an RSS context spanning count queues from start, return its
ID."""
+ output = ethtool(f"-X {cfg.ifname} context new start {start} equal
{count}").stdout
+ values = re.search(r'New RSS context is (\d+)', output).group(1)
+ return int(values)
+
+
def set_flow_rule(cfg):
output = ethtool(f"-N {cfg.ifname} flow-type tcp6 dst-port {cfg.port} action
{cfg.target}").stdout
values = re.search(r'ID (\d+)', output).group(1)
@@ -127,17 +134,56 @@ def _require_ntuple(cfg):
defer(ethtool, f"-K {cfg.ifname} ntuple-filters off")
+def rss_multiqueue(cfg):
+ """Steer the test flow to a multi-queue RSS context for multi-thread
zcrx."""
+ channels = cfg.ethnl.channels_get({'header': {'dev-index': cfg.ifindex}})
+ channels = channels['combined-count']
+ if channels < 3:
+ raise KsftSkipEx('Test requires NETIF with at least 3 combined
channels')
+
+ rings = cfg.ethnl.rings_get({'header': {'dev-index': cfg.ifindex}})
+ rx_rings = rings['rx']
+ hds_thresh = rings.get('hds-thresh', 0)
+
+ cfg.ethnl.rings_set({'header': {'dev-index': cfg.ifindex},
+ 'tcp-data-split': 'enabled',
+ 'hds-thresh': 0,
+ 'rx': 64})
+ defer(cfg.ethnl.rings_set, {'header': {'dev-index': cfg.ifindex},
+ 'tcp-data-split': 'unknown',
+ 'hds-thresh': hds_thresh,
+ 'rx': rx_rings})
+ defer(mp_clear_wait, cfg)
+
+ cfg.num_threads = 2
+ cfg.target = channels - cfg.num_threads
+ ethtool(f"-X {cfg.ifname} equal {cfg.target}")
+ defer(ethtool, f"-X {cfg.ifname} default")
+
+ rss_ctx_id = create_rss_ctx_multi(cfg, cfg.target, cfg.num_threads)
+ defer(ethtool, f"-X {cfg.ifname} delete context {rss_ctx_id}")
+
+ flow_rule_id = set_flow_rule_rss(cfg, rss_ctx_id)
+ defer(ethtool, f"-N {cfg.ifname} delete {flow_rule_id}")
+
+
@ksft_variants([
KsftNamedVariant("single", single),
KsftNamedVariant("rss", rss),
+ KsftNamedVariant("rss_multiqueue", rss_multiqueue),
])
def test_zcrx(cfg, setup) -> None:
cfg.require_ipver('6')
_require_ntuple(cfg)
+ cfg.num_threads = 1
+
setup(cfg)
- rx_cmd = f"{cfg.bin_local} -s -p {cfg.port} -i {cfg.ifname} -q
{cfg.target}"
- tx_cmd = f"{cfg.bin_remote} -c -h {cfg.addr_v['6']} -p {cfg.port} -l 12840"
+
+ rx_cmd = (f"{cfg.bin_local} -s -p {cfg.port} -i {cfg.ifname} "
+ f"-q {cfg.target} -t {cfg.num_threads}")
+ tx_cmd = (f"{cfg.bin_remote} -c -h {cfg.addr_v['6']} -p {cfg.port} "
+ f"-l 12840 -t {cfg.num_threads}")
with bkg(rx_cmd, exit_wait=True):
wait_port_listen(cfg.port, proto="tcp")
cmd(tx_cmd, host=cfg.remote)
Reviewed-by: David Wei <[email protected]>