Re: [PATCH net-next] selftests/net: Add two xdp tests to xdp.py

From: Jakub Kicinski

Date: Wed Apr 01 2026 - 16:21:06 EST


On Wed, 1 Apr 2026 13:27:46 +0800 Leon Hwang wrote:
> In "bpf: Disallow freplace on XDP with mismatched xdp_has_frags values" [1],
> these two XDP tests are suggested to add to xdp.py.
>
> 1. Verify the failure of attaching non-frag-capable prog to mtu=9k driver.
> 2. Verify the failure of updating frag-capable prog with non-frag-capable
> prog, when the frag-capable prog attaches to mtu=9k driver.
>
> They have been verified against Mellanox CX6 and Intel 82599ES NICs.
>
> With dropping other tests, here are the test logs.
>
> # ethtool -i eth0
> driver: mlx5_core
> version: 6.19.0-061900-generic
>
> # NETIF=eth0 python3 xdp.py
> TAP version 13
> 1..2
> ok 1 xdp.test_xdp_native_attach_sb_to_mb
> ok 2 xdp.test_xdp_native_update_mb_to_sb
> # Totals: pass:2 fail:0 xfail:0 xpass:0 skip:0 error:0
>
> # ethtool -i eth0
> driver: ixgbe
> version: 6.19.0-061900-generic
>
> # NETIF=eth0 python3 xdp.py
> TAP version 13
> 1..2
> ok 1 xdp.test_xdp_native_attach_sb_to_mb # SKIP RTNETLINK answers: Invalid argument
> ok 2 xdp.test_xdp_native_update_mb_to_sb # SKIP RTNETLINK answers: Invalid argument
> # Totals: pass:0 fail:0 xfail:0 xpass:0 skip:2 error:0
>
> Links:
> [1] https://lore.kernel.org/bpf/20260326124205.1a3bb825@xxxxxxxxxx/

Thanks for working on it!

> diff --git a/tools/testing/selftests/drivers/net/xdp.py b/tools/testing/selftests/drivers/net/xdp.py
> index d86446569f89..fe34b491778b 100755
> --- a/tools/testing/selftests/drivers/net/xdp.py
> +++ b/tools/testing/selftests/drivers/net/xdp.py
> @@ -13,7 +13,7 @@ from enum import Enum
>
> from lib.py import ksft_run, ksft_exit, ksft_eq, ksft_ge, ksft_ne, ksft_pr
> from lib.py import KsftNamedVariant, ksft_variants
> -from lib.py import KsftFailEx, NetDrvEpEnv
> +from lib.py import KsftFailEx, KsftSkipEx, NetDrvEpEnv
> from lib.py import EthtoolFamily, NetdevFamily, NlError
> from lib.py import bkg, cmd, rand_port, wait_port_listen
> from lib.py import ip, defer
> @@ -693,6 +693,55 @@ def test_xdp_native_qstats(cfg, act):
> ksft_ge(after['tx-packets'], before['tx-packets'])
>
>
> +def _set_jumbo_mtu(cfg, mtu):
> + ip(f"link set dev {cfg.ifname} mtu {mtu}")
> + defer(ip, f"link set dev {cfg.ifname} mtu 1500")

cfg records the original MTU, you can copy this line from here:
https://elixir.bootlin.com/linux/v7.0-rc6/source/tools/testing/selftests/drivers/net/gro.py#L88

> +def _exec_cmd(cfg, obj, sec, ip_opts=""):
> + return cmd(f"ip {ip_opts} link set dev {cfg.ifname} xdpdrv obj {obj} sec {sec}", shell=True, fail=False)

We shouldn't need the shell=True where?
Also it's probably cleaner to pass fail as optional argument here
so that you can let this throw an exception in the cases we expect
to succeed instead of having to check in the caller explicitly

> +def test_xdp_native_attach_sb_to_mb(cfg):
> + obj = cfg.net_lib_dir / "xdp_dummy.bpf.o"
> + mtu = 9000
> +
> + _set_jumbo_mtu(cfg, mtu)
> +
> + probe = _exec_cmd(cfg, obj, "xdp.frags")
> + if probe.ret != 0:
> + output = probe.stderr.strip() or probe.stdout.strip()
> + raise KsftSkipEx(output or "device does not support multi-buffer XDP")

May be simpler and cleaner to print the whole command separately:

if probe.ret != 0:
ksft_pr(probe)
raise KsftSkipEx("device does not support multi-buffer XDP")

> + ip(f"link set dev {cfg.ifname} xdpdrv off")
> +
> + probe = _exec_cmd(cfg, obj, "xdp")
> + if probe.ret == 0:
> + ip(f"link set dev {cfg.ifname} xdpdrv off")
> + raise KsftFailEx(f"driver unexpectedly allows non-multi-buffer XDP at MTU {mtu}")

Hm, TBH I don't think this sb_to_mb case is adding any coverage.
Let's just add the test case below?


> +def test_xdp_native_update_mb_to_sb(cfg):
> + obj = cfg.net_lib_dir / "xdp_dummy.bpf.o"
> +
> + _set_jumbo_mtu(cfg, 9000)
> +
> + attach = _exec_cmd(cfg, obj, "xdp.frags")
> + if attach.ret != 0:
> + output = attach.stderr.strip() or attach.stdout.strip()
> + raise KsftSkipEx(output or "device does not support multi-buffer XDP")
> +
> + defer(ip, f"link set dev {cfg.ifname} xdpdrv off")
> +
> + update1 = _exec_cmd(cfg, obj, "xdp.frags", "-force")
> + if update1.ret != 0:
> + raise KsftFailEx("device fails to update multi-buffer XDP")
> +
> + update2 = _exec_cmd(cfg, obj, "xdp", "-force")
> + if update2.ret == 0:
> + raise KsftFailEx("device unexpectedly updates non-multi-buffer XDP")
--
pw-bot: cr