xref: /linux/tools/testing/selftests/drivers/net/hw/nic_link_layer.py (revision 7f71507851fc7764b36a3221839607d3a45c2025)
1#!/usr/bin/env python3
2# SPDX-License-Identifier: GPL-2.0
3
4#Introduction:
5#This file has basic link layer tests for generic NIC drivers.
6#The test comprises of auto-negotiation, speed and duplex checks.
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#Required minimum ethtool version is 6.10 (supports json)
25#Default values:
26#time_delay = 8 #time taken to wait for transitions to happen, in seconds.
27
28import time
29import argparse
30from lib.py import ksft_run, ksft_exit, ksft_pr, ksft_eq
31from lib.py import KsftFailEx, KsftSkipEx
32from lib.py import NetDrvEpEnv
33from lib.py import LinkConfig
34
35def _pre_test_checks(cfg: object, link_config: LinkConfig) -> None:
36    if link_config.partner_netif is None:
37        KsftSkipEx("Partner interface is not available")
38    if not link_config.check_autoneg_supported() or not link_config.check_autoneg_supported(remote=True):
39        KsftSkipEx(f"Auto-negotiation not supported for interface {cfg.ifname} or {link_config.partner_netif}")
40    if not link_config.verify_link_up():
41        raise KsftSkipEx(f"Link state of interface {cfg.ifname} is DOWN")
42
43def verify_autonegotiation(cfg: object, expected_state: str, link_config: LinkConfig) -> None:
44    if not link_config.verify_link_up():
45        raise KsftSkipEx(f"Link state of interface {cfg.ifname} is DOWN")
46    """Verifying the autonegotiation state in partner"""
47    partner_autoneg_output = link_config.get_ethtool_field("auto-negotiation", remote=True)
48    if partner_autoneg_output is None:
49        KsftSkipEx(f"Auto-negotiation state not available for interface {link_config.partner_netif}")
50    partner_autoneg_state = "on" if partner_autoneg_output is True else "off"
51
52    ksft_eq(partner_autoneg_state, expected_state)
53
54    """Verifying the autonegotiation state of local"""
55    autoneg_output = link_config.get_ethtool_field("auto-negotiation")
56    if autoneg_output is None:
57        KsftSkipEx(f"Auto-negotiation state not available for interface {cfg.ifname}")
58    actual_state = "on" if autoneg_output is True else "off"
59
60    ksft_eq(actual_state, expected_state)
61
62    """Verifying the link establishment"""
63    link_available = link_config.get_ethtool_field("link-detected")
64    if link_available is None:
65        KsftSkipEx(f"Link status not available for interface {cfg.ifname}")
66    if link_available != True:
67        raise KsftSkipEx("Link not established at interface {cfg.ifname} after changing auto-negotiation")
68
69def test_autonegotiation(cfg: object, link_config: LinkConfig, time_delay: int) -> None:
70    _pre_test_checks(cfg, link_config)
71    for state in ["off", "on"]:
72        if not link_config.set_autonegotiation_state(state, remote=True):
73            raise KsftSkipEx(f"Unable to set auto-negotiation state for interface {link_config.partner_netif}")
74        if not link_config.set_autonegotiation_state(state):
75            raise KsftSkipEx(f"Unable to set auto-negotiation state for interface {cfg.ifname}")
76        time.sleep(time_delay)
77        verify_autonegotiation(cfg, state, link_config)
78
79def test_network_speed(cfg: object, link_config: LinkConfig, time_delay: int) -> None:
80    _pre_test_checks(cfg, link_config)
81    common_link_modes = link_config.common_link_modes
82    if not common_link_modes:
83        KsftSkipEx("No common link modes exist")
84    speeds, duplex_modes = link_config.get_speed_duplex_values(common_link_modes)
85
86    if speeds and duplex_modes and len(speeds) == len(duplex_modes):
87        for idx in range(len(speeds)):
88            speed = speeds[idx]
89            duplex = duplex_modes[idx]
90            if not link_config.set_speed_and_duplex(speed, duplex):
91                raise KsftFailEx(f"Unable to set speed and duplex parameters for {cfg.ifname}")
92            time.sleep(time_delay)
93            if not link_config.verify_speed_and_duplex(speed, duplex):
94                raise KsftSkipEx(f"Error occurred while verifying speed and duplex states for interface {cfg.ifname}")
95    else:
96        if not speeds or not duplex_modes:
97            KsftSkipEx(f"No supported speeds or duplex modes found for interface {cfg.ifname}")
98        else:
99            KsftSkipEx("Mismatch in the number of speeds and duplex modes")
100
101def main() -> None:
102    parser = argparse.ArgumentParser(description="Run basic link layer tests for NIC driver")
103    parser.add_argument('--time-delay', type=int, default=8, help='Time taken to wait for transitions to happen(in seconds). Default is 8 seconds.')
104    args = parser.parse_args()
105    time_delay = args.time_delay
106    with NetDrvEpEnv(__file__, nsim_test=False) as cfg:
107        link_config = LinkConfig(cfg)
108        ksft_run(globs=globals(), case_pfx={"test_"}, args=(cfg, link_config, time_delay,))
109        link_config.reset_interface()
110    ksft_exit()
111
112if __name__ == "__main__":
113    main()
114