xref: /linux/tools/testing/selftests/net/nl_netdev.py (revision 860a9bed265146b10311bcadbbcef59c3af4454d)
1#!/usr/bin/env python3
2# SPDX-License-Identifier: GPL-2.0
3
4import time
5from lib.py import ksft_run, ksft_pr, ksft_eq, ksft_ge, ksft_busy_wait
6from lib.py import NetdevFamily, NetdevSimDev, ip
7
8
9def empty_check(nf) -> None:
10    devs = nf.dev_get({}, dump=True)
11    ksft_ge(len(devs), 1)
12
13
14def lo_check(nf) -> None:
15    lo_info = nf.dev_get({"ifindex": 1})
16    ksft_eq(len(lo_info['xdp-features']), 0)
17    ksft_eq(len(lo_info['xdp-rx-metadata-features']), 0)
18
19
20def page_pool_check(nf) -> None:
21    with NetdevSimDev() as nsimdev:
22        nsim = nsimdev.nsims[0]
23
24        def up():
25            ip(f"link set dev {nsim.ifname} up")
26
27        def down():
28            ip(f"link set dev {nsim.ifname} down")
29
30        def get_pp():
31            pp_list = nf.page_pool_get({}, dump=True)
32            return [pp for pp in pp_list if pp.get("ifindex") == nsim.ifindex]
33
34        # No page pools when down
35        down()
36        ksft_eq(len(get_pp()), 0)
37
38        # Up, empty page pool appears
39        up()
40        pp_list = get_pp()
41        ksft_ge(len(pp_list), 0)
42        refs = sum([pp["inflight"] for pp in pp_list])
43        ksft_eq(refs, 0)
44
45        # Down, it disappears, again
46        down()
47        pp_list = get_pp()
48        ksft_eq(len(pp_list), 0)
49
50        # Up, allocate a page
51        up()
52        nsim.dfs_write("pp_hold", "y")
53        pp_list = nf.page_pool_get({}, dump=True)
54        refs = sum([pp["inflight"] for pp in pp_list if pp.get("ifindex") == nsim.ifindex])
55        ksft_ge(refs, 1)
56
57        # Now let's leak a page
58        down()
59        pp_list = get_pp()
60        ksft_eq(len(pp_list), 1)
61        refs = sum([pp["inflight"] for pp in pp_list])
62        ksft_eq(refs, 1)
63        attached = [pp for pp in pp_list if "detach-time" not in pp]
64        ksft_eq(len(attached), 0)
65
66        # New pp can get created, and we'll have two
67        up()
68        pp_list = get_pp()
69        attached = [pp for pp in pp_list if "detach-time" not in pp]
70        detached = [pp for pp in pp_list if "detach-time" in pp]
71        ksft_eq(len(attached), 1)
72        ksft_eq(len(detached), 1)
73
74        # Free the old page and the old pp is gone
75        nsim.dfs_write("pp_hold", "n")
76        # Freeing check is once a second so we may need to retry
77        ksft_busy_wait(lambda: len(get_pp()) == 1, deadline=2)
78
79        # And down...
80        down()
81        ksft_eq(len(get_pp()), 0)
82
83        # Last, leave the page hanging for destroy, nothing to check
84        # we're trying to exercise the orphaning path in the kernel
85        up()
86        nsim.dfs_write("pp_hold", "y")
87
88
89def main() -> None:
90    nf = NetdevFamily()
91    ksft_run([empty_check, lo_check, page_pool_check],
92             args=(nf, ))
93
94
95if __name__ == "__main__":
96    main()
97