mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	selftests: drv-net: test XDP, HDS auto and the ioctl path
Test XDP and HDS interaction. While at it add a test for using the IOCTL, as that turned out to be the real culprit. Testing bnxt: # NETIF=eth0 ./ksft-net-drv/drivers/net/hds.py KTAP version 1 1..12 ok 1 hds.get_hds ok 2 hds.get_hds_thresh ok 3 hds.set_hds_disable # SKIP disabling of HDS not supported by the device ok 4 hds.set_hds_enable ok 5 hds.set_hds_thresh_zero ok 6 hds.set_hds_thresh_max ok 7 hds.set_hds_thresh_gt ok 8 hds.set_xdp ok 9 hds.enabled_set_xdp ok 10 hds.ioctl ok 11 hds.ioctl_set_xdp ok 12 hds.ioctl_enabled_set_xdp # Totals: pass:11 fail:0 xfail:0 xpass:0 skip:1 error:0 and netdevsim: # ./ksft-net-drv/drivers/net/hds.py KTAP version 1 1..12 ok 1 hds.get_hds ok 2 hds.get_hds_thresh ok 3 hds.set_hds_disable ok 4 hds.set_hds_enable ok 5 hds.set_hds_thresh_zero ok 6 hds.set_hds_thresh_max ok 7 hds.set_hds_thresh_gt ok 8 hds.set_xdp ok 9 hds.enabled_set_xdp ok 10 hds.ioctl ok 11 hds.ioctl_set_xdp ok 12 hds.ioctl_enabled_set_xdp # Totals: pass:12 fail:0 xfail:0 xpass:0 skip:0 error:0 Netdevsim needs a sane default for tx/rx ring size. ethtool 6.11 is needed for the --disable-netlink option. Acked-by: Stanislav Fomichev <sdf@fomichev.me> Tested-by: Taehee Yoo <ap420073@gmail.com> Link: https://patch.msgid.link/20250221025141.1132944-2-kuba@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
		
							parent
							
								
									db10fde5c4
								
							
						
					
					
						commit
						29b036be1b
					
				
					 4 changed files with 160 additions and 3 deletions
				
			
		| 
						 | 
					@ -184,9 +184,11 @@ static const struct ethtool_ops nsim_ethtool_ops = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void nsim_ethtool_ring_init(struct netdevsim *ns)
 | 
					static void nsim_ethtool_ring_init(struct netdevsim *ns)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						ns->ethtool.ring.rx_pending = 512;
 | 
				
			||||||
	ns->ethtool.ring.rx_max_pending = 4096;
 | 
						ns->ethtool.ring.rx_max_pending = 4096;
 | 
				
			||||||
	ns->ethtool.ring.rx_jumbo_max_pending = 4096;
 | 
						ns->ethtool.ring.rx_jumbo_max_pending = 4096;
 | 
				
			||||||
	ns->ethtool.ring.rx_mini_max_pending = 4096;
 | 
						ns->ethtool.ring.rx_mini_max_pending = 4096;
 | 
				
			||||||
 | 
						ns->ethtool.ring.tx_pending = 512;
 | 
				
			||||||
	ns->ethtool.ring.tx_max_pending = 4096;
 | 
						ns->ethtool.ring.tx_max_pending = 4096;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,17 +2,54 @@
 | 
				
			||||||
# SPDX-License-Identifier: GPL-2.0
 | 
					# SPDX-License-Identifier: GPL-2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import errno
 | 
					import errno
 | 
				
			||||||
 | 
					import os
 | 
				
			||||||
from lib.py import ksft_run, ksft_exit, ksft_eq, ksft_raises, KsftSkipEx
 | 
					from lib.py import ksft_run, ksft_exit, ksft_eq, ksft_raises, KsftSkipEx
 | 
				
			||||||
from lib.py import EthtoolFamily, NlError
 | 
					from lib.py import CmdExitFailure, EthtoolFamily, NlError
 | 
				
			||||||
