public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
From: David Gibson <david@gibson.dropbear.id.au>
To: passt-dev@passt.top, Stefano Brivio <sbrivio@redhat.com>
Cc: crosa@redhat.com, jarichte@redhat.com,
	David Gibson <david@gibson.dropbear.id.au>
Subject: [PATCH 19/27] tasst: Add helper to wait for IP address to appear
Date: Tue, 27 Jun 2023 12:54:20 +1000	[thread overview]
Message-ID: <20230627025429.2209702-20-david@gibson.dropbear.id.au> (raw)
In-Reply-To: <20230627025429.2209702-1-david@gibson.dropbear.id.au>

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 <david@gibson.dropbear.id.au>
---
 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 <david@gibson.dropbear.id.au>
+
+"""
+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')
-- 
@@ -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


  parent reply	other threads:[~2023-06-27  2:54 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-06-27  2:54 [PATCH 00/27] RFC: Start converting passt & pasta tests to Avocado using special plugin David Gibson
2023-06-27  2:54 ` [PATCH 01/27] avocado: Make a duplicate copy of testsuite for comparison purposes David Gibson
2023-06-27  2:54 ` [PATCH 02/27] avocado: Don't double download assets for test/ and oldtest/ David Gibson
2023-06-27  2:54 ` [PATCH 03/27] avocado: Move static checkers to avocado David Gibson
2023-06-27  2:54 ` [PATCH 04/27] avocado: Introduce "avocado-classless" plugin, runner and outline David Gibson
2023-06-27  2:54 ` [PATCH 05/27] avocado, test: Add static checkers for Python code David Gibson
2023-06-27  2:54 ` [PATCH 06/27] avocado: Resolver implementation for avocado-classless plugin David Gibson
2023-06-27  2:54 ` [PATCH 07/27] avocado: Add basic assertion helpers to " David Gibson
2023-06-27  2:54 ` [PATCH 08/27] tasst, avocado: Introduce library of common test helpers David Gibson
2023-06-27  2:54 ` [PATCH 09/27] avocado-classless: Test matrices by composition David Gibson
2023-06-27  2:54 ` [PATCH 10/27] tasst: Helper functions for executing commands in different places David Gibson
2023-06-27  2:54 ` [PATCH 11/27] avocado-classless: Allow overriding default timeout David Gibson
2023-06-27  2:54 ` [PATCH 12/27] avocado: Convert build tests to avocado David Gibson
2023-06-27  2:54 ` [PATCH 13/27] tasst: Add helpers for running background commands on sites David Gibson
2023-06-27  2:54 ` [PATCH 14/27] tasst: Add helper to get network interface names for a site David Gibson
2023-06-27  2:54 ` [PATCH 15/27] tasst: Add helpers to run commands with nstool David Gibson
2023-06-27  2:54 ` [PATCH 16/27] tasst: Add ifup and network address helpers to Site David Gibson
2023-06-27  2:54 ` [PATCH 17/27] tasst: Helper for creating veth devices between namespaces David Gibson
2023-06-27  2:54 ` [PATCH 18/27] tasst: Add helper for getting MTU of a network interface David Gibson
2023-06-27  2:54 ` David Gibson [this message]
2023-06-27  2:54 ` [PATCH 20/27] tasst: Add helpers for getting a site's routes David Gibson
2023-06-27  2:54 ` [PATCH 21/27] tasst: Helpers to test transferring data between sites David Gibson
2023-06-27  2:54 ` [PATCH 22/27] tasst: IP address allocation helpers David Gibson
2023-06-27  2:54 ` [PATCH 23/27] tasst: Helpers for running daemons with a pidfile David Gibson
2023-06-27  2:54 ` [PATCH 24/27] tasst: Helpers for testing NDP behaviour David Gibson
2023-06-27  2:54 ` [PATCH 25/27] tasst: Helpers for testing DHCP & DHCPv6 behaviour David Gibson
2023-06-27  2:54 ` [PATCH 26/27] tasst: Helpers to construct a simple network environment for tests David Gibson
2023-06-27  2:54 ` [PATCH 27/27] avocado: Convert basic pasta tests David Gibson
2023-07-05  0:30   ` Stefano Brivio
2023-07-05  3:27     ` David Gibson
2023-07-07 17:42       ` Stefano Brivio
2023-07-10  7:45         ` David Gibson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230627025429.2209702-20-david@gibson.dropbear.id.au \
    --to=david@gibson.dropbear.id.au \
    --cc=crosa@redhat.com \
    --cc=jarichte@redhat.com \
    --cc=passt-dev@passt.top \
    --cc=sbrivio@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://passt.top/passt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for IMAP folder(s).