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 15from lib.py import ksft_exit, ksft_run 16from lib.py import KsftSkipEx, KsftFailEx 17from lib.py import NetDrvEnv 18from lib.py import bkg, ip, cmd, ethtool 19import time 20 21def _get_rx_ring_entries(cfg): 22 output = ethtool(f"-g {cfg.ifname}", json=True) 23 return output[0]["rx"] 24 25def 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 41def 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 47def 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 53def 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 59if __name__ == "__main__": 60 main() 61