Merge pull request #912 from kernelkit/various-test-updates

Various test updates
This commit is contained in:
Ahmed Karic
2025-01-28 15:17:15 +01:00
committed by GitHub
22 changed files with 362 additions and 172 deletions
@@ -0,0 +1,30 @@
=== Dual bridges on one device
==== Description
Verify that it is possible to ping through a bridge to another bridge via VETH interfaces.
....
PING --> br0 br1 10.0.0.2
/ \ /
PC - target:data veth0a - veth0b
....
==== Topology
ifdef::topdoc[]
image::{topdoc}../../test/case/ietf_interfaces/dual_bridge/topology.svg[Dual bridges on one device topology]
endif::topdoc[]
ifndef::topdoc[]
ifdef::testgroup[]
image::dual_bridge/topology.svg[Dual bridges on one device topology]
endif::testgroup[]
ifndef::testgroup[]
image::topology.svg[Dual bridges on one device topology]
endif::testgroup[]
endif::topdoc[]
==== Test sequence
. Set up topology and attach to target DUTs
. Configure two bridges linked and a veth pair
. Verify ping from host:data to 10.0.0.2
<<<
@@ -1,6 +1,6 @@
=== GRETAP bridged with physical interface
==== Description
Undefined
Test that gretap works as it should and that it possible to bridge it.
==== Topology
ifdef::topdoc[]
@@ -1,6 +1,6 @@
=== VXLAN bridged with physical interface
==== Description
Undefined
Test that vxlan works as it should and that it possible to bridge it.
==== Topology
ifdef::topdoc[]
@@ -33,11 +33,15 @@ endif::topdoc[]
. Configure VETH pair
. Configure bridge br-D and associated interfaces
. Configure br-Q and associated interfaces
. Configure GRE Tunnels
. Configure VxLAN Tunnels
. Verify interface 'lo' is of type loopback
. Verify interfaces 'ethX' and 'ethQ' are of type 'ethernet' (or etherlike if running Qemu)
. Verify interfaces 'br-0', 'br-X', 'br-D' and 'br-Q' are of type 'bridge'
. Verify interfaces 'veth0a' and 'veth0b' are of type 'veth'
. Verify interfaces 'veth0a.20', 'ethQ.10', 'ethX.30', 'ethQ.10' and 'br-Q.40' are of type 'vlan'
. Verify GRE interfaces 'gre-v4', 'gre-v6', 'gretap-v4' and 'gretap-v6'
. Verify VxLAN interfaces 'vxlan-v4' and 'vxlan-v6'
<<<
+4 -1
View File
@@ -3,9 +3,12 @@
<<<
include::mdns_enable_disable/Readme.adoc[]
include::mdns_allow_deny/Readme.adoc[]
include::services_basic/Readme.adoc[]
include::lldp_enable_disable/Readme.adoc[]
include::ssh_server_config/Readme.adoc[]
+5 -6
View File
@@ -1,11 +1,10 @@
---
- name: lldp_enable_disable
case: lldp_enable_disable/test.py
# Disabled, see #654 for more information. Once that issue is fixed,
# we should split this test into service_mdns and service_lldp, where
# the LLDP test can be skipped if there are no links available that
# are transparent with respect to IEEE link-local multicast.
#- name: services_basic
# case: services_basic/test.py
- name: mdns_enable_disable
case: mdns_enable_disable/test.py
- name: mdns_allow_deny
case: mdns_allow_deny/test.py
@@ -0,0 +1 @@
lldp_enable_disable.adoc
@@ -0,0 +1,28 @@
=== LLDP enable disable
==== Description
Verify that LLDP can be enabled and disabled.
Operation and non-operation are confirmed using tcpdump.
==== Topology
ifdef::topdoc[]
image::{topdoc}../../test/case/infix_services/lldp_enable_disable/topology.svg[LLDP enable disable topology]
endif::topdoc[]
ifndef::topdoc[]
ifdef::testgroup[]
image::lldp_enable_disable/topology.svg[LLDP enable disable topology]
endif::testgroup[]
ifndef::testgroup[]
image::topology.svg[LLDP enable disable topology]
endif::testgroup[]
endif::topdoc[]
==== Test sequence
. Set up topology and attach to target DUT
. Enable target interface and disable LLDP
. Enable LLDP
. Verify LLDP packets arrival on host:data
. Disable LLDP
. Verify no LLDP packets on host:data
<<<
+91
View File
@@ -0,0 +1,91 @@
#!/usr/bin/env python3
"""LLDP enable disable
Verify that LLDP can be enabled and disabled.
Operation and non-operation are confirmed using tcpdump.
"""
import time
import infamy
with infamy.Test() as test:
with test.step("Set up topology and attach to target DUT"):
env = infamy.Env()
target = env.attach("target", "mgmt")
lldp_link = env.ltop.get_link("host", "target", flt=lambda e: "ieee-mc" in e.get("requires", "").split())
if not lldp_link:
print("Skipping test: No link providing ieee-mc found in the topology.")
test.skip()
log_hport, _ = lldp_link
_, phy_hport = env.ltop.xlate("host", log_hport)
with test.step("Enable target interface and disable LLDP"):
target.put_config_dicts({
"ietf-interfaces": {
"interfaces": {
"interface": [
{
"name": target["data"],
"enabled": True
}
]
}
}
})
target.put_config_dicts({
"ieee802-dot1ab-lldp": {
"lldp": {
"enabled": False
}
}
})
sniffing_period = 10
def verify(enabled, sec):
"""Verify lldp traffic, or no traffic if lldp is disabled."""
with infamy.IsolatedMacVlan(phy_hport) as netns:
snif = infamy.Sniffer(netns, "ether proto 0x88cc")
act = "enabling" if enabled else "disabling"
target.put_config_dicts({
"ieee802-dot1ab-lldp": {
"lldp": {
"enabled": enabled
}
}
})
if enabled:
target.put_config_dicts({
"ieee802-dot1ab-lldp": {
"lldp": {
"message-tx-interval": 1
}
}
})
with snif:
print("host: collecting network traffic ...")
print(f"target: {act} LLDP service ...")
time.sleep(sec)
return snif.output()
with test.step("Enable LLDP"):
rc = verify(True, sniffing_period)
with test.step("Verify LLDP packets arrival on host:data"):
if "LLDP" not in rc.stdout:
test.fail()
with test.step("Disable LLDP"):
rc = verify(False, sniffing_period)
with test.step("Verify no LLDP packets on host:data"):
if "LLDP" in rc.stdout:
test.fail()
test.succeed()
@@ -18,6 +18,6 @@ graph "1x2" {
requires="infix",
];
host:data -- target:data [color=black, fontcolor=black, fontsize=12, taillabel="10.0.0.1/24", headlabel="10.0.0.10/24"]
host:mgmt -- target:mgmt [requires="mgmt", color="lightgrey"]
host:data -- target:data [color=black, fontcolor=black, fontsize=12, taillabel="10.0.0.1/24", headlabel="10.0.0.10/24", requires="ieee-mc"]
}

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

