From patchwork Tue Apr 16 00:45:51 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Kicinski X-Patchwork-Id: 13630938 X-Patchwork-Delegate: kuba@kernel.org 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 44EEC17FF; Tue, 16 Apr 2024 00:46:02 +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=1713228363; cv=none; b=PqOAJMC9601kjDDQjUVjfLcmpFizxXtDy1q9Skv+wZWFgn+mYbju1LRrj6jZrtfHnjXbJMVnEFLzD0V04w/I4dra+u3l3JgQtM0VGF3/mc8TvnM84Wxa0ajLvBtNey9lIWI2SjX/XDke2f3KQs+abQRSVe71xmh16x9QOuTGs7o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713228363; c=relaxed/simple; bh=iNZKXPBcjfgMkeh6eFR/vPN9uOlTrnue8ygafyAn8PI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KR7cPIJrCPi8k9CnorxUzZi3lk8Rp74DDREKmz+PGLTwSJk2lRRrXcqAPmUnwlY4jJkURM9+GyedA+54aFWMJ8c9HrfQZt2VysqkvSmRVRuAb3i1H/oJFIVUA/8xDYATS+4/KNUFaZUoYabKKsHgSh9ictqhAwPgaw8tWWEvlbw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=UON5JF6e; 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="UON5JF6e" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 668F8C32786; Tue, 16 Apr 2024 00:46:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1713228362; bh=iNZKXPBcjfgMkeh6eFR/vPN9uOlTrnue8ygafyAn8PI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=UON5JF6e37Z0no2i8XS43agDIo8fpjnUsy2hNBeJDSLdInQvT/ESdYfrnOVy2kzz8 7PRPTnLMgOCgOCNlEI8s5OWK+wRHsfF/EZMAt4A6BI5Gc1r4i7YRfVWqd3nVpP5+Jy KslKjJt97GaTWTkA59eZ4I5BjyCyPCPIc33Nl1hhzWVXpkeYLQg18MOz/yDHl89oh8 KsSnoxSezfJfoUmhYKFacoilSCIWbYgU5LYJYA+DH5iObZ0GlU+2Aq3JkI32RGHVdS WBgsY/RLWmSl7BgRpsa4Vg97rqSNapdF0c2B15gTlFkmI2qjNOJHJQrIP+f2nYUaGB 19L09Odq9QaQQ== 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 v2 1/6] selftests: drv-net: add stdout to the command failed exception Date: Mon, 15 Apr 2024 17:45:51 -0700 Message-ID: <20240416004556.1618804-2-kuba@kernel.org> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240416004556.1618804-1-kuba@kernel.org> References: <20240416004556.1618804-1-kuba@kernel.org> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: kuba@kernel.org ping prints all the info to stdout. To make debug easier capture stdout in the Exception raised when command unexpectedly fails. Signed-off-by: Jakub Kicinski --- tools/testing/selftests/net/lib/py/utils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/net/lib/py/utils.py b/tools/testing/selftests/net/lib/py/utils.py index f0d425731fd4..19612348c30d 100644 --- a/tools/testing/selftests/net/lib/py/utils.py +++ b/tools/testing/selftests/net/lib/py/utils.py @@ -33,7 +33,8 @@ import subprocess 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)) + raise Exception("Command failed: %s\nSTDOUT: %s\nSTDERR: %s" % + (self.proc.args, stdout, stderr)) def ip(args, json=None, ns=None): From patchwork Tue Apr 16 00:45:52 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Kicinski X-Patchwork-Id: 13630939 X-Patchwork-Delegate: kuba@kernel.org 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 986D03D7A; Tue, 16 Apr 2024 00:46:03 +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=1713228363; cv=none; b=YnZQX/TXoQtWwkIs9Fe2bgwDsO7qK5akl/1urYHXowPC7P5JeyZvGtkzpuAOeVMAQGxCNIPbgEvDUvKxRa924Ppr3+2gS5DpEfywv+D6tvoR8W6JIvLU/WDZrysh7r/0PMmvOJRbmP/Zx60Sf/Kx9IQTIJcy4SR/Fm9tlu7VnPI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713228363; c=relaxed/simple; bh=7pnzslXkSvchRavsLakdswzhlJdLRYa1UEolq6woMV0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=q9nK2Rl8ezXzGe4rdY3iWhrXYrmonNos0HtkjPECVDXTiuXkwHtHBw46eNtmgXorw0YWw07pWGKT3tBPqGnkSmuOJXN/lIJtDZkm0qvSpuhCHcYps61UAkbSg/AOv/7RILHbbZMm2wsVVxyGi71qU9Pa3hjiZm7tukzlu4EgQmg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=QSQkfxyl; 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="QSQkfxyl" Received: by smtp.kernel.org (Postfix) with ESMTPSA id DB903C2BD11; Tue, 16 Apr 2024 00:46:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1713228363; bh=7pnzslXkSvchRavsLakdswzhlJdLRYa1UEolq6woMV0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=QSQkfxylBHNUhOdARpP2zjR3Z2oq4gZ1icsg8IiyFVqbrS+8XXD/nINN4+l/jGeaq Pv0nUDHZ7rccmNZ2N8aTx9bZsfoKMXf07Ohm1C9B8lBcNsjMr5r5dRkGLUFT2oyMOL BFyy/BtJLjwjd01R9N9+PDL7VEYnLcoLZQeQRzmBhGxZ2C+98HvVVIJegNqyg5xe9G E08lNcT9utWgiZg+VbbcGwQ8BMdw9cQDOFqaWmdNXsjS5W4P6a/A0+j1r7lEu4vP5U ItGAh0JDZmZeSTI4EDhNm0LX3/H9hq2rljkpFnK2XgV3n/Lk9EmiVdP00izIXCh1Ah 0HSh5QuSR2Bkw== 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 v2 2/6] selftests: drv-net: add config for netdevsim Date: Mon, 15 Apr 2024 17:45:52 -0700 Message-ID: <20240416004556.1618804-3-kuba@kernel.org> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240416004556.1618804-1-kuba@kernel.org> References: <20240416004556.1618804-1-kuba@kernel.org> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: kuba@kernel.org Real driver testing will obviously require enabling more options, but will require more manual setup in the first place. For CIs running purely software tests we need to enable netdevsim. Signed-off-by: Jakub Kicinski --- tools/testing/selftests/drivers/net/config | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 tools/testing/selftests/drivers/net/config diff --git a/tools/testing/selftests/drivers/net/config b/tools/testing/selftests/drivers/net/config new file mode 100644 index 000000000000..f6a58ce8a230 --- /dev/null +++ b/tools/testing/selftests/drivers/net/config @@ -0,0 +1,2 @@ +CONFIG_IPV6=y +CONFIG_NETDEVSIM=m From patchwork Tue Apr 16 00:45:53 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Kicinski X-Patchwork-Id: 13630940 X-Patchwork-Delegate: kuba@kernel.org 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 063486AC0; Tue, 16 Apr 2024 00:46:03 +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=1713228364; cv=none; b=louOktdfTyXRaj0u7sHxa/1n5Q9BlQBVzwOHguGj/tp7ZL5EFDtS0IUPoQfz5iBc6jEucy8hFBzvfTMBLWeujTlwDokS7ebkoE0hyNkOmdJUn4EZVC6t1nnP/xjWsAXcaxeRRPcxRDgqsD1v43EJOMWpWbi6xS3tdOmqZEONJt8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713228364; c=relaxed/simple; bh=Sq1yJX/p7e6wKVnfy1b9yJfgXqWpseordfnRF9WlYKc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Ay8sSgzvYW5MrmzMZXFn7N5hJUpK8umldFzoAsMq8V8DGkoE8EJZ6YC6vDndFCfZiTHdwPO00ZoTmDsDhCNIrb6EOrnj0iBeJJ2GYxukNIHoBx+5ez41+MQeuPcyV98uFDcpXe4OIBwJVwmlHgTzlehzwg83ltULbxt/bf3NYXg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=jY8AMBh+; 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="jY8AMBh+" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5DDA6C113CC; Tue, 16 Apr 2024 00:46:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1713228363; bh=Sq1yJX/p7e6wKVnfy1b9yJfgXqWpseordfnRF9WlYKc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=jY8AMBh+7m788lOlgV621O5uFvim2azwXq1hACDg66DBreX3QDW+vj7FbAlHt8j2K ZaqLoYeaB5HWWRuc6Op8a30iKT0Eq985uqKgjwth73ZRVjX5GQBg8JoF3bqUP/MYms utBABHw4lXbFaN/O3n/ZzM5JDdY0TyfT8sGK/tav1KqDh+RRgz7fRQYMe5cwGbjT/n X7or2hsLRzN/6Byx7JTDAYEsoOQkSddl+7LJBSVgpraj2RQZT43kKm+lVEwLSVxQPn 3ekaopYkI9ke6Bppt4hf15/CnWczcmsbNgj+Kbv35sfoAHeNG7a5gIpRIcdNPT70Gf a9JB42PgnUcCg== 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 v2 3/6] selftests: drv-net: define endpoint structures Date: Mon, 15 Apr 2024 17:45:53 -0700 Message-ID: <20240416004556.1618804-4-kuba@kernel.org> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240416004556.1618804-1-kuba@kernel.org> References: <20240416004556.1618804-1-kuba@kernel.org> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: kuba@kernel.org 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 --- .../selftests/drivers/net/lib/py/__init__.py | 1 + .../selftests/drivers/net/lib/py/remote.py | 13 +++++++ .../drivers/net/lib/py/remote_netns.py | 15 ++++++++ .../drivers/net/lib/py/remote_ssh.py | 34 +++++++++++++++++++ tools/testing/selftests/net/lib/py/utils.py | 19 ++++++----- 5 files changed, 73 insertions(+), 9 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..d86b997d27d4 --- /dev/null +++ b/tools/testing/selftests/drivers/net/lib/py/remote.py @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0 + +import importlib + +_modules = {} + +def Remote(kind, args): + global _modules + + if kind not in _modules: + _modules[kind] = importlib.import_module("..remote_" + kind, __name__) + + return getattr(_modules[kind], "Remote")(args) 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..7d8ab7a1bf92 --- /dev/null +++ b/tools/testing/selftests/drivers/net/lib/py/remote_netns.py @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0 + +from lib.py import cmd + + +class Remote: + def __init__(self, name): + self.name = name + + def cmd(self, *args): + c = cmd(*args, ns=self.name) + return c.stdout, c.stderr, c.ret + + def deploy(self, what): + return 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..c056b15991ff --- /dev/null +++ b/tools/testing/selftests/drivers/net/lib/py/remote_ssh.py @@ -0,0 +1,34 @@ +# SPDX-License-Identifier: GPL-2.0 + +import os +import shlex +import string +import random + +from lib.py import cmd + + +class Remote: + def __init__(self, name): + self.name = name + self._tmpdir = None + + def __del__(self): + if self._tmpdir: + self.cmd("rm -rf " + self._tmpdir) + self._tmpdir = None + + def cmd(self, comm, *args): + c = cmd("ssh " + self.name + " " + shlex.quote(comm), *args) + return c.stdout, c.stderr, c.ret + + 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() + self.cmd("mkdir " + self._tmpdir) + file_name = self._tmpdir + "/" + self._mktmp() + os.path.basename(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..d47d684d9e02 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,10 +13,13 @@ import subprocess 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) + if host: + self.stdout, self.stderr, self.ret = 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: @@ -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 Tue Apr 16 00:45:54 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Kicinski X-Patchwork-Id: 13630941 X-Patchwork-Delegate: kuba@kernel.org 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 93F88A94F; Tue, 16 Apr 2024 00:46:04 +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=1713228364; cv=none; b=cziBE6YYW7+oTTcZwLhrRDD9LMsTUToTA3oAY4dljVRLBUdaN9P4x3zDuG78H5M3ClQ+eh4FRjr0VZKkEbSz4kQ7CoDvODAIEx1RlXYZL5QkgKg0rOQ8Ddb+w+aofJw+04A7aCPtrAr4Pm9OcdnmUGii7/4Er1eVF0Cdb95uJf8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713228364; c=relaxed/simple; bh=U5+EVNFryCl6AbqRDTDECqncYZkgnEzOhvv/pOI/KNg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=PXxr+6Y6ye/q9i0i0QeO9SnR3e4XUGranB71W7j+5ztM7DC6Y5lBgpQxJSjosc1gnkHsOBzSFQH+uzoaP/TOi/AvryRVV1lonaOnPf+hr/eL/R83LjYPvztEmfq+bwluGVn+szaCU8S8fKfzQ68WUcoiMaTaFtWyLaP7Tdw8Nh8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ogqa3Zsb; 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="ogqa3Zsb" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D4CBEC4AF07; Tue, 16 Apr 2024 00:46:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1713228364; bh=U5+EVNFryCl6AbqRDTDECqncYZkgnEzOhvv/pOI/KNg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ogqa3ZsboKb/chTbmpyOUKzKeRofiNdTH/u4+IOOC1+jQKWkloaxw+4SfdrqEBUnX bEj0ciXgoRSrfR7ylP4NLH+0R+4mLg+8T2x/Pl1IHAOBuHF4snXugrjByJyEu3OaT3 AKnL1w7lXEWPErpTrZQXj3hW+H1R+1qgKtXoVZbYMFttlO50Ly+rZwBD1joQ1SEKtI 8oivkI+YskjZrLrtihvUhuuCEwuAPgXgBY/xc8x7p9rlGYa8N6MiVWHidxETd3kI4U z3HdjFgjOIhvOuzJ/dlwBjhWAq++C4j3xnn5ZOMvBzhVHmPxuPGYWtV/bbSaHwx2+l 1XtBF/4YJi6Vg== 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 v2 4/6] selftests: drv-net: factor out parsing of the env Date: Mon, 15 Apr 2024 17:45:54 -0700 Message-ID: <20240416004556.1618804-5-kuba@kernel.org> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240416004556.1618804-1-kuba@kernel.org> References: <20240416004556.1618804-1-kuba@kernel.org> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: kuba@kernel.org 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 Tue Apr 16 00:45:55 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Kicinski X-Patchwork-Id: 13630942 X-Patchwork-Delegate: kuba@kernel.org 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 BF8E9AD55; Tue, 16 Apr 2024 00:46:04 +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=1713228364; cv=none; b=Dw4wM11fIeV8Q9W8rklr31lDLX9mQFxB/XieRTsVdtAKsxdBtMwaKhIst+sJfKClgx3lukoHstrFz74DLaprQgTwrV+5gS2hb9ei3zcw9hJZuhSFcv+V2ENhZ1rp1w+PflWPxu7eAeqW0hNcQvw1UJ/o48LkjiZCUd6MXD7QsME= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713228364; c=relaxed/simple; bh=1PvkdRwOvd9p3qhuBIsx4SJ+RuGU9OVHKX0p6+vnOOQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=DVEazs7TmNU8KIFfTLnHf74YfoKGB2FiGQh+k4wzhy03yF6+diHLH5e/EwR4u0Rm0nEsZroNFSBcA5urI4RzoZ9jxJ3B+FysWLMjbBM3RCaszRypZ4Z5XjE8OXbdzsZjJhm1Cg+OfvWnOxF5zGFpLR88dWZO2434SlO8Ujb9PC0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=aZg5b2I9; 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="aZg5b2I9" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5472EC4AF1B; Tue, 16 Apr 2024 00:46:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1713228364; bh=1PvkdRwOvd9p3qhuBIsx4SJ+RuGU9OVHKX0p6+vnOOQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=aZg5b2I9cUDohJ7G4cRx9pmZdm3nkog/Rml/axmgblnOc8O5PZW51G0thZt1o/D4y Bv9F7eBlw5x2b9zoRNNjE56EPkqD2iIo5bOuJIu9YMD8HJStibnXIHuJ2ETaGBdOWi E9kJcDwnFJ+sSvwghklwpHL/U7gPR+Wz9A2otaLkkL3HtNpab3k00mVKiFxgVy7bEE P98vHTPxCW4rL6hfdGmwGmMNTnP7wBtBl74Q5yiHNI3IwI5biDts13L2yNONu2H8Wt D0QkjUaIKvjXO5JBt0nwbo/SMjZnbWYHfqOmMufH32m2kn+ZgFM88U74pu03V7VxuK eHBixc3e6b6WQ== 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 v2 5/6] selftests: drv-net: construct environment for running tests which require an endpoint Date: Mon, 15 Apr 2024 17:45:55 -0700 Message-ID: <20240416004556.1618804-6-kuba@kernel.org> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240416004556.1618804-1-kuba@kernel.org> References: <20240416004556.1618804-1-kuba@kernel.org> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: kuba@kernel.org 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..d6d1ec8f3a77 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) + + 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 Tue Apr 16 00:45:56 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Kicinski X-Patchwork-Id: 13630943 X-Patchwork-Delegate: kuba@kernel.org 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 80B38F9E8; Tue, 16 Apr 2024 00:46:05 +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=1713228365; cv=none; b=tCz+qELX/z4HetbmGLHwzS3eTAG0kkaMTxw2aXI3n9P75thYry4vpVhIe0NdJbiTuZTbaomfLcu8bBhEX56iNVi8xIn84xI4t/5WcyD6qjDQW4iIh/wIzz/CJwxfHuJsSHGqyu4Rvl+LYjBg+XgN16OTUiq3fu5jcXNITN17KNA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713228365; c=relaxed/simple; bh=y9sov6G1b9aY1nBElEZFBTccJq2jlrMvMtldou9HhZ4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=W+Ign38+sdA/FGco+GHh3CCydxbCo+tWuCX9EFVhcJXM6+4ykcSDmmypbzu2S26oZrQf+5KIpz5hdD7a9xtK1AcBeDBhPR/WrsmSD+hc/u8ME6tsToeJMKRa2OwBTkqfNx8+B5HSS0zL9mloTwnYoo0SWFwrTl/64VpABJAFcQk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=jK7vx2hu; 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="jK7vx2hu" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C8409C4AF0A; Tue, 16 Apr 2024 00:46:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1713228365; bh=y9sov6G1b9aY1nBElEZFBTccJq2jlrMvMtldou9HhZ4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=jK7vx2huxUkpe0ejXTzoWwg1Di4AzhlxmWPWVWTMRFZbMKwZE0GUvT8PRRtqV7T43 GT+R8R0HPAC+hPB9BwRjBiCr+QaLY/RZFYXhYvtVWgdBkBGkGrppgJomb5BLm8PZ4r lx4D/FfGRmt5+2XpU++NXmNNlAbVRplBYjOtP2uIhfjc0jwHLCGCp4tsj+II8ygXxi obHZXYavyERu+5GKHyeKv6FRbB1x4D7TztinRugxheNGR3OT1cYn/FrBt1p4yJwVFW Ni2hirumzKhA7w4SURqpBFugRKxsbDdIr9mXgcOPfiZgrdmJaSKC+J8Z1FzSUEHSIY 0KmFuSADRwBxA== 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 v2 6/6] selftests: drv-net: add a trivial ping test Date: Mon, 15 Apr 2024 17:45:56 -0700 Message-ID: <20240416004556.1618804-7-kuba@kernel.org> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240416004556.1618804-1-kuba@kernel.org> References: <20240416004556.1618804-1-kuba@kernel.org> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: kuba@kernel.org 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.ping_v4 # ok 2 ping.ping_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.ping_v4 ok 2 ping.ping_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.ping_v4 # ok 2 ping.ping_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 | 32 ++++++++++++++++++++ 2 files changed, 36 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..2d74f15a52a0 --- /dev/null +++ b/tools/testing/selftests/drivers/net/ping.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0 + +from lib.py import ksft_run, KsftXfailEx +from lib.py import NetDrvEpEnv +from lib.py import cmd + + +def ping_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 ping_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([ping_v4, ping_v6], + args=(cfg, )) + + +if __name__ == "__main__": + main()