mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
selftests: drv-net: tso: enable test cases based on hw_features
tso.py uses the active features at the time of test execution
as the set of available gso features to test. This means if a gso
feature is supported but toggled off at test start, the test will be
skipped with a "Device does not support {feature}" message.
Instead, we can enumerate the set of toggleable features by capturing
the driver's hw_features bitmap. To avoid configuration side-effects
from running the test, we also snapshot the wanted_features flag set
before making any feature changes, and then attempt to restore the
same set of wanted_features before test exit.
Fixes: 0d0f4174f6 ("selftests: drv-net: add a simple TSO test")
Signed-off-by: Daniel Zahka <daniel.zahka@gmail.com>
Link: https://patch.msgid.link/20250723184740.4075410-2-daniel.zahka@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
407c114c98
commit
266b835e5e
|
|
@ -119,15 +119,30 @@ def build_tunnel(cfg, outer_ipver, tun_info):
|
||||||
return remote_v4, remote_v6
|
return remote_v4, remote_v6
|
||||||
|
|
||||||
|
|
||||||
|
def restore_wanted_features(cfg):
|
||||||
|
features_cmd = ""
|
||||||
|
for feature in cfg.hw_features:
|
||||||
|
setting = "on" if feature in cfg.wanted_features else "off"
|
||||||
|
features_cmd += f" {feature} {setting}"
|
||||||
|
try:
|
||||||
|
ethtool(f"-K {cfg.ifname} {features_cmd}")
|
||||||
|
except Exception as e:
|
||||||
|
ksft_pr(f"WARNING: failure restoring wanted features: {e}")
|
||||||
|
|
||||||
|
|
||||||
def test_builder(name, cfg, outer_ipver, feature, tun=None, inner_ipver=None):
|
def test_builder(name, cfg, outer_ipver, feature, tun=None, inner_ipver=None):
|
||||||
"""Construct specific tests from the common template."""
|
"""Construct specific tests from the common template."""
|
||||||
def f(cfg):
|
def f(cfg):
|
||||||
cfg.require_ipver(outer_ipver)
|
cfg.require_ipver(outer_ipver)
|
||||||
|
defer(restore_wanted_features, cfg)
|
||||||
|
|
||||||
if not cfg.have_stat_super_count and \
|
if not cfg.have_stat_super_count and \
|
||||||
not cfg.have_stat_wire_count:
|
not cfg.have_stat_wire_count:
|
||||||
raise KsftSkipEx(f"Device does not support LSO queue stats")
|
raise KsftSkipEx(f"Device does not support LSO queue stats")
|
||||||
|
|
||||||
|
if feature not in cfg.hw_features:
|
||||||
|
raise KsftSkipEx(f"Device does not support {feature}")
|
||||||
|
|
||||||
ipver = outer_ipver
|
ipver = outer_ipver
|
||||||
if tun:
|
if tun:
|
||||||
remote_v4, remote_v6 = build_tunnel(cfg, ipver, tun)
|
remote_v4, remote_v6 = build_tunnel(cfg, ipver, tun)
|
||||||
|
|
@ -138,12 +153,12 @@ def test_builder(name, cfg, outer_ipver, feature, tun=None, inner_ipver=None):
|
||||||
|
|
||||||
tun_partial = tun and tun[1]
|
tun_partial = tun and tun[1]
|
||||||
# Tunnel which can silently fall back to gso-partial
|
# Tunnel which can silently fall back to gso-partial
|
||||||
has_gso_partial = tun and 'tx-gso-partial' in cfg.features
|
has_gso_partial = tun and 'tx-gso-partial' in cfg.hw_features
|
||||||
|
|
||||||
# For TSO4 via partial we need mangleid
|
# For TSO4 via partial we need mangleid
|
||||||
if ipver == "4" and feature in cfg.partial_features:
|
if ipver == "4" and feature in cfg.partial_features:
|
||||||
ksft_pr("Testing with mangleid enabled")
|
ksft_pr("Testing with mangleid enabled")
|
||||||
if 'tx-tcp-mangleid-segmentation' not in cfg.features:
|
if 'tx-tcp-mangleid-segmentation' not in cfg.hw_features:
|
||||||
ethtool(f"-K {cfg.ifname} tx-tcp-mangleid-segmentation on")
|
ethtool(f"-K {cfg.ifname} tx-tcp-mangleid-segmentation on")
|
||||||
defer(ethtool, f"-K {cfg.ifname} tx-tcp-mangleid-segmentation off")
|
defer(ethtool, f"-K {cfg.ifname} tx-tcp-mangleid-segmentation off")
|
||||||
|
|
||||||
|
|
@ -161,11 +176,8 @@ def test_builder(name, cfg, outer_ipver, feature, tun=None, inner_ipver=None):
|
||||||
should_lso=tun_partial)
|
should_lso=tun_partial)
|
||||||
|
|
||||||
# Full feature enabled.
|
# Full feature enabled.
|
||||||
if feature in cfg.features:
|
ethtool(f"-K {cfg.ifname} {feature} on")
|
||||||
ethtool(f"-K {cfg.ifname} {feature} on")
|
run_one_stream(cfg, ipver, remote_v4, remote_v6, should_lso=True)
|
||||||
run_one_stream(cfg, ipver, remote_v4, remote_v6, should_lso=True)
|
|
||||||
else:
|
|
||||||
raise KsftXfailEx(f"Device does not support {feature}")
|
|
||||||
|
|
||||||
f.__name__ = name + ((outer_ipver + "_") if tun else "") + "ipv" + inner_ipver
|
f.__name__ = name + ((outer_ipver + "_") if tun else "") + "ipv" + inner_ipver
|
||||||
return f
|
return f
|
||||||
|
|
@ -176,23 +188,39 @@ def query_nic_features(cfg) -> None:
|
||||||
cfg.have_stat_super_count = False
|
cfg.have_stat_super_count = False
|
||||||
cfg.have_stat_wire_count = False
|
cfg.have_stat_wire_count = False
|
||||||
|
|
||||||
cfg.features = set()
|
|
||||||
features = cfg.ethnl.features_get({"header": {"dev-index": cfg.ifindex}})
|
features = cfg.ethnl.features_get({"header": {"dev-index": cfg.ifindex}})
|
||||||
for f in features["active"]["bits"]["bit"]:
|
|
||||||
cfg.features.add(f["name"])
|
cfg.wanted_features = set()
|
||||||
|
for f in features["wanted"]["bits"]["bit"]:
|
||||||
|
cfg.wanted_features.add(f["name"])
|
||||||
|
|
||||||
|
cfg.hw_features = set()
|
||||||
|
hw_all_features_cmd = ""
|
||||||
|
for f in features["hw"]["bits"]["bit"]:
|
||||||
|
if f.get("value", False):
|
||||||
|
feature = f["name"]
|
||||||
|
cfg.hw_features.add(feature)
|
||||||
|
hw_all_features_cmd += f" {feature} on"
|
||||||
|
try:
|
||||||
|
ethtool(f"-K {cfg.ifname} {hw_all_features_cmd}")
|
||||||
|
except Exception as e:
|
||||||
|
ksft_pr(f"WARNING: failure enabling all hw features: {e}")
|
||||||
|
ksft_pr("partial gso feature detection may be impacted")
|
||||||
|
|
||||||
# Check which features are supported via GSO partial
|
# Check which features are supported via GSO partial
|
||||||
cfg.partial_features = set()
|
cfg.partial_features = set()
|
||||||
if 'tx-gso-partial' in cfg.features:
|
if 'tx-gso-partial' in cfg.hw_features:
|
||||||
ethtool(f"-K {cfg.ifname} tx-gso-partial off")
|
ethtool(f"-K {cfg.ifname} tx-gso-partial off")
|
||||||
|
|
||||||
no_partial = set()
|
no_partial = set()
|
||||||
features = cfg.ethnl.features_get({"header": {"dev-index": cfg.ifindex}})
|
features = cfg.ethnl.features_get({"header": {"dev-index": cfg.ifindex}})
|
||||||
for f in features["active"]["bits"]["bit"]:
|
for f in features["active"]["bits"]["bit"]:
|
||||||
no_partial.add(f["name"])
|
no_partial.add(f["name"])
|
||||||
cfg.partial_features = cfg.features - no_partial
|
cfg.partial_features = cfg.hw_features - no_partial
|
||||||
ethtool(f"-K {cfg.ifname} tx-gso-partial on")
|
ethtool(f"-K {cfg.ifname} tx-gso-partial on")
|
||||||
|
|
||||||
|
restore_wanted_features(cfg)
|
||||||
|
|
||||||
stats = cfg.netnl.qstats_get({"ifindex": cfg.ifindex}, dump=True)
|
stats = cfg.netnl.qstats_get({"ifindex": cfg.ifindex}, dump=True)
|
||||||
if stats:
|
if stats:
|
||||||
if 'tx-hw-gso-packets' in stats[0]:
|
if 'tx-hw-gso-packets' in stats[0]:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user