99 lines
2.7 KiB
Python
99 lines
2.7 KiB
Python
|
#!/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()
|