All of lore.kernel.org
 help / color / mirror / Atom feed
From: Todd Freed <toddfreed@meta.com>
To: <netdev@vger.kernel.org>, <toddfreed@meta.com>
Cc: "David S. Miller" <davem@davemloft.net>,
	"Andrew Lunn" <andrew+netdev@lunn.ch>,
	"Björn Töpel" <bjorn@kernel.org>,
	bpf@vger.kernel.org, "Daniel Borkmann" <daniel@iogearbox.net>,
	"Daniel Zahka" <daniel.zahka@gmail.com>,
	"Donald Hunter" <donald.hunter@gmail.com>,
	"Eric Dumazet" <edumazet@kernel.org>,
	"Jakub Kicinski" <kuba@kernel.org>,
	"Jamal Hadi Salim" <jhs@mojatatu.com>,
	"Jiri Pirko" <jiri@resnulli.us>,
	"John Fastabend" <john.fastabend@gmail.com>,
	linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-kselftest@vger.kernel.org, linux-rdma@vger.kernel.org,
	"Martin KaFai Lau" <martin.lau@linux.dev>,
	"Paolo Abeni" <pabeni@redhat.com>,
	"Saeed Mahameed" <saeedm@nvidia.com>,
	"Simon Horman" <horms@kernel.org>,
	"Tariq Toukan" <tariqt@nvidia.com>,
	"Wei Wang" <weiwan@google.com>,
	"Willem de Bruijn" <willemdebruijn.kernel@gmail.com>
Subject: [PATCH net-next v1 12/15] selftests: drv-net: psp: test that software encap on ingress drops
Date: Tue, 10 Nov 2026 16:55:30 -0800	[thread overview]
Message-ID: <20261111005533.6436-13-toddfreed@meta.com> (raw)
In-Reply-To: <20261111005533.6436-1-toddfreed@meta.com>

encap on ingress is hardware offload only. In software, the packet is
dropped.

Verify it on traffic of a client behind a veth, with encap on the veth's
ingress: forwarded, the packets must not reach the remote in clear text,
and to a local address, they must not reach the local socket.

  data_tc_encap_routed  routed packets are dropped by encap, IPv4 and
                        IPv6
  data_tc_encap_local   so are packets to a local address

Signed-off-by: Todd Freed <toddfreed@meta.com>
---
 tools/testing/selftests/drivers/net/config |   2 +
 tools/testing/selftests/drivers/net/psp.py | 159 ++++++++++++++++++++-
 2 files changed, 159 insertions(+), 2 deletions(-)

diff --git a/tools/testing/selftests/drivers/net/config b/tools/testing/selftests/drivers/net/config
index baf1c9d0dd13..b39de6e64263 100644
--- a/tools/testing/selftests/drivers/net/config
+++ b/tools/testing/selftests/drivers/net/config
@@ -5,6 +5,7 @@ CONFIG_DUMMY=m
 CONFIG_INET_PSP=y
 CONFIG_IPV6=y
 CONFIG_MACSEC=m
+CONFIG_NET_ACT_GACT=m
 CONFIG_NET_ACT_MIRRED=m
 CONFIG_NET_ACT_PSP=m
 CONFIG_NET_ACT_SKBEDIT=m
@@ -25,5 +26,6 @@ CONFIG_NET_SCH_PRIO=m
 CONFIG_PPP=y
 CONFIG_PPPOE=y
 CONFIG_TLS=y
+CONFIG_VETH=m
 CONFIG_VLAN_8021Q=m
 CONFIG_XDP_SOCKETS=y
diff --git a/tools/testing/selftests/drivers/net/psp.py b/tools/testing/selftests/drivers/net/psp.py
index fb7544410051..f7613fcd2fbf 100755
--- a/tools/testing/selftests/drivers/net/psp.py
+++ b/tools/testing/selftests/drivers/net/psp.py
@@ -22,7 +22,7 @@ from lib.py import ksft_variants, KsftNamedVariant
 from lib.py import KsftSkipEx, KsftFailEx
 from lib.py import NetDrvEpEnv, NetDrvContEnv
 from lib.py import Netlink, NlError, PSPFamily, RtnlFamily
