mirror of
https://github.com/torvalds/linux.git
synced 2026-05-22 14:12:07 +02:00
selftests: drv-net: construct environment for running tests which require an endpoint
Nothing surprising here, hopefully. Wrap the variables from the environment into a class or spawn a netdevsim based env and pass it to the tests. Reviewed-by: Willem de Bruijn <willemb@google.com> Link: https://lore.kernel.org/r/20240420025237.3309296-4-kuba@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
5433892950
commit
1880f272d2
|
|
@ -23,8 +23,41 @@ or::
|
|||
# Variable set in a file
|
||||
NETIF=eth0
|
||||
|
||||
Please note that the config parser is very simple, if there are
|
||||
any non-alphanumeric characters in the value it needs to be in
|
||||
double quotes.
|
||||
|
||||
NETIF
|
||||
~~~~~
|
||||
|
||||
Name of the netdevice against which the test should be executed.
|
||||
When empty or not set software devices will be used.
|
||||
|
||||
LOCAL_V4, LOCAL_V6, REMOTE_V4, REMOTE_V6
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Local and remote endpoint IP addresses.
|
||||
|
||||
REMOTE_TYPE
|
||||
~~~~~~~~~~~
|
||||
|
||||
Communication method used to run commands on the remote endpoint.
|
||||
Test framework has built-in support for ``netns`` and ``ssh`` channels.
|
||||
``netns`` assumes the "remote" interface is part of the same
|
||||
host, just moved to the specified netns.
|
||||
``ssh`` communicates with remote endpoint over ``ssh`` and ``scp``.
|
||||
Using persistent SSH connections is strongly encouraged to avoid
|
||||
the latency of SSH connection setup on every command.
|
||||
|
||||
Communication methods are defined by classes in ``lib/py/remote_{name}.py``.
|
||||
It should be possible to add a new method without modifying any of
|
||||
the framework, by simply adding an appropriately named file to ``lib/py``.
|
||||
|
||||
REMOTE_ARGS
|
||||
~~~~~~~~~~~
|
||||
|
||||
Arguments used to construct the communication channel.
|
||||
Communication channel dependent::
|
||||
|
||||
for netns - name of the "remote" namespace
|
||||
for ssh - name/address of the remote host
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@ import os
|
|||
import shlex
|
||||
from pathlib import Path
|
||||
from lib.py import ip
|
||||
from lib.py import NetdevSimDev
|
||||
from lib.py import NetNS, NetdevSimDev
|
||||
from .remote import Remote
|
||||
|
||||
|
||||
def _load_env_file(src_path):
|
||||
|
|
@ -59,3 +60,98 @@ class NetDrvEnv:
|
|||
self._ns = None
|
||||
|
||||
|
||||
class NetDrvEpEnv:
|
||||
"""
|
||||
Class for an environment with a local device and "remote endpoint"
|
||||
which can be used to send traffic in.
|
||||
|
||||
For local testing it creates two network namespaces and a pair
|
||||
of netdevsim devices.
|
||||
"""
|
||||
|
||||
# Network prefixes used for local tests
|
||||
nsim_v4_pfx = "192.0.2."
|
||||
nsim_v6_pfx = "2001:db8::"
|
||||
|
||||
def __init__(self, src_path):
|
||||
|
||||
self.env = _load_env_file(src_path)
|
||||
|
||||
# Things we try to destroy
|
||||
self.remote = None
|
||||
# These are for local testing state
|
||||
self._netns = None
|
||||
self._ns = None
|
||||
self._ns_peer = None
|
||||
|
||||
if "NETIF" in self.env:
|
||||
self.dev = ip("link show dev " + self.env['NETIF'], json=True)[0]
|
||||
|
||||
self.v4 = self.env.get("LOCAL_V4")
|
||||
self.v6 = self.env.get("LOCAL_V6")
|
||||
self.remote_v4 = self.env.get("REMOTE_V4")
|
||||
self.remote_v6 = self.env.get("REMOTE_V6")
|
||||
kind = self.env["REMOTE_TYPE"]
|
||||
args = self.env["REMOTE_ARGS"]
|
||||
else:
|
||||
self.create_local()
|
||||
|
||||
self.dev = self._ns.nsims[0].dev
|
||||
|
||||
self.v4 = self.nsim_v4_pfx + "1"
|
||||
self.v6 = self.nsim_v6_pfx + "1"
|
||||
self.remote_v4 = self.nsim_v4_pfx + "2"
|
||||
self.remote_v6 = self.nsim_v6_pfx + "2"
|
||||
kind = "netns"
|
||||
args = self._netns.name
|
||||
|
||||
self.remote = Remote(kind, args, src_path)
|
||||
|
||||
self.addr = self.v6 if self.v6 else self.v4
|
||||
self.remote_addr = self.remote_v6 if self.remote_v6 else self.remote_v4
|
||||
|
||||
self.ifname = self.dev['ifname']
|
||||
self.ifindex = self.dev['ifindex']
|
||||
|
||||
def create_local(self):
|
||||
self._netns = NetNS()
|
||||
self._ns = NetdevSimDev()
|
||||
self._ns_peer = NetdevSimDev(ns=self._netns)
|
||||
|
||||
with open("/proc/self/ns/net") as nsfd0, \
|
||||
open("/var/run/netns/" + self._netns.name) as nsfd1:
|
||||
ifi0 = self._ns.nsims[0].ifindex
|
||||
ifi1 = self._ns_peer.nsims[0].ifindex
|
||||
NetdevSimDev.ctrl_write('link_device',
|
||||
f'{nsfd0.fileno()}:{ifi0} {nsfd1.fileno()}:{ifi1}')
|
||||
|
||||
ip(f" addr add dev {self._ns.nsims[0].ifname} {self.nsim_v4_pfx}1/24")
|
||||
ip(f"-6 addr add dev {self._ns.nsims[0].ifname} {self.nsim_v6_pfx}1/64 nodad")
|
||||
ip(f" link set dev {self._ns.nsims[0].ifname} up")
|
||||
|
||||
ip(f" addr add dev {self._ns_peer.nsims[0].ifname} {self.nsim_v4_pfx}2/24", ns=self._netns)
|
||||
ip(f"-6 addr add dev {self._ns_peer.nsims[0].ifname} {self.nsim_v6_pfx}2/64 nodad", ns=self._netns)
|
||||
ip(f" link set dev {self._ns_peer.nsims[0].ifname} up", ns=self._netns)
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, ex_type, ex_value, ex_tb):
|
||||
"""
|
||||
__exit__ gets called at the end of a "with" block.
|
||||
"""
|
||||
self.__del__()
|
||||
|
||||
def __del__(self):
|
||||
if self._ns:
|
||||
self._ns.remove()
|
||||
self._ns = None
|
||||
if self._ns_peer:
|
||||
self._ns_peer.remove()
|
||||
self._ns_peer = None
|
||||
if self._netns:
|
||||
del self._netns
|
||||
self._netns = None
|
||||
if self.remote:
|
||||
del self.remote
|
||||
self.remote = None
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
from .consts import KSRC
|
||||
from .ksft import *
|
||||
from .netns import NetNS
|
||||
from .nsim import *
|
||||
from .utils import *
|
||||
from .ynl import NlError, YnlFamily, EthtoolFamily, NetdevFamily, RtnlFamily
|
||||
|
|
|
|||
31
tools/testing/selftests/net/lib/py/netns.py
Normal file
31
tools/testing/selftests/net/lib/py/netns.py
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
from .utils import ip
|
||||
import random
|
||||
import string
|
||||
|
||||
|
||||
class NetNS:
|
||||
def __init__(self, name=None):
|
||||
if name:
|
||||
self.name = name
|
||||
else:
|
||||
self.name = ''.join(random.choice(string.ascii_lowercase) for _ in range(8))
|
||||
ip('netns add ' + self.name)
|
||||
|
||||
def __del__(self):
|
||||
if self.name:
|
||||
ip('netns del ' + self.name)
|
||||
self.name = None
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, ex_type, ex_value, ex_tb):
|
||||
self.__del__()
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def __repr__(self):
|
||||
return f"NetNS({self.name})"
|
||||
Loading…
Reference in New Issue
Block a user