diff --git a/test/case/interfaces/Readme.adoc b/test/case/interfaces/Readme.adoc index ad2d20f8..4e1c8b37 100644 --- a/test/case/interfaces/Readme.adoc +++ b/test/case/interfaces/Readme.adoc @@ -7,7 +7,7 @@ Tests verifying interface configuration and management: - IPv4 and IPv6 address assignment and management - IPv4 address auto-configuration mechanisms - Interface aliases and physical address configuration - - Basic routing table configuration and operation + - IPv4 and IPv6 forwarding between interfaces - Linux bridge creation, STP, and VLAN handling - Link aggregation (LAG) setup and failover behavior - IGMP multicast group management and forwarding diff --git a/test/case/interfaces/routing_basic/test.adoc b/test/case/interfaces/routing_basic/test.adoc index fb1ce7aa..1f896230 100644 --- a/test/case/interfaces/routing_basic/test.adoc +++ b/test/case/interfaces/routing_basic/test.adoc @@ -4,8 +4,11 @@ ifdef::topdoc[:imagesdir: {topdoc}../../test/case/interfaces/routing_basic] ==== Description -Verify routing between interfaces is possible. That enable/disable routing -in configuration has the expected result. +Verify that the ietf-ip forwarding setting controls whether IPv4 +and IPv6 traffic is routed between interfaces. When forwarding is +enabled, hosts on separate subnets can reach each other through +the device. When forwarding is disabled, that connectivity is +expected to be lost. ==== Topology @@ -14,11 +17,11 @@ image::topology.svg[Routing basic topology, align=center, scaledwidth=75%] ==== Sequence . Set up topology and attach to target DUTs -. Setup host +. Set up host addresses and default routes . Enable forwarding on target:data1 and target:data2 -. Verify ping from host:data1 to 10.0.0.10 -. Verify ping from host:data2 to 192.168.0.10 +. Verify cross-subnet IPv4 connectivity +. Verify cross-subnet IPv6 connectivity . Disable forwarding on target:data1 and target:data2 -. Verify ping does not work host:data1 to 10.0.0.10 and host:data2 to 192.168.0.10 +. Verify cross-subnet connectivity is lost diff --git a/test/case/interfaces/routing_basic/test.py b/test/case/interfaces/routing_basic/test.py index 01e2ae3f..636e3f85 100755 --- a/test/case/interfaces/routing_basic/test.py +++ b/test/case/interfaces/routing_basic/test.py @@ -1,58 +1,53 @@ #!/usr/bin/env python3 -# ,------------------------------------------------, -# | [TARGET] | -# | | -# | | -# | target:mgmt target:data0 targetgt:data1 | -# | [192.168.0.1] [10.0.0.1] | -# '------------------------------------------------' -# | | | -# | | | -# ,----------------------------------------------, -# | host:mgmt host:data0 host:data1 | -# | [192.168.0.10] [10.0.0.10] | -# | (ns0) (ns1) | -# | | -# | [ HOST ] | -# '----------------------------------------------' - """ Routing basic -Verify routing between interfaces is possible. That enable/disable routing -in configuration has the expected result. +Verify that the ietf-ip forwarding setting controls whether IPv4 +and IPv6 traffic is routed between interfaces. When forwarding is +enabled, hosts on separate subnets can reach each other through +the device. When forwarding is disabled, that connectivity is +expected to be lost. """ import infamy +SUBNETS = [ + {"ipv4": {"gw": "192.168.0.1", "host": "192.168.0.10", "prefix": 24}, + "ipv6": {"gw": "2001:db8:0::1", "host": "2001:db8:0::10", "prefix": 64}}, + {"ipv4": {"gw": "10.0.0.1", "host": "10.0.0.10", "prefix": 24}, + "ipv6": {"gw": "2001:db8:1::1", "host": "2001:db8:1::10", "prefix": 64}}, +] + +def iface_cfg(port, subnet, enable_fwd): + """Build interface config with both IPv4 and IPv6.""" + cfg = {"name": port, "enabled": True} + for family in ("ipv4", "ipv6"): + af = subnet[family] + cfg[family] = { + "forwarding": enable_fwd, + "address": [{"ip": af["gw"], "prefix-length": af["prefix"]}], + } + return cfg + def config_target(target, tport0, tport1, enable_fwd): + """Configure forwarding and addresses for both address families.""" target.put_config_dict("ietf-interfaces", { - "interfaces": { - "interface": [ - { - "name": tport0, - "enabled": True, - "ipv4": { - "forwarding": enable_fwd, - "address": [{ - "ip": "192.168.0.1", - "prefix-length": 24 - }] - } - }, - { - "name": tport1, - "enabled": True, - "ipv4": { - "forwarding": enable_fwd, - "address": [{ - "ip": "10.0.0.1", - "prefix-length": 24 - }] - } - } - ] - } - }) + "interfaces": { + "interface": [ + iface_cfg(tport0, SUBNETS[0], enable_fwd), + iface_cfg(tport1, SUBNETS[1], enable_fwd), + ] + } + }) + +def setup_host(ns, subnet): + """Add IPv4 and IPv6 addresses and default routes.""" + v4 = subnet["ipv4"] + ns.addip(v4["host"]) + ns.addroute("default", v4["gw"]) + + v6 = subnet["ipv6"] + ns.addip(v6["host"], prefix_length=v6["prefix"], proto="ipv6") + ns.addroute("default", v6["gw"], proto="ipv6") with infamy.Test() as test: with test.step("Set up topology and attach to target DUTs"): @@ -65,29 +60,31 @@ with infamy.Test() as test: _, hport1 = env.ltop.xlate("host", "data2") with infamy.IsolatedMacVlan(hport0) as ns0, \ - infamy.IsolatedMacVlan(hport1) as ns1 : + infamy.IsolatedMacVlan(hport1) as ns1: - with test.step("Setup host"): - ns0.addip("192.168.0.10") - ns0.addroute("default", "192.168.0.1") - - ns1.addip("10.0.0.10") - ns1.addroute("default", "10.0.0.1") + with test.step("Set up host addresses and default routes"): + setup_host(ns0, SUBNETS[0]) + setup_host(ns1, SUBNETS[1]) with test.step("Enable forwarding on target:data1 and target:data2"): config_target(target, tport0, tport1, True) - with test.step("Verify ping from host:data1 to 10.0.0.10"): - ns0.must_reach("10.0.0.10") + with test.step("Verify cross-subnet IPv4 connectivity"): + ns0.must_reach(SUBNETS[1]["ipv4"]["host"]) + ns1.must_reach(SUBNETS[0]["ipv4"]["host"]) - with test.step("Verify ping from host:data2 to 192.168.0.10"): - ns1.must_reach("192.168.0.10") + with test.step("Verify cross-subnet IPv6 connectivity"): + ns0.must_reach(SUBNETS[1]["ipv6"]["host"]) + ns1.must_reach(SUBNETS[0]["ipv6"]["host"]) with test.step("Disable forwarding on target:data1 and target:data2"): config_target(target, tport0, tport1, False) - with test.step("Verify ping does not work host:data1 to 10.0.0.10 and host:data2 to 192.168.0.10"): - infamy.parallel(lambda: ns0.must_not_reach("10.0.0.10"), - lambda: ns1.must_not_reach("192.168.0.10")) + with test.step("Verify cross-subnet connectivity is lost"): + infamy.parallel( + lambda: ns0.must_not_reach(SUBNETS[1]["ipv4"]["host"]), + lambda: ns1.must_not_reach(SUBNETS[0]["ipv4"]["host"]), + lambda: ns0.must_not_reach(SUBNETS[1]["ipv6"]["host"]), + lambda: ns1.must_not_reach(SUBNETS[0]["ipv6"]["host"])) test.succeed() diff --git a/test/case/interfaces/routing_basic/topology.dot b/test/case/interfaces/routing_basic/topology.dot index d83b3780..25d3b8c7 100644 --- a/test/case/interfaces/routing_basic/topology.dot +++ b/test/case/interfaces/routing_basic/topology.dot @@ -19,6 +19,6 @@ graph "routing_basic" { ]; host:mgmt -- target:mgmt [requires="mgmt", color="lightgray"] - host:data1 -- target:data1 [color=black, fontcolor=black, fontsize=12, taillabel=".10", label="192.168.0.0/24", headlabel=".1"] - host:data2 -- target:data2 [color=black, fontcolor=black, fontsize=12, taillabel=".10", label="10.0.0.0/24", headlabel=".1"] -} \ No newline at end of file + host:data1 -- target:data1 [color=black, fontcolor=black, fontsize=12, taillabel=".10", label="192.168.0.0/24\n2001:db8:0::/64", headlabel=".1"] + host:data2 -- target:data2 [color=black, fontcolor=black, fontsize=12, taillabel=".10", label="10.0.0.0/24\n2001:db8:1::/64", headlabel=".1"] +} diff --git a/test/case/interfaces/routing_basic/topology.svg b/test/case/interfaces/routing_basic/topology.svg index 3c706e87..581d8c76 100644 --- a/test/case/interfaces/routing_basic/topology.svg +++ b/test/case/interfaces/routing_basic/topology.svg @@ -3,55 +3,57 @@ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> - - + + routing_basic - + host - -host - -mgmt - -data1 - -data2 + +host + +mgmt + +data1 + +data2 target - -mgmt - -data1 - -data2 - -target + +mgmt + +data1 + +data2 + +target host:mgmt--target:mgmt - + host:data1--target:data1 - -192.168.0.0/24 -.1 -.10 + +192.168.0.0/24 +2001:db8:0::/64 +.1 +.10 host:data2--target:data2 - -10.0.0.0/24 -.1 -.10 + +10.0.0.0/24 +2001:db8:1::/64 +.1 +.10