@@ -0,0 +1 @@
mdns_enable_disable.adoc
@@ -0,0 +1,28 @@
=== mDNS enable disable
==== Description
Verify that mDNS can be enabled and disabled.
Operation and non-operation are confirmed using tcpdump.
==== Topology
ifdef::topdoc[]
image::{topdoc}../../test/case/infix_services/mdns_enable_disable/topology.svg[mDNS enable disable topology]
endif::topdoc[]
ifndef::topdoc[]
ifdef::testgroup[]
image::mdns_enable_disable/topology.svg[mDNS enable disable topology]
endif::testgroup[]
ifndef::testgroup[]
image::topology.svg[mDNS enable disable topology]
endif::testgroup[]
endif::topdoc[]
==== Test sequence
. Set up topology and attach to target DUT
. Set IPv4 address 10.0.0.10/24 on target:data and disable mDNS
. Enable mDNS
. Verify on host:data there are packets from 10.0.0.10:5354 (mDNS)
. Disable mDNS
. Verify on host:data there are no packets from 10.0.0.10:5354 (mDNS)
<<<
+88
View File
@@ -0,0 +1,88 @@
#!/usr/bin/env python3
"""mDNS enable disable
Verify that mDNS can be enabled and disabled.
Operation and non-operation are confirmed using tcpdump.
"""
import time
import infamy
with infamy.Test() as test:
with test.step("Set up topology and attach to target DUT"):
env = infamy.Env()
target = env.attach("target", "mgmt")
_, hport = env.ltop.xlate("host", "data")
with test.step("Set IPv4 address 10.0.0.10/24 on target:data and disable mDNS"):
target.put_config_dicts({
"ietf-interfaces": {
"interfaces": {
"interface": [
{
"name": target["data"],
"enabled": True,
"ipv4": {
"address": [
{
"ip": "10.0.0.10",
"prefix-length": 24
}
]
}
}
]
}
}
})
target.put_config_dicts({
"infix-services": {
"mdns": {
"enabled": False
}
}
})
sniffing_period = 10
mdns_ip = "10.0.0.10.5353"
def verify(enabled, sec):
"""Verify mDNS traffic, or no traffic if mDNS is disabled."""
with infamy.IsolatedMacVlan(hport) as netns:
snif = infamy.Sniffer(netns, "port 5353")
act = "enabling" if enabled else "disabling"
netns.addip("10.0.0.1")
netns.addroute("0.0.0.0/0", "10.0.0.1")
target.put_config_dicts({
"infix-services": {
"mdns": {
"enabled": enabled
}
}
})
with snif:
print("host: collecting network traffic ...")
print(f"target: {act} mDNS service ...")
time.sleep(sec)
return snif.output()
with test.step("Enable mDNS"):
rc = verify(True, sniffing_period)
with test.step("Verify on host:data there are packets from 10.0.0.10:5354 (mDNS)"):
if mdns_ip not in rc.stdout:
test.fail()
with test.step("Disable mDNS"):
rc = verify(False, sniffing_period)
with test.step("Verify on host:data there are no packets from 10.0.0.10:5354 (mDNS)"):
if mdns_ip in rc.stdout:
test.fail()
test.succeed()
@@ -0,0 +1,23 @@
graph "1x2" {
layout="neato";
overlap="false";
esep="+80";
node [shape=record, fontname="DejaVu Sans Mono, Book"];
edge [color="cornflowerblue", penwidth="2", fontname="DejaVu Serif, Book"];
host [
label="host | { <mgmt> mgmt | <data> data }",
pos="0,12!",
requires="controller",
];
target [
label="{ <mgmt> mgmt | <data> data } | target",
pos="10,12!",
requires="infix",
];
host:mgmt -- target:mgmt [requires="mgmt", color="lightgrey"]
host:data -- target:data [color=black, fontcolor=black, fontsize=12, taillabel="10.0.0.1/24", headlabel="10.0.0.10/24", requires="ieee-mc"]
}
@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Title: 1x2 Pages: 1 -->
<svg width="424pt" height="55pt"
viewBox="0.00 0.00 424.03 55.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 51)">
<title>1x2</title>
<polygon fill="white" stroke="transparent" points="-4,4 -4,-51 420.03,-51 420.03,4 -4,4"/>
<!-- host -->
<g id="node1" class="node">
<title>host</title>
<polygon fill="none" stroke="black" points="0,-0.5 0,-46.5 100,-46.5 100,-0.5 0,-0.5"/>
<text text-anchor="middle" x="25" y="-19.8" font-family="DejaVu Sans Mono, Book" font-size="14.00">host</text>
<polyline fill="none" stroke="black" points="50,-0.5 50,-46.5 "/>
<text text-anchor="middle" x="75" y="-31.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">mgmt</text>
<polyline fill="none" stroke="black" points="50,-23.5 100,-23.5 "/>
<text text-anchor="middle" x="75" y="-8.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">data</text>
</g>
<!-- target -->
<g id="node2" class="node">
<title>target</title>
<polygon fill="none" stroke="black" points="300.03,-0.5 300.03,-46.5 416.03,-46.5 416.03,-0.5 300.03,-0.5"/>
<text text-anchor="middle" x="325.03" y="-31.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">mgmt</text>
<polyline fill="none" stroke="black" points="300.03,-23.5 350.03,-23.5 "/>
<text text-anchor="middle" x="325.03" y="-8.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">data</text>
<polyline fill="none" stroke="black" points="350.03,-0.5 350.03,-46.5 "/>
<text text-anchor="middle" x="383.03" y="-19.8" font-family="DejaVu Sans Mono, Book" font-size="14.00">target</text>
</g>
<!-- host&#45;&#45;target -->
<g id="edge1" class="edge">
<title>host:mgmt&#45;&#45;target:mgmt</title>
<path fill="none" stroke="lightgrey" stroke-width="2" d="M100,-35.5C100,-35.5 300.03,-35.5 300.03,-35.5"/>
</g>
<!-- host&#45;&#45;target -->
<g id="edge2" class="edge">
<title>host:data&#45;&#45;target:data</title>
<path fill="none" stroke="black" stroke-width="2" d="M100,-11.5C100,-11.5 300.03,-11.5 300.03,-11.5"/>
<text text-anchor="middle" x="262.03" y="-14.9" font-family="DejaVu Serif, Book" font-size="12.00">10.0.0.10/24</text>
<text text-anchor="middle" x="134" y="-14.9" font-family="DejaVu Serif, Book" font-size="12.00">10.0.0.1/24</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

