#!/usr/bin/env python3# SPDX-License-Identifier: GPL-2.0import timefrom lib.py import ksft_run, ksft_exit, ksft_prfrom lib.py import ksft_eq, ksft_ge, ksft_busy_waitfrom lib.py import NetdevFamily, NetdevSimDev, ipdef empty_check(nf) -> None: devs = nf.dev_get({}, dump=True) ksft_ge(len(devs), 1)def lo_check(nf) -> None: lo_info = nf.dev_get({"ifindex": 1}) ksft_eq(len(lo_info['xdp-features']), 0) ksft_eq(len(lo_info['xdp-rx-metadata-features']), 0)def page_pool_check(nf) -> None: with NetdevSimDev() as nsimdev: nsim = nsimdev.nsims[0] def up(): ip(f"link set dev {nsim.ifname} up") def down(): ip(f"link set dev {nsim.ifname} down") def get_pp(): pp_list = nf.page_pool_get({}, dump=True) return [pp for pp in pp_list if pp.get("ifindex") == nsim.ifindex] # No page pools when down down() ksft_eq(len(get_pp()), 0) # Up, empty page pool appears up() pp_list = get_pp() ksft_ge(len(pp_list), 0) refs = sum([pp["inflight"] for pp in pp_list]) ksft_eq(refs, 0) # Down, it disappears, again down() pp_list = get_pp() ksft_eq(len(pp_list), 0) # Up, allocate a page up() nsim.dfs_write("pp_hold", "y") pp_list = nf.page_pool_get({}, dump=True) refs = sum([pp["inflight"] for pp in pp_list if pp.get("ifindex") == nsim.ifindex]) ksft_ge(refs, 1) # Now let's leak a page down() pp_list = get_pp() ksft_eq(len(pp_list), 1) refs = sum([pp["inflight"] for pp in pp_list]) ksft_eq(refs, 1) attached = [pp for pp in pp_list if "detach-time" not in pp] ksft_eq(len(attached), 0) # New pp can get created, and we'll have two up() pp_list = get_pp() attached = [pp for pp in pp_list if "detach-time" not in pp] detached = [pp for pp in pp_list if "detach-time" in pp] ksft_eq(len(attached), 1) ksft_eq(len(detached), 1) # Free the old page and the old pp is gone nsim.dfs_write("pp_hold", "n") # Freeing check is once a second so we may need to retry ksft_busy_wait(lambda: len(get_pp()) == 1, deadline=2) # And down... down() ksft_eq(len(get_pp()), 0) # Last, leave the page hanging for destroy, nothing to check # we're trying to exercise the orphaning path in the kernel up() nsim.dfs_write("pp_hold", "y")def main() -> None: nf = NetdevFamily() ksft_run([empty_check, lo_check, page_pool_check], args=(nf, )) ksft_exit()if __name__ == "__main__": main()
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-2.0
import time
from lib.py import ksft_run, ksft_exit, ksft_pr
from lib.py import ksft_eq, ksft_ge, ksft_busy_wait
from lib.py import NetdevFamily, NetdevSimDev, ip
def empty_check(nf) -> None:
devs = nf.dev_get({}, dump=True)
ksft_ge(len(devs), 1)
def lo_check(nf) -> None:
lo_info = nf.dev_get({"ifindex": 1})
ksft_eq(len(lo_info['xdp-features']), 0)
ksft_eq(len(lo_info['xdp-rx-metadata-features']), 0)
def page_pool_check(nf) -> None:
with NetdevSimDev() as nsimdev:
nsim = nsimdev.nsims[0]
def up():
ip(f"link set dev {nsim.ifname} up")
def down():
ip(f"link set dev {nsim.ifname} down")
def get_pp():
pp_list = nf.page_pool_get({}, dump=True)
return [pp for pp in pp_list if pp.get("ifindex") == nsim.ifindex]
# No page pools when down
down()
ksft_eq(len(get_pp()), 0)
# Up, empty page pool appears
up()
pp_list = get_pp()
ksft_ge(len(pp_list), 0)
refs = sum([pp["inflight"] for pp in pp_list])
ksft_eq(refs, 0)
# Down, it disappears, again
down()
pp_list = get_pp()
ksft_eq(len(pp_list), 0)
# Up, allocate a page
up()
nsim.dfs_write("pp_hold", "y")
pp_list = nf.page_pool_get({}, dump=True)
refs = sum([pp["inflight"] for pp in pp_list if pp.get("ifindex") == nsim.ifindex])
ksft_ge(refs, 1)
# Now let's leak a page
down()
pp_list = get_pp()
ksft_eq(len(pp_list), 1)
refs = sum([pp["inflight"] for pp in pp_list])
ksft_eq(refs, 1)
attached = [pp for pp in pp_list if "detach-time" not in pp]
ksft_eq(len(attached), 0)
# New pp can get created, and we'll have two
up()
pp_list = get_pp()
attached = [pp for pp in pp_list if "detach-time" not in pp]
detached = [pp for pp in pp_list if "detach-time" in pp]
ksft_eq(len(attached), 1)
ksft_eq(len(detached), 1)
# Free the old page and the old pp is gone
nsim.dfs_write("pp_hold", "n")
# Freeing check is once a second so we may need to retry
ksft_busy_wait(lambda: len(get_pp()) == 1, deadline=2)
# And down...
down()
ksft_eq(len(get_pp()), 0)
# Last, leave the page hanging for destroy, nothing to check
# we're trying to exercise the orphaning path in the kernel
up()
nsim.dfs_write("pp_hold", "y")
def main() -> None:
nf = NetdevFamily()
ksft_run([empty_check, lo_check, page_pool_check],
args=(nf, ))
ksft_exit()
if __name__ == "__main__":
main()