#! /usr/bin/python3 # SPDX-License-Identifier: GPL-2.0-or-later # # avocado/pasta.py - Basic tests for pasta mode # # Copyright Red Hat # Author: David Gibson import contextlib import ipaddress import os from tasst import Tasst from tasst.address import LOOPBACK4, LOOPBACK6 from tasst.dhcp import BaseDhcpTasst, DhcpTasstInfo from tasst.dhcpv6 import BaseDhcpv6Tasst, Dhcpv6TasstInfo from tasst.ndp import BaseNdpTasst, NdpTasstInfo from tasst.nstool import UnshareSite from tasst.scenario.simple import simple_net from tasst.transfer import BaseTransferTasst, TcpUploadTasst, UdpTransferTasst, TransferTasstInfo from tasst.typing import typecheck PASTA_BIN = './pasta' class BasePastaTasst(Tasst): IN_FWD_PORT = 10002 SPLICE_FWD_PORT = 10003 @contextlib.contextmanager def setup_pasta(self, configure=False): name = type(self).__name__ with simple_net(name) as simnet: with UnshareSite(name + '.guestns', '-Ucnpf --mount-proc', parent=simnet.simhost, sudo=True) as simnet.guestns: relpid = simnet.guestns.relative_pid(simnet.simhost) pidfile = os.path.join(self.workdir, 'pasta.pid') extra = '' if configure: extra = '--config-net' pastacmd = ('{} -f -t {} -u {} -T {} -U {} -P {} {} {}' .format(PASTA_BIN, self.IN_FWD_PORT, self.IN_FWD_PORT, self.SPLICE_FWD_PORT, self.SPLICE_FWD_PORT, pidfile, extra, relpid)) with simnet.simhost.bg(pastacmd) as pasta: # Wait for the pidfile to be written while not os.path.exists(pidfile) or not open(pidfile).read(): pass # PID of pasta process in simhost namespace pid = int(open(pidfile).read()) yield simnet simnet.simhost.fg('kill -TERM {}'.format(pid)) rc = pasta.wait(timeout=1.0) self.assertEquals(rc, 0) class PastaTasst(BasePastaTasst): def test_ifname(self): with self.setup_pasta() as simnet: self.assertCountEqual(simnet.guestns.ifs(), ('lo', simnet.ifname)) class PastaNdpTasst(BasePastaTasst, BaseNdpTasst): @contextlib.contextmanager def setup_ndp(self): with self.setup_pasta() as simnet: simnet.guestns.ifup(simnet.ifname) yield NdpTasstInfo(simnet.guestns, simnet.ifname, simnet.ip6.network, simnet.gw_ip6_ll.ip) class PastaDhcpTasst(BasePastaTasst, BaseDhcpTasst): @contextlib.contextmanager def setup_dhcp(self): with self.setup_pasta() as simnet: yield DhcpTasstInfo(simnet.guestns, simnet.ifname, simnet.ip4.ip, simnet.gw_ip4.ip, 65520) class PastaDhcpv6Tasst(BasePastaTasst, BaseDhcpv6Tasst): @contextlib.contextmanager def setup_dhcpv6(self): with self.setup_pasta() as simnet: yield Dhcpv6TasstInfo(simnet.guestns, simnet.ifname, simnet.ip6.ip) class PastaConfigNetTasst(BasePastaTasst): def test_addr(self): with self.setup_pasta(configure=True) as simnet: addrs = simnet.guestns.addrs(simnet.ifname, scope='global') self.assertCountEqual(addrs, [simnet.ip4, simnet.ip6]) def test_route4(self): with self.setup_pasta(configure=True) as simnet: (defroute,) = simnet.guestns.routes4(dst='default') gateway = ipaddress.ip_address(defroute['gateway']) self.assertEquals(gateway, simnet.gw_ip4.ip) def test_route6(self): with self.setup_pasta(configure=True) as simnet: (defroute,) = simnet.guestns.routes6(dst='default') gateway = ipaddress.ip_address(defroute['gateway']) self.assertEquals(gateway, simnet.gw_ip6_ll.ip) def test_mtu(self): with self.setup_pasta(configure=True) as simnet: mtu = simnet.guestns.mtu(simnet.ifname) self.assertEquals(mtu, 65520) class PastaOutwardTransferTasst(BasePastaTasst, BaseTransferTasst): """ :avocado: disable """ OUT_CONNECT_PORT = 10000 @contextlib.contextmanager def setup_transfer(self): with self.setup_pasta(configure=True) as simnet: yield TransferTasstInfo(self.DATAFILE, simnet.guestns, simnet.gw, simnet.remote_ip4.ip, simnet.remote_ip6.ip, self.OUT_CONNECT_PORT) class PastaOutwardSmallTcpUploadTasst(PastaOutwardTransferTasst, TcpUploadTasst): DATAFILE = './test/small.bin' class PastaOutwardBigTcpUploadTasst(PastaOutwardSmallTcpUploadTasst): DATAFILE = './test/big.bin' timeout = 30.0 class PastaOutwardUdpTransferTasst(PastaOutwardTransferTasst, UdpTransferTasst): DATAFILE = './test/medium.bin' class PastaInwardTransferTasst(BasePastaTasst, BaseTransferTasst): """ :avocado: disable """ @contextlib.contextmanager def setup_transfer(self): with self.setup_pasta(configure=True) as simnet: yield TransferTasstInfo(self.DATAFILE, simnet.gw, simnet.guestns, simnet.ip4.ip, simnet.ip6.ip, self.IN_FWD_PORT, from_ip4=simnet.remote_ip4.ip, from_ip6=simnet.remote_ip6.ip) class PastaInwardSmallTcpUploadTasst(PastaInwardTransferTasst, TcpUploadTasst): DATAFILE = './test/small.bin' class PastaInwardBigTcpUploadTasst(PastaInwardSmallTcpUploadTasst): DATAFILE = './test/big.bin' timeout = 30.0 class PastaInwardUdpTransferTasst(PastaInwardTransferTasst, UdpTransferTasst): DATAFILE = './test/medium.bin' class PastaSplicedTransferTasst(BasePastaTasst, BaseTransferTasst): """ :avocado: disable """ @contextlib.contextmanager def setup_transfer(self): with self.setup_pasta(configure=True) as simnet: yield TransferTasstInfo(self.DATAFILE, simnet.guestns, simnet.simhost, LOOPBACK4, LOOPBACK6, self.SPLICE_FWD_PORT, listen_ip4=LOOPBACK4, listen_ip6=LOOPBACK6) class PastaSplicedSmallTcpUploadTasst(PastaSplicedTransferTasst, TcpUploadTasst): DATAFILE = './test/small.bin' class PastaSplicedBigTcpUploadTasst(PastaSplicedSmallTcpUploadTasst): DATAFILE = './test/big.bin' timeout = 30.0 class PastaSplicedUdpTransferTasst(PastaSplicedTransferTasst, UdpTransferTasst): DATAFILE = './test/medium.bin'