-from lib.py import NetNSEnter
+from lib.py import NetNS, NetNSEnter
 from lib.py import bkg, rand_port, wait_port_listen
 from lib.py import cmd, ip, tc
 
@@ -1242,6 +1242,160 @@ def data_tc_encap_ingress(cfg):
             del_flt.exec()
 
 
+def _tc_act_stats(dev, pref, host=None):
+    """ Stats of the first action of the ingress filter @pref of @dev """
+    filters = tc(f"-s filter show dev {dev} ingress pref {pref}",
+                 json=True, host=host)
+    for flt in filters:
+        for act in flt.get("options", {}).get("actions", []):
+            return act["stats"]
+    raise KsftFailEx(f"no action on the {dev} pref {pref} filter")
+
+
+def _tc_act_pkts(dev, pref, host=None):
+    """ Packets of the first action of the ingress filter @pref of @dev """
+    return _tc_act_stats(dev, pref, host)["packets"]
+
+
+def _fwd_client(cfg, ipver):
+    """
+    Set up a client in a netns behind veth psp-fwd0, and forward its
+    traffic: only from psp-fwd0, the host's own forwarding settings stay as
+    they are. Return a UDP socket of the client.
+    """
+    ns = NetNS()
+    defer(ns.__del__)
+    ip(f"link add psp-fwd0 type veth peer name psp-fwd1 netns {ns.name}")
+    defer(ip, "link del psp-fwd0")
+    if ipver == "4":
+        fwd = "/proc/sys/net/ipv4/conf/psp-fwd0/forwarding"
+        local, client, plen = "198.51.100.1", "198.51.100.2", 24
+    else:
+        fwd = "/proc/sys/net/ipv6/conf/psp-fwd0/force_forwarding"
+        local, client, plen = "2001:db8:fe::1", "2001:db8:fe::2", 64
+    if not os.path.exists(fwd):
+        raise KsftSkipEx(f"{fwd} not supported")
+    # Goes away with the device
+    with open(fwd, "w", encoding="utf-8") as fp:
+        fp.write("1")
+    # IPv6 may be disabled on new devices
+    if cmd(f"ip addr add {local}/{plen} dev psp-fwd0 nodad",
+           fail=False).ret:
+        raise KsftSkipEx(f"can't add {local} to a new device")
+    ip("link set psp-fwd0 up")
+    ip(f"-n {ns.name} addr add {client}/{plen} dev psp-fwd1 nodad")
+    ip(f"-n {ns.name} link set psp-fwd1 up")
+    ip(f"-n {ns.name} route add default via {local}")
+
+    family = socket.AF_INET if ipver == "4" else socket.AF_INET6
+    with NetNSEnter(ns.name):
+        s = socket.socket(family, socket.SOCK_DGRAM)
+    defer(s.close)
+    return s
+
+
+def _remote_filter(cfg, pref, proto, match):
+    """
+    Add a flower filter on the remote's ingress, to count what gets there.
+    In software only: drivers refresh the counters of offloaded filters
+    periodically, and these counts must be exact.
+    """
+    _tc_clsact(cfg.remote_ifname, host=cfg.remote)
+    tc(f"filter add dev {cfg.remote_ifname} ingress pref {pref} handle 1 "
+       f"protocol {proto} flower skip_hw {match}", host=cfg.remote)
+    defer(tc, f"filter del dev {cfg.remote_ifname} ingress pref {pref} "
+          f"handle 1 protocol {proto} flower", host=cfg.remote)
+
+
+def _tc_encap_ingress(proto, port, tx):
+    """ psp encap on psp-fwd0's ingress, which software drops """
+    _tc_clsact("psp-fwd0")
+    tc(f"filter add dev psp-fwd0 ingress pref 10 protocol {proto} "
+       f"flower ip_proto udp dst_port {port} "
+       f"action psp encap assoc {tx['id']}")
+
+
+@ksft_variants(_get_ip_variants())
+def data_tc_encap_routed(cfg, ipver):
+    """ Test software encap on ingress drops routed packets """
+    cfg.require_ipver(ipver)
+    _init_psp_dev(cfg)
+    _require_tc_psp(cfg)
+
+    proto = _tc_proto(ipver)
+    _, tx = _sockless_assocs(cfg)
+    s = _fwd_client(cfg, ipver)
+
+    port = rand_port(socket.SOCK_DGRAM)
+    _remote_filter(cfg, 10, proto,
+                   f"ip_proto udp dst_port {port} action drop")
+
+    def remote_pkts():
+        return _tc_act_pkts(cfg.remote_ifname, 10, host=cfg.remote)
+
+    def send(n):
+        for _ in range(n):
+            s.sendto(b'0123456789', (cfg.remote_addr_v[ipver], port))
+            time.sleep(0.01)
+        time.sleep(0.2)
+
+    # Without encap the packets are forwarded to the remote, unless
+    # something else, e.g. a FORWARD policy, stops them
+    send(10)
+    sent = remote_pkts()
+    if not sent:
+        raise KsftSkipEx("forwarded packets don't reach the remote")
+
+    # Encap on ingress is hardware offload only: in software the action
+    # drops the packets. They must not reach the remote in clear text.
+    _tc_encap_ingress(proto, port, tx)
+    send(10)
+    ksft_eq(_tc_act_pkts("psp-fwd0", 10), 10)
+    ksft_eq(_tc_act_stats("psp-fwd0", 10)["drops"], 10,
+            comment="dropped by encap")
+    ksft_eq(remote_pkts(), sent)
+
+
+@ksft_variants(_get_ip_variants())
+def data_tc_encap_local(cfg, ipver):
+    """ Test software encap on ingress drops packets to a local address """
+    cfg.require_ipver(ipver)
+    _init_psp_dev(cfg)
+    _require_tc_psp(cfg)
+
+    _, tx = _sockless_assocs(cfg)
+    s = _fwd_client(cfg, ipver)
+    fam = "inet" if ipver == "4" else "inet6"
+    addrs = ip("addr show dev psp-fwd0", json=True)[0]["addr_info"]
+    local = [a["local"] for a in addrs
+             if a["family"] == fam and a["scope"] == "global"][0]
+
+    family = socket.AF_INET if ipver == "4" else socket.AF_INET6
+    with socket.socket(family, socket.SOCK_DGRAM) as srv:
+        srv.bind((local, 0))
+        srv.settimeout(0.5)
+        port = srv.getsockname()[1]
+
+        # Without encap the packets are delivered, unless something
+        # else, e.g. an INPUT policy, stops them
+        s.sendto(b'clear', (local, port))
+        try:
+            got = srv.recv(64)
+        except socket.timeout as e:
+            raise KsftSkipEx("the client's packets aren't delivered") from e
+        ksft_eq(got, b'clear')
+
+        # Encap on ingress is hardware offload only: in software the
+        # action drops the packets, rather than let them be received
+        _tc_encap_ingress(_tc_proto(ipver), port, tx)
+        s.sendto(b'encap', (local, port))
+        with ksft_raises(socket.timeout):
+            srv.recv(64)
+        ksft_eq(_tc_act_pkts("psp-fwd0", 10), 1)
+        ksft_eq(_tc_act_stats("psp-fwd0", 10)["drops"], 1,
+                comment="dropped by encap")
+
+
 def removal_device_tc(cfg):
     """ Test removing a PSD with tc actions holding its assocs """
     cfg.require_nsim()
