Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests: drv-net: wait for carrier

On fast machines the tests run in quick succession so even
when tests clean up after themselves the carrier may need
some time to come back.

Specifically in NIPA when ping.py runs right after netpoll_basic.py
the first ping command fails.

Since the context manager callbacks are now common NetDrvEpEnv
gets an ip link up call as well.

Reviewed-by: Joe Damato <joe@dama.to>
Link: https://patch.msgid.link/20250812142054.750282-1-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+39 -22
+1 -1
tools/testing/selftests/drivers/net/lib/py/__init__.py
··· 15 15 NlError, RtnlFamily, DevlinkFamily 16 16 from net.lib.py import CmdExitFailure 17 17 from net.lib.py import bkg, cmd, bpftool, bpftrace, defer, ethtool, \ 18 - fd_read_timeout, ip, rand_port, tool, wait_port_listen 18 + fd_read_timeout, ip, rand_port, tool, wait_port_listen, wait_file 19 19 from net.lib.py import fd_read_timeout 20 20 from net.lib.py import KsftSkipEx, KsftFailEx, KsftXfailEx 21 21 from net.lib.py import ksft_disruptive, ksft_exit, ksft_pr, ksft_run, \
+20 -21
tools/testing/selftests/drivers/net/lib/py/env.py
··· 4 4 import time 5 5 from pathlib import Path 6 6 from lib.py import KsftSkipEx, KsftXfailEx 7 - from lib.py import ksft_setup 7 + from lib.py import ksft_setup, wait_file 8 8 from lib.py import cmd, ethtool, ip, CmdExitFailure 9 9 from lib.py import NetNS, NetdevSimDev 10 10 from .remote import Remote ··· 24 24 self.net_lib_dir = (Path(__file__).parent / "../../../../net/lib").resolve() 25 25 26 26 self.env = self._load_env_file() 27 + 28 + # Following attrs must be set be inheriting classes 29 + self.dev = None 27 30 28 31 def _load_env_file(self): 29 32 env = os.environ.copy() ··· 51 48 env[pair[0]] = pair[1] 52 49 return ksft_setup(env) 53 50 51 + def __del__(self): 52 + pass 53 + 54 + def __enter__(self): 55 + ip(f"link set dev {self.dev['ifname']} up") 56 + wait_file(f"/sys/class/net/{self.dev['ifname']}/carrier", 57 + lambda x: x.strip() == "1") 58 + 59 + return self 60 + 61 + def __exit__(self, ex_type, ex_value, ex_tb): 62 + """ 63 + __exit__ gets called at the end of a "with" block. 64 + """ 65 + self.__del__() 66 + 54 67 55 68 class NetDrvEnv(NetDrvEnvBase): 56 69 """ ··· 90 71 self.dev = self._ns.nsims[0].dev 91 72 self.ifname = self.dev['ifname'] 92 73 self.ifindex = self.dev['ifindex'] 93 - 94 - def __enter__(self): 95 - ip(f"link set dev {self.dev['ifname']} up") 96 - 97 - return self 98 - 99 - def __exit__(self, ex_type, ex_value, ex_tb): 100 - """ 101 - __exit__ gets called at the end of a "with" block. 102 - """ 103 - self.__del__() 104 74 105 75 def __del__(self): 106 76 if self._ns: ··· 226 218 if (v4 and len(v4) > 1) or (v6 and len(v6) > 1): 227 219 raise Exception("Can't resolve remote interface name, multiple interfaces match") 228 220 return v6[0]["ifname"] if v6 else v4[0]["ifname"] 229 - 230 - def __enter__(self): 231 - return self 232 - 233 - def __exit__(self, ex_type, ex_value, ex_tb): 234 - """ 235 - __exit__ gets called at the end of a "with" block. 236 - """ 237 - self.__del__() 238 221 239 222 def __del__(self): 240 223 if self._ns:
+18
tools/testing/selftests/net/lib/py/utils.py
··· 252 252 if time.monotonic() > end: 253 253 raise Exception("Waiting for port listen timed out") 254 254 time.sleep(sleep) 255 + 256 + 257 + def wait_file(fname, test_fn, sleep=0.005, deadline=5, encoding='utf-8'): 258 + """ 259 + Wait for file contents on the local system to satisfy a condition. 260 + test_fn() should take one argument (file contents) and return whether 261 + condition is met. 262 + """ 263 + end = time.monotonic() + deadline 264 + 265 + with open(fname, "r", encoding=encoding) as fp: 266 + while True: 267 + if test_fn(fp.read()): 268 + break 269 + fp.seek(0) 270 + if time.monotonic() > end: 271 + raise TimeoutError("Wait for file contents failed", fname) 272 + time.sleep(sleep)