diff options
| author | Jakub Kicinski <kuba@kernel.org> | 2026-04-14 08:17:06 -0700 |
|---|---|---|
| committer | Jakub Kicinski <kuba@kernel.org> | 2026-04-14 08:17:06 -0700 |
| commit | 2d7e20c9886f359a4ebd4bdbba53ab2df44667d6 (patch) | |
| tree | f0ddac6f418d7ff552f8d3d79a01221ec268d985 | |
| parent | 34e1a98ff2a87cf4b8de3ccebe9d45273f014aeb (diff) | |
| parent | 1e822171ba9bca7a5d2371bc10358340835bdad3 (diff) | |
Merge branch 'follow-ups-to-nk_qlease-net-selftests'
Daniel Borkmann says:
====================
Follow-ups to nk_qlease net selftests
This is a set of follow-ups addressing [0]:
- Split netdevsim tests from HW tests in nk_qlease and move the SW
tests under selftests/net/
- Remove multiple ksft_run()s to fix the recently enforced hard-fail
- Move all the setup inside the test cases for the ones under
selftests/net/ (I'll defer the HW ones to David)
- Add more test coverage related to queue leasing behavior and corner
cases, so now we have 45 tests in nk_qlease.py with netdevsim
which does not need special HW
====================
Link: https://patch.msgid.link/20260413220809.604592-1-daniel@iogearbox.net
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
| -rw-r--r-- | tools/net/ynl/pyynl/lib/ynl.py | 10 | ||||
| -rwxr-xr-x | tools/testing/selftests/drivers/net/hw/nk_qlease.py | 1142 | ||||
| -rw-r--r-- | tools/testing/selftests/net/Makefile | 1 | ||||
| -rwxr-xr-x | tools/testing/selftests/net/nk_qlease.py | 2109 |
4 files changed, 2120 insertions, 1142 deletions
diff --git a/tools/net/ynl/pyynl/lib/ynl.py b/tools/net/ynl/pyynl/lib/ynl.py index 9c078599cea0..f63c6f828735 100644 --- a/tools/net/ynl/pyynl/lib/ynl.py +++ b/tools/net/ynl/pyynl/lib/ynl.py @@ -731,6 +731,16 @@ class YnlFamily(SpecFamily): bound_f = functools.partial(self._op, op_name) setattr(self, op.ident_name, bound_f) + def close(self): + if self.sock is not None: + self.sock.close() + self.sock = None + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc, tb): + self.close() def ntf_subscribe(self, mcast_name): mcast_id = self.nlproto.get_mcast_id(mcast_name, self.mcast_groups) diff --git a/tools/testing/selftests/drivers/net/hw/nk_qlease.py b/tools/testing/selftests/drivers/net/hw/nk_qlease.py index 2bc5ffe96c7d..aa83dc321328 100755 --- a/tools/testing/selftests/drivers/net/hw/nk_qlease.py +++ b/tools/testing/selftests/drivers/net/hw/nk_qlease.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 # SPDX-License-Identifier: GPL-2.0 -import errno import re import time import threading @@ -10,23 +9,17 @@ from lib.py import ( ksft_run, ksft_exit, ksft_eq, - ksft_ne, ksft_in, ksft_not_in, ksft_raises, ) from lib.py import ( NetDrvContEnv, - NetNS, NetNSEnter, EthtoolFamily, NetdevFamily, - RtnlFamily, - NetdevSimDev, ) from lib.py import ( - NlError, - Netlink, bkg, cmd, defer, @@ -46,1100 +39,6 @@ def set_flow_rule(cfg): return int(values) -def create_netkit(rxqueues): - all_links = ip("-d link show", json=True) - old_idxs = { - link["ifindex"] - for link in all_links - if link.get("linkinfo", {}).get("info_kind") == "netkit" - } - - rtnl = RtnlFamily() - rtnl.newlink( - { - "linkinfo": { - "kind": "netkit", - "data": { - "mode": "l2", - "policy": "forward", - "peer-policy": "forward", - }, - }, - "num-rx-queues": rxqueues, - }, - flags=[Netlink.NLM_F_CREATE, Netlink.NLM_F_EXCL], - ) - - all_links = ip("-d link show", json=True) - nk_links = [ - link - for link in all_links - if link.get("linkinfo", {}).get("info_kind") == "netkit" - and link["ifindex"] not in old_idxs - ] - nk_links.sort(key=lambda x: x["ifindex"]) - return ( - nk_links[1]["ifname"], - nk_links[1]["ifindex"], - nk_links[0]["ifname"], - nk_links[0]["ifindex"], - ) - - -def create_netkit_single(rxqueues): - rtnl = RtnlFamily() - rtnl.newlink( - { - "linkinfo": { - "kind": "netkit", - "data": { - "mode": "l2", - "pairing": "single", - }, - }, - "num-rx-queues": rxqueues, - }, - flags=[Netlink.NLM_F_CREATE, Netlink.NLM_F_EXCL], - ) - - all_links = ip("-d link show", json=True) - nk_links = [ - link - for link in all_links - if link.get("linkinfo", {}).get("info_kind") == "netkit" - and "UP" not in link.get("flags", []) - ] - return nk_links[0]["ifname"], nk_links[0]["ifindex"] - - -def test_remove_phys(netns) -> None: - nsimdev = NetdevSimDev(port_count=1, queue_count=2) - defer(nsimdev.remove) - nsim = nsimdev.nsims[0] - ip(f"link set dev {nsim.ifname} up") - - nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=2) - defer(cmd, f"ip link del dev {nk_host}", fail=False) - - ip(f"link set dev {nk_guest} netns {netns.name}") - ip(f"link set dev {nk_host} up") - ip(f"link set dev {nk_guest} up", ns=netns) - - src_queue = 1 - with NetNSEnter(str(netns)): - netdevnl = NetdevFamily() - result = netdevnl.queue_create( - { - "ifindex": nk_guest_idx, - "type": "rx", - "lease": { - "ifindex": nsim.ifindex, - "queue": {"id": src_queue, "type": "rx"}, - "netns-id": 0, - }, - } - ) - nk_queue_id = result["id"] - - netdevnl = NetdevFamily() - queue_info = netdevnl.queue_get( - {"ifindex": nsim.ifindex, "id": src_queue, "type": "rx"} - ) - ksft_in("lease", queue_info) - ksft_eq(queue_info["lease"]["ifindex"], nk_guest_idx) - ksft_eq(queue_info["lease"]["queue"]["id"], nk_queue_id) - - nsimdev.remove() - time.sleep(0.1) - ret = cmd(f"ip link show dev {nk_host}", fail=False) - ksft_ne(ret.ret, 0) - - -def test_double_lease(netns) -> None: - nsimdev = NetdevSimDev(port_count=1, queue_count=2) - defer(nsimdev.remove) - nsim = nsimdev.nsims[0] - ip(f"link set dev {nsim.ifname} up") - - nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=3) - defer(cmd, f"ip link del dev {nk_host}") - - ip(f"link set dev {nk_guest} netns {netns.name}") - ip(f"link set dev {nk_host} up") - ip(f"link set dev {nk_guest} up", ns=netns) - - src_queue = 1 - with NetNSEnter(str(netns)): - netdevnl = NetdevFamily() - result = netdevnl.queue_create( - { - "ifindex": nk_guest_idx, - "type": "rx", - "lease": { - "ifindex": nsim.ifindex, - "queue": {"id": src_queue, "type": "rx"}, - "netns-id": 0, - }, - } - ) - ksft_eq(result["id"], 1) - - with ksft_raises(NlError) as e: - netdevnl.queue_create( - { - "ifindex": nk_guest_idx, - "type": "rx", - "lease": { - "ifindex": nsim.ifindex, - "queue": {"id": src_queue, "type": "rx"}, - "netns-id": 0, - }, - } - ) - ksft_eq(e.exception.nl_msg.error, -errno.EBUSY) - - -def test_virtual_lessor(netns) -> None: - nk_host_a, _, nk_guest_a, nk_guest_a_idx = create_netkit(rxqueues=2) - defer(cmd, f"ip link del dev {nk_host_a}") - ip(f"link set dev {nk_host_a} up") - ip(f"link set dev {nk_guest_a} up") - - nk_host_b, _, nk_guest_b, nk_guest_b_idx = create_netkit(rxqueues=2) - defer(cmd, f"ip link del dev {nk_host_b}") - - ip(f"link set dev {nk_guest_b} netns {netns.name}") - ip(f"link set dev {nk_host_b} up") - ip(f"link set dev {nk_guest_b} up", ns=netns) - - with NetNSEnter(str(netns)): - netdevnl = NetdevFamily() - with ksft_raises(NlError) as e: - netdevnl.queue_create( - { - "ifindex": nk_guest_b_idx, - "type": "rx", - "lease": { - "ifindex": nk_guest_a_idx, - "queue": {"id": 0, "type": "rx"}, - "netns-id": 0, - }, - } - ) - ksft_eq(e.exception.nl_msg.error, -errno.EINVAL) - - -def test_phys_lessee(_netns) -> None: - nsimdev_a = NetdevSimDev(port_count=1, queue_count=2) - defer(nsimdev_a.remove) - nsim_a = nsimdev_a.nsims[0] - ip(f"link set dev {nsim_a.ifname} up") - - nsimdev_b = NetdevSimDev(port_count=1, queue_count=2) - defer(nsimdev_b.remove) - nsim_b = nsimdev_b.nsims[0] - ip(f"link set dev {nsim_b.ifname} up") - - netdevnl = NetdevFamily() - with ksft_raises(NlError) as e: - netdevnl.queue_create( - { - "ifindex": nsim_a.ifindex, - "type": "rx", - "lease": { - "ifindex": nsim_b.ifindex, - "queue": {"id": 0, "type": "rx"}, - }, - } - ) - ksft_eq(e.exception.nl_msg.error, -errno.EINVAL) - - -def test_different_lessors(netns) -> None: - nsimdev_a = NetdevSimDev(port_count=1, queue_count=2) - defer(nsimdev_a.remove) - nsim_a = nsimdev_a.nsims[0] - ip(f"link set dev {nsim_a.ifname} up") - - nsimdev_b = NetdevSimDev(port_count=1, queue_count=2) - defer(nsimdev_b.remove) - nsim_b = nsimdev_b.nsims[0] - ip(f"link set dev {nsim_b.ifname} up") - - nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=3) - defer(cmd, f"ip link del dev {nk_host}", fail=False) - - ip(f"link set dev {nk_guest} netns {netns.name}") - ip(f"link set dev {nk_host} up") - ip(f"link set dev {nk_guest} up", ns=netns) - - with NetNSEnter(str(netns)): - netdevnl = NetdevFamily() - netdevnl.queue_create( - { - "ifindex": nk_guest_idx, - "type": "rx", - "lease": { - "ifindex": nsim_a.ifindex, - "queue": {"id": 1, "type": "rx"}, - "netns-id": 0, - }, - } - ) - - with ksft_raises(NlError) as e: - netdevnl.queue_create( - { - "ifindex": nk_guest_idx, - "type": "rx", - "lease": { - "ifindex": nsim_b.ifindex, - "queue": {"id": 1, "type": "rx"}, - "netns-id": 0, - }, - } - ) - ksft_eq(e.exception.nl_msg.error, -errno.EOPNOTSUPP) - - -def test_queue_out_of_range(netns) -> None: - nsimdev = NetdevSimDev(port_count=1, queue_count=2) - defer(nsimdev.remove) - nsim = nsimdev.nsims[0] - ip(f"link set dev {nsim.ifname} up") - - nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=2) - defer(cmd, f"ip link del dev {nk_host}", fail=False) - - ip(f"link set dev {nk_guest} netns {netns.name}") - ip(f"link set dev {nk_host} up") - ip(f"link set dev {nk_guest} up", ns=netns) - - with NetNSEnter(str(netns)): - netdevnl = NetdevFamily() - with ksft_raises(NlError) as e: - netdevnl.queue_create( - { - "ifindex": nk_guest_idx, - "type": "rx", - "lease": { - "ifindex": nsim.ifindex, - "queue": {"id": 2, "type": "rx"}, - "netns-id": 0, - }, - } - ) - ksft_eq(e.exception.nl_msg.error, -errno.ERANGE) - - -def test_resize_leased(netns) -> None: - nsimdev = NetdevSimDev(port_count=1, queue_count=2) - defer(nsimdev.remove) - nsim = nsimdev.nsims[0] - ip(f"link set dev {nsim.ifname} up") - - nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=2) - defer(cmd, f"ip link del dev {nk_host}", fail=False) - - ip(f"link set dev {nk_guest} netns {netns.name}") - ip(f"link set dev {nk_host} up") - ip(f"link set dev {nk_guest} up", ns=netns) - - with NetNSEnter(str(netns)): - netdevnl = NetdevFamily() - netdevnl.queue_create( - { - "ifindex": nk_guest_idx, - "type": "rx", - "lease": { - "ifindex": nsim.ifindex, - "queue": {"id": 1, "type": "rx"}, - "netns-id": 0, - }, - } - ) - - ethnl = EthtoolFamily() - with ksft_raises(NlError) as e: - ethnl.channels_set({"header": {"dev-index": nsim.ifindex}, "combined-count": 1}) - ksft_eq(e.exception.nl_msg.error, -errno.EINVAL) - - -def test_self_lease(_netns) -> None: - nk_host, _, _, nk_guest_idx = create_netkit(rxqueues=2) - defer(cmd, f"ip link del dev {nk_host}", fail=False) - - netdevnl = NetdevFamily() - with ksft_raises(NlError) as e: - netdevnl.queue_create( - { - "ifindex": nk_guest_idx, - "type": "rx", - "lease": { - "ifindex": nk_guest_idx, - "queue": {"id": 0, "type": "rx"}, - }, - } - ) - ksft_eq(e.exception.nl_msg.error, -errno.EINVAL) - - -def test_veth_queue_create(netns) -> None: - nsimdev = NetdevSimDev(port_count=1, queue_count=2) - defer(nsimdev.remove) - nsim = nsimdev.nsims[0] - ip(f"link set dev {nsim.ifname} up") - - ip("link add veth0 type veth peer name veth1") - defer(cmd, "ip link del dev veth0", fail=False) - - all_links = ip("-d link show", json=True) - veth_peer = [ - link - for link in all_links - if link.get("ifname") == "veth1" - ] - veth_peer_idx = veth_peer[0]["ifindex"] - - ip(f"link set dev veth1 netns {netns.name}") - ip("link set dev veth0 up") - ip("link set dev veth1 up", ns=netns) - - with NetNSEnter(str(netns)): - netdevnl = NetdevFamily() - with ksft_raises(NlError) as e: - netdevnl.queue_create( - { - "ifindex": veth_peer_idx, - "type": "rx", - "lease": { - "ifindex": nsim.ifindex, - "queue": {"id": 1, "type": "rx"}, - "netns-id": 0, - }, - } - ) - ksft_eq(e.exception.nl_msg.error, -errno.EINVAL) - - -def test_create_tx_type(netns) -> None: - nsimdev = NetdevSimDev(port_count=1, queue_count=2) - defer(nsimdev.remove) - nsim = nsimdev.nsims[0] - ip(f"link set dev {nsim.ifname} up") - - nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=2) - defer(cmd, f"ip link del dev {nk_host}", fail=False) - - ip(f"link set dev {nk_guest} netns {netns.name}") - ip(f"link set dev {nk_host} up") - ip(f"link set dev {nk_guest} up", ns=netns) - - with NetNSEnter(str(netns)): - netdevnl = NetdevFamily() - with ksft_raises(NlError) as e: - netdevnl.queue_create( - { - "ifindex": nk_guest_idx, - "type": "tx", - "lease": { - "ifindex": nsim.ifindex, - "queue": {"id": 1, "type": "rx"}, - "netns-id": 0, - }, - } - ) - ksft_eq(e.exception.nl_msg.error, -errno.EINVAL) - - -def test_create_primary(_netns) -> None: - nsimdev = NetdevSimDev(port_count=1, queue_count=2) - defer(nsimdev.remove) - nsim = nsimdev.nsims[0] - ip(f"link set dev {nsim.ifname} up") - - nk_host, nk_host_idx, _, _ = create_netkit(rxqueues=2) - defer(cmd, f"ip link del dev {nk_host}", fail=False) - - ip(f"link set dev {nk_host} up") - - netdevnl = NetdevFamily() - with ksft_raises(NlError) as e: - netdevnl.queue_create( - { - "ifindex": nk_host_idx, - "type": "rx", - "lease": { - "ifindex": nsim.ifindex, - "queue": {"id": 1, "type": "rx"}, - }, - } - ) - ksft_eq(e.exception.nl_msg.error, -errno.EOPNOTSUPP) - - -def test_create_limit(netns) -> None: - nsimdev = NetdevSimDev(port_count=1, queue_count=2) - defer(nsimdev.remove) - nsim = nsimdev.nsims[0] - ip(f"link set dev {nsim.ifname} up") - - nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=1) - defer(cmd, f"ip link del dev {nk_host}", fail=False) - - ip(f"link set dev {nk_guest} netns {netns.name}") - ip(f"link set dev {nk_host} up") - ip(f"link set dev {nk_guest} up", ns=netns) - - with NetNSEnter(str(netns)): - netdevnl = NetdevFamily() - with ksft_raises(NlError) as e: - netdevnl.queue_create( - { - "ifindex": nk_guest_idx, - "type": "rx", - "lease": { - "ifindex": nsim.ifindex, - "queue": {"id": 1, "type": "rx"}, - "netns-id": 0, - }, - } - ) - ksft_eq(e.exception.nl_msg.error, -errno.EINVAL) - - -def test_link_flap_phys(netns) -> None: - nsimdev = NetdevSimDev(port_count=1, queue_count=2) - defer(nsimdev.remove) - nsim = nsimdev.nsims[0] - ip(f"link set dev {nsim.ifname} up") - - nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=2) - defer(cmd, f"ip link del dev {nk_host}") - - ip(f"link set dev {nk_guest} netns {netns.name}") - ip(f"link set dev {nk_host} up") - ip(f"link set dev {nk_guest} up", ns=netns) - - src_queue = 1 - with NetNSEnter(str(netns)): - netdevnl = NetdevFamily() - result = netdevnl.queue_create( - { - "ifindex": nk_guest_idx, - "type": "rx", - "lease": { - "ifindex": nsim.ifindex, - "queue": {"id": src_queue, "type": "rx"}, - "netns-id": 0, - }, - } - ) - nk_queue_id = result["id"] - - netdevnl = NetdevFamily() - queue_info = netdevnl.queue_get( - {"ifindex": nsim.ifindex, "id": src_queue, "type": "rx"} - ) - ksft_in("lease", queue_info) - ksft_eq(queue_info["lease"]["queue"]["id"], nk_queue_id) - - # Link flap the physical device - ip(f"link set dev {nsim.ifname} down") - ip(f"link set dev {nsim.ifname} up") - - # Verify lease survives the flap - queue_info = netdevnl.queue_get( - {"ifindex": nsim.ifindex, "id": src_queue, "type": "rx"} - ) - ksft_in("lease", queue_info) - ksft_eq(queue_info["lease"]["queue"]["id"], nk_queue_id) - - -def test_queue_get_virtual(netns) -> None: - nsimdev = NetdevSimDev(port_count=1, queue_count=2) - defer(nsimdev.remove) - nsim = nsimdev.nsims[0] - ip(f"link set dev {nsim.ifname} up") - - nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=2) - defer(cmd, f"ip link del dev {nk_host}") - - ip(f"link set dev {nk_guest} netns {netns.name}") - ip(f"link set dev {nk_host} up") - ip(f"link set dev {nk_guest} up", ns=netns) - - src_queue = 1 - with NetNSEnter(str(netns)): - netdevnl = NetdevFamily() - result = netdevnl.queue_create( - { - "ifindex": nk_guest_idx, - "type": "rx", - "lease": { - "ifindex": nsim.ifindex, - "queue": {"id": src_queue, "type": "rx"}, - "netns-id": 0, - }, - } - ) - nk_queue_id = result["id"] - - # queue-get on virtual device's leased queue should not show lease - # info (lease info is only shown from the physical device's side) - queue_info = netdevnl.queue_get( - {"ifindex": nk_guest_idx, "id": nk_queue_id, "type": "rx"} - ) - ksft_eq(queue_info["id"], nk_queue_id) - ksft_eq(queue_info["ifindex"], nk_guest_idx) - ksft_not_in("lease", queue_info) - - # Default queue (not leased) also has no lease info - queue_info = netdevnl.queue_get( - {"ifindex": nk_guest_idx, "id": 0, "type": "rx"} - ) - ksft_not_in("lease", queue_info) - - -def test_remove_virt_first(netns) -> None: - nsimdev = NetdevSimDev(port_count=1, queue_count=2) - defer(nsimdev.remove) - nsim = nsimdev.nsims[0] - ip(f"link set dev {nsim.ifname} up") - - nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=2) - - ip(f"link set dev {nk_guest} netns {netns.name}") - ip(f"link set dev {nk_host} up") - ip(f"link set dev {nk_guest} up", ns=netns) - - src_queue = 1 - with NetNSEnter(str(netns)): - netdevnl = NetdevFamily() - result = netdevnl.queue_create( - { - "ifindex": nk_guest_idx, - "type": "rx", - "lease": { - "ifindex": nsim.ifindex, - "queue": {"id": src_queue, "type": "rx"}, - "netns-id": 0, - }, - } - ) - ksft_eq(result["id"], 1) - - netdevnl = NetdevFamily() - queue_info = netdevnl.queue_get( - {"ifindex": nsim.ifindex, "id": src_queue, "type": "rx"} - ) - ksft_in("lease", queue_info) - ksft_eq(queue_info["lease"]["queue"]["id"], result["id"]) - - # Delete netkit (virtual device removed first, physical stays) - cmd(f"ip link del dev {nk_host}") - - # Verify lease is cleaned up on physical device - queue_info = netdevnl.queue_get( - {"ifindex": nsim.ifindex, "id": src_queue, "type": "rx"} - ) - ksft_not_in("lease", queue_info) - - -def test_multiple_leases(netns) -> None: - nsimdev = NetdevSimDev(port_count=1, queue_count=3) - defer(nsimdev.remove) - nsim = nsimdev.nsims[0] - ip(f"link set dev {nsim.ifname} up") - - nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=4) - defer(cmd, f"ip link del dev {nk_host}", fail=False) - - ip(f"link set dev {nk_guest} netns {netns.name}") - ip(f"link set dev {nk_host} up") - ip(f"link set dev {nk_guest} up", ns=netns) - - with NetNSEnter(str(netns)): - netdevnl = NetdevFamily() - r1 = netdevnl.queue_create( - { - "ifindex": nk_guest_idx, - "type": "rx", - "lease": { - "ifindex": nsim.ifindex, - "queue": {"id": 1, "type": "rx"}, - "netns-id": 0, - }, - } - ) - r2 = netdevnl.queue_create( - { - "ifindex": nk_guest_idx, - "type": "rx", - "lease": { - "ifindex": nsim.ifindex, - "queue": {"id": 2, "type": "rx"}, - "netns-id": 0, - }, - } - ) - - ksft_eq(r1["id"], 1) - ksft_eq(r2["id"], 2) - - # Verify both leases visible on physical device - netdevnl = NetdevFamily() - q1 = netdevnl.queue_get( - {"ifindex": nsim.ifindex, "id": 1, "type": "rx"} - ) - q2 = netdevnl.queue_get( - {"ifindex": nsim.ifindex, "id": 2, "type": "rx"} - ) - ksft_in("lease", q1) - ksft_in("lease", q2) - ksft_eq(q1["lease"]["ifindex"], nk_guest_idx) - ksft_eq(q2["lease"]["ifindex"], nk_guest_idx) - ksft_eq(q1["lease"]["queue"]["id"], r1["id"]) - ksft_eq(q2["lease"]["queue"]["id"], r2["id"]) - - -def test_lease_queue_tx_type(netns) -> None: - nsimdev = NetdevSimDev(port_count=1, queue_count=2) - defer(nsimdev.remove) - nsim = nsimdev.nsims[0] - ip(f"link set dev {nsim.ifname} up") - - nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=2) - defer(cmd, f"ip link del dev {nk_host}", fail=False) - - ip(f"link set dev {nk_guest} netns {netns.name}") - ip(f"link set dev {nk_host} up") - ip(f"link set dev {nk_guest} up", ns=netns) - - with NetNSEnter(str(netns)): - netdevnl = NetdevFamily() - with ksft_raises(NlError) as e: - netdevnl.queue_create( - { - "ifindex": nk_guest_idx, - "type": "rx", - "lease": { - "ifindex": nsim.ifindex, - "queue": {"id": 1, "type": "tx"}, - "netns-id": 0, - }, - } - ) - ksft_eq(e.exception.nl_msg.error, -errno.EINVAL) - - -def test_invalid_netns(netns) -> None: - nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=2) - defer(cmd, f"ip link del dev {nk_host}", fail=False) - - ip(f"link set dev {nk_guest} netns {netns.name}") - ip(f"link set dev {nk_host} up") - ip(f"link set dev {nk_guest} up", ns=netns) - - with NetNSEnter(str(netns)): - netdevnl = NetdevFamily() - with ksft_raises(NlError) as e: - netdevnl.queue_create( - { - "ifindex": nk_guest_idx, - "type": "rx", - "lease": { - "ifindex": 1, - "queue": {"id": 0, "type": "rx"}, - "netns-id": 999, - }, - } - ) - ksft_eq(e.exception.nl_msg.error, -errno.ENONET) - - -def test_invalid_phys_ifindex(netns) -> None: - nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=2) - defer(cmd, f"ip link del dev {nk_host}", fail=False) - - ip(f"link set dev {nk_guest} netns {netns.name}") - ip(f"link set dev {nk_host} up") - ip(f"link set dev {nk_guest} up", ns=netns) - - with NetNSEnter(str(netns)): - netdevnl = NetdevFamily() - with ksft_raises(NlError) as e: - netdevnl.queue_create( - { - "ifindex": nk_guest_idx, - "type": "rx", - "lease": { - "ifindex": 99999, - "queue": {"id": 0, "type": "rx"}, - "netns-id": 0, - }, - } - ) - ksft_eq(e.exception.nl_msg.error, -errno.ENODEV) - - -def test_multi_netkit_remove_phys(netns) -> None: - nsimdev = NetdevSimDev(port_count=1, queue_count=3) - defer(nsimdev.remove) - nsim = nsimdev.nsims[0] - ip(f"link set dev {nsim.ifname} up") - - # Create two netkit pairs, each leasing a different physical queue - nk_host_a, _, nk_guest_a, nk_guest_a_idx = create_netkit(rxqueues=2) - defer(cmd, f"ip link del dev {nk_host_a}", fail=False) - - nk_host_b, _, nk_guest_b, nk_guest_b_idx = create_netkit(rxqueues=2) - defer(cmd, f"ip link del dev {nk_host_b}", fail=False) - - ip(f"link set dev {nk_guest_a} netns {netns.name}") - ip(f"link set dev {nk_host_a} up") - ip(f"link set dev {nk_guest_a} up", ns=netns) - - ip(f"link set dev {nk_guest_b} netns {netns.name}") - ip(f"link set dev {nk_host_b} up") - ip(f"link set dev {nk_guest_b} up", ns=netns) - - with NetNSEnter(str(netns)): - netdevnl = NetdevFamily() - netdevnl.queue_create( - { - "ifindex": nk_guest_a_idx, - "type": "rx", - "lease": { - "ifindex": nsim.ifindex, - "queue": {"id": 1, "type": "rx"}, - "netns-id": 0, - }, - } - ) - netdevnl.queue_create( - { - "ifindex": nk_guest_b_idx, - "type": "rx", - "lease": { - "ifindex": nsim.ifindex, - "queue": {"id": 2, "type": "rx"}, - "netns-id": 0, - }, - } - ) - - # Removing the physical device should take down both netkit pairs - nsimdev.remove() - time.sleep(0.1) - ret = cmd(f"ip link show dev {nk_host_a}", fail=False) - ksft_ne(ret.ret, 0) - ret = cmd(f"ip link show dev {nk_host_b}", fail=False) - ksft_ne(ret.ret, 0) - - -def test_single_remove_phys(_netns) -> None: - nsimdev = NetdevSimDev(port_count=1, queue_count=2) - defer(nsimdev.remove) - nsim = nsimdev.nsims[0] - ip(f"link set dev {nsim.ifname} up") - - nk_name, nk_idx = create_netkit_single(rxqueues=2) - defer(cmd, f"ip link del dev {nk_name}", fail=False) - - ip(f"link set dev {nk_name} up") - - netdevnl = NetdevFamily() - netdevnl.queue_create( - { - "ifindex": nk_idx, - "type": "rx", - "lease": { - "ifindex": nsim.ifindex, - "queue": {"id": 1, "type": "rx"}, - }, - } - ) - - # Removing the physical device should take down the single netkit device - nsimdev.remove() - time.sleep(0.1) - ret = cmd(f"ip link show dev {nk_name}", fail=False) - ksft_ne(ret.ret, 0) - - -def test_link_flap_virt(netns) -> None: - nsimdev = NetdevSimDev(port_count=1, queue_count=2) - defer(nsimdev.remove) - nsim = nsimdev.nsims[0] - ip(f"link set dev {nsim.ifname} up") - - nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=2) - defer(cmd, f"ip link del dev {nk_host}") - - ip(f"link set dev {nk_guest} netns {netns.name}") - ip(f"link set dev {nk_host} up") - ip(f"link set dev {nk_guest} up", ns=netns) - - src_queue = 1 - with NetNSEnter(str(netns)): - netdevnl = NetdevFamily() - result = netdevnl.queue_create( - { - "ifindex": nk_guest_idx, - "type": "rx", - "lease": { - "ifindex": nsim.ifindex, - "queue": {"id": src_queue, "type": "rx"}, - "netns-id": 0, - }, - } - ) - nk_queue_id = result["id"] - - netdevnl = NetdevFamily() - queue_info = netdevnl.queue_get( - {"ifindex": nsim.ifindex, "id": src_queue, "type": "rx"} - ) - ksft_in("lease", queue_info) - ksft_eq(queue_info["lease"]["queue"]["id"], nk_queue_id) - - # Link flap the virtual (netkit) device - ip(f"link set dev {nk_guest} down", ns=netns) - ip(f"link set dev {nk_guest} up", ns=netns) - - # Verify lease survives the virtual device flap - queue_info = netdevnl.queue_get( - {"ifindex": nsim.ifindex, "id": src_queue, "type": "rx"} - ) - ksft_in("lease", queue_info) - ksft_eq(queue_info["lease"]["queue"]["id"], nk_queue_id) - - -def test_phys_queue_no_lease(netns) -> None: - nsimdev = NetdevSimDev(port_count=1, queue_count=2) - defer(nsimdev.remove) - nsim = nsimdev.nsims[0] - ip(f"link set dev {nsim.ifname} up") - - nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=2) - defer(cmd, f"ip link del dev {nk_host}") - - ip(f"link set dev {nk_guest} netns {netns.name}") - ip(f"link set dev {nk_host} up") - ip(f"link set dev {nk_guest} up", ns=netns) - - with NetNSEnter(str(netns)): - netdevnl = NetdevFamily() - netdevnl.queue_create( - { - "ifindex": nk_guest_idx, - "type": "rx", - "lease": { - "ifindex": nsim.ifindex, - "queue": {"id": 1, "type": "rx"}, - "netns-id": 0, - }, - } - ) - - # Physical queue 0 (not leased) should have no lease info - netdevnl = NetdevFamily() - queue_info = netdevnl.queue_get( - {"ifindex": nsim.ifindex, "id": 0, "type": "rx"} - ) - ksft_not_in("lease", queue_info) - - # Physical queue 1 (leased) should have lease info - queue_info = netdevnl.queue_get( - {"ifindex": nsim.ifindex, "id": 1, "type": "rx"} - ) - ksft_in("lease", queue_info) - - -def test_same_ns_lease(_netns) -> None: - nsimdev = NetdevSimDev(port_count=1, queue_count=2) - defer(nsimdev.remove) - nsim = nsimdev.nsims[0] - ip(f"link set dev {nsim.ifname} up") - - nk_name, nk_idx = create_netkit_single(rxqueues=2) - defer(cmd, f"ip link del dev {nk_name}", fail=False) - - ip(f"link set dev {nk_name} up") - - netdevnl = NetdevFamily() - result = netdevnl.queue_create( - { - "ifindex": nk_idx, - "type": "rx", - "lease": { - "ifindex": nsim.ifindex, - "queue": {"id": 1, "type": "rx"}, - }, - } - ) - ksft_eq(result["id"], 1) - - # Same namespace: lease info should NOT have netns-id - queue_info = netdevnl.queue_get( - {"ifindex": nsim.ifindex, "id": 1, "type": "rx"} - ) - ksft_in("lease", queue_info) - ksft_eq(queue_info["lease"]["ifindex"], nk_idx) - ksft_eq(queue_info["lease"]["queue"]["id"], result["id"]) - ksft_not_in("netns-id", queue_info["lease"]) - - -def test_resize_after_unlease(netns) -> None: - nsimdev = NetdevSimDev(port_count=1, queue_count=2) - defer(nsimdev.remove) - nsim = nsimdev.nsims[0] - ip(f"link set dev {nsim.ifname} up") - - nk_host, _, nk_guest, nk_guest_idx = create_netkit(rxqueues=2) - - ip(f"link set dev {nk_guest} netns {netns.name}") - ip(f"link set dev {nk_host} up") - ip(f"link set dev {nk_guest} up", ns=netns) - - with NetNSEnter(str(netns)): - netdevnl = NetdevFamily() - netdevnl.queue_create( - { - "ifindex": nk_guest_idx, - "type": "rx", - "lease": { - "ifindex": nsim.ifindex, - "queue": {"id": 1, "type": "rx"}, - "netns-id": 0, - }, - } - ) - - # Resize should fail while lease is active - ethnl = EthtoolFamily() - |
