Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'selftests-drv-net-fix-issues-in-devlink_rate_tc_bw-py'

Carolina Jubran says:

====================
selftests: drv-net: Fix issues in devlink_rate_tc_bw.py

This series fixes issues in the devlink_rate_tc_bw.py selftest and
introduces a new Iperf3Runner that helps with measurement handling.
====================

Link: https://patch.msgid.link/20251130091938.4109055-1-cjubran@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+157 -112
+1
tools/testing/selftests/drivers/net/hw/Makefile
··· 20 20 TEST_PROGS = \ 21 21 csum.py \ 22 22 devlink_port_split.py \ 23 + devlink_rate_tc_bw.py \ 23 24 devmem.py \ 24 25 ethtool.sh \ 25 26 ethtool_extended_state.sh \
+3 -2
tools/testing/selftests/drivers/net/hw/lib/py/__init__.py
··· 28 28 ksft_setup, ksft_variants, KsftNamedVariant 29 29 from net.lib.py import ksft_eq, ksft_ge, ksft_in, ksft_is, ksft_lt, \ 30 30 ksft_ne, ksft_not_in, ksft_raises, ksft_true, ksft_gt, ksft_not_none 31 - from drivers.net.lib.py import GenerateTraffic, Remote 31 + from drivers.net.lib.py import GenerateTraffic, Remote, Iperf3Runner 32 32 from drivers.net.lib.py import NetDrvEnv, NetDrvEpEnv 33 33 34 34 __all__ = ["NetNS", "NetNSEnter", "NetdevSimDev", ··· 44 44 "ksft_eq", "ksft_ge", "ksft_in", "ksft_is", "ksft_lt", 45 45 "ksft_ne", "ksft_not_in", "ksft_raises", "ksft_true", "ksft_gt", 46 46 "ksft_not_none", "ksft_not_none", 47 - "NetDrvEnv", "NetDrvEpEnv", "GenerateTraffic", "Remote"] 47 + "NetDrvEnv", "NetDrvEpEnv", "GenerateTraffic", "Remote", 48 + "Iperf3Runner"] 48 49 except ModuleNotFoundError as e: 49 50 print("Failed importing `net` library from kernel sources") 50 51 print(str(e))
+3 -2
tools/testing/selftests/drivers/net/lib/py/__init__.py
··· 44 44 "ksft_not_none", "ksft_not_none"] 45 45 46 46 from .env import NetDrvEnv, NetDrvEpEnv 47 - from .load import GenerateTraffic 47 + from .load import GenerateTraffic, Iperf3Runner 48 48 from .remote import Remote 49 49 50 - __all__ += ["NetDrvEnv", "NetDrvEpEnv", "GenerateTraffic", "Remote"] 50 + __all__ += ["NetDrvEnv", "NetDrvEpEnv", "GenerateTraffic", "Remote", 51 + "Iperf3Runner"] 51 52 except ModuleNotFoundError as e: 52 53 print("Failed importing `net` library from kernel sources") 53 54 print(str(e))
+76 -8
tools/testing/selftests/drivers/net/lib/py/load.py
··· 2 2 3 3 import re 4 4 import time 5 + import json 5 6 6 7 from lib.py import ksft_pr, cmd, ip, rand_port, wait_port_listen 7 8 8 - class GenerateTraffic: 9 - def __init__(self, env, port=None): 9 + 10 + class Iperf3Runner: 11 + """ 12 + Sets up and runs iperf3 traffic. 13 + """ 14 + def __init__(self, env, port=None, server_ip=None, client_ip=None): 10 15 env.require_cmd("iperf3", local=True, remote=True) 11 - 12 16 self.env = env 13 - 14 17 self.port = rand_port() if port is None else port 15 - self._iperf_server = cmd(f"iperf3 -s -1 -p {self.port}", background=True) 18 + self.server_ip = server_ip 19 + self.client_ip = client_ip 20 + 21 + def _build_server(self): 22 + cmdline = f"iperf3 -s -1 -p {self.port}" 23 + if self.server_ip: 24 + cmdline += f" -B {self.server_ip}" 25 + return cmdline 26 + 27 + def _build_client(self, streams, duration, reverse): 28 + host = self.env.addr if self.server_ip is None else self.server_ip 29 + cmdline = f"iperf3 -c {host} -p {self.port} -P {streams} -t {duration} -J" 30 + if self.client_ip: 31 + cmdline += f" -B {self.client_ip}" 32 + if reverse: 33 + cmdline += " --reverse" 34 + return cmdline 35 + 36 + def start_server(self): 37 + """ 38 + Starts an iperf3 server with optional bind IP. 39 + """ 40 + cmdline = self._build_server() 41 + proc = cmd(cmdline, background=True) 16 42 wait_port_listen(self.port) 17 43 time.sleep(0.1) 18 - self._iperf_client = cmd(f"iperf3 -c {env.addr} -P 16 -p {self.port} -t 86400", 19 - background=True, host=env.remote) 44 + return proc 45 + 46 + def start_client(self, background=False, streams=1, duration=10, reverse=False): 47 + """ 48 + Starts the iperf3 client with the configured options. 49 + """ 50 + cmdline = self._build_client(streams, duration, reverse) 51 + return cmd(cmdline, background=background, host=self.env.remote) 52 + 53 + def measure_bandwidth(self, reverse=False): 54 + """ 55 + Runs an iperf3 measurement and returns the average bandwidth (Gbps). 56 + Discards the first and last few reporting intervals and uses only the 57 + middle part of the run where throughput is typically stable. 58 + """ 59 + self.start_server() 60 + result = self.start_client(duration=10, reverse=reverse) 61 + 62 + if result.ret != 0: 63 + raise RuntimeError("iperf3 failed to run successfully") 64 + try: 65 + out = json.loads(result.stdout) 66 + except json.JSONDecodeError as exc: 67 + raise ValueError("Failed to parse iperf3 JSON output") from exc 68 + 69 + intervals = out.get("intervals", []) 70 + samples = [i["sum"]["bits_per_second"] / 1e9 for i in intervals] 71 + if len(samples) < 10: 72 + raise ValueError(f"iperf3 returned too few intervals: {len(samples)}") 73 + # Discard potentially unstable first and last 3 seconds. 74 + stable = samples[3:-3] 75 + 76 + avg = sum(stable) / len(stable) 77 + 78 + return avg 79 + 80 + 81 + class GenerateTraffic: 82 + def __init__(self, env, port=None): 83 + self.env = env 84 + self.runner = Iperf3Runner(env, port) 85 + 86 + self._iperf_server = self.runner.start_server() 87 + self._iperf_client = self.runner.start_client(background=True, streams=16, duration=86400) 20 88 21 89 # Wait for traffic to ramp up 22 90 if not self._wait_pkts(pps=1000): ··· 129 61 def _wait_client_stopped(self, sleep=0.005, timeout=5): 130 62 end = time.monotonic() + timeout 131 63 132 - live_port_pattern = re.compile(fr":{self.port:04X} 0[^6] ") 64 + live_port_pattern = re.compile(fr":{self.runner.port:04X} 0[^6] ") 133 65 134 66 while time.monotonic() < end: 135 67 data = cmd("cat /proc/net/tcp*", host=self.env.remote).stdout