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 rx_type = 'rx' 49 if channels.get('combined-count', 0) > 0: 50 rx_type = 'combined' 51 52 expected = curr_queues - 1 53 cmd(f"ethtool -L {cfg.dev['ifname']} {rx_type} {expected}", timeout=10) 54 queues = nl_get_queues(cfg, nl) 55 ksft_eq(queues, expected) 56 57 expected = curr_queues 58 cmd(f"ethtool -L {cfg.dev['ifname']} {rx_type} {expected}", timeout=10) 59 queues = nl_get_queues(cfg, nl) 60 ksft_eq(queues, expected) 61 62 63@ksft_disruptive 64def check_down(cfg, nl) -> None: 65 # Check the NAPI IDs before interface goes down and hides them 66 napis = nl.napi_get({'ifindex': cfg.ifindex}, dump=True) 67 68 ip(f"link set dev {cfg.dev['ifname']} down") 69 defer(ip, f"link set dev {cfg.dev['ifname']} up") 70 71 with ksft_raises(NlError) as cm: 72 nl.queue_get({'ifindex': cfg.ifindex, 'id': 0, 'type': 'rx'}) 73 ksft_eq(cm.exception.nl_msg.error, -errno.ENOENT) 74 75 if napis: 76 with ksft_raises(NlError) as cm: 77 nl.napi_get({'id': napis[0]['id']}) 78 ksft_eq(cm.exception.nl_msg.error, -errno.ENOENT) 79 80 81def main() -> None: 82 with NetDrvEnv(__file__, queue_count=100) as cfg: 83 ksft_run([get_queues, addremove_queues, check_down], args=(cfg, NetdevFamily())) 84 ksft_exit() 85 86 87if __name__ == "__main__": 88 main() 89