Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests: net-drv: remove the nic_performance and nic_link_layer tests

Revert fbbf93556f0c ("selftests: nic_performance: Add selftest for performance of NIC driver")
Revert c087dc54394b ("selftests: nic_link_layer: Add selftest case for speed and duplex states")
Revert 6116075e18f7 ("selftests: nic_link_layer: Add link layer selftest for NIC driver")

These tests don't clean up after themselves, don't use the disruptive
annotations, don't get included in make install etc. etc. The tests
were added before we have any "HW" runner, so the issues were missed.
Our CI doesn't have any way of excluding broken tests, remove these
for now to stop the random pollution of results due to broken env.
We can always add them back once / if fixed.

Acked-by: Stanislav Fomichev <sdf@fomichev.me>
Reviewed-by: David Wei <dw@davidwei.uk>
Link: https://patch.msgid.link/20250507140109.929801-1-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+1 -494
-2
tools/testing/selftests/drivers/net/hw/Makefile
··· 15 15 iou-zcrx.py \ 16 16 irq.py \ 17 17 loopback.sh \ 18 - nic_link_layer.py \ 19 - nic_performance.py \ 20 18 pp_alloc_fail.py \ 21 19 rss_ctx.py \ 22 20 rss_input_xfrm.py \
-1
tools/testing/selftests/drivers/net/hw/lib/py/__init__.py
··· 9 9 sys.path.append(KSFT_DIR.as_posix()) 10 10 from net.lib.py import * 11 11 from drivers.net.lib.py import * 12 - from .linkconfig import LinkConfig 13 12 except ModuleNotFoundError as e: 14 13 ksft_pr("Failed importing `net` library from kernel sources") 15 14 ksft_pr(str(e))
-222
tools/testing/selftests/drivers/net/hw/lib/py/linkconfig.py
··· 1 - # SPDX-License-Identifier: GPL-2.0 2 - 3 - from lib.py import cmd, ethtool, ip 4 - from lib.py import ksft_pr, ksft_eq, KsftSkipEx 5 - from typing import Optional 6 - import re 7 - import time 8 - import json 9 - 10 - #The LinkConfig class is implemented to handle the link layer configurations. 11 - #Required minimum ethtool version is 6.10 12 - 13 - class LinkConfig: 14 - """Class for handling the link layer configurations""" 15 - def __init__(self, cfg: object) -> None: 16 - self.cfg = cfg 17 - self.partner_netif = self.get_partner_netif_name() 18 - 19 - """Get the initial link configuration of local interface""" 20 - self.common_link_modes = self.get_common_link_modes() 21 - 22 - def get_partner_netif_name(self) -> Optional[str]: 23 - partner_netif = None 24 - try: 25 - if not self.verify_link_up(): 26 - return None 27 - """Get partner interface name""" 28 - partner_json_output = ip("addr show", json=True, host=self.cfg.remote) 29 - for interface in partner_json_output: 30 - for addr in interface.get('addr_info', []): 31 - if addr.get('local') == self.cfg.remote_addr: 32 - partner_netif = interface['ifname'] 33 - ksft_pr(f"Partner Interface name: {partner_netif}") 34 - if partner_netif is None: 35 - ksft_pr("Unable to get the partner interface name") 36 - except Exception as e: 37 - print(f"Unexpected error occurred while getting partner interface name: {e}") 38 - self.partner_netif = partner_netif 39 - return partner_netif 40 - 41 - def verify_link_up(self) -> bool: 42 - """Verify whether the local interface link is up""" 43 - with open(f"/sys/class/net/{self.cfg.ifname}/operstate", "r") as fp: 44 - link_state = fp.read().strip() 45 - 46 - if link_state == "down": 47 - ksft_pr(f"Link state of interface {self.cfg.ifname} is DOWN") 48 - return False 49 - else: 50 - return True 51 - 52 - def reset_interface(self, local: bool = True, remote: bool = True) -> bool: 53 - ksft_pr("Resetting interfaces in local and remote") 54 - if remote: 55 - if self.verify_link_up(): 56 - if self.partner_netif is not None: 57 - ifname = self.partner_netif 58 - link_up_cmd = f"ip link set up {ifname}" 59 - link_down_cmd = f"ip link set down {ifname}" 60 - reset_cmd = f"{link_down_cmd} && sleep 5 && {link_up_cmd}" 61 - try: 62 - cmd(reset_cmd, host=self.cfg.remote) 63 - except Exception as e: 64 - ksft_pr(f"Unexpected error occurred while resetting remote: {e}") 65 - else: 66 - ksft_pr("Partner interface not available") 67 - if local: 68 - ifname = self.cfg.ifname 69 - link_up_cmd = f"ip link set up {ifname}" 70 - link_down_cmd = f"ip link set down {ifname}" 71 - reset_cmd = f"{link_down_cmd} && sleep 5 && {link_up_cmd}" 72 - try: 73 - cmd(reset_cmd) 74 - except Exception as e: 75 - ksft_pr(f"Unexpected error occurred while resetting local: {e}") 76 - time.sleep(10) 77 - if self.verify_link_up() and self.get_ethtool_field("link-detected"): 78 - ksft_pr("Local and remote interfaces reset to original state") 79 - return True 80 - else: 81 - ksft_pr("Error occurred after resetting interfaces. Link is DOWN.") 82 - return False 83 - 84 - def set_speed_and_duplex(self, speed: str, duplex: str, autoneg: bool = True) -> bool: 85 - """Set the speed and duplex state for the interface""" 86 - autoneg_state = "on" if autoneg is True else "off" 87 - process = None 88 - try: 89 - process = ethtool(f"--change {self.cfg.ifname} speed {speed} duplex {duplex} autoneg {autoneg_state}") 90 - except Exception as e: 91 - ksft_pr(f"Unexpected error occurred while setting speed/duplex: {e}") 92 - if process is None or process.ret != 0: 93 - return False 94 - else: 95 - ksft_pr(f"Speed: {speed} Mbps, Duplex: {duplex} set for Interface: {self.cfg.ifname}") 96 - return True 97 - 98 - def verify_speed_and_duplex(self, expected_speed: str, expected_duplex: str) -> bool: 99 - if not self.verify_link_up(): 100 - return False 101 - """Verifying the speed and duplex state for the interface""" 102 - with open(f"/sys/class/net/{self.cfg.ifname}/speed", "r") as fp: 103 - actual_speed = fp.read().strip() 104 - with open(f"/sys/class/net/{self.cfg.ifname}/duplex", "r") as fp: 105 - actual_duplex = fp.read().strip() 106 - 107 - ksft_eq(actual_speed, expected_speed) 108 - ksft_eq(actual_duplex, expected_duplex) 109 - return True 110 - 111 - def set_autonegotiation_state(self, state: str, remote: bool = False) -> bool: 112 - common_link_modes = self.common_link_modes 113 - speeds, duplex_modes = self.get_speed_duplex_values(self.common_link_modes) 114 - speed = speeds[0] 115 - duplex = duplex_modes[0] 116 - if not speed or not duplex: 117 - ksft_pr("No speed or duplex modes found") 118 - return False 119 - 120 - speed_duplex_cmd = f"speed {speed} duplex {duplex}" if state == "off" else "" 121 - if remote: 122 - if not self.verify_link_up(): 123 - return False 124 - """Set the autonegotiation state for the partner""" 125 - command = f"-s {self.partner_netif} {speed_duplex_cmd} autoneg {state}" 126 - partner_autoneg_change = None 127 - """Set autonegotiation state for interface in remote pc""" 128 - try: 129 - partner_autoneg_change = ethtool(command, host=self.cfg.remote) 130 - except Exception as e: 131 - ksft_pr(f"Unexpected error occurred while changing auto-neg in remote: {e}") 132 - if partner_autoneg_change is None or partner_autoneg_change.ret != 0: 133 - ksft_pr(f"Not able to set autoneg parameter for interface {self.partner_netif}.") 134 - return False 135 - ksft_pr(f"Autoneg set as {state} for {self.partner_netif}") 136 - else: 137 - """Set the autonegotiation state for the interface""" 138 - try: 139 - process = ethtool(f"-s {self.cfg.ifname} {speed_duplex_cmd} autoneg {state}") 140 - if process.ret != 0: 141 - ksft_pr(f"Not able to set autoneg parameter for interface {self.cfg.ifname}") 142 - return False 143 - except Exception as e: 144 - ksft_pr(f"Unexpected error occurred while changing auto-neg in local: {e}") 145 - return False 146 - ksft_pr(f"Autoneg set as {state} for {self.cfg.ifname}") 147 - return True 148 - 149 - def check_autoneg_supported(self, remote: bool = False) -> bool: 150 - if not remote: 151 - local_autoneg = self.get_ethtool_field("supports-auto-negotiation") 152 - if local_autoneg is None: 153 - ksft_pr(f"Unable to fetch auto-negotiation status for interface {self.cfg.ifname}") 154 - """Return autoneg status of the local interface""" 155 - return local_autoneg 156 - else: 157 - if not self.verify_link_up(): 158 - raise KsftSkipEx("Link is DOWN") 159 - """Check remote auto-negotiation support status""" 160 - partner_autoneg = False 161 - if self.partner_netif is not None: 162 - partner_autoneg = self.get_ethtool_field("supports-auto-negotiation", remote=True) 163 - if partner_autoneg is None: 164 - ksft_pr(f"Unable to fetch auto-negotiation status for interface {self.partner_netif}") 165 - return partner_autoneg 166 - 167 - def get_common_link_modes(self) -> set[str]: 168 - common_link_modes = [] 169 - """Populate common link modes""" 170 - link_modes = self.get_ethtool_field("supported-link-modes") 171 - partner_link_modes = self.get_ethtool_field("link-partner-advertised-link-modes") 172 - if link_modes is None: 173 - raise KsftSkipEx(f"Link modes not available for {self.cfg.ifname}") 174 - if partner_link_modes is None: 175 - raise KsftSkipEx(f"Partner link modes not available for {self.cfg.ifname}") 176 - common_link_modes = set(link_modes) and set(partner_link_modes) 177 - return common_link_modes 178 - 179 - def get_speed_duplex_values(self, link_modes: list[str]) -> tuple[list[str], list[str]]: 180 - speed = [] 181 - duplex = [] 182 - """Check the link modes""" 183 - for data in link_modes: 184 - parts = data.split('/') 185 - speed_value = re.match(r'\d+', parts[0]) 186 - if speed_value: 187 - speed.append(speed_value.group()) 188 - else: 189 - ksft_pr(f"No speed value found for interface {self.ifname}") 190 - return None, None 191 - duplex.append(parts[1].lower()) 192 - return speed, duplex 193 - 194 - def get_ethtool_field(self, field: str, remote: bool = False) -> Optional[str]: 195 - process = None 196 - if not remote: 197 - """Get the ethtool field value for the local interface""" 198 - try: 199 - process = ethtool(self.cfg.ifname, json=True) 200 - except Exception as e: 201 - ksft_pr("Required minimum ethtool version is 6.10") 202 - ksft_pr(f"Unexpected error occurred while getting ethtool field in local: {e}") 203 - return None 204 - else: 205 - if not self.verify_link_up(): 206 - return None 207 - """Get the ethtool field value for the remote interface""" 208 - self.cfg.require_cmd("ethtool", remote=True) 209 - if self.partner_netif is None: 210 - ksft_pr(f"Partner interface name is unavailable.") 211 - return None 212 - try: 213 - process = ethtool(self.partner_netif, json=True, host=self.cfg.remote) 214 - except Exception as e: 215 - ksft_pr("Required minimum ethtool version is 6.10") 216 - ksft_pr(f"Unexpected error occurred while getting ethtool field in remote: {e}") 217 - return None 218 - json_data = process[0] 219 - """Check if the field exist in the json data""" 220 - if field not in json_data: 221 - raise KsftSkipEx(f'Field {field} does not exist in the output of interface {json_data["ifname"]}') 222 - return json_data[field]
-137
tools/testing/selftests/drivers/net/hw/nic_performance.py
··· 1 - #!/usr/bin/env python3 2 - # SPDX-License-Identifier: GPL-2.0 3 - 4 - #Introduction: 5 - #This file has basic performance test for generic NIC drivers. 6 - #The test comprises of throughput check for TCP and UDP streams. 7 - # 8 - #Setup: 9 - #Connect the DUT PC with NIC card to partner pc back via ethernet medium of your choice(RJ45, T1) 10 - # 11 - # DUT PC Partner PC 12 - #┌───────────────────────┐ ┌──────────────────────────┐ 13 - #│ │ │ │ 14 - #│ │ │ │ 15 - #│ ┌───────────┐ │ │ 16 - #│ │DUT NIC │ Eth │ │ 17 - #│ │Interface ─┼─────────────────────────┼─ any eth Interface │ 18 - #│ └───────────┘ │ │ 19 - #│ │ │ │ 20 - #│ │ │ │ 21 - #└───────────────────────┘ └──────────────────────────┘ 22 - # 23 - #Configurations: 24 - #To prevent interruptions, Add ethtool, ip to the sudoers list in remote PC and get the ssh key from remote. 25 - #Required minimum ethtool version is 6.10 26 - #Change the below configuration based on your hw needs. 27 - # """Default values""" 28 - #time_delay = 8 #time taken to wait for transitions to happen, in seconds. 29 - #test_duration = 10 #performance test duration for the throughput check, in seconds. 30 - #send_throughput_threshold = 80 #percentage of send throughput required to pass the check 31 - #receive_throughput_threshold = 50 #percentage of receive throughput required to pass the check 32 - 33 - import time 34 - import json 35 - import argparse 36 - from lib.py import ksft_run, ksft_exit, ksft_pr, ksft_true 37 - from lib.py import KsftFailEx, KsftSkipEx, GenerateTraffic 38 - from lib.py import NetDrvEpEnv, bkg, wait_port_listen 39 - from lib.py import cmd 40 - from lib.py import LinkConfig 41 - 42 - class TestConfig: 43 - def __init__(self, time_delay: int, test_duration: int, send_throughput_threshold: int, receive_throughput_threshold: int) -> None: 44 - self.time_delay = time_delay 45 - self.test_duration = test_duration 46 - self.send_throughput_threshold = send_throughput_threshold 47 - self.receive_throughput_threshold = receive_throughput_threshold 48 - 49 - def _pre_test_checks(cfg: object, link_config: LinkConfig) -> None: 50 - if not link_config.verify_link_up(): 51 - KsftSkipEx(f"Link state of interface {cfg.ifname} is DOWN") 52 - common_link_modes = link_config.common_link_modes 53 - if common_link_modes is None: 54 - KsftSkipEx("No common link modes found") 55 - if link_config.partner_netif == None: 56 - KsftSkipEx("Partner interface is not available") 57 - if link_config.check_autoneg_supported(): 58 - KsftSkipEx("Auto-negotiation not supported by local") 59 - if link_config.check_autoneg_supported(remote=True): 60 - KsftSkipEx("Auto-negotiation not supported by remote") 61 - cfg.require_cmd("iperf3", remote=True) 62 - 63 - def check_throughput(cfg: object, link_config: LinkConfig, test_config: TestConfig, protocol: str, traffic: GenerateTraffic) -> None: 64 - common_link_modes = link_config.common_link_modes 65 - speeds, duplex_modes = link_config.get_speed_duplex_values(common_link_modes) 66 - """Test duration in seconds""" 67 - duration = test_config.test_duration 68 - 69 - ksft_pr(f"{protocol} test") 70 - test_type = "-u" if protocol == "UDP" else "" 71 - 72 - send_throughput = [] 73 - receive_throughput = [] 74 - for idx in range(0, len(speeds)): 75 - if link_config.set_speed_and_duplex(speeds[idx], duplex_modes[idx]) == False: 76 - raise KsftFailEx(f"Not able to set speed and duplex parameters for {cfg.ifname}") 77 - time.sleep(test_config.time_delay) 78 - if not link_config.verify_link_up(): 79 - raise KsftSkipEx(f"Link state of interface {cfg.ifname} is DOWN") 80 - 81 - send_command=f"{test_type} -b 0 -t {duration} --json" 82 - receive_command=f"{test_type} -b 0 -t {duration} --reverse --json" 83 - 84 - send_result = traffic.run_remote_test(cfg, command=send_command) 85 - if send_result.ret != 0: 86 - raise KsftSkipEx("Error occurred during data transmit: {send_result.stdout}") 87 - 88 - send_output = send_result.stdout 89 - send_data = json.loads(send_output) 90 - 91 - """Convert throughput to Mbps""" 92 - send_throughput.append(round(send_data['end']['sum_sent']['bits_per_second'] / 1e6, 2)) 93 - ksft_pr(f"{protocol}: Send throughput: {send_throughput[idx]} Mbps") 94 - 95 - receive_result = traffic.run_remote_test(cfg, command=receive_command) 96 - if receive_result.ret != 0: 97 - raise KsftSkipEx("Error occurred during data receive: {receive_result.stdout}") 98 - 99 - receive_output = receive_result.stdout 100 - receive_data = json.loads(receive_output) 101 - 102 - """Convert throughput to Mbps""" 103 - receive_throughput.append(round(receive_data['end']['sum_received']['bits_per_second'] / 1e6, 2)) 104 - ksft_pr(f"{protocol}: Receive throughput: {receive_throughput[idx]} Mbps") 105 - 106 - """Check whether throughput is not below the threshold (default values set at start)""" 107 - for idx in range(0, len(speeds)): 108 - send_threshold = float(speeds[idx]) * float(test_config.send_throughput_threshold / 100) 109 - receive_threshold = float(speeds[idx]) * float(test_config.receive_throughput_threshold / 100) 110 - ksft_true(send_throughput[idx] >= send_threshold, f"{protocol}: Send throughput is below threshold for {speeds[idx]} Mbps in {duplex_modes[idx]} duplex") 111 - ksft_true(receive_throughput[idx] >= receive_threshold, f"{protocol}: Receive throughput is below threshold for {speeds[idx]} Mbps in {duplex_modes[idx]} duplex") 112 - 113 - def test_tcp_throughput(cfg: object, link_config: LinkConfig, test_config: TestConfig, traffic: GenerateTraffic) -> None: 114 - _pre_test_checks(cfg, link_config) 115 - check_throughput(cfg, link_config, test_config, 'TCP', traffic) 116 - 117 - def test_udp_throughput(cfg: object, link_config: LinkConfig, test_config: TestConfig, traffic: GenerateTraffic) -> None: 118 - _pre_test_checks(cfg, link_config) 119 - check_throughput(cfg, link_config, test_config, 'UDP', traffic) 120 - 121 - def main() -> None: 122 - parser = argparse.ArgumentParser(description="Run basic performance test for NIC driver") 123 - parser.add_argument('--time-delay', type=int, default=8, help='Time taken to wait for transitions to happen(in seconds). Default is 8 seconds.') 124 - parser.add_argument('--test-duration', type=int, default=10, help='Performance test duration for the throughput check, in seconds. Default is 10 seconds.') 125 - parser.add_argument('--stt', type=int, default=80, help='Send throughput Threshold: Percentage of send throughput upon actual throughput required to pass the throughput check (in percentage). Default is 80.') 126 - parser.add_argument('--rtt', type=int, default=50, help='Receive throughput Threshold: Percentage of receive throughput upon actual throughput required to pass the throughput check (in percentage). Default is 50.') 127 - args=parser.parse_args() 128 - test_config = TestConfig(args.time_delay, args.test_duration, args.stt, args.rtt) 129 - with NetDrvEpEnv(__file__, nsim_test=False) as cfg: 130 - traffic = GenerateTraffic(cfg) 131 - link_config = LinkConfig(cfg) 132 - ksft_run(globs=globals(), case_pfx={"test_"}, args=(cfg, link_config, test_config, traffic, )) 133 - link_config.reset_interface() 134 - ksft_exit() 135 - 136 - if __name__ == "__main__": 137 - main()
+1 -19
tools/testing/selftests/drivers/net/lib/py/load.py
··· 2 2 3 3 import time 4 4 5 - from lib.py import ksft_pr, cmd, ip, rand_port, wait_port_listen, bkg 5 + from lib.py import ksft_pr, cmd, ip, rand_port, wait_port_listen 6 6 7 7 class GenerateTraffic: 8 8 def __init__(self, env, port=None): ··· 22 22 if not self._wait_pkts(pps=1000): 23 23 self.stop(verbose=True) 24 24 raise Exception("iperf3 traffic did not ramp up") 25 - 26 - def run_remote_test(self, env: object, port=None, command=None): 27 - if port is None: 28 - port = rand_port() 29 - try: 30 - server_cmd = f"iperf3 -s 1 -p {port} --one-off" 31 - with bkg(server_cmd, host=env.remote): 32 - #iperf3 opens TCP connection as default in server 33 - #-u to be specified in client command for UDP 34 - wait_port_listen(port, host=env.remote) 35 - except Exception as e: 36 - raise Exception(f"Unexpected error occurred while running server command: {e}") 37 - try: 38 - client_cmd = f"iperf3 -c {env.remote_addr} -p {port} {command}" 39 - proc = cmd(client_cmd) 40 - return proc 41 - except Exception as e: 42 - raise Exception(f"Unexpected error occurred while running client command: {e}") 43 25 44 26 def _wait_pkts(self, pkt_cnt=None, pps=None): 45 27 """