Message ID | 20250216182453.226325-6-gal@nvidia.com (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | Symmetric OR-XOR RSS hash | expand |
On Sun, 16 Feb 2025 20:24:53 +0200 Gal Pressman wrote: > + # Check for symmetric xor/or-xor > + if input_xfrm and (input_xfrm == 1 or input_xfrm == 2): > + port1 = _get_rand_port(cfg.remote) > + port2 = _get_rand_port(cfg.remote) > + ksft_pr(f'Running traffic on ports: {port1 = }, {port2 = }') > + > + cnts = _get_rx_cnts(cfg) > + GenerateTraffic(cfg, port=port1, parallel=1, > + cport=port2).wait_pkts_and_stop(20000) > + cnts = _get_rx_cnts(cfg, prev=cnts) > + rxq1 = _get_active_rx_queue(cnts) > + ksft_pr(f'Received traffic on {rxq1 = }') > + > + cnts = _get_rx_cnts(cfg) > + GenerateTraffic(cfg, port=port2, parallel=1, > + cport=port1).wait_pkts_and_stop(20000) > + cnts = _get_rx_cnts(cfg, prev=cnts) > + rxq2 = _get_active_rx_queue(cnts) > + ksft_pr(f'Received traffic on {rxq2 = }') > + > + ksft_eq( > + rxq1, rxq2, comment=f"Received traffic on different queues ({rxq1} != {rxq2}) while symmetric hash is configured") Wouldn't it be both faster and less error prone to test this with UDP sockets? sock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) sock.connect(cfg.remove_addr_v[ipver], remote_port) sock.recvmsg(100) tgt = f"{ipver}:{cfg.addr_v[ipver]}:{local_port},sourceport={remote_port}" cmd("echo a | socat - UDP" + tgt, host=cfg.remote) cpu = sock.getsockopt(socket.SOL_SOCKET, socket.SO_INCOMING_CPU) Run this for 10 pairs for ports, make sure we hit at least 2 CPUs, and that the CPUs match for each pair. Would be good to test both IPv4 and IPv6. I'm going to merge: https://lore.kernel.org/all/20250217194200.3011136-4-kuba@kernel.org/ it should make writing the v4 + v6 test combos easier.
On 18/02/2025 2:19, Jakub Kicinski wrote: > Wouldn't it be both faster and less error prone to test this with UDP > sockets? > > sock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) > sock.connect(cfg.remove_addr_v[ipver], remote_port) > sock.recvmsg(100) > > tgt = f"{ipver}:{cfg.addr_v[ipver]}:{local_port},sourceport={remote_port}" > cmd("echo a | socat - UDP" + tgt, host=cfg.remote) > > cpu = sock.getsockopt(socket.SOL_SOCKET, socket.SO_INCOMING_CPU) > > Run this for 10 pairs for ports, make sure we hit at least 2 CPUs, > and that the CPUs match for each pair. Thanks, I can do that. > > Would be good to test both IPv4 and IPv6. I'm going to merge: > https://lore.kernel.org/all/20250217194200.3011136-4-kuba@kernel.org/ > it should make writing the v4 + v6 test combos easier. Should I wait for it to get merged?
On Tue, 18 Feb 2025 22:26:25 +0200 Gal Pressman wrote: > > Would be good to test both IPv4 and IPv6. I'm going to merge: > > https://lore.kernel.org/all/20250217194200.3011136-4-kuba@kernel.org/ > > it should make writing the v4 + v6 test combos easier. > > Should I wait for it to get merged? Yes, please, I remove the members you'd need to use to test both v4 and v6 so you patch will stop working once mine is merged. Stan reported a problem, I'll repost once again and hopefully the new version goes in tomorrow.
diff --git a/tools/testing/selftests/drivers/net/hw/Makefile b/tools/testing/selftests/drivers/net/hw/Makefile index 21ba64ce1e34..23dca086f84f 100644 --- a/tools/testing/selftests/drivers/net/hw/Makefile +++ b/tools/testing/selftests/drivers/net/hw/Makefile @@ -15,6 +15,7 @@ TEST_PROGS = \ nic_performance.py \ pp_alloc_fail.py \ rss_ctx.py \ + rss_input_xfrm.py \ # TEST_FILES := \ diff --git a/tools/testing/selftests/drivers/net/hw/rss_input_xfrm.py b/tools/testing/selftests/drivers/net/hw/rss_input_xfrm.py new file mode 100755 index 000000000000..e32df852f091 --- /dev/null +++ b/tools/testing/selftests/drivers/net/hw/rss_input_xfrm.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0 + +from lib.py import ksft_run, ksft_exit, ksft_eq, ksft_pr +from lib.py import NetDrvEpEnv +from lib.py import EthtoolFamily, NetdevFamily +from lib.py import KsftSkipEx +from lib.py import rand_port, check_port_available_remote +from lib.py import GenerateTraffic +from rss_ctx import _get_rx_cnts + + +def _get_active_rx_queue(cnts): + return cnts.index(max(cnts)) + + +def _get_rand_port(remote): + for _ in range(1000): + port = rand_port() + try: + check_port_available_remote(port, remote) + return port + except: + continue + + raise Exception("Can't find any free unprivileged port") + + +def test_rss_input_xfrm(cfg): + """ + Test symmetric input_xfrm. + If symmetric RSS hash is configured, send traffic twice, swapping the + src/dst TCP ports, and verify that the same queue is receiving the traffic + in both cases (IPs are constant). + """ + + input_xfrm = cfg.ethnl.rss_get( + {'header': {'dev-name': cfg.ifname}}).get('input_xfrm') + + # Check for symmetric xor/or-xor + if input_xfrm and (input_xfrm == 1 or input_xfrm == 2): + port1 = _get_rand_port(cfg.remote) + port2 = _get_rand_port(cfg.remote) + ksft_pr(f'Running traffic on ports: {port1 = }, {port2 = }') + + cnts = _get_rx_cnts(cfg) + GenerateTraffic(cfg, port=port1, parallel=1, + cport=port2).wait_pkts_and_stop(20000) + cnts = _get_rx_cnts(cfg, prev=cnts) + rxq1 = _get_active_rx_queue(cnts) + ksft_pr(f'Received traffic on {rxq1 = }') + + cnts = _get_rx_cnts(cfg) + GenerateTraffic(cfg, port=port2, parallel=1, + cport=port1).wait_pkts_and_stop(20000) + cnts = _get_rx_cnts(cfg, prev=cnts) + rxq2 = _get_active_rx_queue(cnts) + ksft_pr(f'Received traffic on {rxq2 = }') + + ksft_eq( + rxq1, rxq2, comment=f"Received traffic on different queues ({rxq1} != {rxq2}) while symmetric hash is configured") + else: + raise KsftSkipEx("Symmetric RSS hash not requested") + + +def main() -> None: + with NetDrvEpEnv(__file__, nsim_test=False) as cfg: + cfg.ethnl = EthtoolFamily() + cfg.netdevnl = NetdevFamily() + + ksft_run([test_rss_input_xfrm], + args=(cfg, )) + ksft_exit() + + +if __name__ == "__main__": + main() diff --git a/tools/testing/selftests/drivers/net/lib/py/load.py b/tools/testing/selftests/drivers/net/lib/py/load.py index da5af2c680fa..76aaa65c0367 100644 --- a/tools/testing/selftests/drivers/net/lib/py/load.py +++ b/tools/testing/selftests/drivers/net/lib/py/load.py @@ -5,7 +5,7 @@ import time from lib.py import ksft_pr, cmd, ip, rand_port, wait_port_listen, bkg class GenerateTraffic: - def __init__(self, env, port=None): + def __init__(self, env, port=None, cport=None, parallel=16): env.require_cmd("iperf3", remote=True) self.env = env @@ -15,7 +15,10 @@ class GenerateTraffic: self._iperf_server = cmd(f"iperf3 -s -1 -p {port}", background=True) wait_port_listen(port) time.sleep(0.1) - self._iperf_client = cmd(f"iperf3 -c {env.addr} -P 16 -p {port} -t 86400", + client_cmd = f"iperf3 -c {env.addr} -P {parallel} -p {port} -t 86400" + if cport and parallel == 1: + client_cmd = f"{client_cmd} --cport {cport}" + self._iperf_client = cmd(client_cmd, background=True, host=env.remote) # Wait for traffic to ramp up