Memory provider HW selftests (i.e. zcrx, devmem) require setting up a netdev with e.g. flow steering rules. Add a new MemPrvEnv that sets up the test env, restoring it to the original state prior to the test. This also speeds up tests since each individual test case don't need to repeat the setup/teardown. Signed-off-by: David Wei --- .../drivers/net/hw/lib/py/__init__.py | 5 +- .../selftests/drivers/net/lib/py/__init__.py | 4 +- .../selftests/drivers/net/lib/py/env.py | 71 ++++++++++++++++++- 3 files changed, 75 insertions(+), 5 deletions(-) diff --git a/tools/testing/selftests/drivers/net/hw/lib/py/__init__.py b/tools/testing/selftests/drivers/net/hw/lib/py/__init__.py index fb010a48a5a1..09f120be9075 100644 --- a/tools/testing/selftests/drivers/net/hw/lib/py/__init__.py +++ b/tools/testing/selftests/drivers/net/hw/lib/py/__init__.py @@ -29,7 +29,7 @@ try: from net.lib.py import ksft_eq, ksft_ge, ksft_in, ksft_is, ksft_lt, \ ksft_ne, ksft_not_in, ksft_raises, ksft_true, ksft_gt, ksft_not_none from drivers.net.lib.py import GenerateTraffic, Remote - from drivers.net.lib.py import NetDrvEnv, NetDrvEpEnv + from drivers.net.lib.py import NetDrvEnv, NetDrvEpEnv, MemPrvEnv __all__ = ["NetNS", "NetNSEnter", "NetdevSimDev", "EthtoolFamily", "NetdevFamily", "NetshaperFamily", @@ -44,7 +44,8 @@ try: "ksft_eq", "ksft_ge", "ksft_in", "ksft_is", "ksft_lt", "ksft_ne", "ksft_not_in", "ksft_raises", "ksft_true", "ksft_gt", "ksft_not_none", "ksft_not_none", - "NetDrvEnv", "NetDrvEpEnv", "GenerateTraffic", "Remote"] + "GenerateTraffic", "Remote", + "NetDrvEnv", "NetDrvEpEnv", "MemPrvEnv"] except ModuleNotFoundError as e: print("Failed importing `net` library from kernel sources") print(str(e)) diff --git a/tools/testing/selftests/drivers/net/lib/py/__init__.py b/tools/testing/selftests/drivers/net/lib/py/__init__.py index b0c6300150fb..dde4e80811c7 100644 --- a/tools/testing/selftests/drivers/net/lib/py/__init__.py +++ b/tools/testing/selftests/drivers/net/lib/py/__init__.py @@ -43,11 +43,11 @@ try: "ksft_ne", "ksft_not_in", "ksft_raises", "ksft_true", "ksft_gt", "ksft_not_none", "ksft_not_none"] - from .env import NetDrvEnv, NetDrvEpEnv + from .env import NetDrvEnv, NetDrvEpEnv, MemPrvEnv from .load import GenerateTraffic from .remote import Remote - __all__ += ["NetDrvEnv", "NetDrvEpEnv", "GenerateTraffic", "Remote"] + __all__ += ["NetDrvEnv", "NetDrvEpEnv", "MemPrvEnv", "GenerateTraffic", "Remote"] except ModuleNotFoundError as e: print("Failed importing `net` library from kernel sources") print(str(e)) diff --git a/tools/testing/selftests/drivers/net/lib/py/env.py b/tools/testing/selftests/drivers/net/lib/py/env.py index 01be3d9b9720..3e19b57ef5e0 100644 --- a/tools/testing/selftests/drivers/net/lib/py/env.py +++ b/tools/testing/selftests/drivers/net/lib/py/env.py @@ -1,12 +1,14 @@ # SPDX-License-Identifier: GPL-2.0 import os +import re import time from pathlib import Path from lib.py import KsftSkipEx, KsftXfailEx from lib.py import ksft_setup, wait_file -from lib.py import cmd, ethtool, ip, CmdExitFailure +from lib.py import cmd, ethtool, ip, rand_port, CmdExitFailure from lib.py import NetNS, NetdevSimDev +from lib.py import EthtoolFamily from .remote import Remote @@ -283,3 +285,70 @@ class NetDrvEpEnv(NetDrvEnvBase): data.get('stats-block-usecs', 0) / 1000 / 1000 time.sleep(self._stats_settle_time) + + +class MemPrvEnv(NetDrvEpEnv): + def __init__(self, src_path, rss=False, rss_num=1, **kwargs): + super().__init__(src_path, False, **kwargs) + + self.ethnl = EthtoolFamily() + self.cleaned_up = False + + channels = self.ethnl.channels_get({'header': {'dev-index': self.ifindex}}) + self.channels = channels['combined-count'] + if self.channels < 2: + raise KsftSkipEx('Test requires NETIF with at least 2 combined channels') + + if rss and rss_num > self.channels - 1: + raise KsftSkipEx(f"Test with {rss_num} queues in RSS context requires NETIF with at least {rss_num + 1} combined channels") + + self.port = rand_port() + rings = self.ethnl.rings_get({'header': {'dev-index': self.ifindex}}) + self.rx_rings = rings['rx'] + self.hds_thresh = rings.get('hds-thresh', 0) + self.ethnl.rings_set({'header': {'dev-index': self.ifindex}, + 'tcp-data-split': 'enabled', + 'hds-thresh': 0, + 'rx': 64}) + + if rss: + self.target_queue = self.channels - rss_num + ethtool(f"-X {self.ifname} equal {self.target_queue}") + self.rss_ctx_id = self._create_rss_ctx(rss_num) + self.rule_id = self._set_rss_flow_rule() + else: + self.target_queue = self.channels - 1 + ethtool(f"-X {self.ifname} equal {self.target_queue}") + self.rss_ctx_id = None + self.rule_id = self._set_flow_rule() + + def __del__(self): + if self.cleaned_up: + return + + ethtool(f"-N {self.ifname} delete {self.rule_id}") + if self.rss_ctx_id: + self.ethnl.rss_delete_act({'header': {'dev-index': self.ifindex}, + 'context': self.rss_ctx_id}) + + ethtool(f"-X {self.ifname} default") + self.ethnl.rings_set({'header': {'dev-index': self.ifindex}, + 'tcp-data-split': 'unknown', + 'hds-thresh': self.hds_thresh, + 'rx': self.rx_rings}) + self.cleaned_up = True + + def _set_flow_rule(self): + output = ethtool(f"-N {self.ifname} flow-type tcp6 dst-port {self.port} action {self.target_queue}").stdout + values = re.search(r'ID (\d+)', output).group(1) + return int(values) + + def _set_rss_flow_rule(self): + output = ethtool(f"-N {self.ifname} flow-type tcp6 dst-port {self.port} context {self.rss_ctx_id}").stdout + values = re.search(r'ID (\d+)', output).group(1) + return int(values) + + def _create_rss_ctx(self, num): + output = ethtool(f"-X {self.ifname} context new start {self.target_queue} equal {num}").stdout + values = re.search(r'New RSS context is (\d+)', output).group(1) + return int(values) -- 2.47.3