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

selftests: net: add a virtio_net deadlock selftest

The selftest reproduces the deadlock scenario when binding/unbinding XDP
program, XDP socket, rx ring resize on virtio_net interface.

Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Link: https://patch.msgid.link/20250425071018.36078-5-minhquangbui99@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Bui Quang Minh and committed by
Jakub Kicinski
c347fb0f b2b4555c

+61
+1
tools/testing/selftests/drivers/net/hw/Makefile
··· 21 21 rss_ctx.py \ 22 22 rss_input_xfrm.py \ 23 23 tso.py \ 24 + xsk_reconfig.py \ 24 25 # 25 26 26 27 TEST_FILES := \
+60
tools/testing/selftests/drivers/net/hw/xsk_reconfig.py
··· 1 + #!/usr/bin/env python3 2 + # SPDX-License-Identifier: GPL-2.0 3 + 4 + # This is intended to be run on a virtio-net guest interface. 5 + # The test binds the XDP socket to the interface without setting 6 + # the fill ring to trigger delayed refill_work. This helps to 7 + # make it easier to reproduce the deadlock when XDP program, 8 + # XDP socket bind/unbind, rx ring resize race with refill_work on 9 + # the buggy kernel. 10 + # 11 + # The Qemu command to setup virtio-net 12 + # -netdev tap,id=hostnet1,vhost=on,script=no,downscript=no 13 + # -device virtio-net-pci,netdev=hostnet1,iommu_platform=on,disable-legacy=on 14 + 15 + from lib.py import ksft_exit, ksft_run 16 + from lib.py import KsftSkipEx, KsftFailEx 17 + from lib.py import NetDrvEnv 18 + from lib.py import bkg, ip, cmd, ethtool 19 + import time 20 + 21 + def _get_rx_ring_entries(cfg): 22 + output = ethtool(f"-g {cfg.ifname}", json=True) 23 + return output[0]["rx"] 24 + 25 + def setup_xsk(cfg, xdp_queue_id = 0) -> bkg: 26 + # Probe for support 27 + xdp = cmd(f'{cfg.net_lib_dir / "xdp_helper"} - -', fail=False) 28 + if xdp.ret == 255: 29 + raise KsftSkipEx('AF_XDP unsupported') 30 + elif xdp.ret > 0: 31 + raise KsftFailEx('unable to create AF_XDP socket') 32 + 33 + try: 34 + return bkg(f'{cfg.net_lib_dir / "xdp_helper"} {cfg.ifindex} ' \ 35 + '{xdp_queue_id} -z', ksft_wait=3) 36 + except: 37 + raise KsftSkipEx('Failed to bind XDP socket in zerocopy.\n' \ 38 + 'Please consider adding iommu_platform=on ' \ 39 + 'when setting up virtio-net-pci') 40 + 41 + def check_xdp_bind(cfg): 42 + with setup_xsk(cfg): 43 + ip(f"link set dev %s xdp obj %s sec xdp" % 44 + (cfg.ifname, cfg.net_lib_dir / "xdp_dummy.bpf.o")) 45 + ip(f"link set dev %s xdp off" % cfg.ifname) 46 + 47 + def check_rx_resize(cfg): 48 + with setup_xsk(cfg): 49 + rx_ring = _get_rx_ring_entries(cfg) 50 + ethtool(f"-G %s rx %d" % (cfg.ifname, rx_ring // 2)) 51 + ethtool(f"-G %s rx %d" % (cfg.ifname, rx_ring)) 52 + 53 + def main(): 54 + with NetDrvEnv(__file__, nsim_test=False) as cfg: 55 + ksft_run([check_xdp_bind, check_rx_resize], 56 + args=(cfg, )) 57 + ksft_exit() 58 + 59 + if __name__ == "__main__": 60 + main()