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 with open(f"/sys/class/net/{cfg.ifname}/threaded", "wb") as fp: 28 fp.write(str(threaded).encode('utf-8')) 29 30 31def _setup_deferred_cleanup(cfg) -> None: 32 combined = ethtool(f"-l {cfg.ifname}", json=True)[0].get("combined", 0) 33 ksft_ge(combined, 2) 34 defer(ethtool, f"-L {cfg.ifname} combined {combined}") 35 36 threaded = cmd(f"cat /sys/class/net/{cfg.ifname}/threaded").stdout 37 defer(_set_threaded_state, cfg, threaded) 38 39 return combined 40 41 42def napi_init(cfg, nl) -> None: 43 """ 44 Test that threaded state (in the persistent NAPI config) gets updated 45 even when NAPI with given ID is not allocated at the time. 46 """ 47 48 qcnt = _setup_deferred_cleanup(cfg) 49 50 _set_threaded_state(cfg, 1) 51 cmd(f"ethtool -L {cfg.ifname} combined 1") 52 _set_threaded_state(cfg, 0) 53 cmd(f"ethtool -L {cfg.ifname} combined {qcnt}") 54 55 napis = nl.napi_get({'ifindex': cfg.ifindex}, dump=True) 56 for napi in napis: 57 ksft_eq(napi['threaded'], 'disabled') 58 ksft_eq(napi.get('pid'), None) 59 60 cmd(f"ethtool -L {cfg.ifname} combined 1") 61 _set_threaded_state(cfg, 1) 62 cmd(f"ethtool -L {cfg.ifname} combined {qcnt}") 63 64 napis = nl.napi_get({'ifindex': cfg.ifindex}, dump=True) 65 for napi in napis: 66 ksft_eq(napi['threaded'], 'enabled') 67 ksft_ne(napi.get('pid'), None) 68 69 70def enable_dev_threaded_disable_napi_threaded(cfg, nl) -> None: 71 """ 72 Test that when napi threaded is enabled at device level and 73 then disabled at napi level for one napi, the threaded state 74 of all napis is preserved after a change in number of queues. 75 """ 76 77 napis = nl.napi_get({'ifindex': cfg.ifindex}, dump=True) 78 ksft_ge(len(napis), 2) 79 80 napi0_id = napis[0]['id'] 81 napi1_id = napis[1]['id'] 82 83 qcnt = _setup_deferred_cleanup(cfg) 84 85 # set threaded 86 _set_threaded_state(cfg, 1) 87 88 # check napi threaded is set for both napis 89 _assert_napi_threaded_enabled(nl, napi0_id) 90 _assert_napi_threaded_enabled(nl, napi1_id) 91 92 # disable threaded for napi1 93 nl.napi_set({'id': napi1_id, 'threaded': 'disabled'}) 94 95 cmd(f"ethtool -L {cfg.ifname} combined 1") 96 cmd(f"ethtool -L {cfg.ifname} combined {qcnt}") 97 _assert_napi_threaded_enabled(nl, napi0_id) 98 _assert_napi_threaded_disabled(nl, napi1_id) 99 100 101def change_num_queues(cfg, nl) -> None: 102 """ 103 Test that when napi threaded is enabled at device level, 104 the napi threaded state is preserved after a change in 105 number of queues. 106 """ 107 108 napis = nl.napi_get({'ifindex': cfg.ifindex}, dump=True) 109 ksft_ge(len(napis), 2) 110 111 napi0_id = napis[0]['id'] 112 napi1_id = napis[1]['id'] 113 114 qcnt = _setup_deferred_cleanup(cfg) 115 116 # set threaded 117 _set_threaded_state(cfg, 1) 118 119 # check napi threaded is set for both napis 120 _assert_napi_threaded_enabled(nl, napi0_id) 121 _assert_napi_threaded_enabled(nl, napi1_id) 122 123 cmd(f"ethtool -L {cfg.ifname} combined 1") 124 cmd(f"ethtool -L {cfg.ifname} combined {qcnt}") 125 126 # check napi threaded is set for both napis 127 _assert_napi_threaded_enabled(nl, napi0_id) 128 _assert_napi_threaded_enabled(nl, napi1_id) 129 130 131def main() -> None: 132 """ Ksft boiler plate main """ 133 134 with NetDrvEnv(__file__, queue_count=2) as cfg: 135 ksft_run([napi_init, 136 change_num_queues, 137 enable_dev_threaded_disable_napi_threaded], 138 args=(cfg, NetdevFamily())) 139 ksft_exit() 140 141 142if __name__ == "__main__": 143 main() 144