On Tue, Sep 17, 2024 at 08:04:07AM +0530, Mohan Prasad J wrote:
Add selftest file to test basic features of a NIC driver. Tests for link modes, auto-negotiation are placed. Selftest makes use of ksft modules and ethtool. Add selftest file in the Makefile.
Thanks for reworking this.
+++ b/tools/testing/selftests/drivers/net/hw/nic_basic_tests.py @@ -0,0 +1,145 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0
+#Introduction: +#This file has basic tests for generic NIC drivers. +#The test comprises of auto-negotiation, speed and duplex checks. +#Also has tests to check the throughput +# +#Setup: +#Connect the DUT PC with NIC card to partner pc back via ethernet medium of your choice(RJ45, T1) +# +# DUT PC Partner PC +#┌───────────────────────┐ ┌──────────────────────────┐ +#│ │ │ │ +#│ │ │ │ +#│ ┌───────────┐ │ │ +#│ │DUT NIC │ Eth │ │ +#│ │Interface ─┼─────────────────────────┼─ any eth Interface │ +#│ └───────────┘ │ │ +#│ │ │ │ +#│ │ │ │ +#└───────────────────────┘ └──────────────────────────┘ +# +#Configurations: +# Change the below configuration based on your hw needs. +# """Default values""" +sleep_time = 5 #time taken to wait for transitions to happen, in seconds. +test_duration = 5 #performance test duration for the throughput check, in seconds. +throughput_threshold = 0.8 #percentage of throughput required to pass the throughput
+import time +import os +import re +import configparser +import json +from lib.py import ksft_run, ksft_exit, ksft_pr, ksft_eq +from lib.py import KsftFailEx, KsftSkipEx +from lib.py import NetDrvEpEnv +from lib.py import cmd +from lib.py import ethtool
+"""Global variables""" +common_link_modes = []
+def get_ethtool_content(ifname: str, field: str):
- capture = False
- content = []
- """Get the ethtool content for the interface"""
- process = ethtool(f"{ifname}")
- if process.ret != 0:
raise KsftSkipEx(f"Error while getting the ethtool content for interface {ifname}")
- lines = process.stdout.splitlines()
- """Retrieve the content of the field"""
- for line in lines:
if field in line:
capture = True
data = line.split(":")[1].strip()
content.extend(data.split())
continue
Since you have batteries included python:
ethtool --json enp2s0 [sudo] password for andrew: [ { "ifname": "enp2s0", "supported-ports": [ "TP","MII" ], "supported-link-modes": [ "10baseT/Half","10baseT/Full","100baseT/Half","100baseT/Full","1000baseT/Full" ], "supported-pause-frame-use": "Symmetric Receive-only", "supports-auto-negotiation": true, "supported-fec-modes": [ ], "advertised-link-modes": [ "10baseT/Half","10baseT/Full","100baseT/Half","100baseT/Full","1000baseT/Full" ], "advertised-pause-frame-use": "Symmetric Receive-only", "advertised-auto-negotiation": true, "advertised-fec-modes": [ ], "auto-negotiation": false, "master-slave-cfg": "preferred slave", "master-slave-status": "unknown", "port": "Twisted Pair", "phyad": 0, "transceiver": "external", "supports-wake-on": "pumbg", "wake-on": "d", "link-detected": false } ]
You can use a json library to do all the parsing for you.
+def get_speed_duplex(content):
- speed = []
- duplex = []
- """Check the link modes"""
- for data in content:
parts = data.split('/')
speed_value = re.match(r'\d+', parts[0])
if speed_value:
speed.append(speed_value.group())
else:
raise KsftSkipEx(f"No speed value found for interface {ifname}")
duplex.append(parts[1].lower())
- return speed, duplex
+def verify_link_up(ifname: str) -> None:
- """Verify whether the link is up"""
- with open(f"/sys/class/net/{ifname}/operstate", "r") as fp:
link_state = fp.read().strip()
- if link_state == "down":
raise KsftSkipEx(f"Link state of interface {ifname} is DOWN")
+def set_autonegotiation_state(ifname: str, state: str) -> None:
- content = get_ethtool_content(ifname, "Supported link modes:")
- speeds, duplex_modes = get_speed_duplex(content)
- speed = speeds[0]
- duplex = duplex_modes[0]
- if not speed or not duplex:
KsftSkipEx("No speed or duplex modes found")
- """Set the autonegotiation state for the interface"""
- process = ethtool(f"-s {ifname} speed {speed} duplex {duplex} autoneg {state}")
- if process.ret != 0:
raise KsftFailEx(f"Not able to set autoneg parameter for {ifname}")
- ksft_pr(f"Autoneg set as {state} for {ifname}")
+def verify_autonegotiation(ifname: str, expected_state: str) -> None:
- verify_link_up(ifname)
- """Verifying the autonegotiation state"""
- output = get_ethtool_content(ifname, "Auto-negotiation:")
- actual_state = output[0]
- ksft_eq(actual_state, expected_state)
+def test_link_modes(cfg) -> None:
- global common_link_modes
- link_modes = get_ethtool_content(cfg.ifname, "Supported link modes:")
- partner_link_modes = get_ethtool_content(cfg.ifname, "Link partner advertised link modes:")
- if link_modes and partner_link_modes:
for idx1 in range(len(link_modes)):
for idx2 in range(len(partner_link_modes)):
if link_modes[idx1] == partner_link_modes[idx2]:
common_link_modes.append(link_modes[idx1])
break
- else:
raise KsftFailEx("No link modes available")
+def test_autonegotiation(cfg) -> None:
- autoneg = get_ethtool_content(cfg.ifname, "Supports auto-negotiation:")
- if autoneg[0] == "Yes":
for state in ["off", "on"]:
set_autonegotiation_state(cfg.ifname, state)
time.sleep(sleep_time)
One thing you could do here is look at "advertised-link-modes". You would expect it to list a single mode, matching the speed/duplex you requested.
Andrew