Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

selftests: drv-net: rss: validate min RSS table size

Add a test which checks that the RSS table is at least 4x the max
queue count supported by the device. The original RSS spec from
Microsoft stated that the RSS indirection table should be 2 to 8
times the CPU count, presumably assuming queue per CPU. If the
CPU count is not a power of two, however, a power-of-2 table
2x larger than queue count results in a 33% traffic imbalance.
Validate that the indirection table is at least 4x the queue
count. This lowers the imbalance to 16% which empirically
appears to be more acceptable to memcache-like workloads.

Reviewed-by: Willem de Bruijn <willemb@google.com>
Link: https://patch.msgid.link/20260131225454.1225151-1-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+89
+1
tools/testing/selftests/drivers/net/hw/Makefile
··· 35 35 pp_alloc_fail.py \ 36 36 rss_api.py \ 37 37 rss_ctx.py \ 38 + rss_drv.py \ 38 39 rss_flow_label.py \ 39 40 rss_input_xfrm.py \ 40 41 toeplitz.py \
+88
tools/testing/selftests/drivers/net/hw/rss_drv.py
··· 1 + #!/usr/bin/env python3 2 + # SPDX-License-Identifier: GPL-2.0 3 + 4 + """ 5 + Driver-related behavior tests for RSS. 6 + """ 7 + 8 + from lib.py import ksft_run, ksft_exit, ksft_ge 9 + from lib.py import ksft_variants, KsftNamedVariant, KsftSkipEx 10 + from lib.py import defer, ethtool 11 + from lib.py import EthtoolFamily, NlError 12 + from lib.py import NetDrvEnv 13 + 14 + 15 + def _is_power_of_two(n): 16 + return n > 0 and (n & (n - 1)) == 0 17 + 18 + 19 + def _get_rss(cfg, context=0): 20 + return ethtool(f"-x {cfg.ifname} context {context}", json=True)[0] 21 + 22 + 23 + def _test_rss_indir_size(cfg, qcnt, context=0): 24 + """Test that indirection table size is at least 4x queue count.""" 25 + ethtool(f"-L {cfg.ifname} combined {qcnt}") 26 + 27 + rss = _get_rss(cfg, context=context) 28 + indir = rss['rss-indirection-table'] 29 + ksft_ge(len(indir), 4 * qcnt, "Table smaller than 4x") 30 + return len(indir) 31 + 32 + 33 + def _maybe_create_context(cfg, create_context): 34 + """ Either create a context and return its ID or return 0 for main ctx """ 35 + if not create_context: 36 + return 0 37 + try: 38 + ctx = cfg.ethnl.rss_create_act({'header': {'dev-index': cfg.ifindex}}) 39 + ctx_id = ctx['context'] 40 + defer(cfg.ethnl.rss_delete_act, 41 + {'header': {'dev-index': cfg.ifindex}, 'context': ctx_id}) 42 + except NlError: 43 + raise KsftSkipEx("Device does not support additional RSS contexts") 44 + 45 + return ctx_id 46 + 47 + 48 + @ksft_variants([ 49 + KsftNamedVariant("main", False), 50 + KsftNamedVariant("ctx", True), 51 + ]) 52 + def indir_size_4x(cfg, create_context): 53 + """ 54 + Test that the indirection table has at least 4 entries per queue. 55 + Empirically network-heavy workloads like memcache suffer with the 33% 56 + imbalance of a 2x indirection table size. 57 + 4x table translates to a 16% imbalance. 58 + """ 59 + channels = cfg.ethnl.channels_get({'header': {'dev-index': cfg.ifindex}}) 60 + ch_max = channels.get('combined-max', 0) 61 + qcnt = channels['combined-count'] 62 + 63 + if ch_max < 3: 64 + raise KsftSkipEx(f"Not enough queues for the test: max={ch_max}") 65 + 66 + defer(ethtool, f"-L {cfg.ifname} combined {qcnt}") 67 + ethtool(f"-L {cfg.ifname} combined 3") 68 + 69 + ctx_id = _maybe_create_context(cfg, create_context) 70 + 71 + indir_sz = _test_rss_indir_size(cfg, 3, context=ctx_id) 72 + 73 + # Test with max queue count (max - 1 if max is a power of two) 74 + test_max = ch_max - 1 if _is_power_of_two(ch_max) else ch_max 75 + if test_max > 3 and indir_sz < test_max * 4: 76 + _test_rss_indir_size(cfg, test_max, context=ctx_id) 77 + 78 + 79 + def main() -> None: 80 + """ Ksft boiler plate main """ 81 + with NetDrvEnv(__file__) as cfg: 82 + cfg.ethnl = EthtoolFamily() 83 + ksft_run([indir_size_4x], args=(cfg, )) 84 + ksft_exit() 85 + 86 + 87 + if __name__ == "__main__": 88 + main()