From patchwork Wed Apr 17 23:11:39 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Kicinski X-Patchwork-Id: 789567 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 D807A84E00; Wed, 17 Apr 2024 23:11:56 +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=1713395517; cv=none; b=elgeOlji8KoZdY9nYC4DtTaDTVQy5uS+Kv9dwMD0EDE7S/ItyfqNt4qnElWogMFRkNnQldZzM1m5RdDMyimq4YSBVYtQToDxiRiGZBeCUhTB08jmc5dp4xuiaRXY9KT2QWM8XCd97WmEr/ubnFgXwOl0NsvSP1+DHNigkHYvtZA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713395517; c=relaxed/simple; bh=a0FWCf/G0SKI1ff7SEpyzUbSU6RQSFSCIjUKT97X3eY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=VHUqFLWN34ZoIEGnP1EFx2n6nfdBJf1AganGMeHEg2Ba3POklO++NGCNc+Obk83NmY9FdJl2UX8HA6GSVErZIpk8nZpJBWnrabSOuSAshs2hpYgp8Du2Ko6zsPEq8oi6pKCbOhe4MYAqLYKLDeYSox/akZFwutzpDNkGZ39PGDs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=WABhcSK+; 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="WABhcSK+" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 775D0C116B1; Wed, 17 Apr 2024 23:11:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1713395516; bh=a0FWCf/G0SKI1ff7SEpyzUbSU6RQSFSCIjUKT97X3eY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=WABhcSK++zhjv/nkb2/c89gFmhaKDOLFJm0T+O9urpoRdMELR8dTyLkGdCnb9UoiA SK3OovIJ/Fk6WImfV0L9Q8/7VDq4nbs2Qu1CcvnBmKPLpYju77D503flxOTylv/GJE yhsvj24iZWBed80bCitn7dwmPHZL7taDCoy5TpoCOjt0aOtsgLxSY/2Hqi6mMKGkh8 iBS5+hWVXfwSzotj1c30ObWvjQ+5or67z09VKK/s3AWNdlZ00b/nqc4Pgxwm+5J/iO aZhKRTnwVAlJbLMTzblbfFUNTgjSd8UFLFfLuaaPx/TnORnHvWHkDugTvdIAQJcrcT 9GgYoDimY7Swg== From: Jakub Kicinski To: davem@davemloft.net Cc: netdev@vger.kernel.org, edumazet@google.com, pabeni@redhat.com, shuah@kernel.org, petrm@nvidia.com, linux-kselftest@vger.kernel.org, willemdebruijn.kernel@gmail.com, Jakub Kicinski Subject: [PATCH net-next v3 1/8] selftests: net: fix counting totals when some checks fail Date: Wed, 17 Apr 2024 16:11:39 -0700 Message-ID: <20240417231146.2435572-2-kuba@kernel.org> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240417231146.2435572-1-kuba@kernel.org> References: <20240417231146.2435572-1-kuba@kernel.org> Precedence: bulk X-Mailing-List: linux-kselftest@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Totals currently only pay attention to exceptions, if check fails (say ksft_eq()) the test case will be counted as pass: # At /ksft/drivers/net/./ping.py line 18: # Check failed 1 != 2 not ok 1 ping.test_v4 ok 2 ping.test_v6 ok 3 ping.test_tcp # Totals: pass:3 fail:0 xfail:0 xpass:0 skip:0 error:0 ^^^^^^^^^^^^^ Pay attention to the result. Fixes: b86761ff6374 ("selftests: net: add scaffolding for Netlink tests in Python") Signed-off-by: Jakub Kicinski --- tools/testing/selftests/net/lib/py/ksft.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/net/lib/py/ksft.py b/tools/testing/selftests/net/lib/py/ksft.py index 3769b9197213..640dfbf47702 100644 --- a/tools/testing/selftests/net/lib/py/ksft.py +++ b/tools/testing/selftests/net/lib/py/ksft.py @@ -106,7 +106,10 @@ KSFT_RESULT = None continue ktap_result(KSFT_RESULT, cnt, case) - totals['pass'] += 1 + if KSFT_RESULT: + totals['pass'] += 1 + else: + totals['fail'] += 1 print( f"# Totals: pass:{totals['pass']} fail:{totals['fail']} xfail:{totals['xfail']} xpass:0 skip:{totals['skip']} error:0" From patchwork Wed Apr 17 23:11:40 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Kicinski X-Patchwork-Id: 790041 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 A3AD785923; Wed, 17 Apr 2024 23:11:57 +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=1713395517; cv=none; b=WsYmIXKEALFTBaO+rF2vy+HLgA9oab+L/KCPogJqdO0sDYyn/IxdNG/OXOkGYJ3pKz1V9g85fHNmeArwXYhcb+LXEV844JJ6ylBKCVL13VRijA1+U+1lNxVfR0oAy8IU1EQYspVPBaZRxm8c6M/pzESfYDv4+vGrKoPcJohEglk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713395517; c=relaxed/simple; bh=L8RYGfut66Ms4oIXNHvCI2Eazz9Ntss0vK6ONZSR+oI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=CoY+P9BFKgGnI1pTsXLD9awEr0oAPMAK49N/ID27mBPtGN+q5cA9ORp7n2uyLmkvhadwJs12LtslCfX4s8CNpRKF7DtZ+xUveOueIVvbQvlu+SnhnfaQ6x3kU3a3itv9VFmkmAlvrArR9SSX0g5rzEgyTC9B/nnnum+KiySdcH8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=YjezADI3; 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="YjezADI3" Received: by smtp.kernel.org (Postfix) with ESMTPSA id DBDCFC32781; Wed, 17 Apr 2024 23:11:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1713395517; bh=L8RYGfut66Ms4oIXNHvCI2Eazz9Ntss0vK6ONZSR+oI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=YjezADI3DNOwWAXY7qaVqnQywJBxn0Ks7o2Y+cJiHgZFz6tl8wzYp30mMa/jpcZeB bctSZi561VdspQRN1RertlwTUvrAGijqRjLv2vwR/CSIHqn3qlnoGsOIWwKBx+ApvZ yWMkZsf6CnOLyLE8H8K0iwE3VriaOksgSbaa+LFkL8h18WmEufymgUYDzyT+TD+S3t CoeGu/gX4gGedPmzMhvyY78It3gLG/UM6MdTjJIflZxsKxEHQPDg80M9Y4McWEz7FP tTzllt4EkZPeir1tPQH36xrVJJPSGrOOp7Litkrf1HR2U0YYKYPkkuD1abHyUYTNFB C/Ak8M5Sxudiw== From: Jakub Kicinski To: davem@davemloft.net Cc: netdev@vger.kernel.org, edumazet@google.com, pabeni@redhat.com, shuah@kernel.org, petrm@nvidia.com, linux-kselftest@vger.kernel.org, willemdebruijn.kernel@gmail.com, Jakub Kicinski Subject: [PATCH net-next v3 2/8] selftests: net: set the exit code correctly in Python tests Date: Wed, 17 Apr 2024 16:11:40 -0700 Message-ID: <20240417231146.2435572-3-kuba@kernel.org> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240417231146.2435572-1-kuba@kernel.org> References: <20240417231146.2435572-1-kuba@kernel.org> Precedence: bulk X-Mailing-List: linux-kselftest@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Test cases need to exit with non-zero status if they failed, we currently don't do that: # KTAP version 1 # 1..3 # # At /root/ksft-net-drv/drivers/net/./ping.py line 18: # # Check failed 1 != 2 # not ok 1 ping.test_v4 # ok 2 ping.test_v6 # ok 3 ping.test_tcp # # Totals: pass:2 fail:1 xfail:0 xpass:0 skip:0 error:0 ok 1 selftests: drivers/net: ping.py ^^^^ It's a bit tempting to make the exit part of ksft_run(), but that only works well for very trivial setups. We can revisit this later, if people forget to call ksft_exit(). Signed-off-by: Jakub Kicinski --- tools/testing/selftests/drivers/net/stats.py | 4 +++- tools/testing/selftests/net/lib/py/ksft.py | 10 ++++++++++ tools/testing/selftests/net/nl_netdev.py | 4 +++- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/drivers/net/stats.py b/tools/testing/selftests/drivers/net/stats.py index 5a9d4e56b28b..947df3eb681f 100755 --- a/tools/testing/selftests/drivers/net/stats.py +++ b/tools/testing/selftests/drivers/net/stats.py @@ -1,7 +1,8 @@ #!/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 ksft_run, ksft_exit +from lib.py import ksft_in, ksft_true, KsftSkipEx, KsftXfailEx from lib.py import EthtoolFamily, NetdevFamily, RtnlFamily, NlError from lib.py import NetDrvEnv @@ -80,6 +81,7 @@ rtnl = RtnlFamily() with NetDrvEnv(__file__) as cfg: ksft_run([check_pause, check_fec, pkt_byte_sum], args=(cfg, )) + ksft_exit() if __name__ == "__main__": diff --git a/tools/testing/selftests/net/lib/py/ksft.py b/tools/testing/selftests/net/lib/py/ksft.py index 640dfbf47702..25f2572fa540 100644 --- a/tools/testing/selftests/net/lib/py/ksft.py +++ b/tools/testing/selftests/net/lib/py/ksft.py @@ -2,11 +2,13 @@ import builtins import inspect +import sys import time import traceback from .consts import KSFT_MAIN_NAME KSFT_RESULT = None +KSFT_RESULT_ALL = True class KsftSkipEx(Exception): @@ -63,6 +65,9 @@ KSFT_RESULT = None def ktap_result(ok, cnt=1, case="", comment=""): + global KSFT_RESULT_ALL + KSFT_RESULT_ALL = KSFT_RESULT_ALL and ok + res = "" if not ok: res += "not " @@ -114,3 +119,8 @@ KSFT_RESULT = None print( f"# Totals: pass:{totals['pass']} fail:{totals['fail']} xfail:{totals['xfail']} xpass:0 skip:{totals['skip']} error:0" ) + + +def ksft_exit(): + global KSFT_RESULT_ALL + sys.exit(0 if KSFT_RESULT_ALL else 1) diff --git a/tools/testing/selftests/net/nl_netdev.py b/tools/testing/selftests/net/nl_netdev.py index 6909b1760739..93d9d914529b 100755 --- a/tools/testing/selftests/net/nl_netdev.py +++ b/tools/testing/selftests/net/nl_netdev.py @@ -2,7 +2,8 @@ # SPDX-License-Identifier: GPL-2.0 import time -from lib.py import ksft_run, ksft_pr, ksft_eq, ksft_ge, ksft_busy_wait +from lib.py import ksft_run, ksft_exit, ksft_pr +from lib.py import ksft_eq, ksft_ge, ksft_busy_wait from lib.py import NetdevFamily, NetdevSimDev, ip @@ -90,6 +91,7 @@ from lib.py import NetdevFamily, NetdevSimDev, ip nf = NetdevFamily() ksft_run([empty_check, lo_check, page_pool_check], args=(nf, )) + ksft_exit() if __name__ == "__main__": From patchwork Wed Apr 17 23:11:41 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Kicinski X-Patchwork-Id: 789566 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 0563D8563E; Wed, 17 Apr 2024 23:11:57 +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=1713395518; cv=none; b=TsDtLEB+1GmfD8GoXm4gPjPj+ooc78v1yG4vj7mwCWrGVXPjP9mHeUmw4qk3WH+N9i4t9C1V7O2mREaDYADNfSEYGFoSOJDmSblbRrcS9LdBolG5CuZJ32K4d7t7MvjZK5N2+FWhxki1NJC6kTQudC9qTlueGpccG68J5iGh4OE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713395518; c=relaxed/simple; bh=9r/q5QrmyrRF7E9pmJFiMwRvEVAo1tgFGtcXTzt4+to=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=EgyU8hFliXpRZZxHUGqD1lZ42Qzcr94lBFung1Uwh60ORl8Z4e6s9pTX3q5N3Ju7pWl4uIgNtAltXA848gqkXhub8FzRgGyzQiUiGLO2tOoYH1e092W9oZD4w4+QhNsz6KW92PKxLy1/ftWzzDdMJ1boY91HN3yG2j5fqB4lpDs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ARkg/1Ga; 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="ARkg/1Ga" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 50F90C4AF11; Wed, 17 Apr 2024 23:11:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1713395517; bh=9r/q5QrmyrRF7E9pmJFiMwRvEVAo1tgFGtcXTzt4+to=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ARkg/1Ga6+bnfZwkIKiNtNy9uxYInaE8kXB2+HUbrFXSJN0ZCl5CEHyCTPASbLLbj m+WTkQJ7G4oelLT2HROAlq+TZdIwgO5CFoWboGDJIWhMCM8AbZQwMVVqR9/8ZOXsbF lyoZklXhG0vI6GoUFPAqBSh0jgFgToaFb6z3NJOrw5llJjXOB9FO4F8kfEmvfRaAOl MONuJCfwsO/DAgDNcVQ/z3udVwxFVaTppCktDgrGUWgd3J8Aj5JLBlswrVj7hUfMwr SgkCC5wUdRSZMCYcwR9ks0OK0hLbjlJQUuZt4Y0UR9FmYbuDs8UYbAR51LVJAg84y4 O5Udl251iMj/A== From: Jakub Kicinski To: davem@davemloft.net Cc: netdev@vger.kernel.org, edumazet@google.com, pabeni@redhat.com, shuah@kernel.org, petrm@nvidia.com, linux-kselftest@vger.kernel.org, willemdebruijn.kernel@gmail.com, Jakub Kicinski Subject: [PATCH net-next v3 3/8] selftests: drv-net: define endpoint structures Date: Wed, 17 Apr 2024 16:11:41 -0700 Message-ID: <20240417231146.2435572-4-kuba@kernel.org> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240417231146.2435572-1-kuba@kernel.org> References: <20240417231146.2435572-1-kuba@kernel.org> Precedence: bulk X-Mailing-List: linux-kselftest@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Define the remote endpoint "model". To execute most meaningful device driver tests we need to be able to communicate with a remote system, and have it send traffic to the device under test. Various test environments will have different requirements. 0) "Local" netdevsim-based testing can simply use net namespaces. netdevsim supports connecting two devices now, to form a veth-like construct. 1) Similarly on hosts with multiple NICs, the NICs may be connected together with a loopback cable or internal device loopback. One interface may be placed into separate netns, and tests would proceed much like in the netdevsim case. Note that the loopback config or the moving of one interface into a netns is not expected to be part of selftest code. 2) Some systems may need to communicate with the remote endpoint via SSH. 3) Last but not least environment may have its own custom communication method. Fundamentally we only need two operations: - run a command remotely - deploy a binary (if some tool we need is built as part of kselftests) Wrap these two in a class. Use dynamic loading to load the Remote class. This will allow very easy definition of other communication methods without bothering upstream code base. Stick to the "simple" / "no unnecessary abstractions" model for referring to the remote endpoints. The host / remote object are passed as an argument to the usual cmd() or ip() invocation. For example: ip("link show", json=True, host=remote) Signed-off-by: Jakub Kicinski --- v3: - make Remote() return Popen() object - always operate on absolute paths v2: - rename Endpoint -> Remote --- .../selftests/drivers/net/lib/py/__init__.py | 1 + .../selftests/drivers/net/lib/py/remote.py | 15 +++++++ .../drivers/net/lib/py/remote_netns.py | 21 ++++++++++ .../drivers/net/lib/py/remote_ssh.py | 39 +++++++++++++++++++ tools/testing/selftests/net/lib/py/utils.py | 17 ++++---- 5 files changed, 85 insertions(+), 8 deletions(-) create mode 100644 tools/testing/selftests/drivers/net/lib/py/remote.py create mode 100644 tools/testing/selftests/drivers/net/lib/py/remote_netns.py create mode 100644 tools/testing/selftests/drivers/net/lib/py/remote_ssh.py diff --git a/tools/testing/selftests/drivers/net/lib/py/__init__.py b/tools/testing/selftests/drivers/net/lib/py/__init__.py index 4653dffcd962..4789c1a4282d 100644 --- a/tools/testing/selftests/drivers/net/lib/py/__init__.py +++ b/tools/testing/selftests/drivers/net/lib/py/__init__.py @@ -15,3 +15,4 @@ KSFT_DIR = (Path(__file__).parent / "../../../..").resolve() sys.exit(4) from .env import * +from .remote import Remote diff --git a/tools/testing/selftests/drivers/net/lib/py/remote.py b/tools/testing/selftests/drivers/net/lib/py/remote.py new file mode 100644 index 000000000000..b1780b987722 --- /dev/null +++ b/tools/testing/selftests/drivers/net/lib/py/remote.py @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0 + +import os +import importlib + +_modules = {} + +def Remote(kind, args, src_path): + global _modules + + if kind not in _modules: + _modules[kind] = importlib.import_module("..remote_" + kind, __name__) + + dir_path = os.path.abspath(src_path + "/../") + return getattr(_modules[kind], "Remote")(args, dir_path) diff --git a/tools/testing/selftests/drivers/net/lib/py/remote_netns.py b/tools/testing/selftests/drivers/net/lib/py/remote_netns.py new file mode 100644 index 000000000000..7d5eeb0271bc --- /dev/null +++ b/tools/testing/selftests/drivers/net/lib/py/remote_netns.py @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0 + +import os +import subprocess + +from lib.py import cmd + + +class Remote: + def __init__(self, name, dir_path): + self.name = name + self.dir_path = dir_path + + def cmd(self, comm): + return subprocess.Popen(["ip", "netns", "exec", self.name, "bash", "-c", comm], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + + def deploy(self, what): + if os.path.isabs(what): + return what + return os.path.abspath(self.dir_path + "/" + what) diff --git a/tools/testing/selftests/drivers/net/lib/py/remote_ssh.py b/tools/testing/selftests/drivers/net/lib/py/remote_ssh.py new file mode 100644 index 000000000000..924addde19a3 --- /dev/null +++ b/tools/testing/selftests/drivers/net/lib/py/remote_ssh.py @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: GPL-2.0 + +import os +import string +import subprocess +import random + +from lib.py import cmd + + +class Remote: + def __init__(self, name, dir_path): + self.name = name + self.dir_path = dir_path + self._tmpdir = None + + def __del__(self): + if self._tmpdir: + cmd("rm -rf " + self._tmpdir, host=self) + self._tmpdir = None + + def cmd(self, comm): + return subprocess.Popen(["ssh", "-q", self.name, comm], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + + def _mktmp(self): + return ''.join(random.choice(string.ascii_lowercase) for _ in range(8)) + + def deploy(self, what): + if not self._tmpdir: + self._tmpdir = "/tmp/" + self._mktmp() + cmd("mkdir " + self._tmpdir, host=self) + file_name = self._tmpdir + "/" + self._mktmp() + os.path.basename(what) + + if not os.path.isabs(what): + what = os.path.abspath(self.dir_path + "/" + what) + + cmd(f"scp {what} {self.name}:{file_name}") + return file_name diff --git a/tools/testing/selftests/net/lib/py/utils.py b/tools/testing/selftests/net/lib/py/utils.py index 19612348c30d..e80fea9f6562 100644 --- a/tools/testing/selftests/net/lib/py/utils.py +++ b/tools/testing/selftests/net/lib/py/utils.py @@ -4,10 +4,8 @@ import json as _json import subprocess class cmd: - def __init__(self, comm, shell=True, fail=True, ns=None, background=False): + def __init__(self, comm, shell=True, fail=True, ns=None, background=False, host=None): if ns: - if isinstance(ns, NetNS): - ns = ns.name comm = f'ip netns exec {ns} ' + comm self.stdout = None @@ -15,15 +13,18 @@ import subprocess self.ret = None self.comm = comm - self.proc = subprocess.Popen(comm, shell=shell, stdout=subprocess.PIPE, - stderr=subprocess.PIPE) + if host: + self.proc = host.cmd(comm) + else: + 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() + stdout, stderr = self.proc.communicate(timeout=3) self.stdout = stdout.decode("utf-8") self.stderr = stderr.decode("utf-8") self.proc.stdout.close() @@ -37,12 +38,12 @@ import subprocess (self.proc.args, stdout, stderr)) -def ip(args, json=None, ns=None): +def ip(args, json=None, ns=None, host=None): cmd_str = "ip " if json: cmd_str += '-j ' cmd_str += args - cmd_obj = cmd(cmd_str, ns=ns) + cmd_obj = cmd(cmd_str, ns=ns, host=host) if json: return _json.loads(cmd_obj.stdout) return cmd_obj From patchwork Wed Apr 17 23:11:42 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Kicinski X-Patchwork-Id: 790040 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 26AEA86136; Wed, 17 Apr 2024 23:11:58 +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=1713395518; cv=none; b=kKT0H3UL1VZCRPhdMvS0XoNF0sIvEvwU26HfGw8Zqm2cZ0zYC8aGIq+/QQEyQok6K9Ks7i2SWrsS5AzIHUrJirJEA6yTP4O0VRIBdLp7mm09olhFp2E1RrslARZomqr2SJQoOElnBynAukz7VHyqDSkHxKN1h2SRs8RboG+T5LU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713395518; c=relaxed/simple; bh=U5+EVNFryCl6AbqRDTDECqncYZkgnEzOhvv/pOI/KNg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=d3/hQ5d7BE08BosqTHYDlC3zSemYqMNVU9DkVNbBa/j7KdoVyEP84Aked9Mdw6AYxg41Udj3iBmMQUwwDbEzPq4ZQNUe1WSNzNT2CGjbElGz+5Jj4TU5dip94RTdHxVdxFQsk0XnrmDBufcmBrm7oe+jrxanCWHq1ljApBHUJ0g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=WAQR7uvK; 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="WAQR7uvK" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B36E8C072AA; Wed, 17 Apr 2024 23:11:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1713395518; bh=U5+EVNFryCl6AbqRDTDECqncYZkgnEzOhvv/pOI/KNg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=WAQR7uvKFT3E4n3LieDUd/BYPPPxmqHpVxP5STP6KQBHtZg/zKcfBLHGSZF0zRVrj LU9CKZPlWGHRrUk09xrbCg8bY+89jyRwIbBklZRawr/mkRwQW8XVqDFCpthGvBAG3B YhVw0spm/vBkm7YrhDVDQWiolf0apruyfwXo0KCk6yhFF0MPs49yw/2F9xOiPobuXo xDVhyDyBnuAOO8iq7eTPXCUU+Qqphk2c1qejNmzwODaVnFQYcrQ5kRYY3phdQd7xM0 RHC11u/IXIu0VcEmPKT46zZ1Z/au6UhY6bPwYAWBbpoK1hceqkTu5/iDoTnFslYnbf 06cIl5XMZCyCw== From: Jakub Kicinski To: davem@davemloft.net Cc: netdev@vger.kernel.org, edumazet@google.com, pabeni@redhat.com, shuah@kernel.org, petrm@nvidia.com, linux-kselftest@vger.kernel.org, willemdebruijn.kernel@gmail.com, Jakub Kicinski Subject: [PATCH net-next v3 4/8] selftests: drv-net: factor out parsing of the env Date: Wed, 17 Apr 2024 16:11:42 -0700 Message-ID: <20240417231146.2435572-5-kuba@kernel.org> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240417231146.2435572-1-kuba@kernel.org> References: <20240417231146.2435572-1-kuba@kernel.org> Precedence: bulk X-Mailing-List: linux-kselftest@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The tests with a remote end will use a different class, for clarity, but will also need to parse the env. So factor parsing the env out to a function. Signed-off-by: Jakub Kicinski --- .../selftests/drivers/net/lib/py/env.py | 43 +++++++++++-------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/tools/testing/selftests/drivers/net/lib/py/env.py b/tools/testing/selftests/drivers/net/lib/py/env.py index e1abe9491daf..a081e168f3db 100644 --- a/tools/testing/selftests/drivers/net/lib/py/env.py +++ b/tools/testing/selftests/drivers/net/lib/py/env.py @@ -6,12 +6,36 @@ from pathlib import Path from lib.py import ip from lib.py import NetdevSimDev + +def _load_env_file(src_path): + env = os.environ.copy() + + src_dir = Path(src_path).parent.resolve() + if not (src_dir / "net.config").exists(): + return env + + lexer = shlex.shlex(open((src_dir / "net.config").as_posix(), 'r').read()) + k = None + for token in lexer: + if k is None: + k = token + env[k] = "" + elif token == "=": + pass + else: + env[k] = token + k = None + return env + + class NetDrvEnv: + """ + Class for a single NIC / host env, with no remote end + """ def __init__(self, src_path): self._ns = None - self.env = os.environ.copy() - self._load_env_file(src_path) + self.env = _load_env_file(src_path) if 'NETIF' in self.env: self.dev = ip("link show dev " + self.env['NETIF'], json=True)[0] @@ -34,19 +58,4 @@ from lib.py import NetdevSimDev 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 From patchwork Wed Apr 17 23:11:43 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Kicinski X-Patchwork-Id: 789565 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 C995C130A6C; Wed, 17 Apr 2024 23:11:58 +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=1713395518; cv=none; b=tMsnW95MHZopEuJhUw8XQnkft1AouYhgZ/o9k/1RBntXkCdSMLMiA67SMdLEfOzTfxakxL+ppc5srJoEYWZ2h4994TKXtHlaUG6pW6KL1DPAYEv4h7PNp6DiGHYP+qadQ+2rBWkmgYi1J3IcooQrj7R9EAtbN99DH2D8KgbNbAo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713395518; c=relaxed/simple; bh=LWouE9X7rzpJYEbBLAu3hDxweSMYx1hX1X8QWpU0+sk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=LkoDtxDv3Xx3CJyV6T3IuM9XiIMOGn2T+MursJpy9Z0bxKAmQqC/zwC9j9d/cTC4eUHTTpAVgjLkByiTnL84OHDesFvqptD7vC2mNEZOGiBjNLwrMhHjykbqCBswJZOlyL+GRXH6kzW0VDvxiaPDtqQrJ7VVZhD3Xw2hdoJ2LjI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=NwfqyCf/; 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="NwfqyCf/" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2540FC116B1; Wed, 17 Apr 2024 23:11:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1713395518; bh=LWouE9X7rzpJYEbBLAu3hDxweSMYx1hX1X8QWpU0+sk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=NwfqyCf/68mjCEGa7ZsVgTDZ4R/Mvsa/EaL1CnXl0nhz1YW1flRf+mYDc3t2FMhzU hKYaqvuA4EYPZJHVGPyiVxXs44F/IJcpylJwXeerR4Jxh2fp2DTiE86tNslHl7ah1K Y8CDME9cw0m9p2gYlATXtkjDx8o6fgjrIkUFEOVI4xGOIi6XqqdPUi1v59HrvL26rR CD6Gf67dh9V+YLxFkY1YQrOGG+V15e7Sk7zQ4Hy2CvyPZNOXhpgTEtAve+w+vE4r85 ghgg3jvulsFa5feV73oZBx/BXSkd3brM1Trr12SHNOXmkmjcNln5y/cEONhfO8l25A yJvwkRsA6QR6g== From: Jakub Kicinski To: davem@davemloft.net Cc: netdev@vger.kernel.org, edumazet@google.com, pabeni@redhat.com, shuah@kernel.org, petrm@nvidia.com, linux-kselftest@vger.kernel.org, willemdebruijn.kernel@gmail.com, Jakub Kicinski Subject: [PATCH net-next v3 5/8] selftests: drv-net: construct environment for running tests which require an endpoint Date: Wed, 17 Apr 2024 16:11:43 -0700 Message-ID: <20240417231146.2435572-6-kuba@kernel.org> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240417231146.2435572-1-kuba@kernel.org> References: <20240417231146.2435572-1-kuba@kernel.org> Precedence: bulk X-Mailing-List: linux-kselftest@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Nothing surprising here, hopefully. Wrap the variables from the environment into a class or spawn a netdevsim based env and pass it to the tests. Signed-off-by: Jakub Kicinski --- .../testing/selftests/drivers/net/README.rst | 33 +++++++ .../selftests/drivers/net/lib/py/env.py | 98 ++++++++++++++++++- .../testing/selftests/net/lib/py/__init__.py | 1 + tools/testing/selftests/net/lib/py/netns.py | 31 ++++++ 4 files changed, 162 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/net/lib/py/netns.py diff --git a/tools/testing/selftests/drivers/net/README.rst b/tools/testing/selftests/drivers/net/README.rst index 5ef7c417d431..0cbab33dad1f 100644 --- a/tools/testing/selftests/drivers/net/README.rst +++ b/tools/testing/selftests/drivers/net/README.rst @@ -23,8 +23,41 @@ Variables can be set in the environment or by creating a net.config # Variable set in a file NETIF=eth0 +Please note that the config parser is very simple, if there are +any non-alphanumeric characters in the value it needs to be in +double quotes. + NETIF ~~~~~ Name of the netdevice against which the test should be executed. When empty or not set software devices will be used. + +LOCAL_V4, LOCAL_V6, REMOTE_V4, REMOTE_V6 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Local and remote endpoint IP addresses. + +REMOTE_TYPE +~~~~~~~~~~~ + +Communication method used to run commands on the remote endpoint. +Test framework has built-in support for ``netns`` and ``ssh`` channels. +``netns`` assumes the "remote" interface is part of the same +host, just moved to the specified netns. +``ssh`` communicates with remote endpoint over ``ssh`` and ``scp``. +Using persistent SSH connections is strongly encouraged to avoid +the latency of SSH connection setup on every command. + +Communication methods are defined by classes in ``lib/py/remote_{name}.py``. +It should be possible to add a new method without modifying any of +the framework, by simply adding an appropriately named file to ``lib/py``. + +REMOTE_ARGS +~~~~~~~~~~~ + +Arguments used to construct the communication channel. +Communication channel dependent:: + + for netns - name of the "remote" namespace + for ssh - name/address of the remote host diff --git a/tools/testing/selftests/drivers/net/lib/py/env.py b/tools/testing/selftests/drivers/net/lib/py/env.py index a081e168f3db..579c5b34e6fd 100644 --- a/tools/testing/selftests/drivers/net/lib/py/env.py +++ b/tools/testing/selftests/drivers/net/lib/py/env.py @@ -4,7 +4,8 @@ import os import shlex from pathlib import Path from lib.py import ip -from lib.py import NetdevSimDev +from lib.py import NetNS, NetdevSimDev +from .remote import Remote def _load_env_file(src_path): @@ -59,3 +60,98 @@ from lib.py import NetdevSimDev self._ns = None +class NetDrvEpEnv: + """ + Class for an environment with a local device and "remote endpoint" + which can be used to send traffic in. + + For local testing it creates two network namespaces and a pair + of netdevsim devices. + """ + + # Network prefixes used for local tests + nsim_v4_pfx = "192.0.2." + nsim_v6_pfx = "2001:db8::" + + def __init__(self, src_path): + + self.env = _load_env_file(src_path) + + # Things we try to destroy + self.remote = None + # These are for local testing state + self._netns = None + self._ns = None + self._ns_peer = None + + if "NETIF" in self.env: + self.dev = ip("link show dev " + self.env['NETIF'], json=True)[0] + + self.v4 = self.env.get("LOCAL_V4") + self.v6 = self.env.get("LOCAL_V6") + self.remote_v4 = self.env.get("REMOTE_V4") + self.remote_v6 = self.env.get("REMOTE_V6") + kind = self.env["REMOTE_TYPE"] + args = self.env["REMOTE_ARGS"] + else: + self.create_local() + + self.dev = self._ns.nsims[0].dev + + self.v4 = self.nsim_v4_pfx + "1" + self.v6 = self.nsim_v6_pfx + "1" + self.remote_v4 = self.nsim_v4_pfx + "2" + self.remote_v6 = self.nsim_v6_pfx + "2" + kind = "netns" + args = self._netns.name + + self.remote = Remote(kind, args, src_path) + + self.addr = self.v6 if self.v6 else self.v4 + self.remote_addr = self.remote_v6 if self.remote_v6 else self.remote_v4 + + self.ifname = self.dev['ifname'] + self.ifindex = self.dev['ifindex'] + + def create_local(self): + self._netns = NetNS() + self._ns = NetdevSimDev() + self._ns_peer = NetdevSimDev(ns=self._netns) + + with open("/proc/self/ns/net") as nsfd0, \ + open("/var/run/netns/" + self._netns.name) as nsfd1: + ifi0 = self._ns.nsims[0].ifindex + ifi1 = self._ns_peer.nsims[0].ifindex + NetdevSimDev.ctrl_write('link_device', + f'{nsfd0.fileno()}:{ifi0} {nsfd1.fileno()}:{ifi1}') + + ip(f" addr add dev {self._ns.nsims[0].ifname} {self.nsim_v4_pfx}1/24") + ip(f"-6 addr add dev {self._ns.nsims[0].ifname} {self.nsim_v6_pfx}1/64 nodad") + ip(f" link set dev {self._ns.nsims[0].ifname} up") + + ip(f" addr add dev {self._ns_peer.nsims[0].ifname} {self.nsim_v4_pfx}2/24", ns=self._netns) + ip(f"-6 addr add dev {self._ns_peer.nsims[0].ifname} {self.nsim_v6_pfx}2/64 nodad", ns=self._netns) + ip(f" link set dev {self._ns_peer.nsims[0].ifname} up", ns=self._netns) + + 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 + if self._ns_peer: + self._ns_peer.remove() + self._ns_peer = None + if self._netns: + del self._netns + self._netns = None + if self.remote: + del self.remote + self.remote = None diff --git a/tools/testing/selftests/net/lib/py/__init__.py b/tools/testing/selftests/net/lib/py/__init__.py index ded7102df18a..b6d498d125fe 100644 --- a/tools/testing/selftests/net/lib/py/__init__.py +++ b/tools/testing/selftests/net/lib/py/__init__.py @@ -2,6 +2,7 @@ from .consts import KSRC from .ksft import * +from .netns import NetNS from .nsim import * from .utils import * from .ynl import NlError, YnlFamily, EthtoolFamily, NetdevFamily, RtnlFamily diff --git a/tools/testing/selftests/net/lib/py/netns.py b/tools/testing/selftests/net/lib/py/netns.py new file mode 100644 index 000000000000..ecff85f9074f --- /dev/null +++ b/tools/testing/selftests/net/lib/py/netns.py @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: GPL-2.0 + +from .utils import ip +import random +import string + + +class NetNS: + def __init__(self, name=None): + if name: + self.name = name + else: + self.name = ''.join(random.choice(string.ascii_lowercase) for _ in range(8)) + ip('netns add ' + self.name) + + def __del__(self): + if self.name: + ip('netns del ' + self.name) + self.name = None + + def __enter__(self): + return self + + def __exit__(self, ex_type, ex_value, ex_tb): + self.__del__() + + def __str__(self): + return self.name + + def __repr__(self): + return f"NetNS({self.name})" From patchwork Wed Apr 17 23:11:44 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Kicinski X-Patchwork-Id: 790039 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 4174F1411DE; Wed, 17 Apr 2024 23:11:58 +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=1713395519; cv=none; b=llmuIKe1eWQ4z71uA790rISFwTcPer912RyDnPkTRdKze+F1OzEyhsLUJ3GfjKTfUrBY6V5npVcLK0zODE/PUe2KQOzL5nEDT8+ItQri/EVCqkqIO1KJ+cQ0PwKRmR9Dwqw1MAGUlcL2gINhdIMPiXYLYD5DudaOKS5DnMuZI7I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713395519; c=relaxed/simple; bh=17pAk2sHA9rQOuf6BUb0S5PNLhhzSql5gjiWf9LNW4c=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=dsL1ujJ5f3tzIGM/JGCTcAJFAt5rwc3KoiQDsiewJfSaT1NMk4etWAp3JbLxvr1cJL6phkEFbV6QSNqUUEf/1jSyu8DlBZEgr3gMs+2OhXNCxEkmMl7U1LSVLPc/x34CPPNiOKJx5k7lnqLAwJqUrs/s2HtMzDiNE0N9jBmA8ko= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=D/1wiqL/; 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="D/1wiqL/" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 897F9C4AF08; Wed, 17 Apr 2024 23:11:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1713395518; bh=17pAk2sHA9rQOuf6BUb0S5PNLhhzSql5gjiWf9LNW4c=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=D/1wiqL/D3yTeg26GdMXTLGTP5KYPQzYZDN5wJCrnR+OV2v9GnfCrC39x+snhRjN/ ZSJQFza7mQdoy9w8xHjbrt/y4qGzW02ze3wwHU7llJPjvscA9mk8DbevqHMxbEYIaj 6Cm1Zq/SroncWtEi2MbJA1pAIHdof+YQd7Hj4bW9qeoEvseNQ+RQJ4/j66j9iPPxIr 0AHibO1NluMVM7Efh7ydoJ0jl8a1j3cN5CWqK768yhD+NbwgOdpiXxN+SX1infD7el Y+9gVvaKMQJ1z1O9GI7LcTxf4SrhXmhiReTQXR823IhdA2Gce0+jPWx6Xs6BFkW4Yb VX0XmH3XuYzyQ== From: Jakub Kicinski To: davem@davemloft.net Cc: netdev@vger.kernel.org, edumazet@google.com, pabeni@redhat.com, shuah@kernel.org, petrm@nvidia.com, linux-kselftest@vger.kernel.org, willemdebruijn.kernel@gmail.com, Jakub Kicinski Subject: [PATCH net-next v3 6/8] selftests: drv-net: add a trivial ping test Date: Wed, 17 Apr 2024 16:11:44 -0700 Message-ID: <20240417231146.2435572-7-kuba@kernel.org> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240417231146.2435572-1-kuba@kernel.org> References: <20240417231146.2435572-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 for testing with a remote system. Both IPv4 and IPv6 connectivity is optional so tests will XFail is env doesn't define an address for the given family. Using netdevsim: $ ./run_kselftest.sh -t drivers/net:ping.py TAP version 13 1..1 # timeout set to 45 # selftests: drivers/net: ping.py # KTAP version 1 # 1..2 # ok 1 ping.test_v4 # ok 2 ping.test_v6 # # Totals: pass:2 fail:0 xfail:0 xpass:0 skip:0 error:0 ok 1 selftests: drivers/net: ping.py Command line SSH: $ NETIF=virbr0 REMOTE_TYPE=ssh REMOTE_ARGS=root@192.168.122.123 \ LOCAL_V4=192.168.122.1 REMOTE_V4=192.168.122.123 \ ./tools/testing/selftests/drivers/net/ping.py KTAP version 1 1..2 ok 1 ping.test_v4 ok 2 ping.test_v6 # XFAIL # Totals: pass:1 fail:0 xfail:1 xpass:0 skip:0 error:0 Existing devices placed in netns (and using net.config): $ cat drivers/net/net.config NETIF=veth0 REMOTE_TYPE=netns REMOTE_ARGS=red LOCAL_V4="192.168.1.1" REMOTE_V4="192.168.1.2" $ ./run_kselftest.sh -t drivers/net:ping.py TAP version 13 1..1 # timeout set to 45 # selftests: drivers/net: ping.py # KTAP version 1 # 1..2 # ok 1 ping.test_v4 # ok 2 ping.test_v6 # XFAIL # # Totals: pass:1 fail:0 xfail:1 xpass:0 skip:0 error:0 Signed-off-by: Jakub Kicinski --- tools/testing/selftests/drivers/net/Makefile | 5 ++- tools/testing/selftests/drivers/net/ping.py | 33 ++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) create mode 100755 tools/testing/selftests/drivers/net/ping.py diff --git a/tools/testing/selftests/drivers/net/Makefile b/tools/testing/selftests/drivers/net/Makefile index 379cdb1960a7..754ec643768a 100644 --- a/tools/testing/selftests/drivers/net/Makefile +++ b/tools/testing/selftests/drivers/net/Makefile @@ -2,6 +2,9 @@ TEST_INCLUDES := $(wildcard lib/py/*.py) -TEST_PROGS := stats.py +TEST_PROGS := \ + ping.py \ + stats.py \ +# end of TEST_PROGS include ../../lib.mk diff --git a/tools/testing/selftests/drivers/net/ping.py b/tools/testing/selftests/drivers/net/ping.py new file mode 100755 index 000000000000..7dd197836ff1 --- /dev/null +++ b/tools/testing/selftests/drivers/net/ping.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0 + +from lib.py import ksft_run, ksft_exit, KsftXfailEx +from lib.py import NetDrvEpEnv +from lib.py import cmd + + +def test_v4(cfg) -> None: + if not cfg.v4: + raise KsftXfailEx() + + cmd(f"ping -c 1 -W0.5 {cfg.remote_v4}") + cmd(f"ping -c 1 -W0.5 {cfg.v4}", host=cfg.remote) + + +def test_v6(cfg) -> None: + if not cfg.v6: + raise KsftXfailEx() + + cmd(f"ping -c 1 -W0.5 {cfg.remote_v6}") + cmd(f"ping -c 1 -W0.5 {cfg.v6}", host=cfg.remote) + + +def main() -> None: + with NetDrvEpEnv(__file__) as cfg: + ksft_run([test_v4, test_v6], + args=(cfg, )) + ksft_exit() + + +if __name__ == "__main__": + main() From patchwork Wed Apr 17 23:11:45 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Kicinski X-Patchwork-Id: 789564 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 63DF7146D4A; Wed, 17 Apr 2024 23:11:59 +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=1713395519; cv=none; b=YHKfBVHphdT8k+t7PhT8KJxfEgLTN/c3bt57n+w1OhSmiozagsV/HsLpzRHs+nUetYNhlGWdcLSy4N41FUjHrj7q7IaX4Y+P4OglUPHv2UTmblttCNIktjXmi4QEjyqIfTzxK6NuEksJEIKIQkgLDnHj7/kU405/Ba9ftoDdmBo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713395519; c=relaxed/simple; bh=Mr2VNEUpo3DU0d44FbFWmm6+gnfBS9B1jp/iVDpK4jY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=VjhERbvkJh4Px0Wo8X0o8PeYPNwYG/hUxJ23ubAgYBnGMJbx5Dq/3dG59AotwzJtL/TOYVuGDyg3nO43IHwKSVvhH440Ja6fNzBNSdgArNROI1WPZOHuXDuL4d/2e9EciKu9m1qcy09KQnPEhovoHRhJttQCh8L1ccbT34Z4h1g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=iHNLo1hD; 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="iHNLo1hD" Received: by smtp.kernel.org (Postfix) with ESMTPSA id F2726C32781; Wed, 17 Apr 2024 23:11:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1713395519; bh=Mr2VNEUpo3DU0d44FbFWmm6+gnfBS9B1jp/iVDpK4jY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=iHNLo1hD1RuPfROfXFk+PQ9HqymFwXZ0Czh43t9o5xb3vu2hOsjRY8SYBbyhi3xzC 3+GNUXbclLrcSUhH9vF/J0O7dH9C0RmZNy9LZU9L4ue8zs9jjA5IVFidDfsKK7rpsT eI3i8lM/tK1a8RYIEgvYNf7I05JD8WYFuvhoRnaXAkxMK2FwHZJ+/wHNTgIoLkJqD1 EhkMsMxaq6IedWRiS/n2WMYCtG/d49FZc+GzG6Axa/hsyFIi2oc6o5fEoHJZYk9F0Q 1Netjohc7p45OUKMYeaddo7uKwhNYs20cSykff/8sg8ItKk+X1vXEI4dmI2bPDOTcS 6nrj9QzvUz8QQ== From: Jakub Kicinski To: davem@davemloft.net Cc: netdev@vger.kernel.org, edumazet@google.com, pabeni@redhat.com, shuah@kernel.org, petrm@nvidia.com, linux-kselftest@vger.kernel.org, willemdebruijn.kernel@gmail.com, Jakub Kicinski Subject: [PATCH net-next v3 7/8] selftests: net: support matching cases by name prefix Date: Wed, 17 Apr 2024 16:11:45 -0700 Message-ID: <20240417231146.2435572-8-kuba@kernel.org> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240417231146.2435572-1-kuba@kernel.org> References: <20240417231146.2435572-1-kuba@kernel.org> Precedence: bulk X-Mailing-List: linux-kselftest@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 While writing tests with a lot more cases I got tired of having to jump back and forth to add the name of the test to the ksft_run() list. Most unittest frameworks do some name matching, e.g. assume that functions with names starting with test_ are test cases. Support similar flow in ksft_run(). Let the author list the desired prefixes. globals() need to be passed explicitly, IDK how to work around that. Signed-off-by: Jakub Kicinski --- tools/testing/selftests/drivers/net/ping.py | 3 +-- tools/testing/selftests/net/lib/py/ksft.py | 10 +++++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/tools/testing/selftests/drivers/net/ping.py b/tools/testing/selftests/drivers/net/ping.py index 7dd197836ff1..58aefd3e740f 100755 --- a/tools/testing/selftests/drivers/net/ping.py +++ b/tools/testing/selftests/drivers/net/ping.py @@ -24,8 +24,7 @@ from lib.py import cmd def main() -> None: with NetDrvEpEnv(__file__) as cfg: - ksft_run([test_v4, test_v6], - args=(cfg, )) + ksft_run(globs=globals(), case_pfx={"test_"}, args=(cfg, )) ksft_exit() diff --git a/tools/testing/selftests/net/lib/py/ksft.py b/tools/testing/selftests/net/lib/py/ksft.py index 25f2572fa540..fe4025dc5a16 100644 --- a/tools/testing/selftests/net/lib/py/ksft.py +++ b/tools/testing/selftests/net/lib/py/ksft.py @@ -81,7 +81,15 @@ KSFT_RESULT_ALL = True print(res) -def ksft_run(cases, args=()): +def ksft_run(cases=None, globs=None, case_pfx=None, args=()): + cases = cases or [] + + if globs and case_pfx: + for key, value in globs.items(): + stats_with_pfx = bool([pfx for pfx in case_pfx if key.startswith(pfx)]) + if callable(value) and stats_with_pfx: + cases.append(value) + totals = {"pass": 0, "fail": 0, "skip": 0, "xfail": 0} print("KTAP version 1") From patchwork Wed Apr 17 23:11:46 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Kicinski X-Patchwork-Id: 790038 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 2845486642; Wed, 17 Apr 2024 23:11:59 +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=1713395520; cv=none; b=qZAENB8kkozdTV930xA7oeSiQEWuogD9xF7OgK3UsR2sLlgMA9fECub9rbYY5eI22wdvTq2AxuGGH9euyPPKk4eULu2tDCqoDoVRDBqax+JWqfDgDV8fdefijuEK7Bnr8f2H7+JtpFv5lfn+cxr/hI83ZmtiRoOOxwI9Xfssy4E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713395520; c=relaxed/simple; bh=DC11VmWV/vCJfXR7IdGU4BMhT5O7Y8zbY+ZoT49PZoo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=a42VvmoAMD9jt0qn0nsHd3nYr6huD3N744R9zk1tAl3h0cSO/POHssr/axhau3hYryettH9IvLtfuRXd8/pUzxJkmWV0GlbXuyvhEh7PEw4+i1FbbhmEX7uhw0hngci2kztgegkr+5sbHXorX/7sSiP2ANU9K2zGBhLH8r1HDcg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=TYKp4VNS; 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="TYKp4VNS" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 67A0CC3277B; Wed, 17 Apr 2024 23:11:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1713395519; bh=DC11VmWV/vCJfXR7IdGU4BMhT5O7Y8zbY+ZoT49PZoo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=TYKp4VNS2lMzTZfAND/qnEcsUcBot1CElx3m5m9+yNXZD4QK25sDKMD56LJCAKxfR z+Hr87ta/KRr0CMr7ozsR9sh9E4dNOORsD+CrUaRDhXoBro/kzGvdR1CZ9r5zhWM/f 1+fZKm0QJ/nLGjdHvIQboeSEQDURhx9J1d+JpLeLFyG7FpMRtkdL1n1fA9vMhwVB6J 3/QmOmH6W1dvt0pVoM9iGgbkBTObxu+9fXJ05Eu+NWfAJSqPj09+u0qeGEED4txbcg yodAQryiURTx0kVyThQj0aP7OE9FW0iQfZb6vfXvMIqHyLQ9Cyx4RPqScCzhaVScTR g/TK0wsJ/BJgA== From: Jakub Kicinski To: davem@davemloft.net Cc: netdev@vger.kernel.org, edumazet@google.com, pabeni@redhat.com, shuah@kernel.org, petrm@nvidia.com, linux-kselftest@vger.kernel.org, willemdebruijn.kernel@gmail.com, Jakub Kicinski Subject: [PATCH net-next v3 8/8] selftests: drv-net: add a TCP ping test case (and useful helpers) Date: Wed, 17 Apr 2024 16:11:46 -0700 Message-ID: <20240417231146.2435572-9-kuba@kernel.org> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240417231146.2435572-1-kuba@kernel.org> References: <20240417231146.2435572-1-kuba@kernel.org> Precedence: bulk X-Mailing-List: linux-kselftest@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 More complex tests often have to spawn a background process, like a server which will respond to requests or tcpdump. Add support for creating such processes using the with keyword: with bkg("my-daemon", ..): # my-daemon is alive in this block My initial thought was to add this support to cmd() directly but it runs the command in the constructor, so by the time we __enter__ it's too late to make sure we used "background=True". Second useful helper transplanted from net_helper.sh is wait_port_listen(). Signed-off-by: Jakub Kicinski --- tools/testing/selftests/drivers/net/ping.py | 24 +++++++++++++-- tools/testing/selftests/net/lib/py/utils.py | 33 +++++++++++++++++++++ 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/drivers/net/ping.py b/tools/testing/selftests/drivers/net/ping.py index 58aefd3e740f..8532e3be72ba 100755 --- a/tools/testing/selftests/drivers/net/ping.py +++ b/tools/testing/selftests/drivers/net/ping.py @@ -1,9 +1,12 @@ #!/usr/bin/env python3 # SPDX-License-Identifier: GPL-2.0 -from lib.py import ksft_run, ksft_exit, KsftXfailEx +import random + +from lib.py import ksft_run, ksft_exit +from lib.py import ksft_eq, KsftXfailEx from lib.py import NetDrvEpEnv -from lib.py import cmd +from lib.py import bkg, cmd, wait_port_listen def test_v4(cfg) -> None: @@ -22,6 +25,23 @@ from lib.py import cmd cmd(f"ping -c 1 -W0.5 {cfg.v6}", host=cfg.remote) +def test_tcp(cfg) -> None: + port = random.randrange(1024 + (1 << 15)) + with bkg(f"nc -l {cfg.addr} {port}") as nc: + wait_port_listen(port) + + cmd(f"echo ping | nc {cfg.addr} {port}", + shell=True, host=cfg.remote) + ksft_eq(nc.stdout.strip(), "ping") + + port = random.randrange(1024 + (1 << 15)) + with bkg(f"nc -l {cfg.remote_addr} {port}", host=cfg.remote) as nc: + wait_port_listen(port, host=cfg.remote) + + cmd(f"echo ping | nc {cfg.remote_addr} {port}", shell=True) + ksft_eq(nc.stdout.strip(), "ping") + + def main() -> None: with NetDrvEpEnv(__file__) as cfg: ksft_run(globs=globals(), case_pfx={"test_"}, args=(cfg, )) diff --git a/tools/testing/selftests/net/lib/py/utils.py b/tools/testing/selftests/net/lib/py/utils.py index e80fea9f6562..6bacdc99d21b 100644 --- a/tools/testing/selftests/net/lib/py/utils.py +++ b/tools/testing/selftests/net/lib/py/utils.py @@ -1,7 +1,10 @@ # SPDX-License-Identifier: GPL-2.0 import json as _json +import re import subprocess +import time + class cmd: def __init__(self, comm, shell=True, fail=True, ns=None, background=False, host=None): @@ -38,6 +41,18 @@ import subprocess (self.proc.args, stdout, stderr)) +class bkg(cmd): + def __init__(self, comm, shell=True, fail=True, ns=None, host=None): + super().__init__(comm, background=True, + shell=shell, fail=fail, ns=ns, host=host) + + def __enter__(self): + return self + + def __exit__(self, ex_type, ex_value, ex_tb): + return self.process() + + def ip(args, json=None, ns=None, host=None): cmd_str = "ip " if json: @@ -47,3 +62,21 @@ import subprocess if json: return _json.loads(cmd_obj.stdout) return cmd_obj + + +def wait_port_listen(port, proto="tcp", ns=None, host=None, sleep=0.005, deadline=1): + end = time.monotonic() + deadline + + pattern = f":{port:04X} .* " + if proto == "tcp": # for tcp protocol additionally check the socket state + pattern += "0A" + pattern = re.compile(pattern) + + while True: + data = cmd(f'cat /proc/net/{proto}*', ns=ns, host=host, shell=True).stdout + for row in data.split("\n"): + if pattern.search(row): + return + if time.monotonic() > end: + raise Exception("Waiting for port listen timed out") + time.sleep(sleep)