diff --git a/test/case/ietf_interfaces/dual_bridge/dual_bridge.adoc b/test/case/ietf_interfaces/dual_bridge/dual_bridge.adoc new file mode 100644 index 00000000..00d08f40 --- /dev/null +++ b/test/case/ietf_interfaces/dual_bridge/dual_bridge.adoc @@ -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 + + +<<< + diff --git a/test/case/ietf_interfaces/tunnel_bridged/gretap_bridged.adoc b/test/case/ietf_interfaces/tunnel_bridged/gretap_bridged.adoc index 1d3b1594..8b24dc12 100644 --- a/test/case/ietf_interfaces/tunnel_bridged/gretap_bridged.adoc +++ b/test/case/ietf_interfaces/tunnel_bridged/gretap_bridged.adoc @@ -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[] diff --git a/test/case/ietf_interfaces/tunnel_bridged/vxlan_bridged.adoc b/test/case/ietf_interfaces/tunnel_bridged/vxlan_bridged.adoc index 7d20a7dd..92647592 100644 --- a/test/case/ietf_interfaces/tunnel_bridged/vxlan_bridged.adoc +++ b/test/case/ietf_interfaces/tunnel_bridged/vxlan_bridged.adoc @@ -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[] diff --git a/test/case/ietf_interfaces/verify_all_interface_types/verify_all_interface_types.adoc b/test/case/ietf_interfaces/verify_all_interface_types/verify_all_interface_types.adoc index 5563a925..298a3bec 100644 --- a/test/case/ietf_interfaces/verify_all_interface_types/verify_all_interface_types.adoc +++ b/test/case/ietf_interfaces/verify_all_interface_types/verify_all_interface_types.adoc @@ -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' <<< diff --git a/test/case/infix_services/Readme.adoc b/test/case/infix_services/Readme.adoc index 3458ae61..b8f933eb 100644 --- a/test/case/infix_services/Readme.adoc +++ b/test/case/infix_services/Readme.adoc @@ -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[] diff --git a/test/case/infix_services/infix_services.yaml b/test/case/infix_services/infix_services.yaml index 29840c55..c5488a40 100644 --- a/test/case/infix_services/infix_services.yaml +++ b/test/case/infix_services/infix_services.yaml @@ -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 diff --git a/test/case/infix_services/lldp_enable_disable/Readme.adoc b/test/case/infix_services/lldp_enable_disable/Readme.adoc new file mode 120000 index 00000000..218d38b9 --- /dev/null +++ b/test/case/infix_services/lldp_enable_disable/Readme.adoc @@ -0,0 +1 @@ +lldp_enable_disable.adoc \ No newline at end of file diff --git a/test/case/infix_services/lldp_enable_disable/lldp_enable_disable.adoc b/test/case/infix_services/lldp_enable_disable/lldp_enable_disable.adoc new file mode 100644 index 00000000..7d333f04 --- /dev/null +++ b/test/case/infix_services/lldp_enable_disable/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 + + +<<< + diff --git a/test/case/infix_services/lldp_enable_disable/test.py b/test/case/infix_services/lldp_enable_disable/test.py new file mode 100755 index 00000000..6b9f5ac5 --- /dev/null +++ b/test/case/infix_services/lldp_enable_disable/test.py @@ -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() diff --git a/test/case/infix_services/services_basic/topology.dot b/test/case/infix_services/lldp_enable_disable/topology.dot similarity index 87% rename from test/case/infix_services/services_basic/topology.dot rename to test/case/infix_services/lldp_enable_disable/topology.dot index 2e4c6fe7..1cbd7bca 100644 --- a/test/case/infix_services/services_basic/topology.dot +++ b/test/case/infix_services/lldp_enable_disable/topology.dot @@ -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"] } diff --git a/test/case/infix_services/services_basic/topology.svg b/test/case/infix_services/lldp_enable_disable/topology.svg similarity index 100% rename from test/case/infix_services/services_basic/topology.svg rename to test/case/infix_services/lldp_enable_disable/topology.svg diff --git a/test/case/infix_services/mdns_enable_disable/Readme.adoc b/test/case/infix_services/mdns_enable_disable/Readme.adoc new file mode 120000 index 00000000..ca4d53b2 --- /dev/null +++ b/test/case/infix_services/mdns_enable_disable/Readme.adoc @@ -0,0 +1 @@ +mdns_enable_disable.adoc \ No newline at end of file diff --git a/test/case/infix_services/mdns_enable_disable/mdns_enable_disable.adoc b/test/case/infix_services/mdns_enable_disable/mdns_enable_disable.adoc new file mode 100644 index 00000000..5816200f --- /dev/null +++ b/test/case/infix_services/mdns_enable_disable/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) + + +<<< + diff --git a/test/case/infix_services/mdns_enable_disable/test.py b/test/case/infix_services/mdns_enable_disable/test.py new file mode 100755 index 00000000..a3756537 --- /dev/null +++ b/test/case/infix_services/mdns_enable_disable/test.py @@ -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() diff --git a/test/case/infix_services/mdns_enable_disable/topology.dot b/test/case/infix_services/mdns_enable_disable/topology.dot new file mode 100644 index 00000000..1cbd7bca --- /dev/null +++ b/test/case/infix_services/mdns_enable_disable/topology.dot @@ -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 | data }", + pos="0,12!", + requires="controller", + ]; + + target [ + label="{ mgmt | 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"] +} diff --git a/test/case/infix_services/mdns_enable_disable/topology.svg b/test/case/infix_services/mdns_enable_disable/topology.svg new file mode 100644 index 00000000..5b805b37 --- /dev/null +++ b/test/case/infix_services/mdns_enable_disable/topology.svg @@ -0,0 +1,44 @@ + + + + + + +1x2 + + + +host + +host + +mgmt + +data + + + +target + +mgmt + +data + +target + + + +host:mgmt--target:mgmt + + + + +host:data--target:data + +10.0.0.10/24 +10.0.0.1/24 + + + diff --git a/test/case/infix_services/services_basic/Readme.adoc b/test/case/infix_services/services_basic/Readme.adoc deleted file mode 100644 index 84139779..00000000 --- a/test/case/infix_services/services_basic/Readme.adoc +++ /dev/null @@ -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 - - -<<< - diff --git a/test/case/infix_services/services_basic/test.py b/test/case/infix_services/services_basic/test.py deleted file mode 100755 index 50808323..00000000 --- a/test/case/infix_services/services_basic/test.py +++ /dev/null @@ -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() diff --git a/test/case/infix_services/ssh_key_authentication/ssh_key_authentication.adoc b/test/case/infix_services/ssh_key_authentication/ssh_key_authentication.adoc index 04ffc9b0..b5c664b1 100644 --- a/test/case/infix_services/ssh_key_authentication/ssh_key_authentication.adoc +++ b/test/case/infix_services/ssh_key_authentication/ssh_key_authentication.adoc @@ -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 diff --git a/test/case/infix_services/ssh_server_config/ssh_server_config.adoc b/test/case/infix_services/ssh_server_config/ssh_server_config.adoc index 782d8137..ed0f3b7f 100644 --- a/test/case/infix_services/ssh_server_config/ssh_server_config.adoc +++ b/test/case/infix_services/ssh_server_config/ssh_server_config.adoc @@ -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 diff --git a/test/case/use_case/ospf_container/ospf_container.adoc b/test/case/use_case/ospf_container/ospf_container.adoc index 09c9a60b..c6661941 100644 --- a/test/case/use_case/ospf_container/ospf_container.adoc +++ b/test/case/use_case/ospf_container/ospf_container.adoc @@ -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[] diff --git a/test/infamy/netns.py b/test/infamy/netns.py index daa970b7..317e006d 100644 --- a/test/infamy/netns.py +++ b/test/infamy/netns.py @@ -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)