Path: blob/master/tools/testing/selftests/drivers/net/hw/nk_qlease.py
171056 views
#!/usr/bin/env python31# SPDX-License-Identifier: GPL-2.023import re4import time5import threading6from os import path7from lib.py import (8ksft_run,9ksft_exit,10ksft_eq,11ksft_in,12ksft_not_in,13ksft_raises,14)15from lib.py import (16NetDrvContEnv,17NetNSEnter,18EthtoolFamily,19NetdevFamily,20)21from lib.py import (22bkg,23cmd,24defer,25ethtool,26ip,27rand_port,28wait_port_listen,29)30from lib.py import KsftSkipEx, CmdExitFailure313233def set_flow_rule(cfg):34output = ethtool(35f"-N {cfg.ifname} flow-type tcp6 dst-port {cfg.port} action {cfg.src_queue}"36).stdout37values = re.search(r"ID (\d+)", output).group(1)38return int(values)394041def test_iou_zcrx(cfg) -> None:42cfg.require_ipver("6")43ethnl = EthtoolFamily()4445rings = ethnl.rings_get({"header": {"dev-index": cfg.ifindex}})46rx_rings = rings["rx"]47hds_thresh = rings.get("hds-thresh", 0)4849ethnl.rings_set(50{51"header": {"dev-index": cfg.ifindex},52"tcp-data-split": "enabled",53"hds-thresh": 0,54"rx": 64,55}56)57defer(58ethnl.rings_set,59{60"header": {"dev-index": cfg.ifindex},61"tcp-data-split": "unknown",62"hds-thresh": hds_thresh,63"rx": rx_rings,64},65)6667ethtool(f"-X {cfg.ifname} equal {cfg.src_queue}")68defer(ethtool, f"-X {cfg.ifname} default")6970flow_rule_id = set_flow_rule(cfg)71defer(ethtool, f"-N {cfg.ifname} delete {flow_rule_id}")7273rx_cmd = f"ip netns exec {cfg.netns.name} {cfg.bin_local} -s -p {cfg.port} -i {cfg._nk_guest_ifname} -q {cfg.nk_queue}"74tx_cmd = f"{cfg.bin_remote} -c -h {cfg.nk_guest_ipv6} -p {cfg.port} -l 12840"75with bkg(rx_cmd, exit_wait=True):76wait_port_listen(cfg.port, proto="tcp", ns=cfg.netns)77cmd(tx_cmd, host=cfg.remote)787980def test_attrs(cfg) -> None:81cfg.require_ipver("6")82netdevnl = NetdevFamily()83queue_info = netdevnl.queue_get(84{"ifindex": cfg.ifindex, "id": cfg.src_queue, "type": "rx"}85)8687ksft_eq(queue_info["id"], cfg.src_queue)88ksft_eq(queue_info["type"], "rx")89ksft_eq(queue_info["ifindex"], cfg.ifindex)9091ksft_in("lease", queue_info)92lease = queue_info["lease"]93ksft_eq(lease["ifindex"], cfg.nk_guest_ifindex)94ksft_eq(lease["queue"]["id"], cfg.nk_queue)95ksft_eq(lease["queue"]["type"], "rx")96ksft_in("netns-id", lease)979899def test_attach_xdp_with_mp(cfg) -> None:100cfg.require_ipver("6")101ethnl = EthtoolFamily()102103rings = ethnl.rings_get({"header": {"dev-index": cfg.ifindex}})104rx_rings = rings["rx"]105hds_thresh = rings.get("hds-thresh", 0)106107ethnl.rings_set(108{109"header": {"dev-index": cfg.ifindex},110"tcp-data-split": "enabled",111"hds-thresh": 0,112"rx": 64,113}114)115defer(116ethnl.rings_set,117{118"header": {"dev-index": cfg.ifindex},119"tcp-data-split": "unknown",120"hds-thresh": hds_thresh,121"rx": rx_rings,122},123)124125ethtool(f"-X {cfg.ifname} equal {cfg.src_queue}")126defer(ethtool, f"-X {cfg.ifname} default")127128netdevnl = NetdevFamily()129130rx_cmd = f"ip netns exec {cfg.netns.name} {cfg.bin_local} -s -p {cfg.port} -i {cfg._nk_guest_ifname} -q {cfg.nk_queue}"131with bkg(rx_cmd):132wait_port_listen(cfg.port, proto="tcp", ns=cfg.netns)133134time.sleep(0.1)135queue_info = netdevnl.queue_get(136{"ifindex": cfg.ifindex, "id": cfg.src_queue, "type": "rx"}137)138ksft_in("io-uring", queue_info)139140prog = cfg.net_lib_dir / "xdp_dummy.bpf.o"141with ksft_raises(CmdExitFailure):142ip(f"link set dev {cfg.ifname} xdp obj {prog} sec xdp.frags")143144time.sleep(0.1)145queue_info = netdevnl.queue_get(146{"ifindex": cfg.ifindex, "id": cfg.src_queue, "type": "rx"}147)148ksft_not_in("io-uring", queue_info)149150151def test_destroy(cfg) -> None:152cfg.require_ipver("6")153ethnl = EthtoolFamily()154155rings = ethnl.rings_get({"header": {"dev-index": cfg.ifindex}})156rx_rings = rings["rx"]157hds_thresh = rings.get("hds-thresh", 0)158159ethnl.rings_set(160{161"header": {"dev-index": cfg.ifindex},162"tcp-data-split": "enabled",163"hds-thresh": 0,164"rx": 64,165}166)167defer(168ethnl.rings_set,169{170"header": {"dev-index": cfg.ifindex},171"tcp-data-split": "unknown",172"hds-thresh": hds_thresh,173"rx": rx_rings,174},175)176177ethtool(f"-X {cfg.ifname} equal {cfg.src_queue}")178defer(ethtool, f"-X {cfg.ifname} default")179180rx_cmd = f"ip netns exec {cfg.netns.name} {cfg.bin_local} -s -p {cfg.port} -i {cfg._nk_guest_ifname} -q {cfg.nk_queue}"181rx_proc = cmd(rx_cmd, background=True)182wait_port_listen(cfg.port, proto="tcp", ns=cfg.netns)183184netdevnl = NetdevFamily()185queue_info = netdevnl.queue_get(186{"ifindex": cfg.ifindex, "id": cfg.src_queue, "type": "rx"}187)188ksft_in("io-uring", queue_info)189190# ip link del will wait for all refs to drop first, but iou-zcrx is holding191# onto a ref. Terminate iou-zcrx async via a thread after a delay.192kill_timer = threading.Timer(1, rx_proc.proc.terminate)193kill_timer.start()194195ip(f"link del dev {cfg._nk_host_ifname}")196kill_timer.join()197cfg._nk_host_ifname = None198cfg._nk_guest_ifname = None199200queue_info = netdevnl.queue_get(201{"ifindex": cfg.ifindex, "id": cfg.src_queue, "type": "rx"}202)203ksft_not_in("io-uring", queue_info)204205cmd(f"tc filter del dev {cfg.ifname} ingress pref {cfg._bpf_prog_pref}")206cfg._tc_attached = False207208flow_rule_id = set_flow_rule(cfg)209defer(ethtool, f"-N {cfg.ifname} delete {flow_rule_id}")210211rx_cmd = f"{cfg.bin_local} -s -p {cfg.port} -i {cfg.ifname} -q {cfg.src_queue}"212tx_cmd = f"{cfg.bin_remote} -c -h {cfg.addr_v['6']} -p {cfg.port} -l 12840"213with bkg(rx_cmd, exit_wait=True):214wait_port_listen(cfg.port, proto="tcp")215cmd(tx_cmd, host=cfg.remote)216# Short delay since iou cleanup is async and takes a bit of time.217time.sleep(0.1)218queue_info = netdevnl.queue_get(219{"ifindex": cfg.ifindex, "id": cfg.src_queue, "type": "rx"}220)221ksft_not_in("io-uring", queue_info)222223224def main() -> None:225with NetDrvContEnv(__file__, rxqueues=2) as cfg:226cfg.bin_local = path.abspath(227path.dirname(__file__) + "/../../../drivers/net/hw/iou-zcrx"228)229cfg.bin_remote = cfg.remote.deploy(cfg.bin_local)230cfg.port = rand_port()231232ethnl = EthtoolFamily()233channels = ethnl.channels_get({"header": {"dev-index": cfg.ifindex}})234channels = channels["combined-count"]235if channels < 2:236raise KsftSkipEx("Test requires NETIF with at least 2 combined channels")237238cfg.src_queue = channels - 1239240with NetNSEnter(str(cfg.netns)):241netdevnl = NetdevFamily()242bind_result = netdevnl.queue_create(243{244"ifindex": cfg.nk_guest_ifindex,245"type": "rx",246"lease": {247"ifindex": cfg.ifindex,248"queue": {"id": cfg.src_queue, "type": "rx"},249"netns-id": 0,250},251}252)253cfg.nk_queue = bind_result["id"]254255# test_destroy must be last because it destroys the netkit devices256ksft_run(257[test_iou_zcrx, test_attrs, test_attach_xdp_with_mp, test_destroy],258args=(cfg,),259)260ksft_exit()261262263if __name__ == "__main__":264main()265266267