xref: /linux/tools/testing/selftests/drivers/net/napi_threaded.py (revision 63467137ecc0ff6f804d53903ad87a2f0397a18b)
1#!/usr/bin/env python3
2# SPDX-License-Identifier: GPL-2.0
3
4"""
5Test napi threaded states.
6"""
7
8from lib.py import ksft_run, ksft_exit
9from lib.py import ksft_eq, ksft_ne, ksft_ge
10from lib.py import NetDrvEnv, NetdevFamily
11from lib.py import cmd, defer, ethtool
12
13
14def _assert_napi_threaded_enabled(nl, napi_id) -> None:
15    napi = nl.napi_get({'id': napi_id})
16    ksft_eq(napi['threaded'], 'enabled')
17    ksft_ne(napi.get('pid'), None)
18
19
20def _assert_napi_threaded_disabled(nl, napi_id) -> None:
21    napi = nl.napi_get({'id': napi_id})
22    ksft_eq(napi['threaded'], 'disabled')
23    ksft_eq(napi.get('pid'), None)
24
25
26def _set_threaded_state(cfg, threaded) -> None:
27    cmd(f"echo {threaded} > /sys/class/net/{cfg.ifname}/threaded")
28
29
30def _setup_deferred_cleanup(cfg) -> None:
31    combined = ethtool(f"-l {cfg.ifname}", json=True)[0].get("combined", 0)
32    ksft_ge(combined, 2)
33    defer(ethtool, f"-L {cfg.ifname} combined {combined}")
34
35    threaded = cmd(f"cat /sys/class/net/{cfg.ifname}/threaded").stdout
36    defer(_set_threaded_state, cfg, threaded)
37
38    return combined
39
40
41def enable_dev_threaded_disable_napi_threaded(cfg, nl) -> None:
42    """
43    Test that when napi threaded is enabled at device level and
44    then disabled at napi level for one napi, the threaded state
45    of all napis is preserved after a change in number of queues.
46    """
47
48    napis = nl.napi_get({'ifindex': cfg.ifindex}, dump=True)
49    ksft_ge(len(napis), 2)
50
51    napi0_id = napis[0]['id']
52    napi1_id = napis[1]['id']
53
54    qcnt = _setup_deferred_cleanup(cfg)
55
56    # set threaded
57    _set_threaded_state(cfg, 1)
58
59    # check napi threaded is set for both napis
60    _assert_napi_threaded_enabled(nl, napi0_id)
61    _assert_napi_threaded_enabled(nl, napi1_id)
62
63    # disable threaded for napi1
64    nl.napi_set({'id': napi1_id, 'threaded': 'disabled'})
65
66    cmd(f"ethtool -L {cfg.ifname} combined 1")
67    cmd(f"ethtool -L {cfg.ifname} combined {qcnt}")
68    _assert_napi_threaded_enabled(nl, napi0_id)
69    _assert_napi_threaded_disabled(nl, napi1_id)
70
71
72def change_num_queues(cfg, nl) -> None:
73    """
74    Test that when napi threaded is enabled at device level,
75    the napi threaded state is preserved after a change in
76    number of queues.
77    """
78
79    napis = nl.napi_get({'ifindex': cfg.ifindex}, dump=True)
80    ksft_ge(len(napis), 2)
81
82    napi0_id = napis[0]['id']
83    napi1_id = napis[1]['id']
84
85    qcnt = _setup_deferred_cleanup(cfg)
86
87    # set threaded
88    _set_threaded_state(cfg, 1)
89
90    # check napi threaded is set for both napis
91    _assert_napi_threaded_enabled(nl, napi0_id)
92    _assert_napi_threaded_enabled(nl, napi1_id)
93
94    cmd(f"ethtool -L {cfg.ifname} combined 1")
95    cmd(f"ethtool -L {cfg.ifname} combined {qcnt}")
96
97    # check napi threaded is set for both napis
98    _assert_napi_threaded_enabled(nl, napi0_id)
99    _assert_napi_threaded_enabled(nl, napi1_id)
100
101
102def main() -> None:
103    """ Ksft boiler plate main """
104
105    with NetDrvEnv(__file__, queue_count=2) as cfg:
106        ksft_run([change_num_queues,
107                  enable_dev_threaded_disable_napi_threaded],
108                 args=(cfg, NetdevFamily()))
109    ksft_exit()
110
111
112if __name__ == "__main__":
113    main()
114