public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
blob 771cba80d7aef63e6a0905dbb84ee63e5655b3ff 4265 bytes (raw)

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
 
#! /usr/bin/python3

# SPDX-License-Identifier: GPL-2.0-or-later
#
# tasst - Test A Simple Socket Transport
#         library of test helpers for passt & pasta
#
# tasst/ndp.py - Helpers for testing NDP
#
# Copyright Red Hat
# Author: David Gibson <david@gibson.dropbear.id.au>

import contextlib
import ipaddress
import os

from tasst import Tasst, TasstSubData
from tasst.address import IpiAllocator, TEST_NET6_TASST_A
from tasst.nstool import UnshareSite
from tasst.site import Site
from tasst.typing import typecheck


class NdpTasstInfo:
    def __init__(self, site, ifname, net, gw):
        self.site = typecheck(site, Site)
        self.ifname = typecheck(ifname, str)
        self.net = typecheck(net, ipaddress.IPv6Network)
        self.gw = typecheck(gw, ipaddress.IPv6Address)

        site.require_cmds('ip')


class BaseNdpTasst(Tasst):
    """
    Test NDP behaviour.
    
    :avocado: disable
    """

    def setup_ndp(self):
        raise NotImplementedError("{} must implement setup_ndp() method".format(type(self).__name__))

    @contextlib.contextmanager
    def check_setup_ndp(self):
        with self.setup_ndp() as ndp:
            if not isinstance(ndp, NdpTasstInfo):
                raise TypeError("{}.setup_ndp() must yield a NdpTasstInfo instance".format(type(self).__name__))
            yield ndp
    
    def test_addr(self):
        with self.check_setup_ndp() as ndp:
            # Wait for NDP to do its thing
            (addr,) = ndp.site.addr_wait(ndp.ifname, family='inet6', scope='global')

            # The SLAAC address is derived from the guest ns MAC, so
            # probably won't exactly match the host address (we need
            # DHCPv6 for that).  It should be in the right network though.
            self.assertEquals(addr.network, ndp.net)

    def test_route(self):
        with self.check_setup_ndp() as ndp:
            defroutes = ndp.site.routes6(dst='default')
            while not defroutes:
                defroutes = ndp.site.routes6(dst='default')

            self.assertEquals(len(defroutes), 1)
            gateway = ipaddress.ip_address(defroutes[0]['gateway'])
            self.assertEquals(gateway, ndp.gw)


class MetaNdpTasst(BaseNdpTasst):
    """Ugly workaround for
    https://github.com/avocado-framework/avocado/issues/5680.
    Explicitly apply the "meta" tag to inherited tests

    :avocado: disable
    :avocado: tags=meta

    """

    def test_addr(self):
        super().test_addr()

    def test_route(self):
        super().test_route()


class RadvdNdpTasst(MetaNdpTasst):
    timeout = 15.0
    
    @contextlib.contextmanager
    def setup_ndp(self):
        ifname = 'clientif'
        router_ifname = 'routerif'
        prefix = TEST_NET6_TASST_A

        with UnshareSite(type(self).__name__ + '.client', '-Un') as client, \
             UnshareSite(type(self).__name__ + '.router', '-n', parent=client, sudo=True) as router:
            router.require_cmds('radvd')

            client.veth(ifname, router_ifname, router)

            # Configure the simulated router
            ipa = IpiAllocator(prefix)
            (router_ip6,) = ipa.next_ipis()

            confpath = os.path.join(self.workdir, 'radvd.conf')
            pidpath = os.path.join(self.workdir, 'radvd.pid')
            open(confpath, 'w').write(
            '''
            interface {} {{
                AdvSendAdvert on;
                prefix {} {{
                }};
            }};
            '''.format(router_ifname, prefix))

            router.ifup('lo')
            router.ifup('routerif', router_ip6)

            # Configure the client
            client.ifup('lo')
            client.ifup(ifname)

            # Get the router's link-local-address
            (router_ll,) = router.addr_wait(router_ifname, family='inet6', scope='link')

            # Run radvd
            router.fg('radvd -c -C {}'.format(confpath))
            with router.bg('radvd -C {} -p {} -n -d 5'.format(confpath, pidpath), sudo=True) as radvd:
                yield NdpTasstInfo(client, ifname, prefix, router_ll.ip)

                pid = int(open(pidpath).read())
                router.fg('kill {}'.format(pid))
                status = radvd.wait()
                self.assertEquals(status, 0)

debug log:

solving 771cba8 ...
found 771cba8 in https://archives.passt.top/passt-dev/20230531015849.3229596-18-david@gibson.dropbear.id.au/

applying [1/1] https://archives.passt.top/passt-dev/20230531015849.3229596-18-david@gibson.dropbear.id.au/
diff --git a/avocado/tasst/ndp.py b/avocado/tasst/ndp.py
new file mode 100644
index 0000000..771cba8

1:43: trailing whitespace.
    
1:56: trailing whitespace.
    
1:97: trailing whitespace.
    
Checking patch avocado/tasst/ndp.py...
Applied patch avocado/tasst/ndp.py cleanly.
warning: 3 lines add whitespace errors.

index at:
100644 771cba80d7aef63e6a0905dbb84ee63e5655b3ff	avocado/tasst/ndp.py

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).