xref: /linux/tools/testing/selftests/drivers/net/hw/rss_api.py (revision 25489a4f556414445d342951615178368ee45cde)
1#!/usr/bin/env python3
2# SPDX-License-Identifier: GPL-2.0
3
4"""
5API level tests for RSS (mostly Netlink vs IOCTL).
6"""
7
8import glob
9from lib.py import ksft_run, ksft_exit, ksft_eq, ksft_is, ksft_ne
10from lib.py import KsftSkipEx, KsftFailEx
11from lib.py import defer, ethtool
12from lib.py import EthtoolFamily
13from lib.py import NetDrvEnv
14
15
16def _ethtool_create(cfg, act, opts):
17    output = ethtool(f"{act} {cfg.ifname} {opts}").stdout
18    # Output will be something like: "New RSS context is 1" or
19    # "Added rule with ID 7", we want the integer from the end
20    return int(output.split()[-1])
21
22
23def test_rxfh_indir_ntf(cfg):
24    """
25    Check that Netlink notifications are generated when RSS indirection
26    table was modified.
27    """
28
29    qcnt = len(glob.glob(f"/sys/class/net/{cfg.ifname}/queues/rx-*"))
30    if qcnt < 2:
31        raise KsftSkipEx(f"Local has only {qcnt} queues")
32
33    ethnl = EthtoolFamily()
34    ethnl.ntf_subscribe("monitor")
35
36    ethtool(f"--disable-netlink -X {cfg.ifname} weight 0 1")
37    reset = defer(ethtool, f"-X {cfg.ifname} default")
38
39    ntf = next(ethnl.poll_ntf(duration=0.2), None)
40    if ntf is None:
41        raise KsftFailEx("No notification received")
42    ksft_eq(ntf["name"], "rss-ntf")
43    ksft_eq(set(ntf["msg"]["indir"]), {1})
44
45    reset.exec()
46    ntf = next(ethnl.poll_ntf(duration=0.2), None)
47    if ntf is None:
48        raise KsftFailEx("No notification received after reset")
49    ksft_eq(ntf["name"], "rss-ntf")
50    ksft_is(ntf["msg"].get("context"), None)
51    ksft_ne(set(ntf["msg"]["indir"]), {1})
52
53
54def test_rxfh_indir_ctx_ntf(cfg):
55    """
56    Check that Netlink notifications are generated when RSS indirection
57    table was modified on an additional RSS context.
58    """
59
60    qcnt = len(glob.glob(f"/sys/class/net/{cfg.ifname}/queues/rx-*"))
61    if qcnt < 2:
62        raise KsftSkipEx(f"Local has only {qcnt} queues")
63
64    ctx_id = _ethtool_create(cfg, "-X", "context new")
65    defer(ethtool, f"-X {cfg.ifname} context {ctx_id} delete")
66
67    ethnl = EthtoolFamily()
68    ethnl.ntf_subscribe("monitor")
69
70    ethtool(f"--disable-netlink -X {cfg.ifname} context {ctx_id} weight 0 1")
71
72    ntf = next(ethnl.poll_ntf(duration=0.2), None)
73    if ntf is None:
74        raise KsftFailEx("No notification received")
75    ksft_eq(ntf["name"], "rss-ntf")
76    ksft_eq(ntf["msg"].get("context"), ctx_id)
77    ksft_eq(set(ntf["msg"]["indir"]), {1})
78
79
80def main() -> None:
81    """ Ksft boiler plate main """
82
83    with NetDrvEnv(__file__, nsim_test=False) as cfg:
84        ksft_run(globs=globals(), case_pfx={"test_"}, args=(cfg, ))
85    ksft_exit()
86
87
88if __name__ == "__main__":
89    main()
90