@@ -1,30 +0,0 @@
=== Services basic
==== Description
Verify that basic services, such as mDNS and LLDP, can be enabled and
disabled. Operation and non-operation are confirmed using tcpdump.
==== Topology
ifdef::topdoc[]
image::../../test/case/infix_services/services_basic/topology.svg[Services basic topology]
endif::topdoc[]
ifndef::topdoc[]
ifdef::testgroup[]
image::services_basic/topology.svg[Services basic topology]
endif::testgroup[]
ifndef::testgroup[]
image::topology.svg[Services basic topology]
endif::testgroup[]
endif::topdoc[]
==== Test sequence
. Set up topology and attach to target DUT
. Set IPv4 address 10.0.0.10/24 on target:data and disable mDNS and LLDP
. Enable mDNS and LLDP and toggle target:data DOWN and UP to trigger service
. Verify on host:data there are packets from 10.0.0.10:5354 (mDNS)
. Verify on host:data there are LLDP packets sent from 10.0.0.10
. Disable mDNS and LLDP
. Verify on host:data there are no packets from 10.0.0.10:5354 (mDNS)
. Verify on host:data there are no LLDP packets sent from 10.0.0.10
<<<
@@ -1,125 +0,0 @@
#!/usr/bin/env python3
"""Services basic
Verify that basic services, such as mDNS and LLDP, can be enabled and
disabled. Operation and non-operation are confirmed using tcpdump.
"""
import time
import infamy
def toggle(updown):
"""Toggle port down/up to kick services"""
_, port = env.ltop.xlate("target", "data")
act = "UP" if updown else "DOWN"
print(f"target: taking interface {port} {act} ...")
target.put_config_dict("ietf-interfaces", {
"interfaces": {
"interface": [
{
"name": port,
"enabled": updown
}
]
}
})
def verify(enabled, sec):
"""Verify service traffic, or no traffic in case service not enabled"""
_, hport = env.ltop.xlate("host", "data")
with infamy.IsolatedMacVlan(hport) as netns:
snif = infamy.Sniffer(netns, "port 5353 or ether proto 0x88cc")
act = "enabling" if enabled else "disabling"
netns.addip("10.0.0.1")
netns.addroute("0.0.0.0/0", "10.0.0.1")
# Prevent old-state traffic from being captured before reconf
toggle(False)
with snif:
print("host: collecting network traffic ...")
# Put service enable/disable before starting tcpdump,
# because LLDP lingers and will send a final shutdown
# message that otherwise would get in the capture for
# disable.
print(f"target: {act} LLDP and mDNS services ...")
target.put_config_dict("infix-services", {
"mdns": {
"enabled": enabled
}
})
target.put_config_dict("ieee802-dot1ab-lldp", {
"lldp": {
"enabled": enabled
}
})
toggle(True)
time.sleep(sec)
return snif.output()
with infamy.Test() as test:
with test.step("Set up topology and attach to target DUT"):
env = infamy.Env()
target = env.attach("target", "mgmt")
with test.step("Set IPv4 address 10.0.0.10/24 on target:data and disable mDNS and LLDP"):
_, tport = env.ltop.xlate("target", "data")
target.put_config_dict("ietf-interfaces", {
"interfaces": {
"interface": [
{
"name": tport,
"enabled": True,
"ipv4": {
"address": [
{
"ip": "10.0.0.10",
"prefix-length": 24
}
]
}
}
]
}
})
target.put_config_dict("infix-services", {
"mdns": {
"enabled": False
}
})
target.put_config_dict("ieee802-dot1ab-lldp", {
"lldp": {
"enabled": False
}
})
with test.step("Enable mDNS and LLDP and toggle target:data DOWN and UP to trigger service"):
rc = verify(True, 10)
print(rc.stdout)
with test.step("Verify on host:data there are packets from 10.0.0.10:5354 (mDNS)"):
if "10.0.0.10.5353" not in rc.stdout:
test.fail()
with test.step("Verify on host:data there are LLDP packets sent from 10.0.0.10"):
if "LLDP" not in rc.stdout:
test.fail()
with test.step("Disable mDNS and LLDP"):
rc = verify(False, 10)
print(rc.stdout)
with test.step("Verify on host:data there are no packets from 10.0.0.10:5354 (mDNS)"):
if "10.0.0.10.5353" in rc.stdout:
test.fail()
with test.step("Verify on host:data there are no LLDP packets sent from 10.0.0.10"):
if "LLDP" in rc.stdout:
test.fail()
test.succeed()
@@ -17,6 +17,7 @@ endif::topdoc[]
==== Test sequence
. Connect to the target device
. Create a guest user on the target device
. Wait until SSH server is ready to accept connections
. Write private key to a temporary file
. Verify it is possible to fetch syslog data using public key
@@ -20,6 +20,7 @@ endif::topdoc[]
==== Test sequence
. Setup topology and attach to the target
. Configure SSH server
. Wait until SSH server is ready to accept connections
. Verify SSH public keys
. Verify it is not possible to access SSH on other IP address
. Disable SSH server
@@ -10,7 +10,7 @@ PC, which can act as a link breaker.
.Use-case overview.
[#img-overview]
ifdef::topdoc[]
image::{topdoc}../../test/case/use_case/ospf_container/overview.svg[]
image::../../test/case/use_case/ospf_container/overview.svg[]
endif::topdoc[]
ifndef::topdoc[]
ifdef::testgroup[]
@@ -51,7 +51,7 @@ second bridge, `br1`, only use IPv6 link-local addresses.
.Internal network setup, here router R1 on subnet 10.1.1.1/24.
[#img-setup]
ifdef::topdoc[]
image::{topdoc}../../test/case/use_case/ospf_container/internal-network.svg[Internal networks]
image::../../test/case/use_case/ospf_container/internal-network.svg[Internal networks]
endif::topdoc[]
ifndef::topdoc[]
ifdef::testgroup[]
+8 -5
View File
@@ -46,9 +46,9 @@ class IsolatedMacVlans:
for ns in list(IsolatedMacVlans.Instances):
ns.stop()
def __init__(self, ifmap, lo=True):
def __init__(self, ifmap, lo=True, set_up=True):
self.sleeper = None
self.ifmap, self.lo = ifmap, lo
self.ifmap, self.lo, self.set_up = ifmap, lo, set_up
self.ping_timeout = env.ENV.attr("ping_timeout", 5)
def start(self):
@@ -70,6 +70,10 @@ class IsolatedMacVlans:
sleep 0.1
done
""")
if self.set_up:
self.run(["ip", "link", "set", "dev", ifname, "up"])
except Exception as e:
self.__exit__(None, None, None)
raise e
@@ -220,7 +224,6 @@ class IsolatedMacVlans:
self.runsh(f"""
set -ex
ip link set dev {ifname} up
ip -{p} addr add {addr}/{prefix_length} dev {ifname}
""", check=True)
@@ -296,9 +299,9 @@ class IsolatedMacVlan(IsolatedMacVlans):
eth0 eth1 eth2 eth3
"""
def __init__(self, parent, ifname="iface", lo=True):
def __init__(self, parent, ifname="iface", lo=True, set_up=True):
self._ifname = ifname
return super().__init__(ifmap={ parent: ifname }, lo=lo)
return super().__init__(ifmap={ parent: ifname }, lo=lo, set_up=set_up)
def addip(self, addr, prefix_length=24, proto="ipv4"):
return super().addip(ifname=self._ifname, addr=addr, prefix_length=prefix_length, proto=proto)