1#!/usr/bin/env python3 2# SPDX-License-Identifier: GPL-2.0 3 4"""Run the tools/testing/selftests/net/csum testsuite.""" 5 6from os import path 7 8from lib.py import ksft_run, ksft_exit, KsftSkipEx 9from lib.py import EthtoolFamily, NetDrvEpEnv 10from lib.py import bkg, cmd, wait_port_listen 11 12def test_receive(cfg, ipver="6", extra_args=None): 13 """Test local nic checksum receive. Remote host sends crafted packets.""" 14 if not cfg.have_rx_csum: 15 raise KsftSkipEx(f"Test requires rx checksum offload on {cfg.ifname}") 16 17 ip_args = f"-{ipver} -S {cfg.remote_addr_v[ipver]} -D {cfg.addr_v[ipver]}" 18 19 rx_cmd = f"{cfg.bin_local} -i {cfg.ifname} -n 100 {ip_args} -r 1 -R {extra_args}" 20 tx_cmd = f"{cfg.bin_remote} -i {cfg.ifname} -n 100 {ip_args} -r 1 -T {extra_args}" 21 22 with bkg(rx_cmd, exit_wait=True): 23 wait_port_listen(34000, proto="udp") 24 cmd(tx_cmd, host=cfg.remote) 25 26 27def test_transmit(cfg, ipver="6", extra_args=None): 28 """Test local nic checksum transmit. Remote host verifies packets.""" 29 if (not cfg.have_tx_csum_generic and 30 not (cfg.have_tx_csum_ipv4 and ipver == "4") and 31 not (cfg.have_tx_csum_ipv6 and ipver == "6")): 32 raise KsftSkipEx(f"Test requires tx checksum offload on {cfg.ifname}") 33 34 ip_args = f"-{ipver} -S {cfg.addr_v[ipver]} -D {cfg.remote_addr_v[ipver]}" 35 36 # Cannot randomize input when calculating zero checksum 37 if extra_args != "-U -Z": 38 extra_args += " -r 1" 39 40 rx_cmd = f"{cfg.bin_remote} -i {cfg.ifname} -L 1 -n 100 {ip_args} -R {extra_args}" 41 tx_cmd = f"{cfg.bin_local} -i {cfg.ifname} -L 1 -n 100 {ip_args} -T {extra_args}" 42 43 with bkg(rx_cmd, host=cfg.remote, exit_wait=True): 44 wait_port_listen(34000, proto="udp", host=cfg.remote) 45 cmd(tx_cmd) 46 47 48def test_builder(name, cfg, ipver="6", tx=False, extra_args=""): 49 """Construct specific tests from the common template. 50 51 Most tests follow the same basic pattern, differing only in 52 Direction of the test and optional flags passed to csum.""" 53 def f(cfg): 54 cfg.require_ipver(ipver) 55 56 if tx: 57 test_transmit(cfg, ipver, extra_args) 58 else: 59 test_receive(cfg, ipver, extra_args) 60 61 f.__name__ = f"ipv{ipver}_" + name 62 return f 63 64 65def check_nic_features(cfg) -> None: 66 """Test whether Tx and Rx checksum offload are enabled. 67 68 If the device under test has either off, then skip the relevant tests.""" 69 cfg.have_tx_csum_generic = False 70 cfg.have_tx_csum_ipv4 = False 71 cfg.have_tx_csum_ipv6 = False 72 cfg.have_rx_csum = False 73 74 ethnl = EthtoolFamily() 75 features = ethnl.features_get({"header": {"dev-index": cfg.ifindex}}) 76 for f in features["active"]["bits"]["bit"]: 77 if f["name"] == "tx-checksum-ip-generic": 78 cfg.have_tx_csum_generic = True 79 elif f["name"] == "tx-checksum-ipv4": 80 cfg.have_tx_csum_ipv4 = True 81 elif f["name"] == "tx-checksum-ipv6": 82 cfg.have_tx_csum_ipv6 = True 83 elif f["name"] == "rx-checksum": 84 cfg.have_rx_csum = True 85 86 87def main() -> None: 88 with NetDrvEpEnv(__file__, nsim_test=False) as cfg: 89 check_nic_features(cfg) 90 91 cfg.bin_local = cfg.net_lib_dir / "csum" 92 cfg.bin_remote = cfg.remote.deploy(cfg.bin_local) 93 94 cases = [] 95 for ipver in ["4", "6"]: 96 cases.append(test_builder("rx_tcp", cfg, ipver, False, "-t")) 97 cases.append(test_builder("rx_tcp_invalid", cfg, ipver, False, "-t -E")) 98 99 cases.append(test_builder("rx_udp", cfg, ipver, False, "")) 100 cases.append(test_builder("rx_udp_invalid", cfg, ipver, False, "-E")) 101 102 cases.append(test_builder("tx_udp_csum_offload", cfg, ipver, True, "-U")) 103 cases.append(test_builder("tx_udp_zero_checksum", cfg, ipver, True, "-U -Z")) 104 105 ksft_run(cases=cases, args=(cfg, )) 106 ksft_exit() 107 108 109if __name__ == "__main__": 110 main() 111