* [PATCH net-next v2 00/12] selftests: drv-net: convert GRO and Toeplitz tests to work for drivers in NIPA
@ 2025-11-18 21:51 Jakub Kicinski
2025-11-18 21:51 ` [PATCH net-next v2 01/12] selftests: net: py: coding style improvements Jakub Kicinski
` (12 more replies)
0 siblings, 13 replies; 30+ messages in thread
From: Jakub Kicinski @ 2025-11-18 21:51 UTC (permalink / raw)
To: davem
Cc: netdev, edumazet, pabeni, andrew+netdev, horms,
willemdebruijn.kernel, shuah, sdf, krakauer, linux-kselftest,
petrm, matttbe, Jakub Kicinski
Main objective of this series is to convert the gro.sh and toeplitz.sh
tests to be "NIPA-compatible" - meaning make use of the Python env,
which lets us run the tests against either netdevsim or a real device.
The tests seem to have been written with a different flow in mind.
Namely they source different bash "setup" scripts depending on arguments
passed to the test. While I have nothing against the use of bash and
the overall architecture - the existing code needs quite a bit of work
(don't assume MAC/IP addresses, support remote endpoint over SSH).
If I'm the one fixing it, I'd rather convert them to our "simplistic"
Python.
This series rewrites the tests in Python while addressing their
shortcomings. The functionality of running the test over loopback
on a real device is retained but with a different method of invocation
(see the last patch).
Once again we are dealing with a script which run over a variety of
protocols (combination of [ipv4, ipv6, ipip] x [tcp, udp]). The first
4 patches add support for test variants to our scripts. We use the
term "variant" in the same sense as the C kselftest_harness.h -
variant is just a set of static input arguments.
Note that neither GRO nor the Toeplitz test fully passes for me on
any HW I have access to. But this is unrelated to the conversion.
This series is not making any real functional changes to the tests,
it is limited to improving the "test harness" scripts.
v2:
[patch 5] fix accidental modification of gitignore
[patch 8] fix typo in "compared"
[patch 9] fix typo I -> It
[patch 10] fix typoe configure -> configured
v1: https://lore.kernel.org/20251117205810.1617533-1-kuba@kernel.org
Jakub Kicinski (12):
selftests: net: py: coding style improvements
selftests: net: py: extract the case generation logic
selftests: net: py: add test variants
selftests: drv-net: xdp: use variants for qstat tests
selftests: net: relocate gro and toeplitz tests to drivers/net
selftests: net: py: support ksft ready without wait
selftests: net: py: read ip link info about remote dev
netdevsim: pass packets thru GRO on Rx
selftests: drv-net: add a Python version of the GRO test
selftests: drv-net: hw: convert the Toeplitz test to Python
netdevsim: add loopback support
selftests: net: remove old setup_* scripts
tools/testing/selftests/drivers/net/Makefile | 2 +
.../testing/selftests/drivers/net/hw/Makefile | 6 +-
tools/testing/selftests/net/Makefile | 7 -
tools/testing/selftests/net/lib/Makefile | 1 +
drivers/net/netdevsim/netdev.c | 26 ++-
.../testing/selftests/{ => drivers}/net/gro.c | 5 +-
.../{net => drivers/net/hw}/toeplitz.c | 7 +-
.../testing/selftests/drivers/net/.gitignore | 1 +
tools/testing/selftests/drivers/net/gro.py | 161 ++++++++++++++
.../selftests/drivers/net/hw/.gitignore | 1 +
.../drivers/net/hw/lib/py/__init__.py | 4 +-
.../selftests/drivers/net/hw/toeplitz.py | 208 ++++++++++++++++++
.../selftests/drivers/net/lib/py/__init__.py | 4 +-
.../selftests/drivers/net/lib/py/env.py | 2 +
tools/testing/selftests/drivers/net/xdp.py | 42 ++--
tools/testing/selftests/net/.gitignore | 2 -
tools/testing/selftests/net/gro.sh | 105 ---------
.../selftests/net/lib/ksft_setup_loopback.sh | 111 ++++++++++
.../testing/selftests/net/lib/py/__init__.py | 5 +-
tools/testing/selftests/net/lib/py/ksft.py | 93 ++++++--
tools/testing/selftests/net/lib/py/nsim.py | 2 +-
tools/testing/selftests/net/lib/py/utils.py | 20 +-
tools/testing/selftests/net/setup_loopback.sh | 120 ----------
tools/testing/selftests/net/setup_veth.sh | 45 ----
tools/testing/selftests/net/toeplitz.sh | 199 -----------------
.../testing/selftests/net/toeplitz_client.sh | 28 ---
26 files changed, 630 insertions(+), 577 deletions(-)
rename tools/testing/selftests/{ => drivers}/net/gro.c (99%)
rename tools/testing/selftests/{net => drivers/net/hw}/toeplitz.c (99%)
create mode 100755 tools/testing/selftests/drivers/net/gro.py
create mode 100755 tools/testing/selftests/drivers/net/hw/toeplitz.py
delete mode 100755 tools/testing/selftests/net/gro.sh
create mode 100755 tools/testing/selftests/net/lib/ksft_setup_loopback.sh
delete mode 100644 tools/testing/selftests/net/setup_loopback.sh
delete mode 100644 tools/testing/selftests/net/setup_veth.sh
delete mode 100755 tools/testing/selftests/net/toeplitz.sh
delete mode 100755 tools/testing/selftests/net/toeplitz_client.sh
--
2.51.1
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH net-next v2 01/12] selftests: net: py: coding style improvements
2025-11-18 21:51 [PATCH net-next v2 00/12] selftests: drv-net: convert GRO and Toeplitz tests to work for drivers in NIPA Jakub Kicinski
@ 2025-11-18 21:51 ` Jakub Kicinski
2025-11-19 13:40 ` Petr Machata
2025-11-18 21:51 ` [PATCH net-next v2 02/12] selftests: net: py: extract the case generation logic Jakub Kicinski
` (11 subsequent siblings)
12 siblings, 1 reply; 30+ messages in thread
From: Jakub Kicinski @ 2025-11-18 21:51 UTC (permalink / raw)
To: davem
Cc: netdev, edumazet, pabeni, andrew+netdev, horms,
willemdebruijn.kernel, shuah, sdf, krakauer, linux-kselftest,
petrm, matttbe, Jakub Kicinski
We're about to add more features here and finding new issues with old
ones in place is hard. Address ruff checks:
- bare exceptions
- f-string with no params
- unused import
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
tools/testing/selftests/net/lib/py/ksft.py | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/tools/testing/selftests/net/lib/py/ksft.py b/tools/testing/selftests/net/lib/py/ksft.py
index 83b1574f7719..56dd9bd060cd 100644
--- a/tools/testing/selftests/net/lib/py/ksft.py
+++ b/tools/testing/selftests/net/lib/py/ksft.py
@@ -1,6 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
-import builtins
import functools
import inspect
import signal
@@ -163,7 +162,7 @@ KSFT_DISRUPTIVE = True
entry = global_defer_queue.pop()
try:
entry.exec_only()
- except:
+ except Exception:
ksft_pr(f"Exception while handling defer / cleanup (callback {i} of {qlen_start})!")
tb = traceback.format_exc()
for line in tb.strip().split('\n'):
@@ -181,7 +180,7 @@ KSFT_DISRUPTIVE = True
@functools.wraps(func)
def wrapper(*args, **kwargs):
if not KSFT_DISRUPTIVE:
- raise KsftSkipEx(f"marked as disruptive")
+ raise KsftSkipEx("marked as disruptive")
return func(*args, **kwargs)
return wrapper
@@ -199,7 +198,7 @@ KSFT_DISRUPTIVE = True
return False
try:
return bool(int(value))
- except:
+ except Exception:
raise Exception(f"failed to parse {name}")
if "DISRUPTIVE" in env:
--
2.51.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH net-next v2 02/12] selftests: net: py: extract the case generation logic
2025-11-18 21:51 [PATCH net-next v2 00/12] selftests: drv-net: convert GRO and Toeplitz tests to work for drivers in NIPA Jakub Kicinski
2025-11-18 21:51 ` [PATCH net-next v2 01/12] selftests: net: py: coding style improvements Jakub Kicinski
@ 2025-11-18 21:51 ` Jakub Kicinski
2025-11-19 14:11 ` Petr Machata
2025-11-18 21:51 ` [PATCH net-next v2 03/12] selftests: net: py: add test variants Jakub Kicinski
` (10 subsequent siblings)
12 siblings, 1 reply; 30+ messages in thread
From: Jakub Kicinski @ 2025-11-18 21:51 UTC (permalink / raw)
To: davem
Cc: netdev, edumazet, pabeni, andrew+netdev, horms,
willemdebruijn.kernel, shuah, sdf, krakauer, linux-kselftest,
petrm, matttbe, Jakub Kicinski
In preparation for adding test variants move the test case
collection logic to a dedicated function. New helper returns
(function, args, name, )
tuples. The main test loop can simply run them, not much
logic or discernment needed.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
tools/testing/selftests/net/lib/py/ksft.py | 31 +++++++++++++++-------
1 file changed, 22 insertions(+), 9 deletions(-)
diff --git a/tools/testing/selftests/net/lib/py/ksft.py b/tools/testing/selftests/net/lib/py/ksft.py
index 56dd9bd060cd..52c42c313cf2 100644
--- a/tools/testing/selftests/net/lib/py/ksft.py
+++ b/tools/testing/selftests/net/lib/py/ksft.py
@@ -135,7 +135,7 @@ KSFT_DISRUPTIVE = True
time.sleep(sleep)
-def ktap_result(ok, cnt=1, case="", comment=""):
+def ktap_result(ok, cnt=1, case_name="", comment=""):
global KSFT_RESULT_ALL
KSFT_RESULT_ALL = KSFT_RESULT_ALL and ok
@@ -145,8 +145,8 @@ KSFT_DISRUPTIVE = True
res += "ok "
res += str(cnt) + " "
res += KSFT_MAIN_NAME
- if case:
- res += "." + str(case.__name__)
+ if case_name:
+ res += "." + case_name
if comment:
res += " # " + comment
print(res, flush=True)
@@ -219,9 +219,13 @@ KSFT_DISRUPTIVE = True
ksft_pr(f"Ignoring SIGTERM (cnt: {term_cnt}), already exiting...")
-def ksft_run(cases=None, globs=None, case_pfx=None, args=()):
- cases = cases or []
+def _ksft_generate_test_cases(cases, globs, case_pfx, args):
+ """Generate a flat list of (func, args, name) tuples"""
+ cases = cases or []
+ test_cases = []
+
+ # If using the globs method find all relevant functions
if globs and case_pfx:
for key, value in globs.items():
if not callable(value):
@@ -231,6 +235,15 @@ KSFT_DISRUPTIVE = True
cases.append(value)
break
+ for func in cases:
+ test_cases.append((func, args, func.__name__))
+
+ return test_cases
+
+
+def ksft_run(cases=None, globs=None, case_pfx=None, args=()):
+ test_cases = _ksft_generate_test_cases(cases, globs, case_pfx, args)
+
global term_cnt
term_cnt = 0
prev_sigterm = signal.signal(signal.SIGTERM, _ksft_intr)
@@ -238,19 +251,19 @@ KSFT_DISRUPTIVE = True
totals = {"pass": 0, "fail": 0, "skip": 0, "xfail": 0}
print("TAP version 13", flush=True)
- print("1.." + str(len(cases)), flush=True)
+ print("1.." + str(len(test_cases)), flush=True)
global KSFT_RESULT
cnt = 0
stop = False
- for case in cases:
+ for func, args, name in test_cases:
KSFT_RESULT = True
cnt += 1
comment = ""
cnt_key = ""
try:
- case(*args)
+ func(*args)
except KsftSkipEx as e:
comment = "SKIP " + str(e)
cnt_key = 'skip'
@@ -272,7 +285,7 @@ KSFT_DISRUPTIVE = True
if not cnt_key:
cnt_key = 'pass' if KSFT_RESULT else 'fail'
- ktap_result(KSFT_RESULT, cnt, case, comment=comment)
+ ktap_result(KSFT_RESULT, cnt, name, comment=comment)
totals[cnt_key] += 1
if stop:
--
2.51.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH net-next v2 03/12] selftests: net: py: add test variants
2025-11-18 21:51 [PATCH net-next v2 00/12] selftests: drv-net: convert GRO and Toeplitz tests to work for drivers in NIPA Jakub Kicinski
2025-11-18 21:51 ` [PATCH net-next v2 01/12] selftests: net: py: coding style improvements Jakub Kicinski
2025-11-18 21:51 ` [PATCH net-next v2 02/12] selftests: net: py: extract the case generation logic Jakub Kicinski
@ 2025-11-18 21:51 ` Jakub Kicinski
2025-11-19 14:42 ` Petr Machata
2025-11-18 21:51 ` [PATCH net-next v2 04/12] selftests: drv-net: xdp: use variants for qstat tests Jakub Kicinski
` (9 subsequent siblings)
12 siblings, 1 reply; 30+ messages in thread
From: Jakub Kicinski @ 2025-11-18 21:51 UTC (permalink / raw)
To: davem
Cc: netdev, edumazet, pabeni, andrew+netdev, horms,
willemdebruijn.kernel, shuah, sdf, krakauer, linux-kselftest,
petrm, matttbe, Jakub Kicinski
There's a lot of cases where we try to re-run the same code with
different parameters. We currently need to either use a generator
method or create a "main" case implementation which then gets called
by trivial case functions:
def _test(x, y, z):
...
def case_int():
_test(1, 2, 3)
def case_str():
_test('a', 'b', 'c')
Add support for variants, similar to kselftests_harness.h and
a lot of other frameworks. Variants can be added as decorator
to test functions:
@ksft_variants([(1, 2, 3), ('a', 'b', 'c')])
def case(x, y, z):
...
ksft_run() will auto-generate case names:
case.1_2_3
case.a_b_c
Because the names may not always be pretty (and to avoid forcing
classes to implement case-friendly __str__()) add a wrapper class
KsftNamedVariant which lets the user specify the name for the variant.
Note that ksft_run's args are still supported. ksft_run splices args
and variant params together.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
.../drivers/net/hw/lib/py/__init__.py | 4 +-
.../selftests/drivers/net/lib/py/__init__.py | 4 +-
.../testing/selftests/net/lib/py/__init__.py | 5 +-
tools/testing/selftests/net/lib/py/ksft.py | 57 ++++++++++++++++++-
4 files changed, 63 insertions(+), 7 deletions(-)
diff --git a/tools/testing/selftests/drivers/net/hw/lib/py/__init__.py b/tools/testing/selftests/drivers/net/hw/lib/py/__init__.py
index fb010a48a5a1..0c61debf86fb 100644
--- a/tools/testing/selftests/drivers/net/hw/lib/py/__init__.py
+++ b/tools/testing/selftests/drivers/net/hw/lib/py/__init__.py
@@ -25,7 +25,7 @@ KSFT_DIR = (Path(__file__).parent / "../../../../..").resolve()
fd_read_timeout, ip, rand_port, wait_port_listen, wait_file
from net.lib.py import KsftSkipEx, KsftFailEx, KsftXfailEx
from net.lib.py import ksft_disruptive, ksft_exit, ksft_pr, ksft_run, \
- ksft_setup
+ ksft_setup, ksft_variants, KsftNamedVariant
from net.lib.py import ksft_eq, ksft_ge, ksft_in, ksft_is, ksft_lt, \
ksft_ne, ksft_not_in, ksft_raises, ksft_true, ksft_gt, ksft_not_none
from drivers.net.lib.py import GenerateTraffic, Remote
@@ -40,7 +40,7 @@ KSFT_DIR = (Path(__file__).parent / "../../../../..").resolve()
"wait_port_listen", "wait_file",
"KsftSkipEx", "KsftFailEx", "KsftXfailEx",
"ksft_disruptive", "ksft_exit", "ksft_pr", "ksft_run",
- "ksft_setup",
+ "ksft_setup", "ksft_variants", "KsftNamedVariant",
"ksft_eq", "ksft_ge", "ksft_in", "ksft_is", "ksft_lt",
"ksft_ne", "ksft_not_in", "ksft_raises", "ksft_true", "ksft_gt",
"ksft_not_none", "ksft_not_none",
diff --git a/tools/testing/selftests/drivers/net/lib/py/__init__.py b/tools/testing/selftests/drivers/net/lib/py/__init__.py
index b0c6300150fb..d9d035634a31 100644
--- a/tools/testing/selftests/drivers/net/lib/py/__init__.py
+++ b/tools/testing/selftests/drivers/net/lib/py/__init__.py
@@ -25,7 +25,7 @@ KSFT_DIR = (Path(__file__).parent / "../../../..").resolve()
fd_read_timeout, ip, rand_port, wait_port_listen, wait_file
from net.lib.py import KsftSkipEx, KsftFailEx, KsftXfailEx
from net.lib.py import ksft_disruptive, ksft_exit, ksft_pr, ksft_run, \
- ksft_setup
+ ksft_setup, ksft_variants, KsftNamedVariant
from net.lib.py import ksft_eq, ksft_ge, ksft_in, ksft_is, ksft_lt, \
ksft_ne, ksft_not_in, ksft_raises, ksft_true, ksft_gt, ksft_not_none
@@ -38,7 +38,7 @@ KSFT_DIR = (Path(__file__).parent / "../../../..").resolve()
"wait_port_listen", "wait_file",
"KsftSkipEx", "KsftFailEx", "KsftXfailEx",
"ksft_disruptive", "ksft_exit", "ksft_pr", "ksft_run",
- "ksft_setup",
+ "ksft_setup", "ksft_variants", "KsftNamedVariant",
"ksft_eq", "ksft_ge", "ksft_in", "ksft_is", "ksft_lt",
"ksft_ne", "ksft_not_in", "ksft_raises", "ksft_true", "ksft_gt",
"ksft_not_none", "ksft_not_none"]
diff --git a/tools/testing/selftests/net/lib/py/__init__.py b/tools/testing/selftests/net/lib/py/__init__.py
index 97b7cf2b20eb..40f9ce307dd1 100644
--- a/tools/testing/selftests/net/lib/py/__init__.py
+++ b/tools/testing/selftests/net/lib/py/__init__.py
@@ -8,7 +8,8 @@ from .consts import KSRC
from .ksft import KsftFailEx, KsftSkipEx, KsftXfailEx, ksft_pr, ksft_eq, \
ksft_ne, ksft_true, ksft_not_none, ksft_in, ksft_not_in, ksft_is, \
ksft_ge, ksft_gt, ksft_lt, ksft_raises, ksft_busy_wait, \
- ktap_result, ksft_disruptive, ksft_setup, ksft_run, ksft_exit
+ ktap_result, ksft_disruptive, ksft_setup, ksft_run, ksft_exit, \
+ ksft_variants, KsftNamedVariant
from .netns import NetNS, NetNSEnter
from .nsim import NetdevSim, NetdevSimDev
from .utils import CmdExitFailure, fd_read_timeout, cmd, bkg, defer, \
@@ -21,7 +22,7 @@ __all__ = ["KSRC",
"ksft_ne", "ksft_true", "ksft_not_none", "ksft_in", "ksft_not_in",
"ksft_is", "ksft_ge", "ksft_gt", "ksft_lt", "ksft_raises",
"ksft_busy_wait", "ktap_result", "ksft_disruptive", "ksft_setup",
- "ksft_run", "ksft_exit",
+ "ksft_run", "ksft_exit", "ksft_variants", "KsftNamedVariant",
"NetNS", "NetNSEnter",
"CmdExitFailure", "fd_read_timeout", "cmd", "bkg", "defer",
"bpftool", "ip", "ethtool", "bpftrace", "rand_port",
diff --git a/tools/testing/selftests/net/lib/py/ksft.py b/tools/testing/selftests/net/lib/py/ksft.py
index 52c42c313cf2..47e0af210bee 100644
--- a/tools/testing/selftests/net/lib/py/ksft.py
+++ b/tools/testing/selftests/net/lib/py/ksft.py
@@ -185,6 +185,49 @@ KSFT_DISRUPTIVE = True
return wrapper
+class KsftNamedVariant:
+ """ Named string name + argument list tuple for @ksft_variants """
+
+ def __init__(self, name, *params):
+ self.params = params
+ self.name = name or "_".join([str(x) for x in self.params])
+
+
+def ksft_variants(params):
+ """
+ Decorator defining the sets of inputs for a test.
+ The parameters will be included in the name of the resulting sub-case.
+ Parameters can be either single object, tuple or a KsftNamedVariant.
+ The argument can be a list or a generator.
+
+ Example:
+
+ @ksft_variants([
+ (1, "a"),
+ (2, "b"),
+ KsftNamedVariant("three", 3, "c"),
+ ])
+ def my_case(cfg, a, b):
+ pass # ...
+
+ ksft_run(cases=[my_case], args=(cfg, ))
+
+ Will generate cases:
+ my_case.1_a
+ my_case.2_b
+ my_case.three
+ """
+
+ def decorator(func):
+ @functools.wraps(func)
+ def wrapper():
+ return func
+ wrapper.ksft_variants = params
+ wrapper.original_func = func
+ return wrapper
+ return decorator
+
+
def ksft_setup(env):
"""
Setup test framework global state from the environment.
@@ -236,7 +279,19 @@ KSFT_DISRUPTIVE = True
break
for func in cases:
- test_cases.append((func, args, func.__name__))
+ if hasattr(func, 'ksft_variants'):
+ # Parametrized test - create case for each param
+ for param in func.ksft_variants:
+ if not isinstance(param, KsftNamedVariant):
+ if not isinstance(param, tuple):
+ param = (param, )
+ param = KsftNamedVariant(None, *param)
+
+ test_cases.append((func.original_func,
+ (*args, *param.params),
+ func.__name__ + "." + param.name))
+ else:
+ test_cases.append((func, args, func.__name__))
return test_cases
--
2.51.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH net-next v2 04/12] selftests: drv-net: xdp: use variants for qstat tests
2025-11-18 21:51 [PATCH net-next v2 00/12] selftests: drv-net: convert GRO and Toeplitz tests to work for drivers in NIPA Jakub Kicinski
` (2 preceding siblings ...)
2025-11-18 21:51 ` [PATCH net-next v2 03/12] selftests: net: py: add test variants Jakub Kicinski
@ 2025-11-18 21:51 ` Jakub Kicinski
2025-11-19 14:57 ` Petr Machata
2025-11-18 21:51 ` [PATCH net-next v2 05/12] selftests: net: relocate gro and toeplitz tests to drivers/net Jakub Kicinski
` (8 subsequent siblings)
12 siblings, 1 reply; 30+ messages in thread
From: Jakub Kicinski @ 2025-11-18 21:51 UTC (permalink / raw)
To: davem
Cc: netdev, edumazet, pabeni, andrew+netdev, horms,
willemdebruijn.kernel, shuah, sdf, krakauer, linux-kselftest,
petrm, matttbe, Jakub Kicinski
Use just-added ksft variants for XDP qstat tests.
While at it correct the number of packets, we're sending
1000 packets now.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
tools/testing/selftests/drivers/net/xdp.py | 42 ++++++++--------------
1 file changed, 14 insertions(+), 28 deletions(-)
diff --git a/tools/testing/selftests/drivers/net/xdp.py b/tools/testing/selftests/drivers/net/xdp.py
index 834a37ae7d0d..e54df158dfe9 100755
--- a/tools/testing/selftests/drivers/net/xdp.py
+++ b/tools/testing/selftests/drivers/net/xdp.py
@@ -12,6 +12,7 @@ from dataclasses import dataclass
from enum import Enum
from lib.py import ksft_run, ksft_exit, ksft_eq, ksft_ge, ksft_ne, ksft_pr
+from lib.py import KsftNamedVariant, ksft_variants
from lib.py import KsftFailEx, NetDrvEpEnv
from lib.py import EthtoolFamily, NetdevFamily, NlError
from lib.py import bkg, cmd, rand_port, wait_port_listen
@@ -672,7 +673,18 @@ from lib.py import ip, bpftool, defer
_validate_res(res, offset_lst, pkt_sz_lst)
-def _test_xdp_native_ifc_stats(cfg, act):
+@ksft_variants([
+ KsftNamedVariant("pass", XDPAction.PASS),
+ KsftNamedVariant("drop", XDPAction.DROP),
+ KsftNamedVariant("tx", XDPAction.TX),
+])
+def test_xdp_native_qstats(cfg, act):
+ """
+ Send 1000 messages. Expect XDP action specified in @act.
+ Make sure the packets were counted to interface level qstats
+ (Rx, and Tx if act is TX).
+ """
+
cfg.require_cmd("socat")
bpf_info = BPFProgInfo("xdp_prog", "xdp_native.bpf.o", "xdp", 1500)
@@ -733,30 +745,6 @@ from lib.py import ip, bpftool, defer
ksft_ge(after['tx-packets'], before['tx-packets'])
-def test_xdp_native_qstats_pass(cfg):
- """
- Send 2000 messages, expect XDP_PASS, make sure the packets were counted
- to interface level qstats (Rx).
- """
- _test_xdp_native_ifc_stats(cfg, XDPAction.PASS)
-
-
-def test_xdp_native_qstats_drop(cfg):
- """
- Send 2000 messages, expect XDP_DROP, make sure the packets were counted
- to interface level qstats (Rx).
- """
- _test_xdp_native_ifc_stats(cfg, XDPAction.DROP)
-
-
-def test_xdp_native_qstats_tx(cfg):
- """
- Send 2000 messages, expect XDP_TX, make sure the packets were counted
- to interface level qstats (Rx and Tx)
- """
- _test_xdp_native_ifc_stats(cfg, XDPAction.TX)
-
-
def main():
"""
Main function to execute the XDP tests.
@@ -781,9 +769,7 @@ from lib.py import ip, bpftool, defer
test_xdp_native_adjst_tail_shrnk_data,
test_xdp_native_adjst_head_grow_data,
test_xdp_native_adjst_head_shrnk_data,
- test_xdp_native_qstats_pass,
- test_xdp_native_qstats_drop,
- test_xdp_native_qstats_tx,
+ test_xdp_native_qstats,
],
args=(cfg,))
ksft_exit()
--
2.51.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH net-next v2 05/12] selftests: net: relocate gro and toeplitz tests to drivers/net
2025-11-18 21:51 [PATCH net-next v2 00/12] selftests: drv-net: convert GRO and Toeplitz tests to work for drivers in NIPA Jakub Kicinski
` (3 preceding siblings ...)
2025-11-18 21:51 ` [PATCH net-next v2 04/12] selftests: drv-net: xdp: use variants for qstat tests Jakub Kicinski
@ 2025-11-18 21:51 ` Jakub Kicinski
2025-11-19 15:09 ` Petr Machata
2025-11-18 21:51 ` [PATCH net-next v2 06/12] selftests: net: py: support ksft ready without wait Jakub Kicinski
` (7 subsequent siblings)
12 siblings, 1 reply; 30+ messages in thread
From: Jakub Kicinski @ 2025-11-18 21:51 UTC (permalink / raw)
To: davem
Cc: netdev, edumazet, pabeni, andrew+netdev, horms,
willemdebruijn.kernel, shuah, sdf, krakauer, linux-kselftest,
petrm, matttbe, Jakub Kicinski
The GRO test can run on a real device or a veth.
The Toeplitz hash test can only run on a real device.
Move them from net/ to drivers/net/ and drivers/net/hw/ respectively.
There are two scripts which set up the environment for these tests
setup_loopback.sh and setup_veth.sh. Move those scripts to net/lib.
The paths to the setup files are a little ugly but they will be
deleted shortly.
toeplitz_client.sh is not a test in itself, but rather a helper
to send traffic, so add it to TEST_FILES rather than TEST_PROGS.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
v2:
- fix accidental modification of gitignore
v1: https://lore.kernel.org/20251117205810.1617533-6-kuba@kernel.org
---
tools/testing/selftests/drivers/net/Makefile | 2 ++
tools/testing/selftests/drivers/net/hw/Makefile | 7 ++++++-
tools/testing/selftests/net/Makefile | 7 -------
tools/testing/selftests/net/lib/Makefile | 2 ++
tools/testing/selftests/{ => drivers}/net/gro.c | 2 +-
tools/testing/selftests/{net => drivers/net/hw}/toeplitz.c | 2 +-
tools/testing/selftests/drivers/net/.gitignore | 1 +
tools/testing/selftests/{ => drivers}/net/gro.sh | 4 ++--
tools/testing/selftests/drivers/net/hw/.gitignore | 1 +
.../testing/selftests/{net => drivers/net/hw}/toeplitz.sh | 2 +-
.../selftests/{net => drivers/net/hw}/toeplitz_client.sh | 0
tools/testing/selftests/net/.gitignore | 2 --
tools/testing/selftests/net/{ => lib}/setup_loopback.sh | 0
tools/testing/selftests/net/{ => lib}/setup_veth.sh | 0
14 files changed, 17 insertions(+), 15 deletions(-)
rename tools/testing/selftests/{ => drivers}/net/gro.c (99%)
rename tools/testing/selftests/{net => drivers/net/hw}/toeplitz.c (99%)
rename tools/testing/selftests/{ => drivers}/net/gro.sh (95%)
rename tools/testing/selftests/{net => drivers/net/hw}/toeplitz.sh (98%)
rename tools/testing/selftests/{net => drivers/net/hw}/toeplitz_client.sh (100%)
rename tools/testing/selftests/net/{ => lib}/setup_loopback.sh (100%)
rename tools/testing/selftests/net/{ => lib}/setup_veth.sh (100%)
diff --git a/tools/testing/selftests/drivers/net/Makefile b/tools/testing/selftests/drivers/net/Makefile
index 33f4816216ec..7083a8707c4e 100644
--- a/tools/testing/selftests/drivers/net/Makefile
+++ b/tools/testing/selftests/drivers/net/Makefile
@@ -6,10 +6,12 @@ TEST_INCLUDES := $(wildcard lib/py/*.py) \
../../net/lib.sh \
TEST_GEN_FILES := \
+ gro \
napi_id_helper \
# end of TEST_GEN_FILES
TEST_PROGS := \
+ gro.sh \
hds.py \
napi_id.py \
napi_threaded.py \
diff --git a/tools/testing/selftests/drivers/net/hw/Makefile b/tools/testing/selftests/drivers/net/hw/Makefile
index 8133d1a0051c..c9dced8c934a 100644
--- a/tools/testing/selftests/drivers/net/hw/Makefile
+++ b/tools/testing/selftests/drivers/net/hw/Makefile
@@ -1,6 +1,9 @@
# SPDX-License-Identifier: GPL-2.0+ OR MIT
-TEST_GEN_FILES = iou-zcrx
+TEST_GEN_FILES := \
+ iou-zcrx \
+ toeplitz \
+# end of TEST_GEN_FILES
TEST_PROGS = \
csum.py \
@@ -21,12 +24,14 @@ TEST_PROGS = \
rss_ctx.py \
rss_flow_label.py \
rss_input_xfrm.py \
+ toeplitz.sh \
tso.py \
xsk_reconfig.py \
#
TEST_FILES := \
ethtool_lib.sh \
+ toeplitz_client.sh \
#
TEST_INCLUDES := \
diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile
index b5127e968108..b66ba04f19d9 100644
--- a/tools/testing/selftests/net/Makefile
+++ b/tools/testing/selftests/net/Makefile
@@ -38,7 +38,6 @@ TEST_PROGS := \
fq_band_pktlimit.sh \
gre_gso.sh \
gre_ipv6_lladdr.sh \
- gro.sh \
icmp.sh \
icmp_redirect.sh \
io_uring_zerocopy_tx.sh \
@@ -121,8 +120,6 @@ TEST_PROGS := \
# end of TEST_PROGS
TEST_PROGS_EXTENDED := \
- toeplitz.sh \
- toeplitz_client.sh \
xfrm_policy_add_speed.sh \
# end of TEST_PROGS_EXTENDED
@@ -130,7 +127,6 @@ TEST_GEN_FILES := \
bind_bhash \
cmsg_sender \
fin_ack_lat \
- gro \
hwtstamp_config \
io_uring_zerocopy_tx \
ioam6_parser \
@@ -159,7 +155,6 @@ TEST_GEN_FILES := \
tcp_mmap \
tfo \
timestamping \
- toeplitz \
txring_overwrite \
txtimestamp \
udpgso \
@@ -193,8 +188,6 @@ TEST_FILES := \
in_netns.sh \
lib.sh \
settings \
- setup_loopback.sh \
- setup_veth.sh \
# end of TEST_FILES
# YNL files, must be before "include ..lib.mk"
diff --git a/tools/testing/selftests/net/lib/Makefile b/tools/testing/selftests/net/lib/Makefile
index ce795bc0a1af..c10796933d42 100644
--- a/tools/testing/selftests/net/lib/Makefile
+++ b/tools/testing/selftests/net/lib/Makefile
@@ -8,6 +8,8 @@ CFLAGS += -I../../
TEST_FILES := \
../../../../net/ynl \
../../../../../Documentation/netlink/specs \
+ setup_loopback.sh \
+ setup_veth.sh \
# end of TEST_FILES
TEST_GEN_FILES := \
diff --git a/tools/testing/selftests/net/gro.c b/tools/testing/selftests/drivers/net/gro.c
similarity index 99%
rename from tools/testing/selftests/net/gro.c
rename to tools/testing/selftests/drivers/net/gro.c
index cfc39f70635d..9b9be0cf8f7f 100644
--- a/tools/testing/selftests/net/gro.c
+++ b/tools/testing/selftests/drivers/net/gro.c
@@ -57,7 +57,7 @@
#include <string.h>
#include <unistd.h>
-#include "../kselftest.h"
+#include "../../kselftest.h"
#define DPORT 8000
#define SPORT 1500
diff --git a/tools/testing/selftests/net/toeplitz.c b/tools/testing/selftests/drivers/net/hw/toeplitz.c
similarity index 99%
rename from tools/testing/selftests/net/toeplitz.c
rename to tools/testing/selftests/drivers/net/hw/toeplitz.c
index 9ba03164d73a..bf74aa25345d 100644
--- a/tools/testing/selftests/net/toeplitz.c
+++ b/tools/testing/selftests/drivers/net/hw/toeplitz.c
@@ -52,7 +52,7 @@
#include <sys/types.h>
#include <unistd.h>
-#include "../kselftest.h"
+#include "../../../kselftest.h"
#define TOEPLITZ_KEY_MIN_LEN 40
#define TOEPLITZ_KEY_MAX_LEN 60
diff --git a/tools/testing/selftests/drivers/net/.gitignore b/tools/testing/selftests/drivers/net/.gitignore
index 585ecb4d5dc4..3633c7a3ed65 100644
--- a/tools/testing/selftests/drivers/net/.gitignore
+++ b/tools/testing/selftests/drivers/net/.gitignore
@@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-only
+gro
napi_id_helper
psp_responder
diff --git a/tools/testing/selftests/net/gro.sh b/tools/testing/selftests/drivers/net/gro.sh
similarity index 95%
rename from tools/testing/selftests/net/gro.sh
rename to tools/testing/selftests/drivers/net/gro.sh
index 4c5144c6f652..bd3cf6d02eda 100755
--- a/tools/testing/selftests/net/gro.sh
+++ b/tools/testing/selftests/drivers/net/gro.sh
@@ -90,9 +90,9 @@ while getopts "i:t:p:" opt; do
done
if [ -n "$dev" ]; then
- source setup_loopback.sh
+ source $(dirname $0)/../../net/lib/setup_loopback.sh
else
- source setup_veth.sh
+ source $(dirname $0)/../../net/lib/setup_veth.sh
fi
setup
diff --git a/tools/testing/selftests/drivers/net/hw/.gitignore b/tools/testing/selftests/drivers/net/hw/.gitignore
index 6942bf575497..46540468a775 100644
--- a/tools/testing/selftests/drivers/net/hw/.gitignore
+++ b/tools/testing/selftests/drivers/net/hw/.gitignore
@@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-only
iou-zcrx
ncdevmem
+toeplitz
diff --git a/tools/testing/selftests/net/toeplitz.sh b/tools/testing/selftests/drivers/net/hw/toeplitz.sh
similarity index 98%
rename from tools/testing/selftests/net/toeplitz.sh
rename to tools/testing/selftests/drivers/net/hw/toeplitz.sh
index 8ff172f7bb1b..d236b666dd3b 100755
--- a/tools/testing/selftests/net/toeplitz.sh
+++ b/tools/testing/selftests/drivers/net/hw/toeplitz.sh
@@ -11,7 +11,7 @@
# invoke as ./toeplitz.sh (-i <iface>) -u|-t -4|-6 \
# [(-rss -irq_prefix <irq-pattern-prefix>)|(-rps <rps_map>)]
-source setup_loopback.sh
+source $(dirname $0)/../../../net/lib/setup_loopback.sh
readonly SERVER_IP4="192.168.1.200/24"
readonly SERVER_IP6="fda8::1/64"
readonly SERVER_MAC="aa:00:00:00:00:02"
diff --git a/tools/testing/selftests/net/toeplitz_client.sh b/tools/testing/selftests/drivers/net/hw/toeplitz_client.sh
similarity index 100%
rename from tools/testing/selftests/net/toeplitz_client.sh
rename to tools/testing/selftests/drivers/net/hw/toeplitz_client.sh
diff --git a/tools/testing/selftests/net/.gitignore b/tools/testing/selftests/net/.gitignore
index e89a60581a13..e139b7186c6c 100644
--- a/tools/testing/selftests/net/.gitignore
+++ b/tools/testing/selftests/net/.gitignore
@@ -7,7 +7,6 @@ cmsg_sender
diag_uid
epoll_busy_poll
fin_ack_lat
-gro
hwtstamp_config
io_uring_zerocopy_tx
ioam6_parser
@@ -56,7 +55,6 @@ tcp_port_share
tfo
timestamping
tls
-toeplitz
tools
tun
txring_overwrite
diff --git a/tools/testing/selftests/net/setup_loopback.sh b/tools/testing/selftests/net/lib/setup_loopback.sh
similarity index 100%
rename from tools/testing/selftests/net/setup_loopback.sh
rename to tools/testing/selftests/net/lib/setup_loopback.sh
diff --git a/tools/testing/selftests/net/setup_veth.sh b/tools/testing/selftests/net/lib/setup_veth.sh
similarity index 100%
rename from tools/testing/selftests/net/setup_veth.sh
rename to tools/testing/selftests/net/lib/setup_veth.sh
--
2.51.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH net-next v2 06/12] selftests: net: py: support ksft ready without wait
2025-11-18 21:51 [PATCH net-next v2 00/12] selftests: drv-net: convert GRO and Toeplitz tests to work for drivers in NIPA Jakub Kicinski
` (4 preceding siblings ...)
2025-11-18 21:51 ` [PATCH net-next v2 05/12] selftests: net: relocate gro and toeplitz tests to drivers/net Jakub Kicinski
@ 2025-11-18 21:51 ` Jakub Kicinski
2025-11-19 16:31 ` Petr Machata
2025-11-18 21:51 ` [PATCH net-next v2 07/12] selftests: net: py: read ip link info about remote dev Jakub Kicinski
` (6 subsequent siblings)
12 siblings, 1 reply; 30+ messages in thread
From: Jakub Kicinski @ 2025-11-18 21:51 UTC (permalink / raw)
To: davem
Cc: netdev, edumazet, pabeni, andrew+netdev, horms,
willemdebruijn.kernel, shuah, sdf, krakauer, linux-kselftest,
petrm, matttbe, Jakub Kicinski
There's a common synchronization problem when a script (Python test)
uses a C program to set up some state (usually start a receiving
process for traffic). The script needs to know when the process
has fully initialized. The inverse of the problem exists for shutting
the process down - we need a reliable way to tell the process to exit.
We added helpers to do this safely in
commit 71477137994f ("selftests: drv-net: add a way to wait for a local process")
unfortunately the two operations (wait for init, and shutdown) are
controlled by a single parameter (ksft_wait). Add support for using
ksft_ready without using the second fd for exit.
This is useful for programs which wait for a specific number of packets
to rx so exit_wait is a good match, but we still need to wait for init.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
tools/testing/selftests/net/lib/py/utils.py | 20 ++++++++++++--------
1 file changed, 12 insertions(+), 8 deletions(-)
diff --git a/tools/testing/selftests/net/lib/py/utils.py b/tools/testing/selftests/net/lib/py/utils.py
index cb40ecef9456..106ee1f2df86 100644
--- a/tools/testing/selftests/net/lib/py/utils.py
+++ b/tools/testing/selftests/net/lib/py/utils.py
@@ -32,7 +32,7 @@ import time
Use bkg() instead to run a command in the background.
"""
def __init__(self, comm, shell=None, fail=True, ns=None, background=False,
- host=None, timeout=5, ksft_wait=None):
+ host=None, timeout=5, ksft_ready=None, ksft_wait=None):
if ns:
comm = f'ip netns exec {ns} ' + comm
@@ -52,21 +52,25 @@ import time
# ksft_wait lets us wait for the background process to fully start,
# we pass an FD to the child process, and wait for it to write back.
# Similarly term_fd tells child it's time to exit.
- pass_fds = ()
+ pass_fds = []
env = os.environ.copy()
if ksft_wait is not None:
- rfd, ready_fd = os.pipe()
wait_fd, self.ksft_term_fd = os.pipe()
- pass_fds = (ready_fd, wait_fd, )
- env["KSFT_READY_FD"] = str(ready_fd)
+ pass_fds.append(wait_fd)
env["KSFT_WAIT_FD"] = str(wait_fd)
+ ksft_ready = True # ksft_wait implies ready
+ if ksft_ready is not None:
+ rfd, ready_fd = os.pipe()
+ pass_fds.append(ready_fd)
+ env["KSFT_READY_FD"] = str(ready_fd)
self.proc = subprocess.Popen(comm, shell=shell, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, pass_fds=pass_fds,
env=env)
if ksft_wait is not None:
- os.close(ready_fd)
os.close(wait_fd)
+ if ksft_ready is not None:
+ os.close(ready_fd)
msg = fd_read_timeout(rfd, ksft_wait)
os.close(rfd)
if not msg:
@@ -116,10 +120,10 @@ import time
with bkg("my_binary", ksft_wait=5):
"""
def __init__(self, comm, shell=None, fail=None, ns=None, host=None,
- exit_wait=False, ksft_wait=None):
+ exit_wait=False, ksft_ready=None, ksft_wait=None):
super().__init__(comm, background=True,
shell=shell, fail=fail, ns=ns, host=host,
- ksft_wait=ksft_wait)
+ ksft_ready=ksft_ready, ksft_wait=ksft_wait)
self.terminate = not exit_wait and not ksft_wait
self._exit_wait = exit_wait
self.check_fail = fail
--
2.51.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH net-next v2 07/12] selftests: net: py: read ip link info about remote dev
2025-11-18 21:51 [PATCH net-next v2 00/12] selftests: drv-net: convert GRO and Toeplitz tests to work for drivers in NIPA Jakub Kicinski
` (5 preceding siblings ...)
2025-11-18 21:51 ` [PATCH net-next v2 06/12] selftests: net: py: support ksft ready without wait Jakub Kicinski
@ 2025-11-18 21:51 ` Jakub Kicinski
2025-11-19 15:33 ` Petr Machata
2025-11-18 21:51 ` [PATCH net-next v2 08/12] netdevsim: pass packets thru GRO on Rx Jakub Kicinski
` (5 subsequent siblings)
12 siblings, 1 reply; 30+ messages in thread
From: Jakub Kicinski @ 2025-11-18 21:51 UTC (permalink / raw)
To: davem
Cc: netdev, edumazet, pabeni, andrew+netdev, horms,
willemdebruijn.kernel, shuah, sdf, krakauer, linux-kselftest,
petrm, matttbe, Jakub Kicinski
We're already saving the info about the local dev in env.dev
for the tests, save remote dev as well. This is more symmetric,
env generally provides the same info for local and remote end.
While at it make sure that we reliably get the detailed info
about the local dev. nsim used to read the dev info without -d.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
tools/testing/selftests/drivers/net/lib/py/env.py | 2 ++
tools/testing/selftests/net/lib/py/nsim.py | 2 +-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/drivers/net/lib/py/env.py b/tools/testing/selftests/drivers/net/lib/py/env.py
index 01be3d9b9720..8b644fd84ff2 100644
--- a/tools/testing/selftests/drivers/net/lib/py/env.py
+++ b/tools/testing/selftests/drivers/net/lib/py/env.py
@@ -168,6 +168,8 @@ from .remote import Remote
# resolve remote interface name
self.remote_ifname = self.resolve_remote_ifc()
+ self.remote_dev = ip("-d link show dev " + self.remote_ifname,
+ host=self.remote, json=True)[0]
self._required_cmd = {}
diff --git a/tools/testing/selftests/net/lib/py/nsim.py b/tools/testing/selftests/net/lib/py/nsim.py
index 1a8cbe9acc48..7c640ed64c0b 100644
--- a/tools/testing/selftests/net/lib/py/nsim.py
+++ b/tools/testing/selftests/net/lib/py/nsim.py
@@ -27,7 +27,7 @@ from .utils import cmd, ip
self.port_index = port_index
self.ns = ns
self.dfs_dir = "%s/ports/%u/" % (nsimdev.dfs_dir, port_index)
- ret = ip("-j link show dev %s" % ifname, ns=ns)
+ ret = ip("-d -j link show dev %s" % ifname, ns=ns)
self.dev = json.loads(ret.stdout)[0]
self.ifindex = self.dev["ifindex"]
--
2.51.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH net-next v2 08/12] netdevsim: pass packets thru GRO on Rx
2025-11-18 21:51 [PATCH net-next v2 00/12] selftests: drv-net: convert GRO and Toeplitz tests to work for drivers in NIPA Jakub Kicinski
` (6 preceding siblings ...)
2025-11-18 21:51 ` [PATCH net-next v2 07/12] selftests: net: py: read ip link info about remote dev Jakub Kicinski
@ 2025-11-18 21:51 ` Jakub Kicinski
2025-11-19 15:43 ` Petr Machata
2025-11-18 21:51 ` [PATCH net-next v2 09/12] selftests: drv-net: add a Python version of the GRO test Jakub Kicinski
` (4 subsequent siblings)
12 siblings, 1 reply; 30+ messages in thread
From: Jakub Kicinski @ 2025-11-18 21:51 UTC (permalink / raw)
To: davem
Cc: netdev, edumazet, pabeni, andrew+netdev, horms,
willemdebruijn.kernel, shuah, sdf, krakauer, linux-kselftest,
petrm, matttbe, Jakub Kicinski
To replace veth in software GRO testing with netdevsim we need
GRO support in netdevsim. Luckily we already have NAPI support
so this change is trivial (compared to veth).
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
v2:
- fix typo "compared"
v1: https://lore.kernel.org/20251117205810.1617533-9-kuba@kernel.org
---
drivers/net/netdevsim/netdev.c | 9 ++-------
1 file changed, 2 insertions(+), 7 deletions(-)
diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c
index fa1d97885caa..2b713db16cd0 100644
--- a/drivers/net/netdevsim/netdev.c
+++ b/drivers/net/netdevsim/netdev.c
@@ -433,13 +433,8 @@ static int nsim_rcv(struct nsim_rq *rq, int budget)
}
/* skb might be discard at netif_receive_skb, save the len */
- skblen = skb->len;
- skb_mark_napi_id(skb, &rq->napi);
- ret = netif_receive_skb(skb);
- if (ret == NET_RX_SUCCESS)
- dev_dstats_rx_add(dev, skblen);
- else
- dev_dstats_rx_dropped(dev);
+ dev_dstats_rx_add(dev, skb->len);
+ napi_gro_receive(&rq->napi, skb);
}
nsim_start_peer_tx_queue(dev, rq);
--
2.51.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH net-next v2 09/12] selftests: drv-net: add a Python version of the GRO test
2025-11-18 21:51 [PATCH net-next v2 00/12] selftests: drv-net: convert GRO and Toeplitz tests to work for drivers in NIPA Jakub Kicinski
` (7 preceding siblings ...)
2025-11-18 21:51 ` [PATCH net-next v2 08/12] netdevsim: pass packets thru GRO on Rx Jakub Kicinski
@ 2025-11-18 21:51 ` Jakub Kicinski
2025-11-19 15:54 ` Petr Machata
2025-11-18 21:51 ` [PATCH net-next v2 10/12] selftests: drv-net: hw: convert the Toeplitz test to Python Jakub Kicinski
` (3 subsequent siblings)
12 siblings, 1 reply; 30+ messages in thread
From: Jakub Kicinski @ 2025-11-18 21:51 UTC (permalink / raw)
To: davem
Cc: netdev, edumazet, pabeni, andrew+netdev, horms,
willemdebruijn.kernel, shuah, sdf, krakauer, linux-kselftest,
petrm, matttbe, Jakub Kicinski
Rewrite the existing gro.sh test in Python. The conversion
not exact, the changes are related to integrating the test
with our "remote endpoint" paradigm. The test now reads
the IP addresses from the user config. It resolves the MAC
address (including running over Layer 3 networks).
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
v2:
- fix typo I -> It
v1: https://lore.kernel.org/20251117205810.1617533-10-kuba@kernel.org
---
tools/testing/selftests/drivers/net/Makefile | 2 +-
tools/testing/selftests/drivers/net/gro.c | 3 +
tools/testing/selftests/drivers/net/gro.py | 161 +++++++++++++++++++
tools/testing/selftests/drivers/net/gro.sh | 105 ------------
4 files changed, 165 insertions(+), 106 deletions(-)
create mode 100755 tools/testing/selftests/drivers/net/gro.py
delete mode 100755 tools/testing/selftests/drivers/net/gro.sh
diff --git a/tools/testing/selftests/drivers/net/Makefile b/tools/testing/selftests/drivers/net/Makefile
index 7083a8707c4e..f5c71d993750 100644
--- a/tools/testing/selftests/drivers/net/Makefile
+++ b/tools/testing/selftests/drivers/net/Makefile
@@ -11,7 +11,7 @@ TEST_GEN_FILES := \
# end of TEST_GEN_FILES
TEST_PROGS := \
- gro.sh \
+ gro.py \
hds.py \
napi_id.py \
napi_threaded.py \
diff --git a/tools/testing/selftests/drivers/net/gro.c b/tools/testing/selftests/drivers/net/gro.c
index 9b9be0cf8f7f..995b492f5bcb 100644
--- a/tools/testing/selftests/drivers/net/gro.c
+++ b/tools/testing/selftests/drivers/net/gro.c
@@ -58,6 +58,7 @@
#include <unistd.h>
#include "../../kselftest.h"
+#include "../../net/lib/ksft.h"
#define DPORT 8000
#define SPORT 1500
@@ -1127,6 +1128,8 @@ static void gro_receiver(void)
set_timeout(rxfd);
bind_packetsocket(rxfd);
+ ksft_ready();
+
memset(correct_payload, 0, sizeof(correct_payload));
if (strcmp(testname, "data") == 0) {
diff --git a/tools/testing/selftests/drivers/net/gro.py b/tools/testing/selftests/drivers/net/gro.py
new file mode 100755
index 000000000000..f8ec84e2fbb2
--- /dev/null
+++ b/tools/testing/selftests/drivers/net/gro.py
@@ -0,0 +1,161 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0
+
+"""
+GRO (Generic Receive Offload) conformance tests.
+
+Validates that GRO coalescing works correctly by running the gro
+binary in different configurations and checking for correct packet
+coalescing behavior.
+
+Test cases:
+ - data: Data packets with same size/headers and correct seq numbers coalesce
+ - ack: Pure ACK packets do not coalesce
+ - flags: Packets with PSH, SYN, URG, RST flags do not coalesce
+ - tcp: Packets with incorrect checksum, non-consecutive seqno don't coalesce
+ - ip: Packets with different ECN, TTL, TOS, or IP options don't coalesce
+ - large: Packets larger than GRO_MAX_SIZE don't coalesce
+"""
+
+import os
+from lib.py import ksft_run, ksft_exit, ksft_pr
+from lib.py import NetDrvEpEnv, KsftXfailEx
+from lib.py import cmd, defer, bkg, ip
+from lib.py import ksft_variants
+
+
+def _resolve_dmac(cfg, ipver):
+ """
+ Find the destination MAC address remote host should use to send packets
+ towards the local host. It may be a router / gateway address.
+ """
+
+ attr = "dmac" + ipver
+ # Cache the response across test cases
+ if hasattr(cfg, attr):
+ return getattr(cfg, attr)
+
+ route = ip(f"-{ipver} route get {cfg.addr_v[ipver]}",
+ json=True, host=cfg.remote)[0]
+ gw = route.get("gateway")
+ # Local L2 segment, address directly
+ if not gw:
+ setattr(cfg, attr, cfg.dev['address'])
+ return getattr(cfg, attr)
+
+ # ping to make sure neighbor is resolved,
+ # bind to an interface, for v6 the GW is likely link local
+ cmd(f"ping -c1 -W0 -I{cfg.remote_ifname} {gw}", host=cfg.remote)
+
+ neigh = ip(f"neigh get {gw} dev {cfg.remote_ifname}",
+ json=True, host=cfg.remote)[0]
+ setattr(cfg, attr, neigh['lladdr'])
+ return getattr(cfg, attr)
+
+
+def _write_defer_restore(cfg, path, val, defer_undo=False):
+ with open(path, "r", encoding="utf-8") as fp:
+ orig_val = fp.read().strip()
+ if str(val) == orig_val:
+ return
+ with open(path, "w", encoding="utf-8") as fp:
+ fp.write(val)
+ if defer_undo:
+ defer(_write_defer_restore, cfg, path, orig_val)
+
+
+def _set_mtu_restore(dev, mtu, host):
+ if dev['mtu'] < mtu:
+ ip(f"link set dev {dev['ifname']} mtu {mtu}", host=host)
+ defer(ip, f"link set dev {dev['ifname']} mtu {dev['mtu']}", host=host)
+
+
+def _setup(cfg):
+ """ Setup hardware loopback mode for GRO testing. """
+
+ if not hasattr(cfg, "bin_remote"):
+ cfg.bin_local = cfg.test_dir / "gro"
+ cfg.bin_remote = cfg.remote.deploy(cfg.bin_local)
+
+ flush_path = f"/sys/class/net/{cfg.ifname}/gro_flush_timeout"
+ irq_path = f"/sys/class/net/{cfg.ifname}/napi_defer_hard_irqs"
+
+ _write_defer_restore(cfg, flush_path, "200000", defer_undo=True)
+ _write_defer_restore(cfg, irq_path, "10", defer_undo=True)
+
+ try:
+ # Disable TSO for local tests
+ cfg.require_nsim() # will raise KsftXfailEx if not running on nsim
+
+ cmd(f"ethtool -K {cfg.ifname} gro on tso off")
+ cmd(f"ethtool -K {cfg.remote_ifname} gro on tso off", host=cfg.remote)
+ except KsftXfailEx:
+ pass
+
+def _gro_variants():
+ """Generator that yields all combinations of protocol and test types."""
+
+ for protocol in ["ipv4", "ipv6", "ipip"]:
+ for test_name in ["data", "ack", "flags", "tcp", "ip", "large"]:
+ yield protocol, test_name
+
+
+@ksft_variants(_gro_variants())
+def test(cfg, protocol, test_name):
+ """Run a single GRO test with retries."""
+
+ ipver = "6" if protocol[-1] == "6" else "4"
+ cfg.require_ipver(ipver)
+
+ _setup(cfg)
+
+ # "large" test needs at least 4k MTU
+ if test_name == "large":
+ _set_mtu_restore(cfg.dev, 4096, None)
+ _set_mtu_restore(cfg.remote_dev, 4096, cfg.remote)
+
+ base_cmd_args = [
+ f"--{protocol}",
+ f"--dmac {_resolve_dmac(cfg, ipver)}",
+ f"--smac {cfg.remote_dev['address']}",
+ f"--daddr {cfg.addr_v[ipver]}",
+ f"--saddr {cfg.remote_addr_v[ipver]}",
+ f"--test {test_name}",
+ "--verbose"
+ ]
+ base_args = " ".join(base_cmd_args)
+
+ max_retries = 6
+ for attempt in range(max_retries):
+ rx_cmd = f"{cfg.bin_local} {base_args} --rx --iface {cfg.ifname}"
+ tx_cmd = f"{cfg.bin_remote} {base_args} --iface {cfg.remote_ifname}"
+
+ fail_now = attempt >= max_retries - 1
+
+ with bkg(rx_cmd, ksft_ready=True, exit_wait=True,
+ fail=fail_now) as rx_proc:
+ cmd(tx_cmd, host=cfg.remote)
+
+ if rx_proc.ret == 0:
+ return
+
+ ksft_pr(rx_proc.stdout.strip().replace('\n', '\n# '))
+ ksft_pr(rx_proc.stderr.strip().replace('\n', '\n# '))
+
+ if test_name == "large" and os.environ.get("KSFT_MACHINE_SLOW"):
+ ksft_pr(f"Ignoring {protocol}/{test_name} failure due to slow environment")
+ return
+
+ ksft_pr(f"Attempt {attempt + 1}/{max_retries} failed, retrying...")
+
+
+def main() -> None:
+ """ Ksft boiler plate main """
+
+ with NetDrvEpEnv(__file__) as cfg:
+ ksft_run(cases=[test], args=(cfg,))
+ ksft_exit()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/tools/testing/selftests/drivers/net/gro.sh b/tools/testing/selftests/drivers/net/gro.sh
deleted file mode 100755
index bd3cf6d02eda..000000000000
--- a/tools/testing/selftests/drivers/net/gro.sh
+++ /dev/null
@@ -1,105 +0,0 @@
-#!/bin/bash
-# SPDX-License-Identifier: GPL-2.0
-
-readonly SERVER_MAC="aa:00:00:00:00:02"
-readonly CLIENT_MAC="aa:00:00:00:00:01"
-readonly TESTS=("data" "ack" "flags" "tcp" "ip" "large")
-readonly PROTOS=("ipv4" "ipv6" "ipip")
-dev=""
-test="all"
-proto="ipv4"
-
-run_test() {
- local server_pid=0
- local exit_code=0
- local protocol=$1
- local test=$2
- local ARGS=( "--${protocol}" "--dmac" "${SERVER_MAC}" \
- "--smac" "${CLIENT_MAC}" "--test" "${test}" "--verbose" )
-
- setup_ns
- # Each test is run 6 times to deflake, because given the receive timing,
- # not all packets that should coalesce will be considered in the same flow
- # on every try.
- for tries in {1..6}; do
- # Actual test starts here
- ip netns exec $server_ns ./gro "${ARGS[@]}" "--rx" "--iface" "server" \
- 1>>log.txt &
- server_pid=$!
- sleep 0.5 # to allow for socket init
- ip netns exec $client_ns ./gro "${ARGS[@]}" "--iface" "client" \
- 1>>log.txt
- wait "${server_pid}"
- exit_code=$?
- if [[ ${test} == "large" && -n "${KSFT_MACHINE_SLOW}" && \
- ${exit_code} -ne 0 ]]; then
- echo "Ignoring errors due to slow environment" 1>&2
- exit_code=0
- fi
- if [[ "${exit_code}" -eq 0 ]]; then
- break;
- fi
- done
- cleanup_ns
- echo ${exit_code}
-}
-
-run_all_tests() {
- local failed_tests=()
- for proto in "${PROTOS[@]}"; do
- for test in "${TESTS[@]}"; do
- echo "running test ${proto} ${test}" >&2
- exit_code=$(run_test $proto $test)
- if [[ "${exit_code}" -ne 0 ]]; then
- failed_tests+=("${proto}_${test}")
- fi;
- done;
- done
- if [[ ${#failed_tests[@]} -ne 0 ]]; then
- echo "failed tests: ${failed_tests[*]}. \
- Please see log.txt for more logs"
- exit 1
- else
- echo "All Tests Succeeded!"
- fi;
-}
-
-usage() {
- echo "Usage: $0 \
- [-i <DEV>] \
- [-t data|ack|flags|tcp|ip|large] \
- [-p <ipv4|ipv6>]" 1>&2;
- exit 1;
-}
-
-while getopts "i:t:p:" opt; do
- case "${opt}" in
- i)
- dev="${OPTARG}"
- ;;
- t)
- test="${OPTARG}"
- ;;
- p)
- proto="${OPTARG}"
- ;;
- *)
- usage
- ;;
- esac
-done
-
-if [ -n "$dev" ]; then
- source $(dirname $0)/../../net/lib/setup_loopback.sh
-else
- source $(dirname $0)/../../net/lib/setup_veth.sh
-fi
-
-setup
-trap cleanup EXIT
-if [[ "${test}" == "all" ]]; then
- run_all_tests
-else
- exit_code=$(run_test "${proto}" "${test}")
- exit $exit_code
-fi;
--
2.51.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH net-next v2 10/12] selftests: drv-net: hw: convert the Toeplitz test to Python
2025-11-18 21:51 [PATCH net-next v2 00/12] selftests: drv-net: convert GRO and Toeplitz tests to work for drivers in NIPA Jakub Kicinski
` (8 preceding siblings ...)
2025-11-18 21:51 ` [PATCH net-next v2 09/12] selftests: drv-net: add a Python version of the GRO test Jakub Kicinski
@ 2025-11-18 21:51 ` Jakub Kicinski
2025-11-19 16:39 ` Petr Machata
2025-11-18 21:51 ` [PATCH net-next v2 11/12] netdevsim: add loopback support Jakub Kicinski
` (2 subsequent siblings)
12 siblings, 1 reply; 30+ messages in thread
From: Jakub Kicinski @ 2025-11-18 21:51 UTC (permalink / raw)
To: davem
Cc: netdev, edumazet, pabeni, andrew+netdev, horms,
willemdebruijn.kernel, shuah, sdf, krakauer, linux-kselftest,
petrm, matttbe, Jakub Kicinski
Rewrite the existing toeplitz.sh test in Python. The conversion
is a lot less exact than the GRO one. We use Netlink APIs to
get the device RSS and IRQ information. We expect that the device
has neither RPS nor RFS configured, and set RPS up as part of
the test.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
v2:
- fix typo configure -> configured
v1: https://lore.kernel.org/20251117205810.1617533-11-kuba@kernel.org
---
.../testing/selftests/drivers/net/hw/Makefile | 3 +-
.../selftests/drivers/net/hw/toeplitz.c | 5 +
.../selftests/drivers/net/hw/toeplitz.py | 208 ++++++++++++++++++
.../selftests/drivers/net/hw/toeplitz.sh | 199 -----------------
.../drivers/net/hw/toeplitz_client.sh | 28 ---
5 files changed, 214 insertions(+), 229 deletions(-)
create mode 100755 tools/testing/selftests/drivers/net/hw/toeplitz.py
delete mode 100755 tools/testing/selftests/drivers/net/hw/toeplitz.sh
delete mode 100755 tools/testing/selftests/drivers/net/hw/toeplitz_client.sh
diff --git a/tools/testing/selftests/drivers/net/hw/Makefile b/tools/testing/selftests/drivers/net/hw/Makefile
index c9dced8c934a..1760238e9d4f 100644
--- a/tools/testing/selftests/drivers/net/hw/Makefile
+++ b/tools/testing/selftests/drivers/net/hw/Makefile
@@ -24,14 +24,13 @@ TEST_PROGS = \
rss_ctx.py \
rss_flow_label.py \
rss_input_xfrm.py \
- toeplitz.sh \
+ toeplitz.py \
tso.py \
xsk_reconfig.py \
#
TEST_FILES := \
ethtool_lib.sh \
- toeplitz_client.sh \
#
TEST_INCLUDES := \
diff --git a/tools/testing/selftests/drivers/net/hw/toeplitz.c b/tools/testing/selftests/drivers/net/hw/toeplitz.c
index bf74aa25345d..afc5f910b006 100644
--- a/tools/testing/selftests/drivers/net/hw/toeplitz.c
+++ b/tools/testing/selftests/drivers/net/hw/toeplitz.c
@@ -53,6 +53,7 @@
#include <unistd.h>
#include "../../../kselftest.h"
+#include "../../../net/lib/ksft.h"
#define TOEPLITZ_KEY_MIN_LEN 40
#define TOEPLITZ_KEY_MAX_LEN 60
@@ -576,6 +577,10 @@ int main(int argc, char **argv)
fd_sink = setup_sink();
setup_rings();
+
+ /* Signal to test framework that we're ready to receive */
+ ksft_ready();
+
process_rings();
cleanup_rings();
diff --git a/tools/testing/selftests/drivers/net/hw/toeplitz.py b/tools/testing/selftests/drivers/net/hw/toeplitz.py
new file mode 100755
index 000000000000..34476c431e39
--- /dev/null
+++ b/tools/testing/selftests/drivers/net/hw/toeplitz.py
@@ -0,0 +1,208 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0
+
+"""
+Toeplitz Rx hashing test:
+ - rxhash (the hash value calculation itself);
+ - RSS mapping from rxhash to rx queue;
+ - RPS mapping from rxhash to cpu.
+"""
+
+import glob
+import os
+import socket
+from lib.py import ksft_run, ksft_exit, ksft_pr
+from lib.py import NetDrvEpEnv, EthtoolFamily, NetdevFamily
+from lib.py import cmd, bkg, rand_port, defer
+from lib.py import ksft_in
+from lib.py import ksft_variants, KsftNamedVariant, KsftSkipEx, KsftFailEx
+
+
+def _check_rps_and_rfs_not_configured(cfg):
+ """Verify that RPS is not already configured."""
+
+ for rps_file in glob.glob(f"/sys/class/net/{cfg.ifname}/queues/rx-*/rps_cpus"):
+ with open(rps_file, "r", encoding="utf-8") as fp:
+ val = fp.read().strip()
+ if set(val) - {"0", ","}:
+ raise KsftSkipEx(f"RPS already configured on {rps_file}: {val}")
+
+ rfs_file = "/proc/sys/net/core/rps_sock_flow_entries"
+ with open(rfs_file, "r", encoding="utf-8") as fp:
+ val = fp.read().strip()
+ if val != "0":
+ raise KsftSkipEx(f"RFS already configured {rfs_file}: {val}")
+
+
+def _get_rss_key(cfg):
+ """
+ Read the RSS key from the device.
+ Return a string in the traditional %02x:%02x:%02x:.. format.
+ """
+
+ rss = cfg.ethnl.rss_get({"header": {"dev-index": cfg.ifindex}})
+ return ':'.join(f'{b:02x}' for b in rss["hkey"])
+
+
+def _get_cpu_for_irq(irq):
+ with open(f"/proc/irq/{irq}/smp_affinity_list", "r",
+ encoding="utf-8") as fp:
+ data = fp.read().strip()
+ if "," in data or "-" in data:
+ raise KsftFailEx(f"IRQ{irq} is not mapped to a single core: {data}")
+ return int(data)
+
+
+def _get_irq_cpus(cfg):
+ """
+ Read the list of IRQs for the device Rx queues.
+ """
+ queues = cfg.netnl.queue_get({"ifindex": cfg.ifindex}, dump=True)
+ napis = cfg.netnl.napi_get({"ifindex": cfg.ifindex}, dump=True)
+
+ # Remap into ID-based dicts
+ napis = {n["id"]: n for n in napis}
+ queues = {f"{q['type']}{q['id']}": q for q in queues}
+
+ cpus = []
+ for rx in range(9999):
+ name = f"rx{rx}"
+ if name not in queues:
+ break
+ cpus.append(_get_cpu_for_irq(napis[queues[name]["napi-id"]]["irq"]))
+
+ return cpus
+
+
+def _get_unused_cpus(cfg, count=2):
+ """
+ Get CPUs that are not used by Rx queues.
+ Returns a list of at least 'count' CPU numbers.
+ """
+
+ # Get CPUs used by Rx queues
+ rx_cpus = set(_get_irq_cpus(cfg))
+
+ # Get total number of CPUs
+ num_cpus = os.cpu_count()
+
+ # Find unused CPUs
+ unused_cpus = [cpu for cpu in range(num_cpus) if cpu not in rx_cpus]
+
+ if len(unused_cpus) < count:
+ raise KsftSkipEx(f"Need at {count} CPUs not used by Rx queues, found {len(unused_cpus)}")
+
+ return unused_cpus[:count]
+
+
+def _configure_rps(cfg, rps_cpus):
+ """Configure RPS for all Rx queues."""
+
+ mask = 0
+ for cpu in rps_cpus:
+ mask |= (1 << cpu)
+ mask = hex(mask)[2:]
+
+ # Set RPS bitmap for all rx queues
+ for rps_file in glob.glob(f"/sys/class/net/{cfg.ifname}/queues/rx-*/rps_cpus"):
+ cmd(f"echo {mask} > {rps_file}", shell=True)
+
+ return mask
+
+
+def _send_traffic(cfg, proto_flag, ipver, port):
+ """Send 20 packets of requested type."""
+
+ # Determine protocol and IP version for socat
+ if proto_flag == "-u":
+ proto = "UDP"
+ else:
+ proto = "TCP"
+
+ baddr = f"[{cfg.addr_v['6']}]" if ipver == "6" else cfg.addr_v["4"]
+
+ # Run socat in a loop to send traffic periodically
+ # Use sh -c with a loop similar to toeplitz_client.sh
+ socat_cmd = f"""
+ for i in `seq 20`; do
+ echo "msg $i" | socat -{ipver} -t 0.1 - {proto}:{baddr}:{port};
+ sleep 0.001;
+ done
+ """
+
+ cmd(socat_cmd, shell=True, host=cfg.remote)
+
+
+def _test_variants():
+ for grp in ["", "rss", "rps"]:
+ for l4 in ["tcp", "udp"]:
+ for l3 in ["4", "6"]:
+ name = f"{l4}_ipv{l3}"
+ if grp:
+ name = f"{grp}_{name}"
+ yield KsftNamedVariant(name, "-" + l4[0], l3, grp)
+
+
+@ksft_variants(_test_variants())
+def test(cfg, proto_flag, ipver, grp):
+ """Run a single toeplitz test."""
+
+ cfg.require_ipver(ipver)
+
+ # Check that rxhash is enabled
+ ksft_in("receive-hashing: on", cmd(f"ethtool -k {cfg.ifname}").stdout)
+
+ port = rand_port(socket.SOCK_DGRAM)
+ key = _get_rss_key(cfg)
+
+ toeplitz_path = cfg.test_dir / "toeplitz"
+ rx_cmd = [
+ str(toeplitz_path),
+ "-" + ipver,
+ proto_flag,
+ "-d", str(port),
+ "-i", cfg.ifname,
+ "-k", key,
+ "-T", "1000",
+ "-s",
+ "-v"
+ ]
+
+ if grp:
+ _check_rps_and_rfs_not_configured(cfg)
+ if grp == "rss":
+ irq_cpus = ",".join([str(x) for x in _get_irq_cpus(cfg)])
+ rx_cmd += ["-C", irq_cpus]
+ ksft_pr(f"RSS using CPUs: {irq_cpus}")
+ elif grp == "rps":
+ # Get CPUs not used by Rx queues and configure them for RPS
+ rps_cpus = _get_unused_cpus(cfg, count=2)
+ rps_mask = _configure_rps(cfg, rps_cpus)
+ defer(_configure_rps, cfg, [])
+ rx_cmd += ["-r", rps_mask]
+ ksft_pr(f"RPS using CPUs: {rps_cpus}, mask: {rps_mask}")
+
+ # Run rx in background, it will exit once it has seen enough packets
+ with bkg(" ".join(rx_cmd), ksft_ready=True, exit_wait=True) as rx_proc:
+ while rx_proc.proc.poll() is None:
+ _send_traffic(cfg, proto_flag, ipver, port)
+
+ # Check rx result
+ ksft_pr("Receiver output:")
+ ksft_pr(rx_proc.stdout.strip().replace('\n', '\n# '))
+ if rx_proc.stderr:
+ ksft_pr(rx_proc.stderr.strip().replace('\n', '\n# '))
+
+
+def main() -> None:
+ """Ksft boilerplate main."""
+
+ with NetDrvEpEnv(__file__) as cfg:
+ cfg.ethnl = EthtoolFamily()
+ cfg.netnl = NetdevFamily()
+ ksft_run(cases=[test], args=(cfg,))
+ ksft_exit()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/tools/testing/selftests/drivers/net/hw/toeplitz.sh b/tools/testing/selftests/drivers/net/hw/toeplitz.sh
deleted file mode 100755
index d236b666dd3b..000000000000
--- a/tools/testing/selftests/drivers/net/hw/toeplitz.sh
+++ /dev/null
@@ -1,199 +0,0 @@
-#!/bin/bash
-# SPDX-License-Identifier: GPL-2.0
-#
-# extended toeplitz test: test rxhash plus, optionally, either (1) rss mapping
-# from rxhash to rx queue ('-rss') or (2) rps mapping from rxhash to cpu
-# ('-rps <rps_map>')
-#
-# irq-pattern-prefix can be derived from /sys/kernel/irq/*/action,
-# which is a driver-specific encoding.
-#
-# invoke as ./toeplitz.sh (-i <iface>) -u|-t -4|-6 \
-# [(-rss -irq_prefix <irq-pattern-prefix>)|(-rps <rps_map>)]
-
-source $(dirname $0)/../../../net/lib/setup_loopback.sh
-readonly SERVER_IP4="192.168.1.200/24"
-readonly SERVER_IP6="fda8::1/64"
-readonly SERVER_MAC="aa:00:00:00:00:02"
-
-readonly CLIENT_IP4="192.168.1.100/24"
-readonly CLIENT_IP6="fda8::2/64"
-readonly CLIENT_MAC="aa:00:00:00:00:01"
-
-PORT=8000
-KEY="$(</proc/sys/net/core/netdev_rss_key)"
-TEST_RSS=false
-RPS_MAP=""
-PROTO_FLAG=""
-IP_FLAG=""
-DEV="eth0"
-
-# Return the number of rxqs among which RSS is configured to spread packets.
-# This is determined by reading the RSS indirection table using ethtool.
-get_rss_cfg_num_rxqs() {
- echo $(ethtool -x "${DEV}" |
- grep -E [[:space:]]+[0-9]+:[[:space:]]+ |
- cut -d: -f2- |
- awk '{$1=$1};1' |
- tr ' ' '\n' |
- sort -u |
- wc -l)
-}
-
-# Return a list of the receive irq handler cpus.
-# The list is ordered by the irqs, so first rxq-0 cpu, then rxq-1 cpu, etc.
-# Reads /sys/kernel/irq/ in order, so algorithm depends on
-# irq_{rxq-0} < irq_{rxq-1}, etc.
-get_rx_irq_cpus() {
- CPUS=""
- # sort so that irq 2 is read before irq 10
- SORTED_IRQS=$(for i in /sys/kernel/irq/*; do echo $i; done | sort -V)
- # Consider only as many queues as RSS actually uses. We assume that
- # if RSS_CFG_NUM_RXQS=N, then RSS uses rxqs 0-(N-1).
- RSS_CFG_NUM_RXQS=$(get_rss_cfg_num_rxqs)
- RXQ_COUNT=0
-
- for i in ${SORTED_IRQS}
- do
- [[ "${RXQ_COUNT}" -lt "${RSS_CFG_NUM_RXQS}" ]] || break
- # lookup relevant IRQs by action name
- [[ -e "$i/actions" ]] || continue
- cat "$i/actions" | grep -q "${IRQ_PATTERN}" || continue
- irqname=$(<"$i/actions")
-
- # does the IRQ get called
- irqcount=$(cat "$i/per_cpu_count" | tr -d '0,')
- [[ -n "${irqcount}" ]] || continue
-
- # lookup CPU
- irq=$(basename "$i")
- cpu=$(cat "/proc/irq/$irq/smp_affinity_list")
-
- if [[ -z "${CPUS}" ]]; then
- CPUS="${cpu}"
- else
- CPUS="${CPUS},${cpu}"
- fi
- RXQ_COUNT=$((RXQ_COUNT+1))
- done
-
- echo "${CPUS}"
-}
-
-get_disable_rfs_cmd() {
- echo "echo 0 > /proc/sys/net/core/rps_sock_flow_entries;"
-}
-
-get_set_rps_bitmaps_cmd() {
- CMD=""
- for i in /sys/class/net/${DEV}/queues/rx-*/rps_cpus
- do
- CMD="${CMD} echo $1 > ${i};"
- done
-
- echo "${CMD}"
-}
-
-get_disable_rps_cmd() {
- echo "$(get_set_rps_bitmaps_cmd 0)"
-}
-
-die() {
- echo "$1"
- exit 1
-}
-
-check_nic_rxhash_enabled() {
- local -r pattern="receive-hashing:\ on"
-
- ethtool -k "${DEV}" | grep -q "${pattern}" || die "rxhash must be enabled"
-}
-
-parse_opts() {
- local prog=$0
- shift 1
-
- while [[ "$1" =~ "-" ]]; do
- if [[ "$1" = "-irq_prefix" ]]; then
- shift
- IRQ_PATTERN="^$1-[0-9]*$"
- elif [[ "$1" = "-u" || "$1" = "-t" ]]; then
- PROTO_FLAG="$1"
- elif [[ "$1" = "-4" ]]; then
- IP_FLAG="$1"
- SERVER_IP="${SERVER_IP4}"
- CLIENT_IP="${CLIENT_IP4}"
- elif [[ "$1" = "-6" ]]; then
- IP_FLAG="$1"
- SERVER_IP="${SERVER_IP6}"
- CLIENT_IP="${CLIENT_IP6}"
- elif [[ "$1" = "-rss" ]]; then
- TEST_RSS=true
- elif [[ "$1" = "-rps" ]]; then
- shift
- RPS_MAP="$1"
- elif [[ "$1" = "-i" ]]; then
- shift
- DEV="$1"
- else
- die "Usage: ${prog} (-i <iface>) -u|-t -4|-6 \
- [(-rss -irq_prefix <irq-pattern-prefix>)|(-rps <rps_map>)]"
- fi
- shift
- done
-}
-
-setup() {
- setup_loopback_environment "${DEV}"
-
- # Set up server_ns namespace and client_ns namespace
- setup_macvlan_ns "${DEV}" $server_ns server \
- "${SERVER_MAC}" "${SERVER_IP}"
- setup_macvlan_ns "${DEV}" $client_ns client \
- "${CLIENT_MAC}" "${CLIENT_IP}"
-}
-
-cleanup() {
- cleanup_macvlan_ns $server_ns server $client_ns client
- cleanup_loopback "${DEV}"
-}
-
-parse_opts $0 $@
-
-setup
-trap cleanup EXIT
-
-check_nic_rxhash_enabled
-
-# Actual test starts here
-if [[ "${TEST_RSS}" = true ]]; then
- # RPS/RFS must be disabled because they move packets between cpus,
- # which breaks the PACKET_FANOUT_CPU identification of RSS decisions.
- eval "$(get_disable_rfs_cmd) $(get_disable_rps_cmd)" \
- ip netns exec $server_ns ./toeplitz "${IP_FLAG}" "${PROTO_FLAG}" \
- -d "${PORT}" -i "${DEV}" -k "${KEY}" -T 1000 \
- -C "$(get_rx_irq_cpus)" -s -v &
-elif [[ ! -z "${RPS_MAP}" ]]; then
- eval "$(get_disable_rfs_cmd) $(get_set_rps_bitmaps_cmd ${RPS_MAP})" \
- ip netns exec $server_ns ./toeplitz "${IP_FLAG}" "${PROTO_FLAG}" \
- -d "${PORT}" -i "${DEV}" -k "${KEY}" -T 1000 \
- -r "0x${RPS_MAP}" -s -v &
-else
- ip netns exec $server_ns ./toeplitz "${IP_FLAG}" "${PROTO_FLAG}" \
- -d "${PORT}" -i "${DEV}" -k "${KEY}" -T 1000 -s -v &
-fi
-
-server_pid=$!
-
-ip netns exec $client_ns ./toeplitz_client.sh "${PROTO_FLAG}" \
- "${IP_FLAG}" "${SERVER_IP%%/*}" "${PORT}" &
-
-client_pid=$!
-
-wait "${server_pid}"
-exit_code=$?
-kill -9 "${client_pid}"
-if [[ "${exit_code}" -eq 0 ]]; then
- echo "Test Succeeded!"
-fi
-exit "${exit_code}"
diff --git a/tools/testing/selftests/drivers/net/hw/toeplitz_client.sh b/tools/testing/selftests/drivers/net/hw/toeplitz_client.sh
deleted file mode 100755
index 2fef34f4aba1..000000000000
--- a/tools/testing/selftests/drivers/net/hw/toeplitz_client.sh
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/bin/bash
-# SPDX-License-Identifier: GPL-2.0
-#
-# A simple program for generating traffic for the toeplitz test.
-#
-# This program sends packets periodically for, conservatively, 20 seconds. The
-# intent is for the calling program to kill this program once it is no longer
-# needed, rather than waiting for the 20 second expiration.
-
-send_traffic() {
- expiration=$((SECONDS+20))
- while [[ "${SECONDS}" -lt "${expiration}" ]]
- do
- if [[ "${PROTO}" == "-u" ]]; then
- echo "msg $i" | nc "${IPVER}" -u -w 0 "${ADDR}" "${PORT}"
- else
- echo "msg $i" | nc "${IPVER}" -w 0 "${ADDR}" "${PORT}"
- fi
- sleep 0.001
- done
-}
-
-PROTO=$1
-IPVER=$2
-ADDR=$3
-PORT=$4
-
-send_traffic
--
2.51.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH net-next v2 11/12] netdevsim: add loopback support
2025-11-18 21:51 [PATCH net-next v2 00/12] selftests: drv-net: convert GRO and Toeplitz tests to work for drivers in NIPA Jakub Kicinski
` (9 preceding siblings ...)
2025-11-18 21:51 ` [PATCH net-next v2 10/12] selftests: drv-net: hw: convert the Toeplitz test to Python Jakub Kicinski
@ 2025-11-18 21:51 ` Jakub Kicinski
2025-11-19 17:01 ` Petr Machata
2025-11-18 21:51 ` [PATCH net-next v2 12/12] selftests: net: remove old setup_* scripts Jakub Kicinski
2025-11-18 22:31 ` [PATCH net-next v2 00/12] selftests: drv-net: convert GRO and Toeplitz tests to work for drivers in NIPA Willem de Bruijn
12 siblings, 1 reply; 30+ messages in thread
From: Jakub Kicinski @ 2025-11-18 21:51 UTC (permalink / raw)
To: davem
Cc: netdev, edumazet, pabeni, andrew+netdev, horms,
willemdebruijn.kernel, shuah, sdf, krakauer, linux-kselftest,
petrm, matttbe, Jakub Kicinski
Support device loopback. Apparently this mode has been historically
supported by the toeplitz test and I don't have any HW which lets
me test the conversion..
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/netdevsim/netdev.c | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c
index 2b713db16cd0..6927c1962277 100644
--- a/drivers/net/netdevsim/netdev.c
+++ b/drivers/net/netdevsim/netdev.c
@@ -133,15 +133,21 @@ static netdev_tx_t nsim_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (!nsim_ipsec_tx(ns, skb))
goto out_drop_any;
- peer_ns = rcu_dereference(ns->peer);
- if (!peer_ns)
- goto out_drop_any;
+ /* Check if loopback mode is enabled */
+ if (dev->features & NETIF_F_LOOPBACK) {
+ peer_ns = ns;
+ peer_dev = dev;
+ } else {
+ peer_ns = rcu_dereference(ns->peer);
+ if (!peer_ns)
+ goto out_drop_any;
+ peer_dev = peer_ns->netdev;
+ }
dr = nsim_do_psp(skb, ns, peer_ns, &psp_ext);
if (dr)
goto out_drop_free;
- peer_dev = peer_ns->netdev;
rxq = skb_get_queue_mapping(skb);
if (rxq >= peer_dev->num_rx_queues)
rxq = rxq % peer_dev->num_rx_queues;
@@ -976,7 +982,8 @@ static void nsim_setup(struct net_device *dev)
NETIF_F_FRAGLIST |
NETIF_F_HW_CSUM |
NETIF_F_LRO |
- NETIF_F_TSO;
+ NETIF_F_TSO |
+ NETIF_F_LOOPBACK;
dev->pcpu_stat_type = NETDEV_PCPU_STAT_DSTATS;
dev->max_mtu = ETH_MAX_MTU;
dev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_HW_OFFLOAD;
--
2.51.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH net-next v2 12/12] selftests: net: remove old setup_* scripts
2025-11-18 21:51 [PATCH net-next v2 00/12] selftests: drv-net: convert GRO and Toeplitz tests to work for drivers in NIPA Jakub Kicinski
` (10 preceding siblings ...)
2025-11-18 21:51 ` [PATCH net-next v2 11/12] netdevsim: add loopback support Jakub Kicinski
@ 2025-11-18 21:51 ` Jakub Kicinski
2025-11-19 17:04 ` Petr Machata
2025-11-18 22:31 ` [PATCH net-next v2 00/12] selftests: drv-net: convert GRO and Toeplitz tests to work for drivers in NIPA Willem de Bruijn
12 siblings, 1 reply; 30+ messages in thread
From: Jakub Kicinski @ 2025-11-18 21:51 UTC (permalink / raw)
To: davem
Cc: netdev, edumazet, pabeni, andrew+netdev, horms,
willemdebruijn.kernel, shuah, sdf, krakauer, linux-kselftest,
petrm, matttbe, Jakub Kicinski
gro.sh and toeplitz.sh used to source in two setup scripts
depending on whether the test was expected to be run against
veth or a real device. veth testing is replaced by netdevsim
and existing "remote endpoint" support in our Python tests.
Add a script which sets up loopback mode.
The usage is a little bit more complicated than running
the scripts used to be. Testing used to work like this:
./../gro.sh -i eth0 ...
now the "setup script" has to be run explicitly:
NETIF=eth0 ./../ksft_setup_loopback.sh ./../gro.sh
But the functionality itself is retained.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
tools/testing/selftests/net/lib/Makefile | 3 +-
.../selftests/net/lib/ksft_setup_loopback.sh | 111 ++++++++++++++++
.../selftests/net/lib/setup_loopback.sh | 120 ------------------
tools/testing/selftests/net/lib/setup_veth.sh | 45 -------
4 files changed, 112 insertions(+), 167 deletions(-)
create mode 100755 tools/testing/selftests/net/lib/ksft_setup_loopback.sh
delete mode 100644 tools/testing/selftests/net/lib/setup_loopback.sh
delete mode 100644 tools/testing/selftests/net/lib/setup_veth.sh
diff --git a/tools/testing/selftests/net/lib/Makefile b/tools/testing/selftests/net/lib/Makefile
index c10796933d42..5339f56329e1 100644
--- a/tools/testing/selftests/net/lib/Makefile
+++ b/tools/testing/selftests/net/lib/Makefile
@@ -8,8 +8,7 @@ CFLAGS += -I../../
TEST_FILES := \
../../../../net/ynl \
../../../../../Documentation/netlink/specs \
- setup_loopback.sh \
- setup_veth.sh \
+ ksft_setup_loopback.sh \
# end of TEST_FILES
TEST_GEN_FILES := \
diff --git a/tools/testing/selftests/net/lib/ksft_setup_loopback.sh b/tools/testing/selftests/net/lib/ksft_setup_loopback.sh
new file mode 100755
index 000000000000..3defbb1919c5
--- /dev/null
+++ b/tools/testing/selftests/net/lib/ksft_setup_loopback.sh
@@ -0,0 +1,111 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+# Setup script for running ksft tests over a real interface in loopback mode.
+# This scripts replaces the historical setup_loopback.sh. It puts
+# a (presumably) real hardware interface into loopback mode, creates macvlan
+# interfaces on top and places them in a network namespace for isolation.
+#
+# NETIF env variable must be exported to indicate the real target device.
+# Note that the test will override NETIF with one of the macvlans, the
+# actual ksft test will only see the macvlans.
+#
+# Example use:
+# export NETIF=eth0
+# ./net/lib/ksft_setup_loopback.sh ./drivers/net/gro.py
+
+if [ -z "$NETIF" ]; then
+ echo "Error: NETIF variable not set"
+ exit 1
+fi
+if ! [ -d "/sys/class/net/$NETIF" ]; then
+ echo "Error: Can't find $NETIF, invalid netdevice"
+ exit 1
+fi
+
+# Save original settings for cleanup
+readonly FLUSH_PATH="/sys/class/net/${NETIF}/gro_flush_timeout"
+readonly IRQ_PATH="/sys/class/net/${NETIF}/napi_defer_hard_irqs"
+FLUSH_TIMEOUT="$(< "${FLUSH_PATH}")"
+readonly FLUSH_TIMEOUT
+HARD_IRQS="$(< "${IRQ_PATH}")"
+readonly HARD_IRQS
+
+SERVER_NS=$(mktemp -u server-XXXXXXXX)
+readonly SERVER_NS
+CLIENT_NS=$(mktemp -u client-XXXXXXXX)
+readonly CLIENT_NS
+readonly SERVER_MAC="aa:00:00:00:00:02"
+readonly CLIENT_MAC="aa:00:00:00:00:01"
+
+# ksft expects addresses to communicate with remote
+export LOCAL_V6=2001:db8:1::1
+export REMOTE_V6=2001:db8:1::2
+
+cleanup() {
+ local exit_code=$?
+
+ echo "Cleaning up..."
+
+ # Remove macvlan interfaces and namespaces
+ ip -netns "${SERVER_NS}" link del dev server 2>/dev/null || true
+ ip netns del "${SERVER_NS}" 2>/dev/null || true
+ ip -netns "${CLIENT_NS}" link del dev client 2>/dev/null || true
+ ip netns del "${CLIENT_NS}" 2>/dev/null || true
+
+ # Disable loopback
+ ethtool -K "${NETIF}" loopback off 2>/dev/null || true
+ sleep 1
+
+ echo "${FLUSH_TIMEOUT}" >"${FLUSH_PATH}"
+ echo "${HARD_IRQS}" >"${IRQ_PATH}"
+
+ exit $exit_code
+}
+
+trap cleanup EXIT INT TERM
+
+# Enable loopback mode
+echo "Enabling loopback on ${NETIF}..."
+ethtool -K "${NETIF}" loopback on || {
+ echo "Failed to enable loopback mode"
+ exit 1
+}
+# The interface may need time to get carrier back, but selftests
+# will wait for carrier, so no need to wait / sleep here.
+
+# Use timer on host to trigger the network stack
+# Also disable device interrupt to not depend on NIC interrupt
+# Reduce test flakiness caused by unexpected interrupts
+echo 100000 >"${FLUSH_PATH}"
+echo 50 >"${IRQ_PATH}"
+
+# Create server namespace with macvlan
+ip netns add "${SERVER_NS}"
+ip link add link "${NETIF}" dev server address "${SERVER_MAC}" type macvlan
+ip link set dev server netns "${SERVER_NS}"
+ip -netns "${SERVER_NS}" link set dev server up
+ip -netns "${SERVER_NS}" addr add $LOCAL_V6/64 dev server
+ip -netns "${SERVER_NS}" link set dev lo up
+
+# Create client namespace with macvlan
+ip netns add "${CLIENT_NS}"
+ip link add link "${NETIF}" dev client address "${CLIENT_MAC}" type macvlan
+ip link set dev client netns "${CLIENT_NS}"
+ip -netns "${CLIENT_NS}" link set dev client up
+ip -netns "${CLIENT_NS}" addr add $REMOTE_V6/64 dev client
+ip -netns "${CLIENT_NS}" link set dev lo up
+
+echo "Setup complete!"
+echo " Device: ${NETIF}"
+echo " Server NS: ${SERVER_NS}"
+echo " Client NS: ${CLIENT_NS}"
+echo ""
+
+# Setup environment variables for tests
+export NETIF=server
+export REMOTE_TYPE=netns
+export REMOTE_ARGS="${CLIENT_NS}"
+
+# Run the command
+ip netns exec "${SERVER_NS}" "$@"
diff --git a/tools/testing/selftests/net/lib/setup_loopback.sh b/tools/testing/selftests/net/lib/setup_loopback.sh
deleted file mode 100644
index 2070b57849de..000000000000
--- a/tools/testing/selftests/net/lib/setup_loopback.sh
+++ /dev/null
@@ -1,120 +0,0 @@
-#!/bin/bash
-# SPDX-License-Identifier: GPL-2.0
-
-readonly FLUSH_PATH="/sys/class/net/${dev}/gro_flush_timeout"
-readonly IRQ_PATH="/sys/class/net/${dev}/napi_defer_hard_irqs"
-readonly FLUSH_TIMEOUT="$(< ${FLUSH_PATH})"
-readonly HARD_IRQS="$(< ${IRQ_PATH})"
-readonly server_ns=$(mktemp -u server-XXXXXXXX)
-readonly client_ns=$(mktemp -u client-XXXXXXXX)
-
-netdev_check_for_carrier() {
- local -r dev="$1"
-
- for i in {1..5}; do
- carrier="$(cat /sys/class/net/${dev}/carrier)"
- if [[ "${carrier}" -ne 1 ]] ; then
- echo "carrier not ready yet..." >&2
- sleep 1
- else
- echo "carrier ready" >&2
- break
- fi
- done
- echo "${carrier}"
-}
-
-# Assumes that there is no existing ipvlan device on the physical device
-setup_loopback_environment() {
- local dev="$1"
-
- # Fail hard if cannot turn on loopback mode for current NIC
- ethtool -K "${dev}" loopback on || exit 1
- sleep 1
-
- # Check for the carrier
- carrier=$(netdev_check_for_carrier ${dev})
- if [[ "${carrier}" -ne 1 ]] ; then
- echo "setup_loopback_environment failed"
- exit 1
- fi
-}
-
-setup_macvlan_ns(){
- local -r link_dev="$1"
- local -r ns_name="$2"
- local -r ns_dev="$3"
- local -r ns_mac="$4"
- local -r addr="$5"
-
- ip link add link "${link_dev}" dev "${ns_dev}" \
- address "${ns_mac}" type macvlan
- exit_code=$?
- if [[ "${exit_code}" -ne 0 ]]; then
- echo "setup_macvlan_ns failed"
- exit $exit_code
- fi
-
- [[ -e /var/run/netns/"${ns_name}" ]] || ip netns add "${ns_name}"
- ip link set dev "${ns_dev}" netns "${ns_name}"
- ip -netns "${ns_name}" link set dev "${ns_dev}" up
- if [[ -n "${addr}" ]]; then
- ip -netns "${ns_name}" addr add dev "${ns_dev}" "${addr}"
- fi
-
- sleep 1
-}
-
-cleanup_macvlan_ns(){
- while (( $# >= 2 )); do
- ns_name="$1"
- ns_dev="$2"
- ip -netns "${ns_name}" link del dev "${ns_dev}"
- ip netns del "${ns_name}"
- shift 2
- done
-}
-
-cleanup_loopback(){
- local -r dev="$1"
-
- ethtool -K "${dev}" loopback off
- sleep 1
-
- # Check for the carrier
- carrier=$(netdev_check_for_carrier ${dev})
- if [[ "${carrier}" -ne 1 ]] ; then
- echo "setup_loopback_environment failed"
- exit 1
- fi
-}
-
-setup_interrupt() {
- # Use timer on host to trigger the network stack
- # Also disable device interrupt to not depend on NIC interrupt
- # Reduce test flakiness caused by unexpected interrupts
- echo 100000 >"${FLUSH_PATH}"
- echo 50 >"${IRQ_PATH}"
-}
-
-setup_ns() {
- # Set up server_ns namespace and client_ns namespace
- setup_macvlan_ns "${dev}" ${server_ns} server "${SERVER_MAC}"
- setup_macvlan_ns "${dev}" ${client_ns} client "${CLIENT_MAC}"
-}
-
-cleanup_ns() {
- cleanup_macvlan_ns ${server_ns} server ${client_ns} client
-}
-
-setup() {
- setup_loopback_environment "${dev}"
- setup_interrupt
-}
-
-cleanup() {
- cleanup_loopback "${dev}"
-
- echo "${FLUSH_TIMEOUT}" >"${FLUSH_PATH}"
- echo "${HARD_IRQS}" >"${IRQ_PATH}"
-}
diff --git a/tools/testing/selftests/net/lib/setup_veth.sh b/tools/testing/selftests/net/lib/setup_veth.sh
deleted file mode 100644
index 152bf4c65747..000000000000
--- a/tools/testing/selftests/net/lib/setup_veth.sh
+++ /dev/null
@@ -1,45 +0,0 @@
-#!/bin/bash
-# SPDX-License-Identifier: GPL-2.0
-
-readonly server_ns=$(mktemp -u server-XXXXXXXX)
-readonly client_ns=$(mktemp -u client-XXXXXXXX)
-
-setup_veth_ns() {
- local -r link_dev="$1"
- local -r ns_name="$2"
- local -r ns_dev="$3"
- local -r ns_mac="$4"
-
- [[ -e /var/run/netns/"${ns_name}" ]] || ip netns add "${ns_name}"
- echo 200000 > "/sys/class/net/${ns_dev}/gro_flush_timeout"
- echo 1 > "/sys/class/net/${ns_dev}/napi_defer_hard_irqs"
- ip link set dev "${ns_dev}" netns "${ns_name}" mtu 65535
- ip -netns "${ns_name}" link set dev "${ns_dev}" up
-
- ip netns exec "${ns_name}" ethtool -K "${ns_dev}" gro on tso off
-}
-
-setup_ns() {
- # Set up server_ns namespace and client_ns namespace
- ip link add name server type veth peer name client
-
- setup_veth_ns "${dev}" ${server_ns} server "${SERVER_MAC}"
- setup_veth_ns "${dev}" ${client_ns} client "${CLIENT_MAC}"
-}
-
-cleanup_ns() {
- local ns_name
-
- for ns_name in ${client_ns} ${server_ns}; do
- [[ -e /var/run/netns/"${ns_name}" ]] && ip netns del "${ns_name}"
- done
-}
-
-setup() {
- # no global init setup step needed
- :
-}
-
-cleanup() {
- cleanup_ns
-}
--
2.51.1
^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: [PATCH net-next v2 00/12] selftests: drv-net: convert GRO and Toeplitz tests to work for drivers in NIPA
2025-11-18 21:51 [PATCH net-next v2 00/12] selftests: drv-net: convert GRO and Toeplitz tests to work for drivers in NIPA Jakub Kicinski
` (11 preceding siblings ...)
2025-11-18 21:51 ` [PATCH net-next v2 12/12] selftests: net: remove old setup_* scripts Jakub Kicinski
@ 2025-11-18 22:31 ` Willem de Bruijn
2025-11-19 0:25 ` Jakub Kicinski
12 siblings, 1 reply; 30+ messages in thread
From: Willem de Bruijn @ 2025-11-18 22:31 UTC (permalink / raw)
To: Jakub Kicinski, davem
Cc: netdev, edumazet, pabeni, andrew+netdev, horms,
willemdebruijn.kernel, shuah, sdf, krakauer, linux-kselftest,
petrm, matttbe, Jakub Kicinski
Jakub Kicinski wrote:
> Main objective of this series is to convert the gro.sh and toeplitz.sh
> tests to be "NIPA-compatible" - meaning make use of the Python env,
> which lets us run the tests against either netdevsim or a real device.
>
> The tests seem to have been written with a different flow in mind.
> Namely they source different bash "setup" scripts depending on arguments
> passed to the test. While I have nothing against the use of bash and
> the overall architecture - the existing code needs quite a bit of work
> (don't assume MAC/IP addresses, support remote endpoint over SSH).
> If I'm the one fixing it, I'd rather convert them to our "simplistic"
> Python.
>
> This series rewrites the tests in Python while addressing their
> shortcomings. The functionality of running the test over loopback
> on a real device is retained but with a different method of invocation
> (see the last patch).
>
> Once again we are dealing with a script which run over a variety of
> protocols (combination of [ipv4, ipv6, ipip] x [tcp, udp]). The first
> 4 patches add support for test variants to our scripts. We use the
> term "variant" in the same sense as the C kselftest_harness.h -
> variant is just a set of static input arguments.
>
> Note that neither GRO nor the Toeplitz test fully passes for me on
> any HW I have access to. But this is unrelated to the conversion.
> This series is not making any real functional changes to the tests,
> it is limited to improving the "test harness" scripts.
>
> v2:
> [patch 5] fix accidental modification of gitignore
> [patch 8] fix typo in "compared"
> [patch 9] fix typo I -> It
> [patch 10] fix typoe configure -> configured
> v1: https://lore.kernel.org/20251117205810.1617533-1-kuba@kernel.org
>
> Jakub Kicinski (12):
> selftests: net: py: coding style improvements
> selftests: net: py: extract the case generation logic
> selftests: net: py: add test variants
> selftests: drv-net: xdp: use variants for qstat tests
> selftests: net: relocate gro and toeplitz tests to drivers/net
> selftests: net: py: support ksft ready without wait
> selftests: net: py: read ip link info about remote dev
> netdevsim: pass packets thru GRO on Rx
> selftests: drv-net: add a Python version of the GRO test
> selftests: drv-net: hw: convert the Toeplitz test to Python
> netdevsim: add loopback support
> selftests: net: remove old setup_* scripts
For the series:
Reviewed-by: Willem de Bruijn <willemb@google.com>
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH net-next v2 00/12] selftests: drv-net: convert GRO and Toeplitz tests to work for drivers in NIPA
2025-11-18 22:31 ` [PATCH net-next v2 00/12] selftests: drv-net: convert GRO and Toeplitz tests to work for drivers in NIPA Willem de Bruijn
@ 2025-11-19 0:25 ` Jakub Kicinski
2025-11-19 0:32 ` Willem de Bruijn
0 siblings, 1 reply; 30+ messages in thread
From: Jakub Kicinski @ 2025-11-19 0:25 UTC (permalink / raw)
To: Willem de Bruijn
Cc: davem, netdev, edumazet, pabeni, andrew+netdev, horms, shuah, sdf,
krakauer, linux-kselftest, petrm, matttbe
On Tue, 18 Nov 2025 17:31:50 -0500 Willem de Bruijn wrote:
> For the series:
>
> Reviewed-by: Willem de Bruijn <willemb@google.com>
Thanks! FWIW did some more digging just now, with the indirection table
read from the device and disabling symmetric hash for the test (mlx5
defaults to having it enabled) - the Toeplitz test passes on all
the NICs I have access to (with the caveat that I'm not able to test
IPv4). I'll look closer at the GRO tomorrow.
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH net-next v2 00/12] selftests: drv-net: convert GRO and Toeplitz tests to work for drivers in NIPA
2025-11-19 0:25 ` Jakub Kicinski
@ 2025-11-19 0:32 ` Willem de Bruijn
0 siblings, 0 replies; 30+ messages in thread
From: Willem de Bruijn @ 2025-11-19 0:32 UTC (permalink / raw)
To: Jakub Kicinski, Willem de Bruijn
Cc: davem, netdev, edumazet, pabeni, andrew+netdev, horms, shuah, sdf,
krakauer, linux-kselftest, petrm, matttbe
Jakub Kicinski wrote:
> On Tue, 18 Nov 2025 17:31:50 -0500 Willem de Bruijn wrote:
> > For the series:
> >
> > Reviewed-by: Willem de Bruijn <willemb@google.com>
>
> Thanks! FWIW did some more digging just now, with the indirection table
> read from the device and disabling symmetric hash for the test (mlx5
> defaults to having it enabled) - the Toeplitz test passes on all
> the NICs I have access to (with the caveat that I'm not able to test
> IPv4). I'll look closer at the GRO tomorrow.
Excellent. Symmetric keys makes sense. Though I would have expected
the RSS rules would be the canonical format. Another issue on IPv6 can
be whether the flowlabel is included (which it shouldn't by default).
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH net-next v2 01/12] selftests: net: py: coding style improvements
2025-11-18 21:51 ` [PATCH net-next v2 01/12] selftests: net: py: coding style improvements Jakub Kicinski
@ 2025-11-19 13:40 ` Petr Machata
2025-11-19 14:32 ` Jakub Kicinski
0 siblings, 1 reply; 30+ messages in thread
From: Petr Machata @ 2025-11-19 13:40 UTC (permalink / raw)
To: Jakub Kicinski
Cc: davem, netdev, edumazet, pabeni, andrew+netdev, horms,
willemdebruijn.kernel, shuah, sdf, krakauer, linux-kselftest,
petrm, matttbe
Jakub Kicinski <kuba@kernel.org> writes:
> We're about to add more features here and finding new issues with old
> ones in place is hard. Address ruff checks:
> - bare exceptions
> - f-string with no params
> - unused import
>
> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
> ---
> tools/testing/selftests/net/lib/py/ksft.py | 7 +++----
> 1 file changed, 3 insertions(+), 4 deletions(-)
>
> diff --git a/tools/testing/selftests/net/lib/py/ksft.py b/tools/testing/selftests/net/lib/py/ksft.py
> index 83b1574f7719..56dd9bd060cd 100644
> --- a/tools/testing/selftests/net/lib/py/ksft.py
> +++ b/tools/testing/selftests/net/lib/py/ksft.py
> @@ -1,6 +1,5 @@
> # SPDX-License-Identifier: GPL-2.0
>
> -import builtins
> import functools
> import inspect
> import signal
> @@ -163,7 +162,7 @@ KSFT_DISRUPTIVE = True
> entry = global_defer_queue.pop()
> try:
> entry.exec_only()
> - except:
> + except Exception:
This used to catch KsftTerminate, which we use for SIGTERM handling, now
it doesn't anymore. I think it could legitimately appear in that context
if SIGTERM si delivered while exec_only() is running.
IMHO it should catch BaseException, like ksft_run() already does.
> ksft_pr(f"Exception while handling defer / cleanup (callback {i} of {qlen_start})!")
> tb = traceback.format_exc()
> for line in tb.strip().split('\n'):
> @@ -181,7 +180,7 @@ KSFT_DISRUPTIVE = True
> @functools.wraps(func)
> def wrapper(*args, **kwargs):
> if not KSFT_DISRUPTIVE:
> - raise KsftSkipEx(f"marked as disruptive")
> + raise KsftSkipEx("marked as disruptive")
> return func(*args, **kwargs)
> return wrapper
>
> @@ -199,7 +198,7 @@ KSFT_DISRUPTIVE = True
> return False
> try:
> return bool(int(value))
> - except:
> + except Exception:
> raise Exception(f"failed to parse {name}")
I think this will end up being called from inside the try/except in
ksft_run() and therefore should be OK like this. It's actually more
correct like this, SIGTERM shouldn't cause "failed to parse" errors.
>
> if "DISRUPTIVE" in env:
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH net-next v2 02/12] selftests: net: py: extract the case generation logic
2025-11-18 21:51 ` [PATCH net-next v2 02/12] selftests: net: py: extract the case generation logic Jakub Kicinski
@ 2025-11-19 14:11 ` Petr Machata
0 siblings, 0 replies; 30+ messages in thread
From: Petr Machata @ 2025-11-19 14:11 UTC (permalink / raw)
To: Jakub Kicinski
Cc: davem, netdev, edumazet, pabeni, andrew+netdev, horms,
willemdebruijn.kernel, shuah, sdf, krakauer, linux-kselftest,
petrm, matttbe
Jakub Kicinski <kuba@kernel.org> writes:
> In preparation for adding test variants move the test case
> collection logic to a dedicated function. New helper returns
>
> (function, args, name, )
>
> tuples. The main test loop can simply run them, not much
> logic or discernment needed.
>
> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Reviewed-by: Petr Machata <petrm@nvidia.com>
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH net-next v2 01/12] selftests: net: py: coding style improvements
2025-11-19 13:40 ` Petr Machata
@ 2025-11-19 14:32 ` Jakub Kicinski
2025-11-19 16:06 ` Petr Machata
0 siblings, 1 reply; 30+ messages in thread
From: Jakub Kicinski @ 2025-11-19 14:32 UTC (permalink / raw)
To: Petr Machata
Cc: davem, netdev, edumazet, pabeni, andrew+netdev, horms,
willemdebruijn.kernel, shuah, sdf, krakauer, linux-kselftest,
matttbe
On Wed, 19 Nov 2025 14:40:41 +0100 Petr Machata wrote:
> > @@ -163,7 +162,7 @@ KSFT_DISRUPTIVE = True
> > entry = global_defer_queue.pop()
> > try:
> > entry.exec_only()
> > - except:
> > + except Exception:
>
> This used to catch KsftTerminate, which we use for SIGTERM handling, now
> it doesn't anymore. I think it could legitimately appear in that context
> if SIGTERM si delivered while exec_only() is running.
>
> IMHO it should catch BaseException, like ksft_run() already does.
TBH I haven't thought of this. Are you thinking that we shouldn't
interrupt the execution of deferred cleanups when SIGTERM arrives?
Fair point, but I think we'd need more code to handle that properly 🤔️
Right now we ignore SIGTERM which isn't great. After this patch we'll
no longer ignore it and have the whole test exit. Neither actually
catches the exception and sets stop=True in ksft_run()..
WDYT about leaving this patch as is and doing this on top:
diff --git a/tools/testing/selftests/net/lib/py/ksft.py b/tools/testing/selftests/net/lib/py/ksft.py
index 83b1574f7719..5a667ad22ef4 100644
--- a/tools/testing/selftests/net/lib/py/ksft.py
+++ b/tools/testing/selftests/net/lib/py/ksft.py
@@ -268,7 +268,12 @@ KSFT_DISRUPTIVE = True
KSFT_RESULT = False
cnt_key = 'fail'
- ksft_flush_defer()
+ try:
+ ksft_flush_defer()
+ except BaseException as e:
+ stop |= isinstance(e, KeyboardInterrupt)
+ # Flush was interrupted, try to finish the job best we can
+ ksft_flush_defer()
if not cnt_key:
cnt_key = 'pass' if KSFT_RESULT else 'fail'
^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: [PATCH net-next v2 03/12] selftests: net: py: add test variants
2025-11-18 21:51 ` [PATCH net-next v2 03/12] selftests: net: py: add test variants Jakub Kicinski
@ 2025-11-19 14:42 ` Petr Machata
0 siblings, 0 replies; 30+ messages in thread
From: Petr Machata @ 2025-11-19 14:42 UTC (permalink / raw)
To: Jakub Kicinski
Cc: davem, netdev, edumazet, pabeni, andrew+netdev, horms,
willemdebruijn.kernel, shuah, sdf, krakauer, linux-kselftest,
petrm, matttbe
Jakub Kicinski <kuba@kernel.org> writes:
> diff --git a/tools/testing/selftests/net/lib/py/ksft.py b/tools/testing/selftests/net/lib/py/ksft.py
> index 52c42c313cf2..47e0af210bee 100644
> --- a/tools/testing/selftests/net/lib/py/ksft.py
> +++ b/tools/testing/selftests/net/lib/py/ksft.py
> @@ -185,6 +185,49 @@ KSFT_DISRUPTIVE = True
> return wrapper
>
>
> +class KsftNamedVariant:
> + """ Named string name + argument list tuple for @ksft_variants """
> +
> + def __init__(self, name, *params):
> + self.params = params
> + self.name = name or "_".join([str(x) for x in self.params])
> +
> +
> +def ksft_variants(params):
> + """
> + Decorator defining the sets of inputs for a test.
> + The parameters will be included in the name of the resulting sub-case.
> + Parameters can be either single object, tuple or a KsftNamedVariant.
> + The argument can be a list or a generator.
> +
> + Example:
> +
> + @ksft_variants([
> + (1, "a"),
> + (2, "b"),
> + KsftNamedVariant("three", 3, "c"),
> + ])
> + def my_case(cfg, a, b):
> + pass # ...
> +
> + ksft_run(cases=[my_case], args=(cfg, ))
> +
> + Will generate cases:
> + my_case.1_a
> + my_case.2_b
> + my_case.three
> + """
> +
> + def decorator(func):
> + @functools.wraps(func)
> + def wrapper():
> + return func
> + wrapper.ksft_variants = params
> + wrapper.original_func = func
> + return wrapper
> + return decorator
This uses the wrapper() merely as a vessel to carry the three
attributes. I think the idea would be better expressed as a namedtupple
from collections import namedtuple
KsftCaseFunction = namedtuple("KsftCaseFunction",
['name', 'original_func', 'variants'])
def ksft_variants(params):
return lambda func: KsftCaseFunction(func.__name__, func, params)
> +
> +
> def ksft_setup(env):
> """
> Setup test framework global state from the environment.
> @@ -236,7 +279,19 @@ KSFT_DISRUPTIVE = True
> break
>
> for func in cases:
> - test_cases.append((func, args, func.__name__))
> + if hasattr(func, 'ksft_variants'):
Then this could just be if callable(func) just call it, else the complex
processing.
I'm not married to the namedtuple idea, but I consider using a function
as essentially a struct wrong. It should be a general object.
> + # Parametrized test - create case for each param
> + for param in func.ksft_variants:
> + if not isinstance(param, KsftNamedVariant):
> + if not isinstance(param, tuple):
> + param = (param, )
> + param = KsftNamedVariant(None, *param)
> +
> + test_cases.append((func.original_func,
> + (*args, *param.params),
> + func.__name__ + "." + param.name))
> + else:
> + test_cases.append((func, args, func.__name__))
>
> return test_cases
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH net-next v2 04/12] selftests: drv-net: xdp: use variants for qstat tests
2025-11-18 21:51 ` [PATCH net-next v2 04/12] selftests: drv-net: xdp: use variants for qstat tests Jakub Kicinski
@ 2025-11-19 14:57 ` Petr Machata
0 siblings, 0 replies; 30+ messages in thread
From: Petr Machata @ 2025-11-19 14:57 UTC (permalink / raw)
To: Jakub Kicinski
Cc: davem, netdev, edumazet, pabeni, andrew+netdev, horms,
willemdebruijn.kernel, shuah, sdf, krakauer, linux-kselftest,
petrm, matttbe
Jakub Kicinski <kuba@kernel.org> writes:
> Use just-added ksft variants for XDP qstat tests.
>
> While at it correct the number of packets, we're sending
> 1000 packets now.
>
> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Reviewed-by: Petr Machata <petrm@nvidia.com>
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH net-next v2 05/12] selftests: net: relocate gro and toeplitz tests to drivers/net
2025-11-18 21:51 ` [PATCH net-next v2 05/12] selftests: net: relocate gro and toeplitz tests to drivers/net Jakub Kicinski
@ 2025-11-19 15:09 ` Petr Machata
0 siblings, 0 replies; 30+ messages in thread
From: Petr Machata @ 2025-11-19 15:09 UTC (permalink / raw)
To: Jakub Kicinski
Cc: davem, netdev, edumazet, pabeni, andrew+netdev, horms,
willemdebruijn.kernel, shuah, sdf, krakauer, linux-kselftest,
petrm, matttbe
Jakub Kicinski <kuba@kernel.org> writes:
> The GRO test can run on a real device or a veth.
> The Toeplitz hash test can only run on a real device.
> Move them from net/ to drivers/net/ and drivers/net/hw/ respectively.
>
> There are two scripts which set up the environment for these tests
> setup_loopback.sh and setup_veth.sh. Move those scripts to net/lib.
> The paths to the setup files are a little ugly but they will be
> deleted shortly.
>
> toeplitz_client.sh is not a test in itself, but rather a helper
> to send traffic, so add it to TEST_FILES rather than TEST_PROGS.
>
> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Reviewed-by: Petr Machata <petrm@nvidia.com>
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH net-next v2 07/12] selftests: net: py: read ip link info about remote dev
2025-11-18 21:51 ` [PATCH net-next v2 07/12] selftests: net: py: read ip link info about remote dev Jakub Kicinski
@ 2025-11-19 15:33 ` Petr Machata
0 siblings, 0 replies; 30+ messages in thread
From: Petr Machata @ 2025-11-19 15:33 UTC (permalink / raw)
To: Jakub Kicinski
Cc: davem, netdev, edumazet, pabeni, andrew+netdev, horms,
willemdebruijn.kernel, shuah, sdf, krakauer, linux-kselftest,
petrm, matttbe
Jakub Kicinski <kuba@kernel.org> writes:
> We're already saving the info about the local dev in env.dev
> for the tests, save remote dev as well. This is more symmetric,
> env generally provides the same info for local and remote end.
>
> While at it make sure that we reliably get the detailed info
> about the local dev. nsim used to read the dev info without -d.
>
> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Reviewed-by: Petr Machata <petrm@nvidia.com>
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH net-next v2 08/12] netdevsim: pass packets thru GRO on Rx
2025-11-18 21:51 ` [PATCH net-next v2 08/12] netdevsim: pass packets thru GRO on Rx Jakub Kicinski
@ 2025-11-19 15:43 ` Petr Machata
0 siblings, 0 replies; 30+ messages in thread
From: Petr Machata @ 2025-11-19 15:43 UTC (permalink / raw)
To: Jakub Kicinski
Cc: davem, netdev, edumazet, pabeni, andrew+netdev, horms,
willemdebruijn.kernel, shuah, sdf, krakauer, linux-kselftest,
petrm, matttbe
Jakub Kicinski <kuba@kernel.org> writes:
> To replace veth in software GRO testing with netdevsim we need
> GRO support in netdevsim. Luckily we already have NAPI support
> so this change is trivial (compared to veth).
>
> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Reviewed-by: Petr Machata <petrm@nvidia.com>
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH net-next v2 09/12] selftests: drv-net: add a Python version of the GRO test
2025-11-18 21:51 ` [PATCH net-next v2 09/12] selftests: drv-net: add a Python version of the GRO test Jakub Kicinski
@ 2025-11-19 15:54 ` Petr Machata
0 siblings, 0 replies; 30+ messages in thread
From: Petr Machata @ 2025-11-19 15:54 UTC (permalink / raw)
To: Jakub Kicinski
Cc: davem, netdev, edumazet, pabeni, andrew+netdev, horms,
willemdebruijn.kernel, shuah, sdf, krakauer, linux-kselftest,
petrm, matttbe
Jakub Kicinski <kuba@kernel.org> writes:
> Rewrite the existing gro.sh test in Python. The conversion
> not exact, the changes are related to integrating the test
> with our "remote endpoint" paradigm. The test now reads
> the IP addresses from the user config. It resolves the MAC
> address (including running over Layer 3 networks).
>
> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Reviewed-by: Petr Machata <petrm@nvidia.com>
However:
> + base_cmd_args = [
> + f"--{protocol}",
> + f"--dmac {_resolve_dmac(cfg, ipver)}",
> + f"--smac {cfg.remote_dev['address']}",
> + f"--daddr {cfg.addr_v[ipver]}",
> + f"--saddr {cfg.remote_addr_v[ipver]}",
> + f"--test {test_name}",
> + "--verbose"
> + ]
> + base_args = " ".join(base_cmd_args)
> +
> + max_retries = 6
> + for attempt in range(max_retries):
The original had a comment about flakiness which was IMHO useful. The
"retry failures" paradigm on its own is transparent enough, but the
comment explained why the flakiness comes up.
2c
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH net-next v2 01/12] selftests: net: py: coding style improvements
2025-11-19 14:32 ` Jakub Kicinski
@ 2025-11-19 16:06 ` Petr Machata
0 siblings, 0 replies; 30+ messages in thread
From: Petr Machata @ 2025-11-19 16:06 UTC (permalink / raw)
To: Jakub Kicinski
Cc: Petr Machata, davem, netdev, edumazet, pabeni, andrew+netdev,
horms, willemdebruijn.kernel, shuah, sdf, krakauer,
linux-kselftest, matttbe
Jakub Kicinski <kuba@kernel.org> writes:
> On Wed, 19 Nov 2025 14:40:41 +0100 Petr Machata wrote:
>> > @@ -163,7 +162,7 @@ KSFT_DISRUPTIVE = True
>> > entry = global_defer_queue.pop()
>> > try:
>> > entry.exec_only()
>> > - except:
>> > + except Exception:
>>
>> This used to catch KsftTerminate, which we use for SIGTERM handling, now
>> it doesn't anymore. I think it could legitimately appear in that context
>> if SIGTERM si delivered while exec_only() is running.
>>
>> IMHO it should catch BaseException, like ksft_run() already does.
>
> TBH I haven't thought of this. Are you thinking that we shouldn't
> interrupt the execution of deferred cleanups when SIGTERM arrives?
> Fair point, but I think we'd need more code to handle that properly 🤔️
> Right now we ignore SIGTERM which isn't great. After this patch we'll
> no longer ignore it and have the whole test exit. Neither actually
> catches the exception and sets stop=True in ksft_run()..
Well, previously at least the rest of the defer queue would be run, now
it's skipped. Which -- OK, likely if you SIGTERM in the middle of a
cleanup, chances are the cleanup is stuck and the sigterm then skips it,
which is what you want.
It's a pick your poison. Ignore C-c or ignore deferred cleanups :)
Given this is supposed to be a cleanup patch, it would make sense to
just s/bare except/except BaseException/ and leave the behavior broken.
The commit message indicates it's a NOP make-linter-happy patch, but
then it's not really.
> WDYT about leaving this patch as is and doing this on top:
It's a good stop-gap.
> diff --git a/tools/testing/selftests/net/lib/py/ksft.py b/tools/testing/selftests/net/lib/py/ksft.py
> index 83b1574f7719..5a667ad22ef4 100644
> --- a/tools/testing/selftests/net/lib/py/ksft.py
> +++ b/tools/testing/selftests/net/lib/py/ksft.py
> @@ -268,7 +268,12 @@ KSFT_DISRUPTIVE = True
> KSFT_RESULT = False
> cnt_key = 'fail'
>
> - ksft_flush_defer()
> + try:
> + ksft_flush_defer()
> + except BaseException as e:
> + stop |= isinstance(e, KeyboardInterrupt)
> + # Flush was interrupted, try to finish the job best we can
> + ksft_flush_defer()
>
> if not cnt_key:
> cnt_key = 'pass' if KSFT_RESULT else 'fail'
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH net-next v2 06/12] selftests: net: py: support ksft ready without wait
2025-11-18 21:51 ` [PATCH net-next v2 06/12] selftests: net: py: support ksft ready without wait Jakub Kicinski
@ 2025-11-19 16:31 ` Petr Machata
0 siblings, 0 replies; 30+ messages in thread
From: Petr Machata @ 2025-11-19 16:31 UTC (permalink / raw)
To: Jakub Kicinski
Cc: davem, netdev, edumazet, pabeni, andrew+netdev, horms,
willemdebruijn.kernel, shuah, sdf, krakauer, linux-kselftest,
petrm, matttbe
Jakub Kicinski <kuba@kernel.org> writes:
> There's a common synchronization problem when a script (Python test)
> uses a C program to set up some state (usually start a receiving
> process for traffic). The script needs to know when the process
> has fully initialized. The inverse of the problem exists for shutting
> the process down - we need a reliable way to tell the process to exit.
>
> We added helpers to do this safely in
> commit 71477137994f ("selftests: drv-net: add a way to wait for a local process")
> unfortunately the two operations (wait for init, and shutdown) are
> controlled by a single parameter (ksft_wait). Add support for using
> ksft_ready without using the second fd for exit.
>
> This is useful for programs which wait for a specific number of packets
> to rx so exit_wait is a good match, but we still need to wait for init.
>
> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Reviewed-by: Petr Machata <petrm@nvidia.com>
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH net-next v2 10/12] selftests: drv-net: hw: convert the Toeplitz test to Python
2025-11-18 21:51 ` [PATCH net-next v2 10/12] selftests: drv-net: hw: convert the Toeplitz test to Python Jakub Kicinski
@ 2025-11-19 16:39 ` Petr Machata
0 siblings, 0 replies; 30+ messages in thread
From: Petr Machata @ 2025-11-19 16:39 UTC (permalink / raw)
To: Jakub Kicinski
Cc: davem, netdev, edumazet, pabeni, andrew+netdev, horms,
willemdebruijn.kernel, shuah, sdf, krakauer, linux-kselftest,
petrm, matttbe
Jakub Kicinski <kuba@kernel.org> writes:
> Rewrite the existing toeplitz.sh test in Python. The conversion
> is a lot less exact than the GRO one. We use Netlink APIs to
> get the device RSS and IRQ information. We expect that the device
> has neither RPS nor RFS configured, and set RPS up as part of
> the test.
>
> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Reviewed-by: Petr Machata <petrm@nvidia.com>
> + # Set RPS bitmap for all rx queues
> + for rps_file in glob.glob(f"/sys/class/net/{cfg.ifname}/queues/rx-*/rps_cpus"):
> + cmd(f"echo {mask} > {rps_file}", shell=True)
A bit odd to use echo like this, the other test does this through open /
write. Unless I'm missing something and this actually runs remotely...?
Anyway, not important. Just that maybe eventually some helpers that
support this sysfs-based configuration might be handy.
> + return mask
> +
> +
> +def _send_traffic(cfg, proto_flag, ipver, port):
> + """Send 20 packets of requested type."""
> +
> + # Determine protocol and IP version for socat
> + if proto_flag == "-u":
> + proto = "UDP"
> + else:
> + proto = "TCP"
> +
> + baddr = f"[{cfg.addr_v['6']}]" if ipver == "6" else cfg.addr_v["4"]
> +
> + # Run socat in a loop to send traffic periodically
> + # Use sh -c with a loop similar to toeplitz_client.sh
> + socat_cmd = f"""
> + for i in `seq 20`; do
> + echo "msg $i" | socat -{ipver} -t 0.1 - {proto}:{baddr}:{port};
> + sleep 0.001;
> + done
> + """
Yeah, what with the remote execution, this probably makes sense.
> + cmd(socat_cmd, shell=True, host=cfg.remote)
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH net-next v2 11/12] netdevsim: add loopback support
2025-11-18 21:51 ` [PATCH net-next v2 11/12] netdevsim: add loopback support Jakub Kicinski
@ 2025-11-19 17:01 ` Petr Machata
0 siblings, 0 replies; 30+ messages in thread
From: Petr Machata @ 2025-11-19 17:01 UTC (permalink / raw)
To: Jakub Kicinski
Cc: davem, netdev, edumazet, pabeni, andrew+netdev, horms,
willemdebruijn.kernel, shuah, sdf, krakauer, linux-kselftest,
petrm, matttbe
Jakub Kicinski <kuba@kernel.org> writes:
> Support device loopback. Apparently this mode has been historically
> supported by the toeplitz test and I don't have any HW which lets
> me test the conversion..
>
> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Reviewed-by: Petr Machata <petrm@nvidia.com>
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH net-next v2 12/12] selftests: net: remove old setup_* scripts
2025-11-18 21:51 ` [PATCH net-next v2 12/12] selftests: net: remove old setup_* scripts Jakub Kicinski
@ 2025-11-19 17:04 ` Petr Machata
0 siblings, 0 replies; 30+ messages in thread
From: Petr Machata @ 2025-11-19 17:04 UTC (permalink / raw)
To: Jakub Kicinski
Cc: davem, netdev, edumazet, pabeni, andrew+netdev, horms,
willemdebruijn.kernel, shuah, sdf, krakauer, linux-kselftest,
petrm, matttbe
Jakub Kicinski <kuba@kernel.org> writes:
> gro.sh and toeplitz.sh used to source in two setup scripts
> depending on whether the test was expected to be run against
> veth or a real device. veth testing is replaced by netdevsim
> and existing "remote endpoint" support in our Python tests.
> Add a script which sets up loopback mode.
>
> The usage is a little bit more complicated than running
> the scripts used to be. Testing used to work like this:
>
> ./../gro.sh -i eth0 ...
>
> now the "setup script" has to be run explicitly:
>
> NETIF=eth0 ./../ksft_setup_loopback.sh ./../gro.sh
>
> But the functionality itself is retained.
>
> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Reviewed-by: Petr Machata <petrm@nvidia.com>
^ permalink raw reply [flat|nested] 30+ messages in thread
end of thread, other threads:[~2025-11-19 17:06 UTC | newest]
Thread overview: 30+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-18 21:51 [PATCH net-next v2 00/12] selftests: drv-net: convert GRO and Toeplitz tests to work for drivers in NIPA Jakub Kicinski
2025-11-18 21:51 ` [PATCH net-next v2 01/12] selftests: net: py: coding style improvements Jakub Kicinski
2025-11-19 13:40 ` Petr Machata
2025-11-19 14:32 ` Jakub Kicinski
2025-11-19 16:06 ` Petr Machata
2025-11-18 21:51 ` [PATCH net-next v2 02/12] selftests: net: py: extract the case generation logic Jakub Kicinski
2025-11-19 14:11 ` Petr Machata
2025-11-18 21:51 ` [PATCH net-next v2 03/12] selftests: net: py: add test variants Jakub Kicinski
2025-11-19 14:42 ` Petr Machata
2025-11-18 21:51 ` [PATCH net-next v2 04/12] selftests: drv-net: xdp: use variants for qstat tests Jakub Kicinski
2025-11-19 14:57 ` Petr Machata
2025-11-18 21:51 ` [PATCH net-next v2 05/12] selftests: net: relocate gro and toeplitz tests to drivers/net Jakub Kicinski
2025-11-19 15:09 ` Petr Machata
2025-11-18 21:51 ` [PATCH net-next v2 06/12] selftests: net: py: support ksft ready without wait Jakub Kicinski
2025-11-19 16:31 ` Petr Machata
2025-11-18 21:51 ` [PATCH net-next v2 07/12] selftests: net: py: read ip link info about remote dev Jakub Kicinski
2025-11-19 15:33 ` Petr Machata
2025-11-18 21:51 ` [PATCH net-next v2 08/12] netdevsim: pass packets thru GRO on Rx Jakub Kicinski
2025-11-19 15:43 ` Petr Machata
2025-11-18 21:51 ` [PATCH net-next v2 09/12] selftests: drv-net: add a Python version of the GRO test Jakub Kicinski
2025-11-19 15:54 ` Petr Machata
2025-11-18 21:51 ` [PATCH net-next v2 10/12] selftests: drv-net: hw: convert the Toeplitz test to Python Jakub Kicinski
2025-11-19 16:39 ` Petr Machata
2025-11-18 21:51 ` [PATCH net-next v2 11/12] netdevsim: add loopback support Jakub Kicinski
2025-11-19 17:01 ` Petr Machata
2025-11-18 21:51 ` [PATCH net-next v2 12/12] selftests: net: remove old setup_* scripts Jakub Kicinski
2025-11-19 17:04 ` Petr Machata
2025-11-18 22:31 ` [PATCH net-next v2 00/12] selftests: drv-net: convert GRO and Toeplitz tests to work for drivers in NIPA Willem de Bruijn
2025-11-19 0:25 ` Jakub Kicinski
2025-11-19 0:32 ` Willem de Bruijn
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).