@@ -1760,7 +1914,8 @@ def main() -> None:
                                                           cfg.comm_port),
                                                          timeout=1)
 
-                cases = [data_basic_send, data_mss_adjust, data_tc_basic_send]
+                cases = [data_basic_send, data_mss_adjust, data_tc_basic_send,
+                         data_tc_encap_routed, data_tc_encap_local]
 
                 if has_cont:
                     cases += [
-- 
2.53.0-Meta


  parent reply	other threads:[~2026-11-11  0:56 UTC|newest]

Thread overview: 39+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-11  0:55 [PATCH net-next v1 00/15] psp: introduce socket-less associations Todd Freed
2026-11-11  0:55 ` [PATCH net-next v1 01/15] psp: get netns from net_device instead of sock Todd Freed
2026-11-12  0:56   ` sashiko-bot
2026-11-11  0:55 ` [PATCH net-next v1 02/15] psp: take the psp nexthdr from the packet on encap Todd Freed
2026-11-12  0:56   ` sashiko-bot
2026-11-11  0:55 ` [PATCH net-next v1 03/15] psp: declare psp_assoc_set_tx() in psp.h Todd Freed
2026-11-12  0:56   ` sashiko-bot
2026-11-11  0:55 ` [PATCH net-next v1 04/15] psp: add support for socket-less psp associations Todd Freed
2026-11-11 16:49   ` Daniel Zahka
2026-11-11 18:23     ` Todd Bert Freed
2026-11-11 19:01       ` Daniel Zahka
2026-11-11 21:49         ` Todd Bert Freed
2026-11-12  0:51     ` Todd Bert Freed
2026-11-12  0:57   ` sashiko-bot
2026-11-11  0:55 ` [PATCH net-next v1 05/15] net: add METADATA_PSP dst to carry a psp association on an skb Todd Freed
2026-11-12  0:57   ` sashiko-bot
2026-11-11  0:55 ` [PATCH net-next v1 06/15] net/sched: act_mirred: don't send decrypted skbs from egress to ingress Todd Freed
2026-11-12  0:57   ` sashiko-bot
2026-11-11  0:55 ` [PATCH net-next v1 07/15] bpf: don't redirect " Todd Freed
2026-11-12  0:57   ` sashiko-bot
2026-11-11  0:55 ` [PATCH net-next v1 08/15] psp: only give time-wait sockets of psp connections a validator Todd Freed
2026-11-11 11:37   ` Daniel Zahka
2026-11-12  0:57   ` sashiko-bot
2026-11-11  0:55 ` [PATCH net-next v1 09/15] net/sched: add act_psp for psp transport mode Todd Freed
2026-11-12  0:57   ` sashiko-bot
2026-11-11  0:55 ` [PATCH net-next v1 10/15] net/sched: flower: add psp_spi, psp_ver, and psp_dev matches Todd Freed
2026-11-12  0:57   ` sashiko-bot
2026-11-11  0:55 ` [PATCH net-next v1 11/15] selftests: drv-net: psp: test socket-less associations and the tc psp action Todd Freed
2026-11-12  0:57   ` sashiko-bot
2026-11-11  0:55 ` Todd Freed [this message]
2026-11-12  0:57   ` [PATCH net-next v1 12/15] selftests: drv-net: psp: test that software encap on ingress drops sashiko-bot
2026-11-11  0:55 ` [PATCH net-next v1 13/15] selftests: tc-testing: run dependsOn probes outside the test namespace Todd Freed
2026-11-12  0:57   ` sashiko-bot
2026-11-11  0:55 ` [PATCH net-next v1 14/15] selftests: tc-testing: add tests for the psp action Todd Freed
2026-11-12  0:57   ` sashiko-bot
2026-11-11  0:55 ` [PATCH net-next v1 15/15] Documentation: networking: psp: document socket-less associations Todd Freed
2026-11-12  0:57   ` sashiko-bot
2026-11-11 17:01 ` [PATCH net-next v1 00/15] psp: introduce " Daniel Zahka
2026-11-12 19:35   ` Todd Bert Freed

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=20261111005533.6436-13-toddfreed@meta.com \
    --to=toddfreed@meta.com \
    --cc=andrew+netdev@lunn.ch \
    --cc=bjorn@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel.zahka@gmail.com \
    --cc=daniel@iogearbox.net \
    --cc=davem@davemloft.net \
    --cc=donald.hunter@gmail.com \
    --cc=edumazet@kernel.org \
    --cc=horms@kernel.org \
    --cc=jhs@mojatatu.com \
    --cc=jiri@resnulli.us \
    --cc=john.fastabend@gmail.com \
    --cc=kuba@kernel.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=linux-rdma@vger.kernel.org \
    --cc=martin.lau@linux.dev \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=saeedm@nvidia.com \
    --cc=tariqt@nvidia.com \
    --cc=weiwan@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.