From: Tariq Toukan <tariqt@nvidia.com>
To: Andrew Lunn <andrew+netdev@lunn.ch>,
"David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>, <netdev@vger.kernel.org>,
Paolo Abeni <pabeni@redhat.com>,
Sabrina Dubroca <sd@queasysnail.net>
Cc: Aleksandr Loktionov <aleksandr.loktionov@intel.com>,
Alexei Lazar <alazar@nvidia.com>,
Alexei Starovoitov <ast@kernel.org>,
Allison Henderson <allison.henderson@oracle.com>,
Antonio Quartulli <antonio@openvpn.net>,
Anubhav Singh <anubhavsinggh@google.com>,
Bobby Eshleman <bobbyeshleman@meta.com>,
Boris Pismenny <borisp@nvidia.com>, <bpf@vger.kernel.org>,
Carolina Jubran <cjubran@nvidia.com>, Chris Mi <cmi@nvidia.com>,
Cosmin Ratiu <cratiu@nvidia.com>,
Daniel Borkmann <daniel@iogearbox.net>,
Daniel Zahka <daniel.zahka@gmail.com>, David Wei <dw@davidwei.uk>,
Doruk Tan Ozturk <doruk@0sec.ai>,
Dragos Tatulea <dtatulea@nvidia.com>,
Gal Pressman <gal@nvidia.com>,
Jacob Keller <Jacob.e.keller@intel.com>,
Jesper Dangaard Brouer <hawk@kernel.org>,
"Jianbo Liu" <jianbol@nvidia.com>,
John Fastabend <john.fastabend@gmail.com>,
"Kees Cook" <kees@kernel.org>, Lama Kayal <lkayal@nvidia.com>,
Leon Romanovsky <leon@kernel.org>,
open list <linux-kernel@vger.kernel.org>,
<linux-kselftest@vger.kernel.org>, <linux-rdma@vger.kernel.org>,
Mark Bloch <mbloch@nvidia.com>,
"Matthieu Baerts (NGI0)" <matttbe@kernel.org>,
Patrisious Haddad <phaddad@nvidia.com>,
Petr Machata <petrm@nvidia.com>, "Raed Salem" <raeds@nvidia.com>,
Rahul Rameshbabu <rrameshbabu@nvidia.com>,
"Richard Gobert" <richardbgobert@gmail.com>,
Saeed Mahameed <saeedm@nvidia.com>,
"Shuah Khan" <shuah@kernel.org>,
Shuah Khan <skhan@linuxfoundation.org>,
Simon Horman <horms@kernel.org>,
Stanislav Fomichev <sdf@fomichev.me>,
Stanislav Fomichev <sdf.kernel@gmail.com>,
Tariq Toukan <tariqt@nvidia.com>,
Willem de Bruijn <willemb@google.com>,
Willem de Bruijn <willemdebruijn.kernel@gmail.com>
Subject: [PATCH net-next V3 15/15] selftests: drv-net: Add PSP HW GRO conformance tests
Date: Thu, 3 Sep 2026 11:52:15 +0300 [thread overview]
Message-ID: <20260903085215.3691657-16-tariqt@nvidia.com> (raw)
In-Reply-To: <20260903085215.3691657-1-tariqt@nvidia.com>
From: Cosmin Ratiu <cratiu@nvidia.com>
Add PSP conformance tests using the same gro helper binary as gro.py
does, but in --psp mode. SPIs are procured by psp_gro.py from a real PSP
device and handed off to the gro sender & receiver. The sender crafts
and encrypts packets in software, the receiver relies fully on the HW to
decrypt, decapsulate and do HW GRO.
Because the NIC decrypts and decapsulates before the frames reach the
receiver AF_PACKET tap, it sees the plain frames and the assertions
remain exactly the same as gro.py.
So these tests verify, at length, that the device does PSP HW-GRO the
same way as plain TCP.
Additional PSP-specific tests are defined to check that GRO doesn't
merge packets across PSP versions, SPIs, encryption-status, etc.
Some tests from gro.py are not included because they don't work:
- ip_csum: the checksum is recomputed by psp_dev_rcv().
- tcp_csum: packets are marked with CHECKSUM_UNNECESSARY.
- ip_frag4/ip_frag6: PSP is incompatible with IP fragmentation.
- IPv6 extension header tests: PSP doesn't deal with IPv6 ext headers.
Signed-off-by: Cosmin Ratiu <cratiu@nvidia.com>
Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
---
.../testing/selftests/drivers/net/gro_lib.py | 14 +-
.../testing/selftests/drivers/net/hw/Makefile | 17 ++
.../selftests/drivers/net/hw/psp_gro.py | 172 ++++++++++++++++++
3 files changed, 201 insertions(+), 2 deletions(-)
create mode 100755 tools/testing/selftests/drivers/net/hw/psp_gro.py
diff --git a/tools/testing/selftests/drivers/net/gro_lib.py b/tools/testing/selftests/drivers/net/gro_lib.py
index 4e3d704397fe..519986028980 100644
--- a/tools/testing/selftests/drivers/net/gro_lib.py
+++ b/tools/testing/selftests/drivers/net/gro_lib.py
@@ -121,9 +121,14 @@ def setup_hw_gro(cfg):
# pylint: disable=too-many-arguments,too-many-positional-arguments
+# pylint: disable=too-many-locals
def run_gro_bin(cfg, test_name, protocol=None, num_flows=None,
- order_check=False, verbose=False, fail=False):
- """Runs gro binary with given test and return the process result."""
+ order_check=False, verbose=False, fail=False,
+ common_args=None):
+ """Runs gro binary with given test and return the process result.
+
+ common_args is a list of extra arguments passed to both ends.
+ """
if not hasattr(cfg, "bin_remote"):
cfg.bin_local = cfg.net_lib_dir / "gro"
cfg.bin_remote = cfg.remote.deploy(cfg.bin_local)
@@ -150,6 +155,8 @@ def run_gro_bin(cfg, test_name, protocol=None, num_flows=None,
base_args.append("--order-check")
if verbose:
base_args.append("--verbose")
+ if common_args:
+ base_args += common_args
args = " ".join(base_args)
@@ -169,6 +176,9 @@ def run_with_retries(cfg, test_name, protocol=None, **kwargs):
packets that should coalesce will be considered in the same flow on
every try. Over-coalescing is a hard failure, retries can only
cause false negatives there.
+
+ Extra keyword arguments (num_flows, order_check, verbose,
+ common_args) are forwarded to run_gro_bin().
"""
max_retries = 6
for attempt in range(max_retries):
diff --git a/tools/testing/selftests/drivers/net/hw/Makefile b/tools/testing/selftests/drivers/net/hw/Makefile
index 78bb0169350b..0a7851846708 100644
--- a/tools/testing/selftests/drivers/net/hw/Makefile
+++ b/tools/testing/selftests/drivers/net/hw/Makefile
@@ -13,6 +13,20 @@ else
$(warning excluding iouring tests, liburing not installed or too old)
endif
+# psp_gro.py uses the gro binary in PSP mode, which requires OpenSSL.
+PKG_CONFIG ?= pkg-config
+HAVE_OPENSSL := $(shell echo 'int main(void) { return 0; }' | \
+ $(CC) -x c - -include openssl/evp.h \
+ $(shell $(PKG_CONFIG) --cflags --libs libcrypto 2>/dev/null \
+ || echo -lcrypto) \
+ -o /dev/null >/dev/null 2>&1 && echo 1)
+
+ifeq ($(HAVE_OPENSSL),1)
+COND_PROGS += psp_gro.py
+else
+$(warning excluding PSP GRO tests, libcrypto not installed)
+endif
+
TEST_GEN_FILES := \
$(COND_GEN_FILES) \
# end of TEST_GEN_FILES
@@ -40,6 +54,7 @@ TEST_PROGS = \
nk_qlease.py \
ntuple.py \
pp_alloc_fail.py \
+ $(COND_PROGS) \
rss_api.py \
rss_ctx.py \
rss_drv.py \
@@ -64,6 +79,8 @@ TEST_FILES := \
TEST_INCLUDES := \
$(wildcard lib/py/*.py ../lib/py/*.py) \
+ ../gro_lib.py \
+ ../psp_lib.py \
../../../net/lib.sh \
../../../net/forwarding/ipip_lib.sh \
../../../net/forwarding/lib.sh \
diff --git a/tools/testing/selftests/drivers/net/hw/psp_gro.py b/tools/testing/selftests/drivers/net/hw/psp_gro.py
new file mode 100755
index 000000000000..9af80a022a17
--- /dev/null
+++ b/tools/testing/selftests/drivers/net/hw/psp_gro.py
@@ -0,0 +1,172 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0
+
+"""
+PSP conformance tests built on the GRO test binary.
+
+This reuses the gro binary in --psp mode:
+The sender crafts encapsulated & sw-encrypted PSP packets with the receiver PSP
+rx-assoc, and the receiver device decrypts and decapsulates the packets before
+an AF_PACKET tap gets to analyze them.
+
+All tests from gro.py which could run with PSP are included.
+"""
+
+import socket
+
+from lib.py import ksft_run, ksft_exit
+from lib.py import ksft_variants, KsftNamedVariant
+from lib.py import KsftSkipEx
+from lib.py import NetDrvEpEnv, PSPFamily
+from lib.py import defer, ethtool
+
+# The helpers live next to their other users, gro.py and psp.py. Importing
+# lib.py above puts the selftests root on sys.path, which is what makes these
+# two resolve, so they have to stay after it - pylint wants the opposite.
+# pylint: disable=wrong-import-order,import-error
+from drivers.net.gro_lib import run_with_retries, set_mtu_restore, setup_hw_gro
+from drivers.net.psp_lib import init_psp_dev, require_version
+# pylint: enable=wrong-import-order,import-error
+
+
+# Tests for both IP versions, a subset of gro.py. Missing:
+# - tcp_csum: PSP packets are validated by HW (with the ICV) and marked with
+# CHECKSUM_UNNECESSARY.
+_COMMON = ["data_same", "data_lrg_sml", "data_sml_lrg", "data_lrg_1byte",
+ "data_burst",
+ "ack",
+ "flags_psh", "flags_syn", "flags_rst", "flags_urg", "flags_cwr",
+ "tcp_seq", "tcp_ts", "tcp_opt",
+ "ip_ecn", "ip_tos",
+ "large_max", "large_rem",
+]
+
+# Tests specific to IPv4, a subset of gro.py. Missing:
+# - ip_csum: psp_dev_rcv() recomputes the IP checksum.
+# - ip_frag4: PSP is incompatible with IP fragmentation.
+_V4 = ["ip_ttl", "ip_opt",
+ "ip_id_df1_inc", "ip_id_df1_fixed",
+ "ip_id_df0_inc", "ip_id_df0_fixed",
+ "ip_id_df1_inc_fixed", "ip_id_df1_fixed_inc",
+]
+
+# No IPv6-only tests:
+# - ip_frag6: PSP doesn't support fragmentation
+# - ip_v6ext_same, ip_v6ext_diff: PSP doesn't support IPv6 ext headers.
+
+
+def _psp_variants():
+ for ver in range(4):
+ for proto in ["ipv4", "ipv6"]:
+ for test_name in _COMMON + (_V4 if proto == "ipv4" else []):
+ yield KsftNamedVariant(f"v{ver}_{proto}_{test_name}",
+ ver, proto, test_name)
+
+
+def _ip_variants():
+ """IPv4/IPv6."""
+ for proto in ("ipv4", "ipv6"):
+ yield KsftNamedVariant(proto, proto)
+
+
+def _psp_assoc(cfg, version=0):
+ # This socket receives no traffic, exists solely to own the rx assoc.
+ s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
+ defer(s.close)
+ return cfg.pspnl.rx_assoc({"version": version, "dev-id": cfg.psp_dev_id,
+ "sock-fd": s.fileno()})['rx-key']
+
+
+def _setup(cfg, version, test_name):
+ """Enables PSP and HW GRO on the device under test."""
+ init_psp_dev(cfg)
+ require_version(cfg, version)
+
+ if not hasattr(cfg, "feat"):
+ cfg.feat = ethtool(f"-k {cfg.ifname}", json=True)[0]
+
+ setup_hw_gro(cfg)
+
+ # "large_*" tests need at least 4k MTU
+ if test_name.startswith("large_"):
+ set_mtu_restore(cfg.dev, 4096, None)
+ set_mtu_restore(cfg.remote_dev, 4096, cfg.remote)
+
+
+def _psp_args(cfg, versions):
+ """Produces PSP associations as gro binary --psp-assoc arguments."""
+ keys = [_psp_assoc(cfg, ver) for ver in versions]
+ return [f"--psp-assoc {ver},{key['spi']:x},{key['key'].hex()}"
+ for ver, key in zip(versions, keys)]
+
+
+def _run(cfg, test_name, protocol, versions):
+ """Sets up, associates and runs one gro test case under PSP."""
+ ipver = protocol[-1]
+ cfg.require_ipver(ipver)
+
+ _setup(cfg, max(versions), test_name)
+
+ run_with_retries(cfg, test_name, protocol=protocol, verbose=True,
+ common_args=_psp_args(cfg, versions))
+
+
+@ksft_variants(_psp_variants())
+def test_psp_gro(cfg, version, protocol, test_name):
+ """Runs one gro conformance case with PSP encapsulation."""
+ _run(cfg, test_name, protocol, [version])
+
+
+# PSP-specific GRO tests
+
+@ksft_variants(_ip_variants())
+def test_psp_spi_diff(cfg, protocol):
+ """Frames from two different SPIs must not coalesce."""
+ _run(cfg, "psp_spi_diff", protocol, [0, 0])
+
+
+@ksft_variants(_ip_variants())
+def test_psp_ver_diff(cfg, protocol):
+ """Frames from two different PSP versions must not coalesce."""
+ init_psp_dev(cfg)
+ if len(cfg.psp_info['psp-versions-cap']) < 2:
+ raise KsftSkipEx("Device supports a single PSP version")
+
+ _run(cfg, "psp_ver_diff", protocol, [0, 1])
+
+
+@ksft_variants(_ip_variants())
+def test_psp_mixed(cfg, protocol):
+ """A PSP frame must not coalesce with a clear text one."""
+ _run(cfg, "psp_mixed", protocol, [0])
+
+
+@ksft_variants(_ip_variants())
+def test_psp_after_reconfig(cfg, protocol):
+ """Verifies that decap still works after PSP off + on."""
+ cfg.require_ipver(protocol[-1])
+
+ _setup(cfg, 0, "data_same")
+
+ cap = cfg.psp_info['psp-versions-cap']
+ cfg.pspnl.dev_set({'id': cfg.psp_dev_id, 'psp-versions-ena': []})
+ cfg.pspnl.dev_set({'id': cfg.psp_dev_id, 'psp-versions-ena': cap})
+
+ run_with_retries(cfg, "data_same", protocol=protocol, verbose=True,
+ common_args=_psp_args(cfg, [0]))
+
+
+def main() -> None:
+ """ Ksft boiler plate main """
+
+ with NetDrvEpEnv(__file__, nsim_test=False) as cfg:
+ cfg.pspnl = PSPFamily()
+
+ ksft_run(cases=[test_psp_gro, test_psp_spi_diff, test_psp_ver_diff,
+ test_psp_mixed, test_psp_after_reconfig],
+ args=(cfg, ))
+ ksft_exit()
+
+
+if __name__ == "__main__":
+ main()
--
2.44.0
prev parent reply other threads:[~2026-09-03 8:56 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-03 8:52 [PATCH net-next V3 00/15] net/mlx5e: Add support for HW-GRO to PSP Tariq Toukan
2026-09-03 8:52 ` [PATCH net-next V3 01/15] net/mlx5e: Generalize TC <-> IPsec mutual exclusion Tariq Toukan
2026-09-03 8:52 ` [PATCH net-next V3 02/15] net/mlx5e: ipsec: Block TC offload when IPsec is enabled Tariq Toukan
2026-09-03 8:52 ` [PATCH net-next V3 03/15] net/mlx5e: psp: Block TC offload when PSP " Tariq Toukan
2026-09-03 8:52 ` [PATCH net-next V3 04/15] net/mlx5e: macsec: Block TC offload when MACsec " Tariq Toukan
2026-09-03 8:52 ` [PATCH net-next V3 05/15] net/mlx5e: psp: Move RX marker from ft_metadata to flow_tag Tariq Toukan
2026-09-03 8:52 ` [PATCH net-next V3 06/15] net/mlx5e: ipsec: " Tariq Toukan
2026-09-03 8:52 ` [PATCH net-next V3 07/15] net/mlx5e: macsec: " Tariq Toukan
2026-09-03 8:52 ` [PATCH net-next V3 08/15] net/mlx5e: psp: Handle HW-decapsulated RX PSP packets Tariq Toukan
2026-09-03 8:52 ` [PATCH net-next V3 09/15] net/mlx5e: psp: Add an rx_decap steering table Tariq Toukan
2026-09-03 8:52 ` [PATCH net-next V3 10/15] net/mlx5e: shampo: Flush session on PSP mismatch Tariq Toukan
2026-09-03 8:52 ` [PATCH net-next V3 11/15] net/mlx5e: psp: Dynamically reconfigure based on SHAMPO mode Tariq Toukan
2026-09-03 8:52 ` [PATCH net-next V3 12/15] selftests: drv-net: psp: Extract shared helpers into psp_lib.py Tariq Toukan
2026-09-03 8:52 ` [PATCH net-next V3 13/15] selftests: drv-net: gro: Extract shared helpers into gro_lib.py Tariq Toukan
2026-09-03 8:52 ` [PATCH net-next V3 14/15] selftests: net: gro: Add PSP encapsulation and encryption Tariq Toukan
2026-09-03 10:26 ` Loktionov, Aleksandr
2026-09-03 8:52 ` Tariq Toukan [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260903085215.3691657-16-tariqt@nvidia.com \
--to=tariqt@nvidia.com \
--cc=Jacob.e.keller@intel.com \
--cc=alazar@nvidia.com \
--cc=aleksandr.loktionov@intel.com \
--cc=allison.henderson@oracle.com \
--cc=andrew+netdev@lunn.ch \
--cc=antonio@openvpn.net \
--cc=anubhavsinggh@google.com \
--cc=ast@kernel.org \
--cc=bobbyeshleman@meta.com \
--cc=borisp@nvidia.com \
--cc=bpf@vger.kernel.org \
--cc=cjubran@nvidia.com \
--cc=cmi@nvidia.com \
--cc=cratiu@nvidia.com \
--cc=daniel.zahka@gmail.com \
--cc=daniel@iogearbox.net \
--cc=davem@davemloft.net \
--cc=doruk@0sec.ai \
--cc=dtatulea@nvidia.com \
--cc=dw@davidwei.uk \
--cc=edumazet@google.com \
--cc=gal@nvidia.com \
--cc=hawk@kernel.org \
--cc=horms@kernel.org \
--cc=jianbol@nvidia.com \
--cc=john.fastabend@gmail.com \
--cc=kees@kernel.org \
--cc=kuba@kernel.org \
--cc=leon@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=linux-rdma@vger.kernel.org \
--cc=lkayal@nvidia.com \
--cc=matttbe@kernel.org \
--cc=mbloch@nvidia.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=petrm@nvidia.com \
--cc=phaddad@nvidia.com \
--cc=raeds@nvidia.com \
--cc=richardbgobert@gmail.com \
--cc=rrameshbabu@nvidia.com \
--cc=saeedm@nvidia.com \
--cc=sd@queasysnail.net \
--cc=sdf.kernel@gmail.com \
--cc=sdf@fomichev.me \
--cc=shuah@kernel.org \
--cc=skhan@linuxfoundation.org \
--cc=willemb@google.com \
--cc=willemdebruijn.kernel@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox