Add resize tests to rss_drv.py. Devices without dynamic table sizing are skipped via _require_dynamic_indir_size().
resize_periodic: set a periodic table (equal 2), shrink channels to fold, grow back to unfold. Check the pattern is preserved. Has main and non-default context variants. resize_nonperiodic_reject: set a non-periodic table (equal N), verify that channel reduction is rejected. Pass queue_count=8 to NetDrvEnv so netdevsim is created with enough queues for the resize tests. Signed-off-by: Björn Töpel <[email protected]> --- .../selftests/drivers/net/hw/rss_drv.py | 101 +++++++++++++++++- 1 file changed, 96 insertions(+), 5 deletions(-) diff --git a/tools/testing/selftests/drivers/net/hw/rss_drv.py b/tools/testing/selftests/drivers/net/hw/rss_drv.py index 2d1a33189076..8725500f2955 100755 --- a/tools/testing/selftests/drivers/net/hw/rss_drv.py +++ b/tools/testing/selftests/drivers/net/hw/rss_drv.py @@ -5,9 +5,9 @@ Driver-related behavior tests for RSS. """ -from lib.py import ksft_run, ksft_exit, ksft_ge -from lib.py import ksft_variants, KsftNamedVariant, KsftSkipEx -from lib.py import defer, ethtool +from lib.py import ksft_run, ksft_exit, ksft_eq, ksft_ge +from lib.py import ksft_variants, KsftNamedVariant, KsftSkipEx, KsftFailEx +from lib.py import defer, ethtool, CmdExitFailure from lib.py import EthtoolFamily, NlError from lib.py import NetDrvEnv @@ -45,6 +45,18 @@ def _maybe_create_context(cfg, create_context): return ctx_id +def _require_dynamic_indir_size(cfg, ch_max): + """Skip if the device does not dynamically size its indirection table.""" + ethtool(f"-X {cfg.ifname} default") + ethtool(f"-L {cfg.ifname} combined 2") + small = len(_get_rss(cfg)['rss-indirection-table']) + ethtool(f"-L {cfg.ifname} combined {ch_max}") + large = len(_get_rss(cfg)['rss-indirection-table']) + + if small == large: + raise KsftSkipEx("Device does not dynamically size indirection table") + + @ksft_variants([ KsftNamedVariant("main", False), KsftNamedVariant("ctx", True), @@ -76,11 +88,90 @@ def indir_size_4x(cfg, create_context): _test_rss_indir_size(cfg, test_max, context=ctx_id) +@ksft_variants([ + KsftNamedVariant("main", False), + KsftNamedVariant("ctx", True), +]) +def resize_periodic(cfg, create_context): + """Test that a periodic indirection table survives channel changes. + + Set a periodic table (equal 2), reduce channels to trigger a + fold, then increase to trigger an unfold. Verify the table pattern + is preserved and the size tracks the channel count. + """ + channels = cfg.ethnl.channels_get({'header': {'dev-index': cfg.ifindex}}) + ch_max = channels.get('combined-max', 0) + qcnt = channels['combined-count'] + + if ch_max < 4: + raise KsftSkipEx(f"Not enough queues for the test: max={ch_max}") + + defer(ethtool, f"-L {cfg.ifname} combined {qcnt}") + ethtool(f"-L {cfg.ifname} combined {ch_max}") + + _require_dynamic_indir_size(cfg, ch_max) + + ctx_id = _maybe_create_context(cfg, create_context) + ctx_ref = f"context {ctx_id}" if ctx_id else "" + + ethtool(f"-X {cfg.ifname} {ctx_ref} equal 2") + if not create_context: + defer(ethtool, f"-X {cfg.ifname} default") + + orig_size = len(_get_rss(cfg, context=ctx_id)['rss-indirection-table']) + + # Shrink — should fold + ethtool(f"-L {cfg.ifname} combined 2") + rss = _get_rss(cfg, context=ctx_id) + indir = rss['rss-indirection-table'] + + ksft_ge(orig_size, len(indir), "Table did not shrink") + ksft_eq(set(indir), {0, 1}, "Folded table has wrong queues") + + # Grow back — should unfold + ethtool(f"-L {cfg.ifname} combined {ch_max}") + rss = _get_rss(cfg, context=ctx_id) + indir = rss['rss-indirection-table'] + + ksft_eq(len(indir), orig_size, "Table size not restored") + ksft_eq(set(indir), {0, 1}, "Unfolded table has wrong queues") + + +def resize_nonperiodic_reject(cfg): + """Test that a non-periodic table blocks channel reduction. + + Set equal weight across all queues so the table is not periodic + at any smaller size, then verify channel reduction is rejected. + """ + channels = cfg.ethnl.channels_get({'header': {'dev-index': cfg.ifindex}}) + ch_max = channels.get('combined-max', 0) + qcnt = channels['combined-count'] + + if ch_max < 4: + raise KsftSkipEx(f"Not enough queues for the test: max={ch_max}") + + defer(ethtool, f"-L {cfg.ifname} combined {qcnt}") + ethtool(f"-L {cfg.ifname} combined {ch_max}") + + _require_dynamic_indir_size(cfg, ch_max) + + ethtool(f"-X {cfg.ifname} equal {ch_max}") + defer(ethtool, f"-X {cfg.ifname} default") + + try: + ethtool(f"-L {cfg.ifname} combined 2") + except CmdExitFailure: + pass + else: + raise KsftFailEx("Channel reduction should fail with non-periodic table") + + def main() -> None: """ Ksft boiler plate main """ - with NetDrvEnv(__file__) as cfg: + with NetDrvEnv(__file__, queue_count=8) as cfg: cfg.ethnl = EthtoolFamily() - ksft_run([indir_size_4x], args=(cfg, )) + ksft_run([indir_size_4x, resize_periodic, + resize_nonperiodic_reject], args=(cfg, )) ksft_exit() -- 2.53.0

