mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
selftests: net: add tests for filtered dumps of page pool
Add tests for page pool dumps of a specific ifindex. Link: https://patch.msgid.link/20260506034821.1710113-2-kuba@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
c93799de1b
commit
ce3d4a67a0
|
|
@ -117,6 +117,7 @@ CONFIG_OPENVSWITCH=m
|
|||
CONFIG_OPENVSWITCH_GENEVE=m
|
||||
CONFIG_OPENVSWITCH_GRE=m
|
||||
CONFIG_OPENVSWITCH_VXLAN=m
|
||||
CONFIG_PAGE_POOL_STATS=y
|
||||
CONFIG_PROC_SYSCTL=y
|
||||
CONFIG_PSAMPLE=m
|
||||
CONFIG_RPS=y
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import errno
|
|||
from os import system
|
||||
from lib.py import ksft_run, ksft_exit
|
||||
from lib.py import ksft_eq, ksft_ge, ksft_ne, ksft_raises, ksft_busy_wait
|
||||
from lib.py import NetdevFamily, NetdevSimDev, NlError, ip
|
||||
from lib.py import NetdevFamily, NetdevSimDev, NlError, defer, ip
|
||||
|
||||
|
||||
def empty_check(nf) -> None:
|
||||
|
|
@ -255,6 +255,117 @@ def page_pool_check(nf) -> None:
|
|||
nsim.dfs_write("pp_hold", "y")
|
||||
|
||||
|
||||
def page_pool_dump_ifindex(nf) -> None:
|
||||
"""Test page pool dump filtering by ifindex."""
|
||||
nsimdev1 = NetdevSimDev(queue_count=3)
|
||||
rm_nsim1 = defer(nsimdev1.remove)
|
||||
nsimdev2 = NetdevSimDev(queue_count=5)
|
||||
defer(nsimdev2.remove)
|
||||
|
||||
nsim1 = nsimdev1.nsims[0]
|
||||
nsim2 = nsimdev2.nsims[0]
|
||||
|
||||
ip(f"link set dev {nsim1.ifname} up")
|
||||
ip(f"link set dev {nsim2.ifname} up")
|
||||
|
||||
# Unfiltered dump should have pools from both devices
|
||||
all_pp = nf.page_pool_get({}, dump=True)
|
||||
pp1_all = [pp for pp in all_pp
|
||||
if pp.get("ifindex") == nsim1.ifindex]
|
||||
pp2_all = [pp for pp in all_pp
|
||||
if pp.get("ifindex") == nsim2.ifindex]
|
||||
ksft_ge(len(pp1_all), 1)
|
||||
ksft_ge(len(pp2_all), 1)
|
||||
|
||||
# Filtered dump should only return pools for that device
|
||||
pp1_flt = nf.page_pool_get({'ifindex': nsim1.ifindex}, dump=True)
|
||||
ksft_eq(pp1_flt, pp1_all)
|
||||
|
||||
pp2_flt = nf.page_pool_get({'ifindex': nsim2.ifindex}, dump=True)
|
||||
ksft_eq(pp2_flt, pp2_all)
|
||||
|
||||
# Non-existent ifindex should return empty dump
|
||||
pp_none = nf.page_pool_get({'ifindex': 12345678}, dump=True)
|
||||
ksft_eq(len(pp_none), 0)
|
||||
|
||||
# Device down - no pools for that ifindex
|
||||
ip(f"link set dev {nsim1.ifname} down")
|
||||
pp1_down = nf.page_pool_get({'ifindex': nsim1.ifindex}, dump=True)
|
||||
ksft_eq(len(pp1_down), 0)
|
||||
|
||||
# Remove device, dump by its old ifindex should return empty
|
||||
old_ifindex = nsim1.ifindex
|
||||
rm_nsim1.exec()
|
||||
pp1_gone = nf.page_pool_get({'ifindex': old_ifindex}, dump=True)
|
||||
ksft_eq(len(pp1_gone), 0)
|
||||
|
||||
|
||||
def page_pool_ifindex_leak_check(nf) -> None:
|
||||
"""Test that zombie page pools don't show up under the original ifindex."""
|
||||
nsimdev = NetdevSimDev()
|
||||
rm_nsim = defer(nsimdev.remove)
|
||||
nsim = nsimdev.nsims[0]
|
||||
|
||||
ip(f"link set dev {nsim.ifname} up")
|
||||
nsim.dfs_write("pp_hold", "y")
|
||||
|
||||
pp_up = nf.page_pool_get({'ifindex': nsim.ifindex}, dump=True)
|
||||
ksft_ge(len(pp_up), 1)
|
||||
|
||||
# Remove device with leaked page - pool becomes zombie (orphaned to lo)
|
||||
old_ifindex = nsim.ifindex
|
||||
rm_nsim.exec()
|
||||
|
||||
# Zombie pool should NOT appear under the original device
|
||||
pp_down = nf.page_pool_get({'ifindex': old_ifindex}, dump=True)
|
||||
ksft_eq(len(pp_down), 0)
|
||||
|
||||
# But it should appear in an unfiltered dump (under loopback)
|
||||
pp_all = nf.page_pool_get({}, dump=True)
|
||||
orphans = [pp for pp in pp_all
|
||||
if "detach-time" in pp and "ifindex" not in pp]
|
||||
ksft_ge(len(orphans), 1)
|
||||
|
||||
|
||||
def page_pool_stats_ifindex_check(nf) -> None:
|
||||
"""Test page pool stats dump filtering by ifindex."""
|
||||
nsimdev1 = NetdevSimDev(queue_count=3)
|
||||
defer(nsimdev1.remove)
|
||||
nsimdev2 = NetdevSimDev(queue_count=5)
|
||||
defer(nsimdev2.remove)
|
||||
|
||||
nsim1 = nsimdev1.nsims[0]
|
||||
nsim2 = nsimdev2.nsims[0]
|
||||
|
||||
ip(f"link set dev {nsim1.ifname} up")
|
||||
ip(f"link set dev {nsim2.ifname} up")
|
||||
|
||||
# Unfiltered stats dump
|
||||
all_stats = nf.page_pool_stats_get({}, dump=True)
|
||||
s1_all = [s for s in all_stats
|
||||
if s.get("info", {}).get("ifindex") == nsim1.ifindex]
|
||||
s2_all = [s for s in all_stats
|
||||
if s.get("info", {}).get("ifindex") == nsim2.ifindex]
|
||||
ksft_ge(len(s1_all), 1)
|
||||
ksft_ge(len(s2_all), 1)
|
||||
|
||||
# Filtered stats dump
|
||||
s1_flt = nf.page_pool_stats_get({'info': {'ifindex': nsim1.ifindex}},
|
||||
dump=True)
|
||||
ksft_eq(s1_flt, s1_all)
|
||||
|
||||
# Non-existent ifindex should return empty
|
||||
s_none = nf.page_pool_stats_get({'info': {'ifindex': 12345678}}, dump=True)
|
||||
ksft_eq(len(s_none), 0)
|
||||
|
||||
# info.id should be rejected for stats dump
|
||||
with ksft_raises(NlError) as cm:
|
||||
nf.page_pool_stats_get({'info': {'id': s1_all[0]['info']['id']}},
|
||||
dump=True)
|
||||
ksft_eq(cm.exception.nl_msg.error, -errno.EINVAL)
|
||||
ksft_eq(cm.exception.nl_msg.extack['bad-attr'], '.info.id')
|
||||
|
||||
|
||||
def main() -> None:
|
||||
""" Ksft boiler plate main """
|
||||
nf = NetdevFamily()
|
||||
|
|
@ -265,7 +376,11 @@ def main() -> None:
|
|||
napi_set_threaded,
|
||||
dev_set_threaded,
|
||||
nsim_rxq_reset_down,
|
||||
page_pool_check],
|
||||
page_pool_check,
|
||||
page_pool_dump_ifindex,
|
||||
page_pool_ifindex_leak_check,
|
||||
page_pool_stats_ifindex_check
|
||||
],
|
||||
args=(nf, ))
|
||||
ksft_exit()
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user