mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
selftests/net: psp: support PSP in NetDrvContEnv infrastructure
Add infrastructure to support PSP tests across network namespaces
using NetDrvContEnv with netkit pairs. This enables testing PSP device
association, where a non-PSP-capable device (e.g. netkit) in a guest
namespace is associated with a real PSP device in the host namespace,
allowing the guest to perform PSP encryption/decryption through the
host's PSP hardware.
The topology is:
Host NS: psp_dev_local <---> nk_host
| |
| | (netkit pair)
| |
Remote NS: psp_dev_peer Guest NS: nk_guest
(responder) (PSP tests)
env.py:
- nk_guest_ifindex is queried after moving the device into the guest
namespace, so tests can use it directly for dev-assoc
psp.py:
- PSP device lookup supports container environments where the PSP
device is on the physical interface, not the test interface
- Association helpers handle dev-assoc/dev-disassoc with defer-based
cleanup to prevent state leaks on test assertion failures
- main() tries NetDrvContEnv with primary_rx_redirect and falls back
to NetDrvEpEnv, so existing tests continue to work without the
container environment
Signed-off-by: Wei Wang <weibunny@fb.com>
Link: https://patch.msgid.link/20260608233118.2694144-8-weibunny.kernel@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
593e22f652
commit
1c1c2e5b1f
|
|
@ -8,6 +8,7 @@ CONFIG_NETCONSOLE=m
|
|||
CONFIG_NETCONSOLE_DYNAMIC=y
|
||||
CONFIG_NETCONSOLE_EXTENDED_LOG=y
|
||||
CONFIG_NETDEVSIM=m
|
||||
CONFIG_NETKIT=y
|
||||
CONFIG_NET_SCH_ETF=m
|
||||
CONFIG_NET_SCH_FQ=m
|
||||
CONFIG_PPP=y
|
||||
|
|
|
|||
|
|
@ -470,6 +470,9 @@ class NetDrvContEnv(NetDrvEpEnv):
|
|||
self._init_ns_attached = True
|
||||
ip("netns set init 0", ns=self.netns)
|
||||
ip(f"link set dev {self.nk_guest_ifname} netns {self.netns.name}")
|
||||
nk_guest_dev = ip(f"link show dev {self.nk_guest_ifname}",
|
||||
json=True, ns=self.netns)[0]
|
||||
self.nk_guest_ifindex = nk_guest_dev['ifindex']
|
||||
ip(f"link set dev {self.nk_host_ifname} up")
|
||||
ip(f"-6 addr add fe80::1/64 dev {self.nk_host_ifname} nodad")
|
||||
ip(f"-6 route add {self.nk_guest_ipv6}/128 via fe80::2 dev {self.nk_host_ifname}")
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
import errno
|
||||
import fcntl
|
||||
import os
|
||||
import socket
|
||||
import struct
|
||||
import termios
|
||||
|
|
@ -16,8 +17,10 @@ from lib.py import ksft_true, ksft_eq, ksft_ne, ksft_gt, ksft_raises
|
|||
from lib.py import ksft_not_none
|
||||
from lib.py import ksft_variants, KsftNamedVariant
|
||||
from lib.py import KsftSkipEx
|
||||
from lib.py import NetDrvEpEnv, PSPFamily, NlError
|
||||
from lib.py import NetDrvEpEnv, NetDrvContEnv
|
||||
from lib.py import NlError, PSPFamily
|
||||
from lib.py import bkg, rand_port, wait_port_listen
|
||||
from lib.py import ip
|
||||
|
||||
|
||||
def _get_outq(s):
|
||||
|
|
@ -118,11 +121,13 @@ def _get_stat(cfg, key):
|
|||
# Test case boiler plate
|
||||
#
|
||||
|
||||
def _init_psp_dev(cfg):
|
||||
def _init_psp_dev(cfg, use_psp_ifindex=False):
|
||||
if not hasattr(cfg, 'psp_dev_id'):
|
||||
# Figure out which local device we are testing against
|
||||
# For NetDrvContEnv: use psp_ifindex instead of ifindex
|
||||
target_ifindex = cfg.psp_ifindex if use_psp_ifindex else cfg.ifindex
|
||||
for dev in cfg.pspnl.dev_get({}, dump=True):
|
||||
if dev['ifindex'] == cfg.ifindex:
|
||||
if dev['ifindex'] == target_ifindex:
|
||||
cfg.psp_info = dev
|
||||
cfg.psp_dev_id = cfg.psp_info['id']
|
||||
break
|
||||
|
|
@ -597,13 +602,102 @@ def data_mss_adjust(cfg, ipver):
|
|||
_data_mss_adjust(cfg, ipver)
|
||||
|
||||
|
||||
def _try_disassoc(cfg, psp_dev_id, ifindex, nsid=None):
|
||||
"""Best-effort disassociate, ignoring errors if already removed."""
|
||||
try:
|
||||
params = {'id': psp_dev_id, 'ifindex': ifindex}
|
||||
if nsid is not None:
|
||||
params['nsid'] = nsid
|
||||
cfg.pspnl.dev_disassoc(params)
|
||||
except NlError:
|
||||
pass
|
||||
|
||||
|
||||
def _assoc_nk_guest(cfg):
|
||||
"""Associate nk_guest with PSP device and register cleanup via defer()."""
|
||||
_init_psp_dev(cfg, True)
|
||||
|
||||
cfg.pspnl.dev_assoc({'id': cfg.psp_dev_id,
|
||||
'ifindex': cfg.nk_guest_ifindex,
|
||||
'nsid': cfg.psp_dev_peer_nsid})
|
||||
defer(_disassoc_nk_guest, cfg,
|
||||
cfg.psp_dev_id, cfg.nk_guest_ifindex)
|
||||
|
||||
|
||||
def _disassoc_nk_guest(cfg, psp_dev_id, nk_guest_ifindex):
|
||||
"""Disassociate nk_guest and reset cfg PSP state."""
|
||||
pspnl = PSPFamily()
|
||||
pspnl.dev_disassoc({'id': psp_dev_id, 'ifindex': nk_guest_ifindex,
|
||||
'nsid': cfg.psp_dev_peer_nsid})
|
||||
cfg.pspnl = pspnl
|
||||
del cfg.psp_dev_id
|
||||
del cfg.psp_info
|
||||
|
||||
|
||||
def _get_nsid(ns_name):
|
||||
"""Get the nsid for a namespace."""
|
||||
for entry in ip("netns list-id", json=True):
|
||||
if entry.get("name") == str(ns_name):
|
||||
return entry["nsid"]
|
||||
raise KsftSkipEx(f"nsid not found for namespace {ns_name}")
|
||||
|
||||
|
||||
def _setup_psp_attributes(cfg):
|
||||
# pylint: disable=protected-access
|
||||
"""
|
||||
Set up PSP-specific attributes on the environment.
|
||||
|
||||
This sets attributes needed for PSP tests based on whether we're using
|
||||
netdevsim or a real NIC.
|
||||
"""
|
||||
if cfg._ns is not None:
|
||||
# netdevsim case: PSP device is the local dev (in host namespace)
|
||||
cfg.psp_dev = cfg._ns.nsims[0].dev
|
||||
cfg.psp_ifname = cfg.psp_dev['ifname']
|
||||
cfg.psp_ifindex = cfg.psp_dev['ifindex']
|
||||
|
||||
# PSP peer device is the remote dev (in _netns, where psp_responder runs)
|
||||
cfg.psp_dev_peer = cfg._ns_peer.nsims[0].dev
|
||||
cfg.psp_dev_peer_ifname = cfg.psp_dev_peer['ifname']
|
||||
cfg.psp_dev_peer_ifindex = cfg.psp_dev_peer['ifindex']
|
||||
else:
|
||||
# Real NIC case: PSP device is the local interface
|
||||
cfg.psp_dev = cfg.dev
|
||||
cfg.psp_ifname = cfg.ifname
|
||||
cfg.psp_ifindex = cfg.ifindex
|
||||
|
||||
# PSP peer device is the remote interface
|
||||
cfg.psp_dev_peer = cfg.remote_dev
|
||||
cfg.psp_dev_peer_ifname = cfg.remote_ifname
|
||||
cfg.psp_dev_peer_ifindex = cfg.remote_ifindex
|
||||
|
||||
# Get nsid for the guest namespace (netns) where nk_guest is
|
||||
cfg.psp_dev_peer_nsid = _get_nsid(cfg.netns.name)
|
||||
|
||||
|
||||
|
||||
def main() -> None:
|
||||
""" Ksft boiler plate main """
|
||||
|
||||
with NetDrvEpEnv(__file__) as cfg:
|
||||
# Make sure LOCAL_PREFIX_V6 is set
|
||||
if "LOCAL_PREFIX_V6" not in os.environ:
|
||||
os.environ["LOCAL_PREFIX_V6"] = "2001:db8:2::"
|
||||
|
||||
try:
|
||||
env = NetDrvContEnv(__file__, primary_rx_redirect=True)
|
||||
has_cont = True
|
||||
except KsftSkipEx:
|
||||
env = NetDrvEpEnv(__file__)
|
||||
has_cont = False
|
||||
|
||||
with env as cfg:
|
||||
cfg.pspnl = PSPFamily()
|
||||
|
||||
if has_cont:
|
||||
_setup_psp_attributes(cfg)
|
||||
|
||||
# Set up responder and communication sock
|
||||
# psp_responder runs in _netns (remote namespace with psp_dev_peer)
|
||||
responder = cfg.remote.deploy("psp_responder")
|
||||
|
||||
cfg.comm_port = rand_port()
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user