from lib.py import NetDrvEnv
 | 
					from lib.py import NetDrvEnv
 | 
				
			||||||
 | 
					from lib.py import defer, ethtool, ip
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def get_hds(cfg, netnl) -> None:
 | 
					
 | 
				
			||||||
 | 
					def _get_hds_mode(cfg, netnl) -> str:
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}})
 | 
					        rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}})
 | 
				
			||||||
    except NlError as e:
 | 
					    except NlError as e:
 | 
				
			||||||
        raise KsftSkipEx('ring-get not supported by device')
 | 
					        raise KsftSkipEx('ring-get not supported by device')
 | 
				
			||||||
    if 'tcp-data-split' not in rings:
 | 
					    if 'tcp-data-split' not in rings:
 | 
				
			||||||
        raise KsftSkipEx('tcp-data-split not supported by device')
 | 
					        raise KsftSkipEx('tcp-data-split not supported by device')
 | 
				
			||||||
 | 
					    return rings['tcp-data-split']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _xdp_onoff(cfg):
 | 
				
			||||||
 | 
					    test_dir = os.path.dirname(os.path.realpath(__file__))
 | 
				
			||||||
 | 
					    prog = test_dir + "/../../net/lib/xdp_dummy.bpf.o"
 | 
				
			||||||
 | 
					    ip("link set dev %s xdp obj %s sec xdp" %
 | 
				
			||||||
 | 
					       (cfg.ifname, prog))
 | 
				
			||||||
 | 
					    ip("link set dev %s xdp off" % cfg.ifname)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _ioctl_ringparam_modify(cfg, netnl) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Helper for performing a hopefully unimportant IOCTL SET.
 | 
				
			||||||
 | 
					    IOCTL does not support HDS, so it should not affect the HDS config.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        rings = netnl.rings_get({'header': {'dev-index': cfg.ifindex}})
 | 
				
			||||||
 | 
					    except NlError as e:
 | 
				
			||||||
 | 
					        raise KsftSkipEx('ring-get not supported by device')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if 'tx' not in rings:
 | 
				
			||||||
 | 
					        raise KsftSkipEx('setting Tx ring size not supported')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        ethtool(f"--disable-netlink -G {cfg.ifname} tx {rings['tx'] // 2}")
 | 
				
			||||||
 | 
					    except CmdExitFailure as e:
 | 
				
			||||||
 | 
					        ethtool(f"--disable-netlink -G {cfg.ifname} tx {rings['tx'] * 2}")
 | 
				
			||||||
 | 
					    defer(ethtool, f"-G {cfg.ifname} tx {rings['tx']}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def get_hds(cfg, netnl) -> None:
 | 
				
			||||||
 | 
					    _get_hds_mode(cfg, netnl)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def get_hds_thresh(cfg, netnl) -> None:
 | 
					def get_hds_thresh(cfg, netnl) -> None:
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
| 
						 | 
					@ -104,6 +141,103 @@ def set_hds_thresh_gt(cfg, netnl) -> None:
 | 
				
			||||||
        netnl.rings_set({'header': {'dev-index': cfg.ifindex}, 'hds-thresh': hds_gt})
 | 
					        netnl.rings_set({'header': {'dev-index': cfg.ifindex}, 'hds-thresh': hds_gt})
 | 
				
			||||||
    ksft_eq(e.exception.nl_msg.error, -errno.EINVAL)
 | 
					    ksft_eq(e.exception.nl_msg.error, -errno.EINVAL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def set_xdp(cfg, netnl) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Enable single-buffer XDP on the device.
 | 
				
			||||||
 | 
					    When HDS is in "auto" / UNKNOWN mode, XDP installation should work.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    mode = _get_hds_mode(cfg, netnl)
 | 
				
			||||||
 | 
					    if mode == 'enabled':
 | 
				
			||||||
 | 
					        netnl.rings_set({'header': {'dev-index': cfg.ifindex},
 | 
				
			||||||
 | 
					                         'tcp-data-split': 'unknown'})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    _xdp_onoff(cfg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def enabled_set_xdp(cfg, netnl) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Enable single-buffer XDP on the device.
 | 
				
			||||||
 | 
					    When HDS is in "enabled" mode, XDP installation should not work.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    _get_hds_mode(cfg, netnl)
 | 
				
			||||||
 | 
					    netnl.rings_set({'header': {'dev-index': cfg.ifindex},
 | 
				
			||||||
 | 
					                     'tcp-data-split': 'enabled'})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    defer(netnl.rings_set, {'header': {'dev-index': cfg.ifindex},
 | 
				
			||||||
 | 
					                            'tcp-data-split': 'unknown'})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    with ksft_raises(CmdExitFailure) as e:
 | 
				
			||||||
 | 
					        _xdp_onoff(cfg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def set_xdp(cfg, netnl) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Enable single-buffer XDP on the device.
 | 
				
			||||||
 | 
					    When HDS is in "auto" / UNKNOWN mode, XDP installation should work.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    mode = _get_hds_mode(cfg, netnl)
 | 
				
			||||||
 | 
					    if mode == 'enabled':
 | 
				
			||||||
 | 
					        netnl.rings_set({'header': {'dev-index': cfg.ifindex},
 | 
				
			||||||
 | 
					                         'tcp-data-split': 'unknown'})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    _xdp_onoff(cfg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def enabled_set_xdp(cfg, netnl) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Enable single-buffer XDP on the device.
 | 
				
			||||||
 | 
					    When HDS is in "enabled" mode, XDP installation should not work.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    _get_hds_mode(cfg, netnl)  # Trigger skip if not supported
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    netnl.rings_set({'header': {'dev-index': cfg.ifindex},
 | 
				
			||||||
 | 
					                     'tcp-data-split': 'enabled'})
 | 
				
			||||||
 | 
					    defer(netnl.rings_set, {'header': {'dev-index': cfg.ifindex},
 | 
				
			||||||
 | 
					                            'tcp-data-split': 'unknown'})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    with ksft_raises(CmdExitFailure) as e:
 | 
				
			||||||
 | 
					        _xdp_onoff(cfg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def ioctl(cfg, netnl) -> None:
 | 
				
			||||||
 | 
					    mode1 = _get_hds_mode(cfg, netnl)
 | 
				
			||||||
 | 
					    _ioctl_ringparam_modify(cfg, netnl)
 | 
				
			||||||
 | 
					    mode2 = _get_hds_mode(cfg, netnl)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ksft_eq(mode1, mode2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def ioctl_set_xdp(cfg, netnl) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Like set_xdp(), but we perturb the settings via the legacy ioctl.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    mode = _get_hds_mode(cfg, netnl)
 | 
				
			||||||
 | 
					    if mode == 'enabled':
 | 
				
			||||||
 | 
					        netnl.rings_set({'header': {'dev-index': cfg.ifindex},
 | 
				
			||||||
 | 
					                         'tcp-data-split': 'unknown'})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    _ioctl_ringparam_modify(cfg, netnl)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    _xdp_onoff(cfg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def ioctl_enabled_set_xdp(cfg, netnl) -> None:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Enable single-buffer XDP on the device.
 | 
				
			||||||
 | 
					    When HDS is in "enabled" mode, XDP installation should not work.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    _get_hds_mode(cfg, netnl)  # Trigger skip if not supported
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    netnl.rings_set({'header': {'dev-index': cfg.ifindex},
 | 
				
			||||||
 | 
					                     'tcp-data-split': 'enabled'})
 | 
				
			||||||
 | 
					    defer(netnl.rings_set, {'header': {'dev-index': cfg.ifindex},
 | 
				
			||||||
 | 
					                            'tcp-data-split': 'unknown'})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    with ksft_raises(CmdExitFailure) as e:
 | 
				
			||||||
 | 
					        _xdp_onoff(cfg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def main() -> None:
 | 
					def main() -> None:
 | 
				
			||||||
    with NetDrvEnv(__file__, queue_count=3) as cfg:
 | 
					    with NetDrvEnv(__file__, queue_count=3) as cfg:
 | 
				
			||||||
        ksft_run([get_hds,
 | 
					        ksft_run([get_hds,
 | 
				
			||||||
| 
						 | 
					@ -112,7 +246,12 @@ def main() -> None:
 | 
				
			||||||
                  set_hds_enable,
 | 
					                  set_hds_enable,
 | 
				
			||||||
                  set_hds_thresh_zero,
 | 
					                  set_hds_thresh_zero,
 | 
				
			||||||
                  set_hds_thresh_max,
 | 
					                  set_hds_thresh_max,
 | 
				
			||||||
                  set_hds_thresh_gt],
 | 
					                  set_hds_thresh_gt,
 | 
				
			||||||
 | 
					                  set_xdp,
 | 
				
			||||||
 | 
					                  enabled_set_xdp,
 | 
				
			||||||
 | 
					                  ioctl,
 | 
				
			||||||
 | 
					                  ioctl_set_xdp,
 | 
				
			||||||
 | 
					                  ioctl_enabled_set_xdp],
 | 
				
			||||||
                 args=(cfg, EthtoolFamily()))
 | 
					                 args=(cfg, EthtoolFamily()))
 | 
				
			||||||
    ksft_exit()
 | 
					    ksft_exit()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,7 +9,10 @@ TEST_FILES := ../../../../../Documentation/netlink/specs
 | 
				
			||||||
TEST_FILES += ../../../../net/ynl
 | 
					TEST_FILES += ../../../../net/ynl
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST_GEN_FILES += csum
 | 
					TEST_GEN_FILES += csum
 | 
				
			||||||
 | 
					TEST_GEN_FILES += $(patsubst %.c,%.o,$(wildcard *.bpf.c))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST_INCLUDES := $(wildcard py/*.py sh/*.sh)
 | 
					TEST_INCLUDES := $(wildcard py/*.py sh/*.sh)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
include ../../lib.mk
 | 
					include ../../lib.mk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include ../bpf.mk
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										13
									
								
								tools/testing/selftests/net/lib/xdp_dummy.bpf.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								tools/testing/selftests/net/lib/xdp_dummy.bpf.c
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,13 @@
 | 
				
			||||||
 | 
					// SPDX-License-Identifier: GPL-2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define KBUILD_MODNAME "xdp_dummy"
 | 
				
			||||||
 | 
					#include <linux/bpf.h>
 | 
				
			||||||
 | 
					#include <bpf/bpf_helpers.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SEC("xdp")
 | 
				
			||||||
 | 
					int xdp_dummy_prog(struct xdp_md *ctx)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return XDP_PASS;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					char _license[] SEC("license") = "GPL";
 | 
				
			||||||
		Loading…
	
		Reference in a new issue