From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from gandalf.ozlabs.org (mail.ozlabs.org [IPv6:2404:9400:2221:ea00::3]) by passt.top (Postfix) with ESMTPS id 201FA5A027A for ; Tue, 27 Jun 2023 04:54:46 +0200 (CEST) Received: by gandalf.ozlabs.org (Postfix, from userid 1007) id 4Qqq7K0g00z4wqs; Tue, 27 Jun 2023 12:54:37 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gibson.dropbear.id.au; s=201602; t=1687834477; bh=KvkAa/CskjNuJppkltdXuKvW2Wdho90PxJ1ZuuJ5ZFA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Z4UgzHR5VCO/ACf8WDkrr0ANoiGAi7KW6zdzZFG7YNZPyKDgAPNrA5aqwJD8u1jYg 2QdAC7uQD4Z1sHCVNsgUC/4OkgiHFxtCOv8QpmoFlPqryZoCyA9c6arqmlUh4TszBF TF46yds8xbHyUHbtnE/CJj+6e8x3EZaoXRhnlP1U= From: David Gibson To: passt-dev@passt.top, Stefano Brivio Subject: [PATCH 19/27] tasst: Add helper to wait for IP address to appear Date: Tue, 27 Jun 2023 12:54:20 +1000 Message-ID: <20230627025429.2209702-20-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230627025429.2209702-1-david@gibson.dropbear.id.au> References: <20230627025429.2209702-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Message-ID-Hash: K5P7VGNECDCS7URXLT6UHJRFMF6P7ANY X-Message-ID-Hash: K5P7VGNECDCS7URXLT6UHJRFMF6P7ANY X-MailFrom: dgibson@gandalf.ozlabs.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: crosa@redhat.com, jarichte@redhat.com, David Gibson X-Mailman-Version: 3.3.8 Precedence: list List-Id: Development discussion and patches for passt Archived-At: Archived-At: List-Archive: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: Add a helper to the Site() class to wait for an address with specified characteristics to be ready on an interface. In particular this is useful for waiting for IPv6 SLAAC & DAD (Duplicate Address Detection) to complete. Because DAD is not going to be useful in many of our scenarios, also extend Site.ifup() to allow DAD to be switched to optimistic mode or disabled. Signed-off-by: David Gibson --- test/tasst/exesite.py | 22 ++++++++++++++++++- test/tasst/meta/static_ifup.py | 40 ++++++++++++++++++++++++++++++++++ test/tasst/meta/veth.py | 26 ++++++++++++++++++++++ 3 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 test/tasst/meta/static_ifup.py diff --git a/test/tasst/exesite.py b/test/tasst/exesite.py index 63872c34..423fccbd 100644 --- a/test/tasst/exesite.py +++ b/test/tasst/exesite.py @@ -102,8 +102,22 @@ class Site(contextlib.AbstractContextManager): info = json.loads(self.output('ip -j link show')) return [i['ifname'] for i in info] - def ifup(self, ifname): + def ifup(self, ifname, *addrs, dad=None): self.require_cmds('ip') + if dad == 'disable': + self.fg(f'sysctl net.ipv6.conf.{ifname}.accept_dad=0', sudo=True) + elif dad == 'optimistic': + self.fg(f'sysctl net.ipv6.conf.{ifname}.optimistic_dad=1', + sudo=True) + elif dad is not None: + raise ValueError + + for a in addrs: + if not isinstance(a, ipaddress.IPv4Interface) \ + and not isinstance(a, ipaddress.IPv6Interface): + raise TypeError + self.fg(f'ip addr add {a.with_prefixlen} dev {ifname}', sudo=True) + self.fg(f'ip link set {ifname} up', sudo=True) def addrinfos(self, ifname, **criteria): @@ -129,6 +143,12 @@ class Site(contextlib.AbstractContextManager): (info,) = json.loads(self.output(f'ip -j link show {ifname}')) return info['mtu'] + def addr_wait(self, ifname, **criteria): + while True: + addrs = self.addrs(ifname, **criteria) + if addrs: + return addrs + def test_site(sitefn): def test_true(s): diff --git a/test/tasst/meta/static_ifup.py b/test/tasst/meta/static_ifup.py new file mode 100644 index 00000000..0896c747 --- /dev/null +++ b/test/tasst/meta/static_ifup.py @@ -0,0 +1,40 @@ +#! /usr/bin/env avocado-runner-avocado-classless + +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Copyright Red Hat +# Author: David Gibson + +""" +Test A Simple Socket Transport + +meta/static_ifup - Static address configuration +""" + +import contextlib +import ipaddress + +from avocado_classless.test import assert_eq_unordered, test + +from tasst.nstool import unshare_site + + +IFNAME = 'testveth' +IFNAME_PEER = 'vethpeer' +TEST_IPS = [ipaddress.ip_interface('192.0.2.1/24'), + ipaddress.ip_interface('2001:db8:9a55::1/112'), + ipaddress.ip_interface('10.1.2.3/8')] + + +@contextlib.contextmanager +def setup_ns(): + with unshare_site('ns', '-Un') as ns: + ns.veth(IFNAME, IFNAME_PEER) + ns.ifup(IFNAME, *TEST_IPS, dad='disable') + yield ns + + +@test +def test_addr(): + with setup_ns() as ns: + assert_eq_unordered(ns.addrs(IFNAME, scope='global'), TEST_IPS) diff --git a/test/tasst/meta/veth.py b/test/tasst/meta/veth.py index 053bd9c8..cedcf059 100644 --- a/test/tasst/meta/veth.py +++ b/test/tasst/meta/veth.py @@ -12,6 +12,7 @@ meta/veth.py - Test various veth configurations """ import contextlib +import ipaddress from avocado_classless.test import assert_eq, assert_eq_unordered, test @@ -38,3 +39,28 @@ def test_mtu(): with unconfigured_veth() as (ns1, ns2): assert_eq(ns1.mtu('veth1'), 1500) assert_eq(ns2.mtu('veth2'), 1500) + + +@test +def test_slaac(dad=None): + TESTMAC = '02:aa:bb:cc:dd:ee' + TESTIP = ipaddress.ip_interface('fe80::aa:bbff:fecc:ddee/64') + + with unconfigured_veth() as (ns1, ns2): + ns1.fg(f'ip link set dev veth1 address {TESTMAC}', sudo=True) + + ns1.ifup('veth1', dad=dad) + ns2.ifup('veth2') + + addrs = ns1.addr_wait('veth1', family='inet6', scope='link') + assert_eq(addrs, [TESTIP]) + + +@test +def test_optimistic_dad(): + test_slaac(dad='optimistic') + + +@test +def test_no_dad(): + test_slaac(dad='disable') -- 2.41.0