From patchwork Fri Apr 5 02:45:22 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Kicinski X-Patchwork-Id: 13618386 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 269DB17545; Fri, 5 Apr 2024 02:45:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712285134; cv=none; b=UlppqG3uyJFacKwwnr/lNxyMYntk2ysZT2Q7otDxdZtY0LJlYWZJm3N6p84hiJk8aK+j/5ZsQdFqUcXXEjVP4Ynuxi5vI8MlMk09+O1wFGtjWfp9fDoB2G3HhOCAFpp4G14/vGXpJRj9Vye37nG8c/Xd+rAmmpt6HXLbZGRiIhY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712285134; c=relaxed/simple; bh=unZQHvn/kxtIR9uZeddfSiUMm6D8lZg+s2E/GRHJBvA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=jNDyv0vnjP7UtchlmUMOk2xr2jy3liJJBrYrXWbv/H9ZKI2aoHEsGWMx1YM3fpeMBZB/622mt1k/B2t0SXEwT9L9NpBoQHdvFsDhy962PN+khOYKkuPfUZdhiBpGyVk1USv2fUMTOq1xrLyyX3DLpUAFbqQ/l5TDoJFyL9ue+aA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=UMRceqpE; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="UMRceqpE" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 44149C43390; Fri, 5 Apr 2024 02:45:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1712285133; bh=unZQHvn/kxtIR9uZeddfSiUMm6D8lZg+s2E/GRHJBvA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=UMRceqpEuYcGInWhOqE+XOvI/VL8sUUhzYtgZCLCI0qCFCI9d7QVmuZKYEZhkX1M/ flrf4xS/y08J/5WeEqHmCo8S7zCJ/7XKiM5vgzxa/40LqIFHF6cbI0Iat4yTrJDPcw BYKRRVb3y1JFXDFmhqnXEIN+umhsj51a4Ul8C3J+vUoueHiLnUMjCGUcFZkl4oKbed LcPy2T+tmV/0EmP45tBGzManI2cEHT5pflr08j7cbtTftmIviTm74QJ9X1oXreGdim kIfSc/YOl/8RDwUCEO2xLoVSC7O3sossvPYr0LGDfEK7t2PH6wnLx+gDfGP6F8EdJU NJgYGJsNdfE4Q== From: Jakub Kicinski To: davem@davemloft.net Cc: netdev@vger.kernel.org, edumazet@google.com, pabeni@redhat.com, shuah@kernel.org, sdf@google.com, donald.hunter@gmail.com, linux-kselftest@vger.kernel.org, petrm@nvidia.com, Jakub Kicinski Subject: [PATCH net-next v3 1/5] selftests: net: add scaffolding for Netlink tests in Python Date: Thu, 4 Apr 2024 19:45:22 -0700 Message-ID: <20240405024526.2752998-2-kuba@kernel.org> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240405024526.2752998-1-kuba@kernel.org> References: <20240405024526.2752998-1-kuba@kernel.org> Precedence: bulk X-Mailing-List: linux-kselftest@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add glue code for accessing the YNL library which lives under tools/net and YAML spec files from under Documentation/. Automatically figure out if tests are run in tree or not. Since we'll want to use this library both from net and drivers/net test targets make the library a target as well, and automatically include it when net or drivers/net are included. Making net/lib a target ensures that we end up with only one copy of it, and saves us some path guessing. Add a tiny bit of formatting support to be able to output KTAP from the start. Reviewed-by: Petr Machata Signed-off-by: Jakub Kicinski --- v3: - don't use unnecessary wildcards v2: - include the net/lib only in install - support passing state to tests - don't apply Path() on what's already a Path() - fix spacing in Makefile's filter() - sort imports CC: shuah@kernel.org CC: linux-kselftest@vger.kernel.org --- tools/testing/selftests/Makefile | 9 +- tools/testing/selftests/net/lib/Makefile | 8 ++ .../testing/selftests/net/lib/py/__init__.py | 6 ++ tools/testing/selftests/net/lib/py/consts.py | 9 ++ tools/testing/selftests/net/lib/py/ksft.py | 96 +++++++++++++++++++ tools/testing/selftests/net/lib/py/utils.py | 47 +++++++++ tools/testing/selftests/net/lib/py/ynl.py | 49 ++++++++++ 7 files changed, 223 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/net/lib/Makefile create mode 100644 tools/testing/selftests/net/lib/py/__init__.py create mode 100644 tools/testing/selftests/net/lib/py/consts.py create mode 100644 tools/testing/selftests/net/lib/py/ksft.py create mode 100644 tools/testing/selftests/net/lib/py/utils.py create mode 100644 tools/testing/selftests/net/lib/py/ynl.py diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile index e1504833654d..f533eb7054fe 100644 --- a/tools/testing/selftests/Makefile +++ b/tools/testing/selftests/Makefile @@ -116,6 +116,13 @@ TARGETS += zram TARGETS_HOTPLUG = cpu-hotplug TARGETS_HOTPLUG += memory-hotplug +# Networking tests want the net/lib target, include it automatically +ifneq ($(filter net,$(TARGETS)),) +ifeq ($(filter net/lib,$(TARGETS)),) + INSTALL_DEP_TARGETS := net/lib +endif +endif + # User can optionally provide a TARGETS skiplist. By default we skip # BPF since it has cutting edge build time dependencies which require # more effort to install. @@ -245,7 +252,7 @@ ifdef INSTALL_PATH install -m 744 run_kselftest.sh $(INSTALL_PATH)/ rm -f $(TEST_LIST) @ret=1; \ - for TARGET in $(TARGETS); do \ + for TARGET in $(TARGETS) $(INSTALL_DEP_TARGETS); do \ BUILD_TARGET=$$BUILD/$$TARGET; \ $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET install \ INSTALL_PATH=$(INSTALL_PATH)/$$TARGET \ diff --git a/tools/testing/selftests/net/lib/Makefile b/tools/testing/selftests/net/lib/Makefile new file mode 100644 index 000000000000..48557e6250dd --- /dev/null +++ b/tools/testing/selftests/net/lib/Makefile @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0 + +TEST_FILES := ../../../../../Documentation/netlink/specs +TEST_FILES += ../../../../net/ynl + +TEST_INCLUDES := $(wildcard py/*.py) + +include ../../lib.mk diff --git a/tools/testing/selftests/net/lib/py/__init__.py b/tools/testing/selftests/net/lib/py/__init__.py new file mode 100644 index 000000000000..7823b5c1f8d7 --- /dev/null +++ b/tools/testing/selftests/net/lib/py/__init__.py @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0 + +from .consts import KSRC +from .ksft import * +from .utils import * +from .ynl import NlError, YnlFamily, EthtoolFamily, NetdevFamily, RtnlFamily diff --git a/tools/testing/selftests/net/lib/py/consts.py b/tools/testing/selftests/net/lib/py/consts.py new file mode 100644 index 000000000000..f518ce79d82c --- /dev/null +++ b/tools/testing/selftests/net/lib/py/consts.py @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0 + +import sys +from pathlib import Path + +KSFT_DIR = (Path(__file__).parent / "../../..").resolve() +KSRC = (Path(__file__).parent / "../../../../../..").resolve() + +KSFT_MAIN_NAME = Path(sys.argv[0]).with_suffix("").name diff --git a/tools/testing/selftests/net/lib/py/ksft.py b/tools/testing/selftests/net/lib/py/ksft.py new file mode 100644 index 000000000000..c7210525981c --- /dev/null +++ b/tools/testing/selftests/net/lib/py/ksft.py @@ -0,0 +1,96 @@ +# SPDX-License-Identifier: GPL-2.0 + +import builtins +from .consts import KSFT_MAIN_NAME + +KSFT_RESULT = None + + +class KsftSkipEx(Exception): + pass + + +class KsftXfailEx(Exception): + pass + + +def ksft_pr(*objs, **kwargs): + print("#", *objs, **kwargs) + + +def ksft_eq(a, b, comment=""): + global KSFT_RESULT + if a != b: + KSFT_RESULT = False + ksft_pr("Check failed", a, "!=", b, comment) + + +def ksft_true(a, comment=""): + global KSFT_RESULT + if not a: + KSFT_RESULT = False + ksft_pr("Check failed", a, "does not eval to True", comment) + + +def ksft_in(a, b, comment=""): + global KSFT_RESULT + if a not in b: + KSFT_RESULT = False + ksft_pr("Check failed", a, "not in", b, comment) + + +def ksft_ge(a, b, comment=""): + global KSFT_RESULT + if a < b: + KSFT_RESULT = False + ksft_pr("Check failed", a, "<", b, comment) + + +def ktap_result(ok, cnt=1, case="", comment=""): + res = "" + if not ok: + res += "not " + res += "ok " + res += str(cnt) + " " + res += KSFT_MAIN_NAME + if case: + res += "." + str(case.__name__) + if comment: + res += " # " + comment + print(res) + + +def ksft_run(cases, args=()): + totals = {"pass": 0, "fail": 0, "skip": 0, "xfail": 0} + + print("KTAP version 1") + print("1.." + str(len(cases))) + + global KSFT_RESULT + cnt = 0 + for case in cases: + KSFT_RESULT = True + cnt += 1 + try: + case(*args) + except KsftSkipEx as e: + ktap_result(True, cnt, case, comment="SKIP " + str(e)) + totals['skip'] += 1 + continue + except KsftXfailEx as e: + ktap_result(True, cnt, case, comment="XFAIL " + str(e)) + totals['xfail'] += 1 + continue + except Exception as e: + for line in str(e).split('\n'): + ksft_pr("Exception|", line) + ktap_result(False, cnt, case) + totals['fail'] += 1 + continue + + ktap_result(KSFT_RESULT, cnt, case) + totals['pass'] += 1 + + print( + f"# Totals: pass:{totals['pass']} fail:{totals['fail']} xfail:{totals['xfail']} xpass:0 skip:{totals['skip']} error:0" + ) diff --git a/tools/testing/selftests/net/lib/py/utils.py b/tools/testing/selftests/net/lib/py/utils.py new file mode 100644 index 000000000000..f0d425731fd4 --- /dev/null +++ b/tools/testing/selftests/net/lib/py/utils.py @@ -0,0 +1,47 @@ +# SPDX-License-Identifier: GPL-2.0 + +import json as _json +import subprocess + +class cmd: + def __init__(self, comm, shell=True, fail=True, ns=None, background=False): + if ns: + if isinstance(ns, NetNS): + ns = ns.name + comm = f'ip netns exec {ns} ' + comm + + self.stdout = None + self.stderr = None + self.ret = None + + self.comm = comm + self.proc = subprocess.Popen(comm, shell=shell, stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + if not background: + self.process(terminate=False, fail=fail) + + def process(self, terminate=True, fail=None): + if terminate: + self.proc.terminate() + stdout, stderr = self.proc.communicate() + self.stdout = stdout.decode("utf-8") + self.stderr = stderr.decode("utf-8") + self.proc.stdout.close() + self.proc.stderr.close() + self.ret = self.proc.returncode + + if self.proc.returncode != 0 and fail: + if len(stderr) > 0 and stderr[-1] == "\n": + stderr = stderr[:-1] + raise Exception("Command failed: %s\n%s" % (self.proc.args, stderr)) + + +def ip(args, json=None, ns=None): + cmd_str = "ip " + if json: + cmd_str += '-j ' + cmd_str += args + cmd_obj = cmd(cmd_str, ns=ns) + if json: + return _json.loads(cmd_obj.stdout) + return cmd_obj diff --git a/tools/testing/selftests/net/lib/py/ynl.py b/tools/testing/selftests/net/lib/py/ynl.py new file mode 100644 index 000000000000..1ace58370c06 --- /dev/null +++ b/tools/testing/selftests/net/lib/py/ynl.py @@ -0,0 +1,49 @@ +# SPDX-License-Identifier: GPL-2.0 + +import sys +from pathlib import Path +from .consts import KSRC, KSFT_DIR +from .ksft import ksft_pr, ktap_result + +# Resolve paths +try: + if (KSFT_DIR / "kselftest-list.txt").exists(): + # Running in "installed" selftests + tools_full_path = KSFT_DIR + SPEC_PATH = KSFT_DIR / "net/lib/specs" + + sys.path.append(tools_full_path.as_posix()) + from net.lib.ynl.lib import YnlFamily, NlError + else: + # Running in tree + tools_full_path = KSRC / "tools" + SPEC_PATH = KSRC / "Documentation/netlink/specs" + + sys.path.append(tools_full_path.as_posix()) + from net.ynl.lib import YnlFamily, NlError +except ModuleNotFoundError as e: + ksft_pr("Failed importing `ynl` library from kernel sources") + ksft_pr(str(e)) + ktap_result(True, comment="SKIP") + sys.exit(4) + +# +# Wrapper classes, loading the right specs +# Set schema='' to avoid jsonschema validation, it's slow +# +class EthtoolFamily(YnlFamily): + def __init__(self): + super().__init__((SPEC_PATH / Path('ethtool.yaml')).as_posix(), + schema='') + + +class RtnlFamily(YnlFamily): + def __init__(self): + super().__init__((SPEC_PATH / Path('rt_link.yaml')).as_posix(), + schema='') + + +class NetdevFamily(YnlFamily): + def __init__(self): + super().__init__((SPEC_PATH / Path('netdev.yaml')).as_posix(), + schema='') From patchwork Fri Apr 5 02:45:23 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Kicinski X-Patchwork-Id: 13618387 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B951B17BAA; Fri, 5 Apr 2024 02:45:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712285134; cv=none; b=GuOPbreBd6+bCp3rOSyapngnWSQ7kHdhQH2nlzDwkn9Moy7e7Y1x1A/d27Gdfuhe5lJVEc0pfa8nbY6wjUxP/uUcEU8h94EO9q1F0HhamFU5rx9g7k6J41PouVEXBuI1F5+0+cI0FWLzf37ypuFTOjNo5pqBe9+0eTg0KJ5Maqw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712285134; c=relaxed/simple; bh=IvV+aDZV9LoDJKeFJ1Ku34Z4N3M29tyMD6RuL09yyoA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=fE9++DTTpPN/dVBo0lvwA1vWQYUhdxTkYzTulC/5X5TZvk4kR5Aqgnt+063dX22XESNs6jPbckjqMHLl++zyMVdtTb8pdh9oRBx+LrwrAfqtLxQDVt9Z32XVqWd1dFRQ5goKPOqpLW376EBdzAd/DvFpwSbowRl9tFMX7GRNoSo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=BDcB1IeA; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="BDcB1IeA" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D4955C43399; Fri, 5 Apr 2024 02:45:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1712285134; bh=IvV+aDZV9LoDJKeFJ1Ku34Z4N3M29tyMD6RuL09yyoA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=BDcB1IeA03Bu8noSy2z6U3BLh8W7kOBZSS0UcgZQBnpjWBytfaH6UVNs2QMwoNJRz BFwdu1ytU5BwOZ1T8TednGteeSByxtxNl82uh8AdhrpWWK1JJKnbxGxR4JAWg04jtF EzKHTKgImJnv6sK4QA2JfUTp1dDJFJcvMOdy8cLmd80/6NuPgnh65pViStIfxX9RbC 3Q1Z06JbtjSwa4Z3oIOrPwX8qDHh3opL9gKUthsW7t7bYEmCgdGtQyhU/B5KSFj+xU GQSE8yY0vOiORrkK3PQeND2zSV0bj0WgfUNlRw6qr0Uq4zKDgJ7VdbxUFtyGka9EWP JNwTWaaTaRFdQ== From: Jakub Kicinski To: davem@davemloft.net Cc: netdev@vger.kernel.org, edumazet@google.com, pabeni@redhat.com, shuah@kernel.org, sdf@google.com, donald.hunter@gmail.com, linux-kselftest@vger.kernel.org, petrm@nvidia.com, Jakub Kicinski Subject: [PATCH net-next v3 2/5] selftests: nl_netdev: add a trivial Netlink netdev test Date: Thu, 4 Apr 2024 19:45:23 -0700 Message-ID: <20240405024526.2752998-3-kuba@kernel.org> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240405024526.2752998-1-kuba@kernel.org> References: <20240405024526.2752998-1-kuba@kernel.org> Precedence: bulk X-Mailing-List: linux-kselftest@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add a trivial test using YNL. $ ./tools/testing/selftests/net/nl_netdev.py KTAP version 1 1..2 ok 1 nl_netdev.empty_check ok 2 nl_netdev.lo_check Instantiate the family once, it takes longer than the test itself. Reviewed-by: Petr Machata Signed-off-by: Jakub Kicinski --- v2: - pass family as argument CC: shuah@kernel.org CC: linux-kselftest@vger.kernel.org --- tools/testing/selftests/net/Makefile | 1 + tools/testing/selftests/net/nl_netdev.py | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100755 tools/testing/selftests/net/nl_netdev.py diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile index cb418a2346bc..5e34c93aa51b 100644 --- a/tools/testing/selftests/net/Makefile +++ b/tools/testing/selftests/net/Makefile @@ -34,6 +34,7 @@ TEST_PROGS += gre_gso.sh TEST_PROGS += cmsg_so_mark.sh TEST_PROGS += cmsg_time.sh cmsg_ipv6.sh TEST_PROGS += netns-name.sh +TEST_PROGS += nl_netdev.py TEST_PROGS += srv6_end_dt46_l3vpn_test.sh TEST_PROGS += srv6_end_dt4_l3vpn_test.sh TEST_PROGS += srv6_end_dt6_l3vpn_test.sh diff --git a/tools/testing/selftests/net/nl_netdev.py b/tools/testing/selftests/net/nl_netdev.py new file mode 100755 index 000000000000..2b8b488fb419 --- /dev/null +++ b/tools/testing/selftests/net/nl_netdev.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0 + +from lib.py import ksft_run, ksft_pr, ksft_eq, ksft_ge, NetdevFamily + + +def empty_check(nf) -> None: + devs = nf.dev_get({}, dump=True) + ksft_ge(len(devs), 1) + + +def lo_check(nf) -> None: + lo_info = nf.dev_get({"ifindex": 1}) + ksft_eq(len(lo_info['xdp-features']), 0) + ksft_eq(len(lo_info['xdp-rx-metadata-features']), 0) + + +def main() -> None: + nf = NetdevFamily() + ksft_run([empty_check, lo_check], args=(nf, )) + + +if __name__ == "__main__": + main() From patchwork Fri Apr 5 02:45:24 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Kicinski X-Patchwork-Id: 13618388 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5D58719BA3; Fri, 5 Apr 2024 02:45:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712285135; cv=none; b=a+J0YEtkQfTuCBdJe6jPFiCZPsR8e4ZxOkBCg5RUtx6Xd5qccz705bTgngulMq823WiG/Weu0iK/DC4pmN7eI6GH7h4bOiu28g+YnVJQa6QpKWqZbcGaKrnIx4y5azwoIIkNVyyQW/znlwg/kbaGowXr5CxzwSbYUsO58IeSf9A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712285135; c=relaxed/simple; bh=8zBOozCsRUE20wUotX0eaUXsRl6qJOhNiqFBWZmLX4Y=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=QgIxHghqzHYqykqUMAzyC8Ea/OPfLzFFRNby1+Pzu5/Nj/BW3dZEqJ2jPCC0u0RhxCUjgyoX8iACahNuvv1fJ/oOuL8mzCJ4wBH9oTCZzdwAL3yoXil5ELKJoGF3SjItWAJxKjBL8Rbq9PIW8UT5Qfsbss64u/j48oAgWB0oT4Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=UfWWnXN6; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="UfWWnXN6" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 720DFC43394; Fri, 5 Apr 2024 02:45:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1712285134; bh=8zBOozCsRUE20wUotX0eaUXsRl6qJOhNiqFBWZmLX4Y=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=UfWWnXN689gX8u4dgs0mmnWWHWTr/psYHV93a6WZYXQt9KsLYUFJgXwpccgC6U5LO fgbjQnemZgYPRLsu/oYyFBJZ6LtEz4ZLxDpO6NqfUAxrBHl+k8+QG7+h9nzjBDc00h Vbwqg2GoRVznZzyaNXdqMUa8P75xR/xa96qiwy7N9ddpQTWIArcUTBjUtMd/DduToq KPYVvNwa/MnNyB1839yCAxE9wUPo5e4vnwbpjFqxXmCubFzfEG9qtUdR3iFQkP9zHb QmcKsPca72Llk9yUnjvWh3eWCdehyjjfb2A4F/DhfhAMxv6fa8UPhrE9BDmxiDnODi 2D7eVY531LLNg== From: Jakub Kicinski To: davem@davemloft.net Cc: netdev@vger.kernel.org, edumazet@google.com, pabeni@redhat.com, shuah@kernel.org, sdf@google.com, donald.hunter@gmail.com, linux-kselftest@vger.kernel.org, petrm@nvidia.com, Jakub Kicinski Subject: [PATCH net-next v3 3/5] netdevsim: report stats by default, like a real device Date: Thu, 4 Apr 2024 19:45:24 -0700 Message-ID: <20240405024526.2752998-4-kuba@kernel.org> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240405024526.2752998-1-kuba@kernel.org> References: <20240405024526.2752998-1-kuba@kernel.org> Precedence: bulk X-Mailing-List: linux-kselftest@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Real devices should implement qstats. Devices which support pause or FEC configuration should also report the relevant stats. nsim was missing FEC stats completely, some of the qstats and pause stats required toggling a debugfs knob. Note that the tests which used pause always initialize the setting so they shouldn't be affected by the different starting value. Signed-off-by: Jakub Kicinski --- v3: - spelling in comment - make sure we don't break when more queues present --- drivers/net/netdevsim/ethtool.c | 11 ++++++++ drivers/net/netdevsim/netdev.c | 49 +++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/drivers/net/netdevsim/ethtool.c b/drivers/net/netdevsim/ethtool.c index bd546d4d26c6..3f9c9327f149 100644 --- a/drivers/net/netdevsim/ethtool.c +++ b/drivers/net/netdevsim/ethtool.c @@ -140,6 +140,13 @@ nsim_set_fecparam(struct net_device *dev, struct ethtool_fecparam *fecparam) return 0; } +static void +nsim_get_fec_stats(struct net_device *dev, struct ethtool_fec_stats *fec_stats) +{ + fec_stats->corrected_blocks.total = 123; + fec_stats->uncorrectable_blocks.total = 4; +} + static int nsim_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info) { @@ -163,6 +170,7 @@ static const struct ethtool_ops nsim_ethtool_ops = { .set_channels = nsim_set_channels, .get_fecparam = nsim_get_fecparam, .set_fecparam = nsim_set_fecparam, + .get_fec_stats = nsim_get_fec_stats, .get_ts_info = nsim_get_ts_info, }; @@ -182,6 +190,9 @@ void nsim_ethtool_init(struct netdevsim *ns) nsim_ethtool_ring_init(ns); + ns->ethtool.pauseparam.report_stats_rx = true; + ns->ethtool.pauseparam.report_stats_tx = true; + ns->ethtool.fec.fec = ETHTOOL_FEC_NONE; ns->ethtool.fec.active_fec = ETHTOOL_FEC_NONE; diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c index 8330bc0bcb7e..d7ba447db17c 100644 --- a/drivers/net/netdevsim/netdev.c +++ b/drivers/net/netdevsim/netdev.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -330,6 +331,53 @@ static const struct net_device_ops nsim_vf_netdev_ops = { .ndo_set_features = nsim_set_features, }; +/* We don't have true per-queue stats, yet, so do some random fakery here. + * Only report stuff for queue 0. + */ +static void nsim_get_queue_stats_rx(struct net_device *dev, int idx, + struct netdev_queue_stats_rx *stats) +{ + struct rtnl_link_stats64 rtstats = {}; + + if (!idx) + nsim_get_stats64(dev, &rtstats); + + stats->packets = rtstats.rx_packets - !!rtstats.rx_packets; + stats->bytes = rtstats.rx_bytes; +} + +static void nsim_get_queue_stats_tx(struct net_device *dev, int idx, + struct netdev_queue_stats_tx *stats) +{ + struct rtnl_link_stats64 rtstats = {}; + + if (!idx) + nsim_get_stats64(dev, &rtstats); + + stats->packets = rtstats.tx_packets - !!rtstats.tx_packets; + stats->bytes = rtstats.tx_bytes; +} + +static void nsim_get_base_stats(struct net_device *dev, + struct netdev_queue_stats_rx *rx, + struct netdev_queue_stats_tx *tx) +{ + struct rtnl_link_stats64 rtstats = {}; + + nsim_get_stats64(dev, &rtstats); + + rx->packets = !!rtstats.rx_packets; + rx->bytes = 0; + tx->packets = !!rtstats.tx_packets; + tx->bytes = 0; +} + +static const struct netdev_stat_ops nsim_stat_ops = { + .get_queue_stats_tx = nsim_get_queue_stats_tx, + .get_queue_stats_rx = nsim_get_queue_stats_rx, + .get_base_stats = nsim_get_base_stats, +}; + static void nsim_setup(struct net_device *dev) { ether_setup(dev); @@ -360,6 +408,7 @@ static int nsim_init_netdevsim(struct netdevsim *ns) ns->phc = phc; ns->netdev->netdev_ops = &nsim_netdev_ops; + ns->netdev->stat_ops = &nsim_stat_ops; err = nsim_udp_tunnels_info_create(ns->nsim_dev, ns->netdev); if (err) From patchwork Fri Apr 5 02:45:25 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Kicinski X-Patchwork-Id: 13618389 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D2B591BC40; Fri, 5 Apr 2024 02:45:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712285135; cv=none; b=QqgLzoSrsljI//HUg6E/S+lEbmo3y3K4Tt1R8yvOIjTWnhAlbQEe4rX4zyQH+7NWOzr7Hrm+vVmd3gFrBr7usws/qy4KuCno8XPKhOfaXONtRFPeMhH80oZHGbB+A4J/OffIAk1KAoLaniYTPwVhbjZcpC4ltS0E7Y4Cx0+V2H4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712285135; c=relaxed/simple; bh=rwxiT3e14txKP/L321/tXgZ3D1AVlQgl4Dw9EYspdLQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=BXGI8Wa8xNqcU99tS6Hg3oY7i6x6sToYoFoZpXTWAgWZjxhcLpEpfz626Ozfp27k5Ocip6YD46TvDSg+L1xVA6DpsOkJBoHPlUQMEkS/na8+JMHHUtHCCqodnPLurbAHOhMZg+wLo+kGFx1hiRcoQeHoVld7NXgdF18uw4hG43g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=s9dpv6m7; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="s9dpv6m7" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 12A3FC43390; Fri, 5 Apr 2024 02:45:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1712285135; bh=rwxiT3e14txKP/L321/tXgZ3D1AVlQgl4Dw9EYspdLQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=s9dpv6m73MCC8DXQcMIFM+F6b/22Ph/fis80VkA6JXf3yo1L+xZWba1ZvFc7N8g+8 nhVslNyPizM/hGZb/a1rKyqEEPmr//ykxKCy4fRLkap8+rDYFCRWKVAmsRJFn5F8b0 bGswQzS6A60CYz5gcX7+CtX9BqsFmvsNPUiwDIv19CIb13Na63b3DODPn1raGkFsd0 IUNkPvKPVHgFxh9rmQ91dUpo3ZehAP0MtEpNPQb0JRP2nsBWFqInZVPhldkyvH4LfB 7G1u1nWYIDKc8kQ/pfIR5PBG4dURKm7yF12+S9ZzlQ99HXocbkUURNpHsb5F3ZAWq/ AHSrJmIRwBzsg== From: Jakub Kicinski To: davem@davemloft.net Cc: netdev@vger.kernel.org, edumazet@google.com, pabeni@redhat.com, shuah@kernel.org, sdf@google.com, donald.hunter@gmail.com, linux-kselftest@vger.kernel.org, petrm@nvidia.com, Jakub Kicinski Subject: [PATCH net-next v3 4/5] selftests: drivers: add scaffolding for Netlink tests in Python Date: Thu, 4 Apr 2024 19:45:25 -0700 Message-ID: <20240405024526.2752998-5-kuba@kernel.org> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240405024526.2752998-1-kuba@kernel.org> References: <20240405024526.2752998-1-kuba@kernel.org> Precedence: bulk X-Mailing-List: linux-kselftest@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add drivers/net as a target for mixed-use tests. The setup is expected to work similarly to the forwarding tests. Since we only need one interface (unlike forwarding tests) read the target device name from NETIF. If not present we'll try to run the test against netdevsim. Reviewed-by: Petr Machata Signed-off-by: Jakub Kicinski --- v3: - spelling - remove some fields v2: - mark regex as r"" - add support of using env as with --- tools/testing/selftests/Makefile | 3 +- tools/testing/selftests/drivers/net/Makefile | 7 ++ .../testing/selftests/drivers/net/README.rst | 30 +++++ .../selftests/drivers/net/lib/py/__init__.py | 17 +++ .../selftests/drivers/net/lib/py/env.py | 52 ++++++++ .../testing/selftests/net/lib/py/__init__.py | 1 + tools/testing/selftests/net/lib/py/nsim.py | 115 ++++++++++++++++++ 7 files changed, 224 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/drivers/net/Makefile create mode 100644 tools/testing/selftests/drivers/net/README.rst create mode 100644 tools/testing/selftests/drivers/net/lib/py/__init__.py create mode 100644 tools/testing/selftests/drivers/net/lib/py/env.py create mode 100644 tools/testing/selftests/net/lib/py/nsim.py diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile index f533eb7054fe..6dab886d6f7a 100644 --- a/tools/testing/selftests/Makefile +++ b/tools/testing/selftests/Makefile @@ -17,6 +17,7 @@ TARGETS += devices TARGETS += dmabuf-heaps TARGETS += drivers/dma-buf TARGETS += drivers/s390x/uvdevice +TARGETS += drivers/net TARGETS += drivers/net/bonding TARGETS += drivers/net/team TARGETS += dt @@ -117,7 +118,7 @@ TARGETS_HOTPLUG = cpu-hotplug TARGETS_HOTPLUG += memory-hotplug # Networking tests want the net/lib target, include it automatically -ifneq ($(filter net,$(TARGETS)),) +ifneq ($(filter net drivers/net,$(TARGETS)),) ifeq ($(filter net/lib,$(TARGETS)),) INSTALL_DEP_TARGETS := net/lib endif diff --git a/tools/testing/selftests/drivers/net/Makefile b/tools/testing/selftests/drivers/net/Makefile new file mode 100644 index 000000000000..379cdb1960a7 --- /dev/null +++ b/tools/testing/selftests/drivers/net/Makefile @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0 + +TEST_INCLUDES := $(wildcard lib/py/*.py) + +TEST_PROGS := stats.py + +include ../../lib.mk diff --git a/tools/testing/selftests/drivers/net/README.rst b/tools/testing/selftests/drivers/net/README.rst new file mode 100644 index 000000000000..5ef7c417d431 --- /dev/null +++ b/tools/testing/selftests/drivers/net/README.rst @@ -0,0 +1,30 @@ +Running tests +============= + +Tests are executed within kselftest framework like any other tests. +By default tests execute against software drivers such as netdevsim. +All tests must support running against a real device (SW-only tests +should instead be placed in net/ or drivers/net/netdevsim, HW-only +tests in drivers/net/hw). + +Set appropriate variables to point the tests at a real device. + +Variables +========= + +Variables can be set in the environment or by creating a net.config +file in the same directory as this README file. Example:: + + $ NETIF=eth0 ./some_test.sh + +or:: + + $ cat tools/testing/selftests/drivers/net/net.config + # Variable set in a file + NETIF=eth0 + +NETIF +~~~~~ + +Name of the netdevice against which the test should be executed. +When empty or not set software devices will be used. diff --git a/tools/testing/selftests/drivers/net/lib/py/__init__.py b/tools/testing/selftests/drivers/net/lib/py/__init__.py new file mode 100644 index 000000000000..4653dffcd962 --- /dev/null +++ b/tools/testing/selftests/drivers/net/lib/py/__init__.py @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0 + +import sys +from pathlib import Path + +KSFT_DIR = (Path(__file__).parent / "../../../..").resolve() + +try: + sys.path.append(KSFT_DIR.as_posix()) + from net.lib.py import * +except ModuleNotFoundError as e: + ksft_pr("Failed importing `net` library from kernel sources") + ksft_pr(str(e)) + ktap_result(True, comment="SKIP") + sys.exit(4) + +from .env import * diff --git a/tools/testing/selftests/drivers/net/lib/py/env.py b/tools/testing/selftests/drivers/net/lib/py/env.py new file mode 100644 index 000000000000..e1abe9491daf --- /dev/null +++ b/tools/testing/selftests/drivers/net/lib/py/env.py @@ -0,0 +1,52 @@ +# SPDX-License-Identifier: GPL-2.0 + +import os +import shlex +from pathlib import Path +from lib.py import ip +from lib.py import NetdevSimDev + +class NetDrvEnv: + def __init__(self, src_path): + self._ns = None + + self.env = os.environ.copy() + self._load_env_file(src_path) + + if 'NETIF' in self.env: + self.dev = ip("link show dev " + self.env['NETIF'], json=True)[0] + else: + self._ns = NetdevSimDev() + self.dev = self._ns.nsims[0].dev + self.ifindex = self.dev['ifindex'] + + def __enter__(self): + return self + + def __exit__(self, ex_type, ex_value, ex_tb): + """ + __exit__ gets called at the end of a "with" block. + """ + self.__del__() + + def __del__(self): + if self._ns: + self._ns.remove() + self._ns = None + + def _load_env_file(self, src_path): + src_dir = Path(src_path).parent.resolve() + if not (src_dir / "net.config").exists(): + return + + lexer = shlex.shlex(open((src_dir / "net.config").as_posix(), 'r').read()) + k = None + for token in lexer: + if k is None: + k = token + self.env[k] = "" + elif token == "=": + pass + else: + self.env[k] = token + k = None diff --git a/tools/testing/selftests/net/lib/py/__init__.py b/tools/testing/selftests/net/lib/py/__init__.py index 7823b5c1f8d7..ded7102df18a 100644 --- a/tools/testing/selftests/net/lib/py/__init__.py +++ b/tools/testing/selftests/net/lib/py/__init__.py @@ -2,5 +2,6 @@ from .consts import KSRC from .ksft import * +from .nsim import * from .utils import * from .ynl import NlError, YnlFamily, EthtoolFamily, NetdevFamily, RtnlFamily diff --git a/tools/testing/selftests/net/lib/py/nsim.py b/tools/testing/selftests/net/lib/py/nsim.py new file mode 100644 index 000000000000..b2d696e12805 --- /dev/null +++ b/tools/testing/selftests/net/lib/py/nsim.py @@ -0,0 +1,115 @@ +# SPDX-License-Identifier: GPL-2.0 + +import json +import os +import random +import re +import time +from .utils import cmd, ip + + +class NetdevSim: + """ + Class for netdevsim netdevice and its attributes. + """ + + def __init__(self, nsimdev, port_index, ifname, ns=None): + # In case udev renamed the netdev to according to new schema, + # check if the name matches the port_index. + nsimnamere = re.compile(r"eni\d+np(\d+)") + match = nsimnamere.match(ifname) + if match and int(match.groups()[0]) != port_index + 1: + raise Exception("netdevice name mismatches the expected one") + + self.nsimdev = nsimdev + self.port_index = port_index + ret = ip("-j link show dev %s" % ifname, ns=ns) + self.dev = json.loads(ret.stdout)[0] + + def dfs_write(self, path, val): + self.nsimdev.dfs_write(f'ports/{self.port_index}/' + path, val) + + +class NetdevSimDev: + """ + Class for netdevsim bus device and its attributes. + """ + @staticmethod + def ctrl_write(path, val): + fullpath = os.path.join("/sys/bus/netdevsim/", path) + with open(fullpath, "w") as f: + f.write(val) + + def dfs_write(self, path, val): + fullpath = os.path.join(f"/sys/kernel/debug/netdevsim/netdevsim{self.addr}/", path) + with open(fullpath, "w") as f: + f.write(val) + + def __init__(self, port_count=1, ns=None): + # nsim will spawn in init_net, we'll set to actual ns once we switch it there + self.ns = None + + if not os.path.exists("/sys/bus/netdevsim"): + cmd("modprobe netdevsim") + + addr = random.randrange(1 << 15) + while True: + try: + self.ctrl_write("new_device", "%u %u" % (addr, port_count)) + except OSError as e: + if e.errno == errno.ENOSPC: + addr = random.randrange(1 << 15) + continue + raise e + break + self.addr = addr + + # As probe of netdevsim device might happen from a workqueue, + # so wait here until all netdevs appear. + self.wait_for_netdevs(port_count) + + if ns: + cmd(f"devlink dev reload netdevsim/netdevsim{addr} netns {ns.name}") + self.ns = ns + + cmd("udevadm settle", ns=self.ns) + ifnames = self.get_ifnames() + + self.dfs_dir = "/sys/kernel/debug/netdevsim/netdevsim%u/" % addr + + self.nsims = [] + for port_index in range(port_count): + self.nsims.append(NetdevSim(self, port_index, ifnames[port_index], + ns=ns)) + + def get_ifnames(self): + ifnames = [] + listdir = cmd(f"ls /sys/bus/netdevsim/devices/netdevsim{self.addr}/net/", + ns=self.ns).stdout.split() + for ifname in listdir: + ifnames.append(ifname) + ifnames.sort() + return ifnames + + def wait_for_netdevs(self, port_count): + timeout = 5 + timeout_start = time.time() + + while True: + try: + ifnames = self.get_ifnames() + except FileNotFoundError as e: + ifnames = [] + if len(ifnames) == port_count: + break + if time.time() < timeout_start + timeout: + continue + raise Exception("netdevices did not appear within timeout") + + def remove(self): + self.ctrl_write("del_device", "%u" % (self.addr, )) + + def remove_nsim(self, nsim): + self.nsims.remove(nsim) + self.ctrl_write("devices/netdevsim%u/del_port" % (self.addr, ), + "%u" % (nsim.port_index, )) From patchwork Fri Apr 5 02:45:26 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Kicinski X-Patchwork-Id: 13618390 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8E0BE1CD18; Fri, 5 Apr 2024 02:45:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712285136; cv=none; b=aBaanDZP6Vk15n0knSpMolp5cs5PIb2OxFzMU+QNLK6A84w0Wc+xp5129jNqEXCDsEzgQTIEuohlQPPbCp1kln5aYGNkVzcfvc3XqRtZ2xpQ/OP/2RbLBwQqqGMtbFuT7X+goLnE30CnNNQaZDBgEYaPzvy02O1UfRWaJxEUw5U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712285136; c=relaxed/simple; bh=8hIRahLfJ1A+yfucAwb1LVgvvKA1r+H9v75vdhnDdgE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=fNKnR24UVVFid1k+pLL88XgVR4b16UdC4SNCPQ2Wi/iaVPdjj73SJDoRlSKkn63Pa6OYdS7taIFTPhmQWPCgG8k5b5t6W8xdj35Awe9t/ULan30g44Flu/32sGswN4JmAoxk+jo/GKzDmdiUSrY7Uj5QRTThx2i5f85kBfqRvfY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=czFwjkPg; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="czFwjkPg" Received: by smtp.kernel.org (Postfix) with ESMTPSA id AC862C43394; Fri, 5 Apr 2024 02:45:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1712285136; bh=8hIRahLfJ1A+yfucAwb1LVgvvKA1r+H9v75vdhnDdgE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=czFwjkPgkfZmbOiOckQHm5Tf1ewP9kYVCfsoSsjiVWxpuF3ou5dHDXQ1ewAJJQGKz yk8Uc3St1DQkxR+PtiNlaHdWmMwHCZd2RfnQszy+aagifdAPpn4rFtRCTJ5qmas3sF cOm6zSW9N8mD0QF11/hUNecaMovAUWiR7fffMIK/c5m/kMEIJU0tlwdV+tUtRBdezL bFRv6oq3PT+yUnJmrnZpES6AquMMgaQBhl2HpPqWayj/rw1JiIzEWLrFjr2SiUxT7B KLGMT8Ink2XcBVi/wIqIPKVoJ5bFpZhrWpfeRA4lcEDaOmAHWfn/Nebn1PLdlgHCkQ IIc7wwELbUDJg== From: Jakub Kicinski To: davem@davemloft.net Cc: netdev@vger.kernel.org, edumazet@google.com, pabeni@redhat.com, shuah@kernel.org, sdf@google.com, donald.hunter@gmail.com, linux-kselftest@vger.kernel.org, petrm@nvidia.com, Jakub Kicinski Subject: [PATCH net-next v3 5/5] testing: net-drv: add a driver test for stats reporting Date: Thu, 4 Apr 2024 19:45:26 -0700 Message-ID: <20240405024526.2752998-6-kuba@kernel.org> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240405024526.2752998-1-kuba@kernel.org> References: <20240405024526.2752998-1-kuba@kernel.org> Precedence: bulk X-Mailing-List: linux-kselftest@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add a very simple test to make sure drivers report expected stats. Drivers which implement FEC or pause configuration should report relevant stats. Qstats must be reported, at least packet and byte counts, and they must match total device stats. Tested with netdevsim, bnxt, in-tree and installed. Signed-off-by: Jakub Kicinski --- v2: - pass cfg as argument - use with --- tools/testing/selftests/drivers/net/stats.py | 86 ++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100755 tools/testing/selftests/drivers/net/stats.py diff --git a/tools/testing/selftests/drivers/net/stats.py b/tools/testing/selftests/drivers/net/stats.py new file mode 100755 index 000000000000..5a9d4e56b28b --- /dev/null +++ b/tools/testing/selftests/drivers/net/stats.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0 + +from lib.py import ksft_run, ksft_in, ksft_true, KsftSkipEx, KsftXfailEx +from lib.py import EthtoolFamily, NetdevFamily, RtnlFamily, NlError +from lib.py import NetDrvEnv + +ethnl = EthtoolFamily() +netfam = NetdevFamily() +rtnl = RtnlFamily() + + +def check_pause(cfg) -> None: + global ethnl + + try: + ethnl.pause_get({"header": {"dev-index": cfg.ifindex}}) + except NlError as e: + if e.error == 95: + raise KsftXfailEx("pause not supported by the device") + raise + + data = ethnl.pause_get({"header": {"dev-index": cfg.ifindex, + "flags": {'stats'}}}) + ksft_true(data['stats'], "driver does not report stats") + + +def check_fec(cfg) -> None: + global ethnl + + try: + ethnl.fec_get({"header": {"dev-index": cfg.ifindex}}) + except NlError as e: + if e.error == 95: + raise KsftXfailEx("FEC not supported by the device") + raise + + data = ethnl.fec_get({"header": {"dev-index": cfg.ifindex, + "flags": {'stats'}}}) + ksft_true(data['stats'], "driver does not report stats") + + +def pkt_byte_sum(cfg) -> None: + global netfam, rtnl + + def get_qstat(test): + global netfam + stats = netfam.qstats_get({}, dump=True) + if stats: + for qs in stats: + if qs["ifindex"]== test.ifindex: + return qs + + qstat = get_qstat(cfg) + if qstat is None: + raise KsftSkipEx("qstats not supported by the device") + + for key in ['tx-packets', 'tx-bytes', 'rx-packets', 'rx-bytes']: + ksft_in(key, qstat, "Drivers should always report basic keys") + + # Compare stats, rtnl stats and qstats must match, + # but the interface may be up, so do a series of dumps + # each time the more "recent" stats must be higher or same. + def stat_cmp(rstat, qstat): + for key in ['tx-packets', 'tx-bytes', 'rx-packets', 'rx-bytes']: + if rstat[key] != qstat[key]: + return rstat[key] - qstat[key] + return 0 + + for _ in range(10): + rtstat = rtnl.getlink({"ifi-index": cfg.ifindex})['stats'] + if stat_cmp(rtstat, qstat) < 0: + raise Exception("RTNL stats are lower, fetched later") + qstat = get_qstat(cfg) + if stat_cmp(rtstat, qstat) > 0: + raise Exception("Qstats are lower, fetched later") + + +def main() -> None: + with NetDrvEnv(__file__) as cfg: + ksft_run([check_pause, check_fec, pkt_byte_sum], + args=(cfg, )) + + +if __name__ == "__main__": + main()