import os import time from pathlib import Path from lib.py import KsftSkipEx, KsftXfailEx from lib.py import ksft_setup, wait_file from lib.py import cmd, ethtool, ip, CmdExitFailure from lib.py import NetNS, NetdevSimDev from .remote import Remote
class NetDrvEnvBase: """
Base classfor a NIC / host environments
Attributes:
test_dir: Path to the source directory of the test
net_lib_dir: Path to the net/lib directory """ def __init__(self, src_path):
self.src_path = Path(src_path)
self.test_dir = self.src_path.parent.resolve()
self.net_lib_dir = (Path(__file__).parent / "../../../../net/lib").resolve()
self.env = self._load_env_file()
# Following attrs must be set be inheriting classes
self.dev = None
with open((src_dir / "net.config").as_posix(), 'r') as fp: for line in fp.readlines():
full_file = line # Strip comments
pos = line.find("#") if pos >= 0:
line = line[:pos]
line = line.strip() ifnot line: continue
pair = line.split('=', maxsplit=1) if len(pair) != 2: raise Exception("Can't parse configuration line:", full_file)
env[pair[0]] = pair[1] return ksft_setup(env)
def __del__(self): pass
def __enter__(self):
ip(f"link set dev {self.dev['ifname']} up")
wait_file(f"/sys/class/net/{self.dev['ifname']}/carrier", lambda x: x.strip() == "1")
return self
def __exit__(self, ex_type, ex_value, ex_tb): """
__exit__ gets called at the end of a "with" block. """
self.__del__()
class NetDrvEnv(NetDrvEnvBase): """ Classfor a single NIC / host env, with no remote end """ def __init__(self, src_path, nsim_test=None, **kwargs):
super().__init__(src_path)
self._ns = None
if'NETIF'in self.env: if nsim_test isTrue: raise KsftXfailEx("Test only works on netdevsim")
self.dev = ip("-d link show dev " + self.env['NETIF'], json=True)[0] else: if nsim_test isFalse: raise KsftXfailEx("Test does not work on netdevsim")
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)
for choice in vars_needed: for entry in choice: if entry in self.env: break else:
missing.append(choice) # Make sure v4 / v6 configs are symmetric if ("LOCAL_V6"in self.env) != ("REMOTE_V6"in self.env):
missing.append(["LOCAL_V6", "REMOTE_V6"]) if ("LOCAL_V4"in self.env) != ("REMOTE_V4"in self.env):
missing.append(["LOCAL_V4", "REMOTE_V4"]) if missing: raise Exception("Invalid environment, missing configuration:", missing, "Please see tools/testing/selftests/drivers/net/README.rst")
def resolve_remote_ifc(self):
v4 = v6 = None if self.remote_addr_v["4"]:
v4 = ip("addr show to " + self.remote_addr_v["4"], json=True, host=self.remote) if self.remote_addr_v["6"]:
v6 = ip("addr show to " + self.remote_addr_v["6"], json=True, host=self.remote) if v4 and v6 and v4[0]["ifname"] != v6[0]["ifname"]: raise Exception("Can't resolve remote interface name, v4 and v6 don't match") if (v4 and len(v4) > 1) or (v6 and len(v6) > 1): raise Exception("Can't resolve remote interface name, multiple interfaces match") return v6[0]["ifname"] if v6 else v4[0]["ifname"]
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
def wait_hw_stats_settle(self): """
Wait for HW stats to become consistent, some devices DMA HW stats
periodically so events won't be reflected until next sync.
Good drivers will tell us via ethtool what their sync period is. """ if self._stats_settle_time isNone:
data = {} try:
data = ethtool("-c " + self.ifname, json=True)[0] except CmdExitFailure as e: if"Operation not supported"notin e.cmd.stderr: raise
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.