1#!/usr/bin/env python3 2# SPDX-License-Identifier: GPL-2.0 3 4from lib.py import ksft_disruptive, ksft_exit, ksft_run 5from lib.py import ksft_eq, ksft_raises, KsftSkipEx 6from lib.py import EthtoolFamily, NetdevFamily, NlError 7from lib.py import NetDrvEnv 8from lib.py import cmd, defer, ip 9import errno 10import glob 11 12 13def sys_get_queues(ifname, qtype='rx') -> int: 14 folders = glob.glob(f'/sys/class/net/{ifname}/queues/{qtype}-*') 15 return len(folders) 16 17 18def nl_get_queues(cfg, nl, qtype='rx'): 19 queues = nl.queue_get({'ifindex': cfg.ifindex}, dump=True) 20 if queues: 21 return len([q for q in queues if q['type'] == qtype]) 22 return None 23 24 25def get_queues(cfg, nl) -> None: 26 snl = NetdevFamily(recv_size=4096) 27 28 for qtype in ['rx', 'tx']: 29 queues = nl_get_queues(cfg, snl, qtype) 30 if not queues: 31 raise KsftSkipEx('queue-get not supported by device') 32 33 expected = sys_get_queues(cfg.dev['ifname'], qtype) 34 ksft_eq(queues, expected) 35 36 37def addremove_queues(cfg, nl) -> None: 38 queues = nl_get_queues(cfg, nl) 39 if not queues: 40 raise KsftSkipEx('queue-get not supported by device') 41 42 curr_queues = sys_get_queues(cfg.dev['ifname']) 43 if curr_queues == 1: 44 raise KsftSkipEx('cannot decrement queue: already at 1') 45 46 netnl = EthtoolFamily() 47 channels = netnl.channels_get({'header': {'dev-index': cfg.ifindex}}) 48 if channels['combined-count'] == 0: 49 rx_type = 'rx' 50 else: 51 rx_type = 'combined' 52 53 expected = curr_queues - 1 54 cmd(f"ethtool -L {cfg.dev['ifname']} {rx_type} {expected}", timeout=10) 55 queues = nl_get_queues(cfg, nl) 56 ksft_eq(queues, expected) 57 58 expected = curr_queues 59 cmd(f"ethtool -L {cfg.dev['ifname']} {rx_type} {expected}", timeout=10) 60 queues = nl_get_queues(cfg, nl) 61 ksft_eq(queues, expected) 62 63 64@ksft_disruptive 65def check_down(cfg, nl) -> None: 66 # Check the NAPI IDs before interface goes down and hides them 67 napis = nl.napi_get({'ifindex': cfg.ifindex}, dump=True) 68 69 ip(f"link set dev {cfg.dev['ifname']} down") 70 defer(ip, f"link set dev {cfg.dev['ifname']} up") 71 72 with ksft_raises(NlError) as cm: 73 nl.queue_get({'ifindex': cfg.ifindex, 'id': 0, 'type': 'rx'}) 74 ksft_eq(cm.exception.nl_msg.error, -errno.ENOENT) 75 76 if napis: 77 with ksft_raises(NlError) as cm: 78 nl.napi_get({'id': napis[0]['id']}) 79 ksft_eq(cm.exception.nl_msg.error, -errno.ENOENT) 80 81 82def main() -> None: 83 with NetDrvEnv(__file__, queue_count=100) as cfg: 84 ksft_run([get_queues, addremove_queues, check_down], args=(cfg, NetdevFamily())) 85 ksft_exit() 86 87 88if __name__ == "__main__": 89 main() 90