diff options
Diffstat (limited to 'tools/testing/selftests/drivers')
| -rw-r--r-- | tools/testing/selftests/drivers/net/hw/Makefile | 1 | ||||
| -rwxr-xr-x | tools/testing/selftests/drivers/net/hw/devlink_rate_cross_esw.py | 296 | ||||
| -rwxr-xr-x | tools/testing/selftests/drivers/net/hw/rss_ctx.py | 11 | ||||
| -rwxr-xr-x | tools/testing/selftests/drivers/net/hw/toeplitz.py | 22 | ||||
| -rw-r--r-- | tools/testing/selftests/drivers/net/lib/py/env.py | 27 | ||||
| -rwxr-xr-x | tools/testing/selftests/drivers/net/xdp.py | 94 |
6 files changed, 424 insertions, 27 deletions
diff --git a/tools/testing/selftests/drivers/net/hw/Makefile b/tools/testing/selftests/drivers/net/hw/Makefile index fd0535a96d84..234db5c2c90c 100644 --- a/tools/testing/selftests/drivers/net/hw/Makefile +++ b/tools/testing/selftests/drivers/net/hw/Makefile @@ -20,6 +20,7 @@ TEST_GEN_FILES := \ TEST_PROGS = \ csum.py \ devlink_port_split.py \ + devlink_rate_cross_esw.py \ devlink_rate_tc_bw.py \ devmem.py \ ethtool.sh \ diff --git a/tools/testing/selftests/drivers/net/hw/devlink_rate_cross_esw.py b/tools/testing/selftests/drivers/net/hw/devlink_rate_cross_esw.py new file mode 100755 index 000000000000..4416f024cb76 --- /dev/null +++ b/tools/testing/selftests/drivers/net/hw/devlink_rate_cross_esw.py @@ -0,0 +1,296 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0 + +""" +Devlink Rate Cross-eswitch Scheduling Test Suite +================================================== + +Control-plane tests for cross-eswitch TX scheduling via devlink-rate. +Validates that VFs from different PFs on the same chip can share +rate groups using the cross-device parent-dev attribute. + +Preconditions: +- NETIF points to a bond device with exactly two interfaces. +- the interfaces must be two PFs from different devices sharing the same chip. +- (for mlx5): the two interfaces are in switchdev mode and configured in a LAG: + - devlink dev eswitch set $DEV1 mode switchdev + - devlink dev eswitch set $DEV2 mode switchdev + - devlink dev param set $DEV1 name esw_multiport value 1 cmode runtime + - devlink dev param set $DEV2 name esw_multiport value 1 cmode runtime +- test cases will be skipped if: + - the number of interfaces in the bond device is != 2. + - the kernel doesn't support devlink rates. + - the devlink API doesn't support cross-device parents (ENODEV). + - cross-esw rate scheduling returns EOPNOTSUPP. +""" + +import errno +import glob +import os +import time + +from lib.py import ksft_pr, ksft_eq, ksft_run, ksft_exit +from lib.py import KsftSkipEx, KsftFailEx +from lib.py import NetDrvEnv, DevlinkFamily +from lib.py import NlError +from lib.py import cmd, defer, ip, tool + + +# --- Discovery and setup --- + + +def get_bond_slaves(bond_ifname): + """Returns sorted list of slave netdev names for a bond.""" + pattern = f"/sys/class/net/{bond_ifname}/lower_*" + lowers = glob.glob(pattern) + if not lowers: + raise KsftSkipEx(f"No bond slaves for {bond_ifname}") + slaves = [] + for path in sorted(lowers): + name = os.path.basename(path) + if name.startswith("lower_"): + name = name[len("lower_"):] + slaves.append(name) + return slaves + + +def discover_pfs(cfg): + """Discovers both PFs from bond slaves.""" + slaves = get_bond_slaves(cfg.ifname) + if len(slaves) != 2: + raise KsftSkipEx(f"Need 2 bond slaves, found {len(slaves)}") + + pf0, pf1 = slaves[0], slaves[1] + ksft_pr(f"PF0: {pf0} PF1: {pf1}") + return pf0, pf1 + + +def get_pci_addr(ifname): + """Resolves PCI address for a network interface.""" + return os.path.basename(os.path.realpath(f"/sys/class/net/{ifname}/device")) + + +def get_vf_port_index(pf_pci): + """Finds devlink port-index for vf0 under pf_pci.""" + ports = tool("devlink", "port show", json=True)["port"] + for port_name, props in ports.items(): + if port_name.startswith(f"pci/{pf_pci}/") and props.get("vfnum") == 0: + return int(port_name.split("/")[-1]) + raise KsftSkipEx(f"VF port not found for {pf_pci}") + + +def cleanup_esw(pf): + """Removes VFs if created by tests.""" + cmd(f"echo 0 > /sys/class/net/{pf}/device/sriov_numvfs", shell=True, fail=False) + + +def setup_esw(pf): + """Creates 1 VF on 'pf'.""" + path = f"/sys/class/net/{pf}/device/sriov_numvfs" + cmd(f"echo 0 > {path}", shell=True) + cmd(f"echo 1 > {path}", shell=True) + defer(cleanup_esw, pf) + time.sleep(2) + + vf_dir = f"/sys/class/net/{pf}/device/virtfn0/net" + entries = os.listdir(vf_dir) if os.path.isdir(vf_dir) else [] + if not entries: + raise KsftSkipEx(f"VF not found for {pf}") + ip(f"link set dev {entries[0]} up") + + pf_pci = get_pci_addr(pf) + vf_idx = get_vf_port_index(pf_pci) + ksft_pr(f"Created VF {vf_idx} on PF {pf} ({pf_pci})") + return pf_pci, vf_idx + + +# --- Rate operation helpers --- + + +def rate_new(devnl, dev_pci, node_name, **kwargs): + """Creates rate node.""" + params = { + "bus-name": "pci", + "dev-name": dev_pci, + "rate-node-name": node_name, + } + params.update(kwargs) + try: + devnl.rate_new(params) + except NlError as e: + if e.error == errno.EOPNOTSUPP: + raise KsftSkipEx("rate_new not supported") from e + raise KsftFailEx("rate_new failed") from e + + +def rate_get(devnl, dev_pci, node_name): + """Gets rate node.""" + params = { + "bus-name": "pci", + "dev-name": dev_pci, + "rate-node-name": node_name, + } + return devnl.rate_get(params) + + +def rate_get_leaf(devnl, dev_pci, port_index): + """Gets rate leaf (VF).""" + params = { + "bus-name": "pci", + "dev-name": dev_pci, + "port-index": port_index, + } + return devnl.rate_get(params) + + +def rate_del(devnl, dev_pci, node_name): + """Deletes rate node.""" + devnl.rate_del({ + "bus-name": "pci", + "dev-name": dev_pci, + "rate-node-name": node_name, + }) + + +def rate_set_leaf(devnl, dev_pci, port_index, **kwargs): + """Sets rate attributes on a leaf (VF).""" + params = { + "bus-name": "pci", + "dev-name": dev_pci, + "port-index": port_index, + } + params.update(kwargs) + try: + devnl.rate_set(params) + except NlError as e: + if e.error == errno.EOPNOTSUPP: + raise KsftSkipEx("rate_set not supported") from e + raise KsftFailEx("rate_set failed") from e + + +def rate_set_leaf_parent(devnl, dev_pci, port_index, + parent_name, parent_dev_pci=None): + """Sets a leaf's parent, optionally cross-esw.""" + params = { + "bus-name": "pci", + "dev-name": dev_pci, + "port-index": port_index, + "rate-parent-node-name": parent_name, + } + if parent_dev_pci: + params["parent-dev"] = { + "bus-name": "pci", + "dev-name": parent_dev_pci, + } + try: + devnl.rate_set(params) + except NlError as e: + if e.error == errno.EOPNOTSUPP: + raise KsftSkipEx("rate_set not supported") from e + if parent_dev_pci and e.error == errno.ENODEV: + raise KsftSkipEx("Cross-esw scheduling not supported") from e + raise KsftFailEx("rate_set failed") from e + + +def rate_clear_leaf_parent(devnl, dev_pci, port_index): + """Clears a leaf's parent.""" + rate_set_leaf_parent(devnl, dev_pci, port_index, "") + + +def rate_set_node(devnl, dev_pci, node_name, **kwargs): + """Sets rate attributes on a node.""" + params = { + "bus-name": "pci", + "dev-name": dev_pci, + "rate-node-name": node_name, + } + params.update(kwargs) + devnl.rate_set(params) + + +# --- Test cases --- + + +def test_same_esw_parent(cfg): + """Assigns PF0's VF to PF0's group (same esw baseline).""" + pf0, _ = discover_pfs(cfg) + pf0_pci, vf0_idx = setup_esw(pf0) + + rate_new(cfg.devnl, pf0_pci, "group0") + defer(rate_del, cfg.devnl, pf0_pci, "group0") + ksft_pr("rate-new succeeded") + + rate_set_leaf_parent(cfg.devnl, pf0_pci, vf0_idx, "group0") + defer(rate_clear_leaf_parent, cfg.devnl, pf0_pci, vf0_idx) + + ksft_pr("Same-esw parent assignment succeeded") + + +def test_cross_esw_parent(cfg): + """Sets cross-esw parent, then clear it.""" + pf0, pf1 = discover_pfs(cfg) + pf0_pci, _ = setup_esw(pf0) + pf1_pci, vf1_idx = setup_esw(pf1) + + rate_new(cfg.devnl, pf0_pci, "group1") + defer(rate_del, cfg.devnl, pf0_pci, "group1") + ksft_pr("rate-new succeeded") + + rate_set_leaf_parent(cfg.devnl, pf1_pci, vf1_idx, + "group1", parent_dev_pci=pf0_pci) + defer(rate_clear_leaf_parent, cfg.devnl, pf1_pci, vf1_idx) + + ksft_pr("Cross-esw parent set and clear succeeded") + + +def test_tx_rates_on_cross_esw(cfg): + """Sets tx_max on group and tx_share on leaves in a cross-esw setup.""" + pf0, pf1 = discover_pfs(cfg) + pf0_pci, vf0_idx = setup_esw(pf0) + pf1_pci, vf1_idx = setup_esw(pf1) + + rate_new(cfg.devnl, pf0_pci, "group2", **{"rate-tx-max": 10000000}) + defer(rate_del, cfg.devnl, pf0_pci, "group2") + ksft_pr("rate-new succeeded") + + rate_set_leaf_parent(cfg.devnl, pf1_pci, vf1_idx, + "group2", parent_dev_pci=pf0_pci) + defer(rate_clear_leaf_parent, cfg.devnl, pf1_pci, vf1_idx) + ksft_pr("set parent cross-esw succeeded") + + rate_set_leaf_parent(cfg.devnl, pf0_pci, vf0_idx, "group2") + defer(rate_clear_leaf_parent, cfg.devnl, pf0_pci, vf0_idx) + ksft_pr("set parent same esw succeeded") + + rate_set_leaf(cfg.devnl, pf0_pci, vf0_idx, **{"rate-tx-share": 1000000}) + rate = rate_get_leaf(cfg.devnl, pf0_pci, vf0_idx) + ksft_eq(rate["rate-tx-share"], 1000000) + rate_set_leaf(cfg.devnl, pf1_pci, vf1_idx, **{"rate-tx-share": 2000000}) + rate = rate_get_leaf(cfg.devnl, pf1_pci, vf1_idx) + ksft_eq(rate["rate-tx-share"], 2000000) + rate_set_node(cfg.devnl, pf0_pci, "group2", **{"rate-tx-max": 250000000}) + rate = rate_get(cfg.devnl, pf0_pci, "group2") + ksft_eq(rate["rate-tx-max"], 250000000) + + ksft_pr("tx_max and tx_share set on cross-esw group") + + +def main() -> None: + """Main function.""" + + with NetDrvEnv(__file__, nsim_test=False) as cfg: + cfg.devnl = DevlinkFamily() + + ksft_run( + cases=[ + test_same_esw_parent, + test_cross_esw_parent, + test_tx_rates_on_cross_esw, + ], + args=(cfg,), + ) + ksft_exit() + + +if __name__ == "__main__": + main() diff --git a/tools/testing/selftests/drivers/net/hw/rss_ctx.py b/tools/testing/selftests/drivers/net/hw/rss_ctx.py index f36f76d6ca59..5b25fa89c629 100755 --- a/tools/testing/selftests/drivers/net/hw/rss_ctx.py +++ b/tools/testing/selftests/drivers/net/hw/rss_ctx.py @@ -651,9 +651,14 @@ def test_rss_context_overlap(cfg, other_ctx=0): ntuple = defer(ethtool, f"-N {cfg.ifname} delete {ntuple_id}") # Test the main context - cnts = _get_rx_cnts(cfg) - GenerateTraffic(cfg, port=port).wait_pkts_and_stop(20000) - cnts = _get_rx_cnts(cfg, prev=cnts) + attempts = 3 + for attempt in range(attempts): + cnts = _get_rx_cnts(cfg) + GenerateTraffic(cfg, port=port).wait_pkts_and_stop(20000) + cnts = _get_rx_cnts(cfg, prev=cnts) + if sum(cnts[:2]) >= 7000 and sum(cnts[2:4]) >= 7000: + break + ksft_pr(f"Skewed queue distribution, attempt {attempt + 1}/{attempts}: " + str(cnts)) ksft_ge(sum(cnts[ :4]), 20000, "traffic on main context: " + str(cnts)) ksft_ge(sum(cnts[ :2]), 7000, "traffic on main context (1/2): " + str(cnts)) diff --git a/tools/testing/selftests/drivers/net/hw/toeplitz.py b/tools/testing/selftests/drivers/net/hw/toeplitz.py index cd7e080e6f84..571732198b93 100755 --- a/tools/testing/selftests/drivers/net/hw/toeplitz.py +++ b/tools/testing/selftests/drivers/net/hw/toeplitz.py @@ -21,6 +21,8 @@ from lib.py import ksft_variants, KsftNamedVariant, KsftSkipEx, KsftFailEx ETH_RSS_HASH_TOP = 1 # Must match RPS_MAX_CPUS in toeplitz.c RPS_MAX_CPUS = 16 +# Cap Rx queues so IRQ pinning leaves free CPUs in the RPS_MAX_CPUS range +QUEUE_CAP = 8 def _check_rps_and_rfs_not_configured(cfg): @@ -48,6 +50,25 @@ def _get_cpu_for_irq(irq): return int(data) +def _cap_queue_count(cfg): + ehdr = {"header": {"dev-index": cfg.ifindex}} + chans = cfg.ethnl.channels_get(ehdr) + + config = {} + restore = {} + for key in ("combined-count", "rx-count"): + cur = chans.get(key, 0) + if cur > QUEUE_CAP: + config[key] = QUEUE_CAP + restore[key] = cur + + if not config: + return + + cfg.ethnl.channels_set(ehdr | config) + defer(cfg.ethnl.channels_set, ehdr | restore) + + def _get_irq_cpus(cfg): """ Read the list of IRQs for the device Rx queues. @@ -177,6 +198,7 @@ def test(cfg, proto_flag, ipver, grp): ] if grp: + _cap_queue_count(cfg) _check_rps_and_rfs_not_configured(cfg) if grp == "rss": irq_cpus = ",".join([str(x) for x in _get_irq_cpus(cfg)]) diff --git a/tools/testing/selftests/drivers/net/lib/py/env.py b/tools/testing/selftests/drivers/net/lib/py/env.py index e4ab99b905b1..e4acf3d8333f 100644 --- a/tools/testing/selftests/drivers/net/lib/py/env.py +++ b/tools/testing/selftests/drivers/net/lib/py/env.py @@ -159,13 +159,7 @@ class NetDrvEpEnv(NetDrvEnvBase): self.remote = Remote(kind, args, src_path) - self.addr_ipver = "6" if self.addr_v["6"] else "4" - self.addr = self.addr_v[self.addr_ipver] - self.remote_addr = self.remote_addr_v[self.addr_ipver] - - # Bracketed addresses, some commands need IPv6 to be inside [] - self.baddr = f"[{self.addr_v['6']}]" if self.addr_v["6"] else self.addr_v["4"] - self.remote_baddr = f"[{self.remote_addr_v['6']}]" if self.remote_addr_v["6"] else self.remote_addr_v["4"] + self.set_ipver("6" if self.addr_v["6"] else "4") self.ifname = self.dev['ifname'] self.ifindex = self.dev['ifindex'] @@ -252,6 +246,25 @@ class NetDrvEpEnv(NetDrvEnvBase): if not self.addr_v[ipver] or not self.remote_addr_v[ipver]: raise KsftSkipEx(f"Test requires IPv{ipver} connectivity") + def set_ipver(self, ipver): + """ + Modify the IP version used by the generic address fields. + """ + if ipver == getattr(self, "addr_ipver", None): + return + + self.require_ipver(ipver) + + self.addr_ipver = ipver + self.addr = self.addr_v[ipver] + self.remote_addr = self.remote_addr_v[ipver] + + # Bracketed addresses, some commands need IPv6 to be inside [] + self.baddr = (f"[{self.addr_v['6']}]" if ipver == "6" + else self.addr_v["4"]) + self.remote_baddr = (f"[{self.remote_addr_v['6']}]" if ipver == "6" + else self.remote_addr_v["4"]) + def require_nsim(self, nsim_test=True): """Require or exclude netdevsim for this test""" if nsim_test and self._ns is None: diff --git a/tools/testing/selftests/drivers/net/xdp.py b/tools/testing/selftests/drivers/net/xdp.py index 2ad5932299e8..0369929f3c51 100755 --- a/tools/testing/selftests/drivers/net/xdp.py +++ b/tools/testing/selftests/drivers/net/xdp.py @@ -172,25 +172,45 @@ def _test_pass(cfg, bpf_info, msg_sz): ksft_eq(stats[XDPStats.RX.value], stats[XDPStats.PASS.value], "RX and PASS stats mismatch") -def test_xdp_native_pass_sb(cfg): +_ipvers = [ + KsftNamedVariant("ipv4", "4"), + KsftNamedVariant("ipv6", "6"), +] + + +def _set_ipver_defer_restore(cfg, ipver): + old_ipver = cfg.addr_ipver + cfg.set_ipver(ipver) + defer(cfg.set_ipver, old_ipver) + + +@ksft_variants(_ipvers) +def test_xdp_native_pass_sb(cfg, ipver): """ Tests the XDP_PASS action for single buffer case. Args: cfg: Configuration object containing network settings. + ipver: IP version to use ("4" or "6"). """ + _set_ipver_defer_restore(cfg, ipver) + bpf_info = BPFProgInfo("xdp_prog", "xdp_native.bpf.o", "xdp", 1500) _test_pass(cfg, bpf_info, 256) -def test_xdp_native_pass_mb(cfg): +@ksft_variants(_ipvers) +def test_xdp_native_pass_mb(cfg, ipver): """ Tests the XDP_PASS action for a multi-buff size. Args: cfg: Configuration object containing network settings. + ipver: IP version to use ("4" or "6"). """ + _set_ipver_defer_restore(cfg, ipver) + bpf_info = BPFProgInfo("xdp_prog_frags", "xdp_native.bpf.o", "xdp.frags", 9000) _test_pass(cfg, bpf_info, 8000) @@ -219,25 +239,33 @@ def _test_drop(cfg, bpf_info, msg_sz): ksft_eq(stats[XDPStats.RX.value], stats[XDPStats.DROP.value], "RX and DROP stats mismatch") -def test_xdp_native_drop_sb(cfg): +@ksft_variants(_ipvers) +def test_xdp_native_drop_sb(cfg, ipver): """ Tests the XDP_DROP action for a signle-buff case. Args: cfg: Configuration object containing network settings. + ipver: IP version to use ("4" or "6"). """ + _set_ipver_defer_restore(cfg, ipver) + bpf_info = BPFProgInfo("xdp_prog", "xdp_native.bpf.o", "xdp", 1500) _test_drop(cfg, bpf_info, 256) -def test_xdp_native_drop_mb(cfg): +@ksft_variants(_ipvers) +def test_xdp_native_drop_mb(cfg, ipver): """ Tests the XDP_DROP action for a multi-buff case. Args: cfg: Configuration object containing network settings. + ipver: IP version to use ("4" or "6"). """ + _set_ipver_defer_restore(cfg, ipver) + bpf_info = BPFProgInfo("xdp_prog_frags", "xdp_native.bpf.o", "xdp.frags", 9000) _test_drop(cfg, bpf_info, 8000) @@ -287,13 +315,17 @@ def _test_xdp_native_tx(cfg, bpf_info, payload_lens): ksft_eq(stats[XDPStats.TX.value], expected_pkts, "TX stats mismatch") -def test_xdp_native_tx_sb(cfg): +@ksft_variants(_ipvers) +def test_xdp_native_tx_sb(cfg, ipver): """ Tests the XDP_TX action for a single-buff case. Args: cfg: Configuration object containing network settings. + ipver: IP version to use ("4" or "6"). """ + _set_ipver_defer_restore(cfg, ipver) + bpf_info = BPFProgInfo("xdp_prog", "xdp_native.bpf.o", "xdp", 1500) # Ensure there's enough room for an ETH / IP / UDP header @@ -302,13 +334,17 @@ def test_xdp_native_tx_sb(cfg): _test_xdp_native_tx(cfg, bpf_info, [0, 1500 // 2, 1500 - pkt_hdr_len]) -def test_xdp_native_tx_mb(cfg): +@ksft_variants(_ipvers) +def test_xdp_native_tx_mb(cfg, ipver): """ Tests the XDP_TX action for a multi-buff case. Args: cfg: Configuration object containing network settings. + ipver: IP version to use ("4" or "6"). """ + _set_ipver_defer_restore(cfg, ipver) + bpf_info = BPFProgInfo("xdp_prog_frags", "xdp_native.bpf.o", "xdp.frags", 9000) # The first packet ensures we exercise the fragmented code path. @@ -447,13 +483,17 @@ def _test_xdp_native_tail_adjst(cfg, pkt_sz_lst, offset_lst): return {"status": "pass"} -def test_xdp_native_adjst_tail_grow_data(cfg): +@ksft_variants(_ipvers) +def test_xdp_native_adjst_tail_grow_data(cfg, ipver): """ Tests the XDP tail adjustment by growing packet data. Args: cfg: Configuration object containing network settings. + ipver: IP version to use ("4" or "6"). """ + _set_ipver_defer_restore(cfg, ipver) + pkt_sz_lst = [512, 1024, 2048] offset_lst = [1, 16, 32, 64, 128, 256] res = _test_xdp_native_tail_adjst( @@ -465,13 +505,17 @@ def test_xdp_native_adjst_tail_grow_data(cfg): _validate_res(res, offset_lst, pkt_sz_lst) -def test_xdp_native_adjst_tail_shrnk_data(cfg): +@ksft_variants(_ipvers) +def test_xdp_native_adjst_tail_shrnk_data(cfg, ipver): """ Tests the XDP tail adjustment by shrinking packet data. Args: cfg: Configuration object containing network settings. + ipver: IP version to use ("4" or "6"). """ + _set_ipver_defer_restore(cfg, ipver) + pkt_sz_lst = [512, 1024, 2048] offset_lst = [-16, -32, -64, -128, -256] res = _test_xdp_native_tail_adjst( @@ -535,7 +579,7 @@ def _test_xdp_native_head_adjst(cfg, prog, pkt_sz_lst, offset_lst): # after we eat into it. We send large-enough packets, but if HDS # is enabled head will only contain headers. Don't try to eat # more than 28 bytes (UDPv4 + eth hdr left: (14 + 20 + 8) - 14) - l2_cut_off = 28 if cfg.addr_ipver == 4 else 48 + l2_cut_off = 28 if cfg.addr_ipver == "4" else 48 if pkt_sz > hds_thresh and offset > l2_cut_off: ksft_pr( f"Failed run: pkt_sz ({pkt_sz}) > HDS threshold ({hds_thresh}) and " @@ -579,18 +623,22 @@ def _test_xdp_native_head_adjst(cfg, prog, pkt_sz_lst, offset_lst): return {"status": "pass"} -def test_xdp_native_adjst_head_grow_data(cfg): +@ksft_variants(_ipvers) +def test_xdp_native_adjst_head_grow_data(cfg, ipver): """ Tests the XDP headroom growth support. Args: cfg: Configuration object containing network settings. + ipver: IP version to use ("4" or "6"). This function sets up the packet size and offset lists, then calls the _test_xdp_native_head_adjst_mb function to perform the actual test. The test is passed if the headroom is successfully extended for given packet sizes and offsets. """ + _set_ipver_defer_restore(cfg, ipver) + pkt_sz_lst = [512, 1024, 2048] # Negative values result in headroom shrinking, resulting in growing of payload @@ -600,18 +648,22 @@ def test_xdp_native_adjst_head_grow_data(cfg): _validate_res(res, offset_lst, pkt_sz_lst) -def test_xdp_native_adjst_head_shrnk_data(cfg): +@ksft_variants(_ipvers) +def test_xdp_native_adjst_head_shrnk_data(cfg, ipver): """ Tests the XDP headroom shrinking support. Args: cfg: Configuration object containing network settings. + ipver: IP version to use ("4" or "6"). This function sets up the packet size and offset lists, then calls the _test_xdp_native_head_adjst_mb function to perform the actual test. The test is passed if the headroom is successfully shrunk for given packet sizes and offsets. """ + _set_ipver_defer_restore(cfg, ipver) + pkt_sz_lst = [512, 1024, 2048] # Positive values result in headroom growing, resulting in shrinking of payload @@ -621,12 +673,19 @@ def test_xdp_native_adjst_head_shrnk_data(cfg): _validate_res(res, offset_lst, pkt_sz_lst) -@ksft_variants([ - KsftNamedVariant("pass", XDPAction.PASS), - KsftNamedVariant("drop", XDPAction.DROP), - KsftNamedVariant("tx", XDPAction.TX), -]) -def test_xdp_native_qstats(cfg, act): +def _qstats_variants(): + actions = [ + ("pass", XDPAction.PASS), + ("drop", XDPAction.DROP), + ("tx", XDPAction.TX), + ] + for ipver in ["4", "6"]: + for name, act in actions: + yield KsftNamedVariant(f"{name}_ipv{ipver}", act, ipver) + + +@ksft_variants(_qstats_variants()) +def test_xdp_native_qstats(cfg, act, ipver): """ Send 1000 messages. Expect XDP action specified in @act. Make sure the packets were counted to interface level qstats @@ -634,6 +693,7 @@ def test_xdp_native_qstats(cfg, act): """ cfg.require_cmd("socat") + _set_ipver_defer_restore(cfg, ipver) bpf_info = BPFProgInfo("xdp_prog", "xdp_native.bpf.o", "xdp", 1500) prog_info = _load_xdp_prog(cfg, bpf_info) |
