selftests: drv-net: rss_ctx: test RSS contexts persist after ifdown/up

Add a test to verify that RSS contexts persist across interface
down/up along with their associated Ntuple filters. Another test
that creates contexts/rules keeping interface down and test their
persistence is also added.

Tested on bnxt_en:

 TAP version 13
 1..1
 # timeout set to 0
 # selftests: drivers/net/hw: rss_ctx.py
 # TAP version 13
 # 1..2
 # ok 1 rss_ctx.test_rss_context_persist_create_and_ifdown
 # ok 2 rss_ctx.test_rss_context_persist_ifdown_and_create # SKIP Create context not supported with interface down
 # # Totals: pass:1 fail:0 xfail:0 xpass:0 skip:1 error:0

Reviewed-by: Andy Gospodarek <andrew.gospodarek@broadcom.com>
Signed-off-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
Signed-off-by: Michael Chan <michael.chan@broadcom.com>
Link: https://patch.msgid.link/20260219185313.2682148-4-michael.chan@broadcom.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Pavan Chebbi 2026-02-19 10:53:13 -08:00 committed by Jakub Kicinski
parent c1bbd9900d
commit ce5a0f4612

View File

@ -4,13 +4,15 @@
import datetime import datetime
import random import random
import re import re
import time
from lib.py import ksft_run, ksft_pr, ksft_exit from lib.py import ksft_run, ksft_pr, ksft_exit
from lib.py import ksft_eq, ksft_ne, ksft_ge, ksft_in, ksft_lt, ksft_true, ksft_raises from lib.py import ksft_eq, ksft_ne, ksft_ge, ksft_in, ksft_lt, ksft_true, ksft_raises
from lib.py import NetDrvEpEnv from lib.py import NetDrvEpEnv
from lib.py import EthtoolFamily, NetdevFamily from lib.py import EthtoolFamily, NetdevFamily
from lib.py import KsftSkipEx, KsftFailEx from lib.py import KsftSkipEx, KsftFailEx
from lib.py import ksft_disruptive
from lib.py import rand_port from lib.py import rand_port
from lib.py import ethtool, ip, defer, GenerateTraffic, CmdExitFailure from lib.py import cmd, ethtool, ip, defer, GenerateTraffic, CmdExitFailure, wait_file
def _rss_key_str(key): def _rss_key_str(key):
@ -809,6 +811,98 @@ def test_rss_default_context_rule(cfg):
'noise' : (0, 1) }) 'noise' : (0, 1) })
@ksft_disruptive
def test_rss_context_persist_ifupdown(cfg, pre_down=False):
"""
Test that RSS contexts and their associated ntuple filters persist across
an interface down/up cycle.
"""
require_ntuple(cfg)
qcnt = len(_get_rx_cnts(cfg))
if qcnt < 6:
try:
ethtool(f"-L {cfg.ifname} combined 6")
defer(ethtool, f"-L {cfg.ifname} combined {qcnt}")
except Exception as exc:
raise KsftSkipEx("Not enough queues for the test") from exc
ethtool(f"-X {cfg.ifname} equal 2")
defer(ethtool, f"-X {cfg.ifname} default")
ifup = defer(ip, f"link set dev {cfg.ifname} up")
if pre_down:
ip(f"link set dev {cfg.ifname} down")
try:
ctx1_id = ethtool_create(cfg, "-X", "context new start 2 equal 2")
defer(ethtool, f"-X {cfg.ifname} context {ctx1_id} delete")
except CmdExitFailure as exc:
raise KsftSkipEx("Create context not supported with interface down") from exc
ctx2_id = ethtool_create(cfg, "-X", "context new start 4 equal 2")
defer(ethtool, f"-X {cfg.ifname} context {ctx2_id} delete")
port_ctx2 = rand_port()
flow = f"flow-type tcp{cfg.addr_ipver} dst-ip {cfg.addr} dst-port {port_ctx2} context {ctx2_id}"
ntuple_id = ethtool_create(cfg, "-N", flow)
defer(ethtool, f"-N {cfg.ifname} delete {ntuple_id}")
if not pre_down:
ip(f"link set dev {cfg.ifname} down")
ifup.exec()
wait_file(f"/sys/class/net/{cfg.ifname}/carrier",
lambda x: x.strip() == "1", deadline=20)
remote_addr = cfg.remote_addr_v[cfg.addr_ipver]
for _ in range(10):
if cmd(f"ping -c 1 -W 1 {remote_addr}", fail=False).ret == 0:
break
time.sleep(1)
else:
raise KsftSkipEx("Cannot reach remote host after interface up")
ctxs = cfg.ethnl.rss_get({'header': {'dev-name': cfg.ifname}}, dump=True)
data1 = [c for c in ctxs if c.get('context') == ctx1_id]
ksft_eq(len(data1), 1, f"Context {ctx1_id} should persist after ifup")
data2 = [c for c in ctxs if c.get('context') == ctx2_id]
ksft_eq(len(data2), 1, f"Context {ctx2_id} should persist after ifup")
_ntuple_rule_check(cfg, ntuple_id, ctx2_id)
cnts = _get_rx_cnts(cfg)
GenerateTraffic(cfg).wait_pkts_and_stop(20000)
cnts = _get_rx_cnts(cfg, prev=cnts)
main_traffic = sum(cnts[0:2])
ksft_ge(main_traffic, 18000, f"Main context traffic distribution: {cnts}")
ksft_lt(sum(cnts[2:6]), 500, f"Other context queues should be mostly empty: {cnts}")
_send_traffic_check(cfg, port_ctx2, f"context {ctx2_id}",
{'target': (4, 5),
'noise': (0, 1),
'empty': (2, 3)})
def test_rss_context_persist_create_and_ifdown(cfg):
"""
Create RSS contexts then cycle the interface down and up.
"""
test_rss_context_persist_ifupdown(cfg, pre_down=False)
def test_rss_context_persist_ifdown_and_create(cfg):
"""
Bring interface down first, then create RSS contexts and bring up.
"""
test_rss_context_persist_ifupdown(cfg, pre_down=True)
def main() -> None: def main() -> None:
with NetDrvEpEnv(__file__, nsim_test=False) as cfg: with NetDrvEpEnv(__file__, nsim_test=False) as cfg:
cfg.context_cnt = None cfg.context_cnt = None
@ -823,7 +917,9 @@ def main() -> None:
test_rss_context_out_of_order, test_rss_context4_create_with_cfg, test_rss_context_out_of_order, test_rss_context4_create_with_cfg,
test_flow_add_context_missing, test_flow_add_context_missing,
test_delete_rss_context_busy, test_rss_ntuple_addition, test_delete_rss_context_busy, test_rss_ntuple_addition,
test_rss_default_context_rule], test_rss_default_context_rule,
test_rss_context_persist_create_and_ifdown,
test_rss_context_persist_ifdown_and_create],
args=(cfg, )) args=(cfg, ))
ksft_exit() ksft_exit()