99 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			99 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
| #! /usr/bin/python3 -sP
 | |
| # 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()
 |