xref: /linux/tools/testing/selftests/drivers/net/hw/xsk_reconfig.py (revision b803c4a4f78834b31ebfbbcea350473333760559)
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