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