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