Merge pull request #839 from kernelkit/ospf-tests

Add a new test for default-route-advertise
This commit is contained in:
Mattias Walström
2024-11-28 12:20:00 +01:00
committed by GitHub
7 changed files with 524 additions and 5 deletions
+2
View File
@@ -14,6 +14,8 @@ include::ospf_multiarea/Readme.adoc[]
include::ospf_bfd/Readme.adoc[]
include::ospf_default_route_advertise/Readme.adoc[]
include::route_pref_ospf/Readme.adoc[]
include::route_pref_dhcp/Readme.adoc[]
+4 -1
View File
@@ -13,7 +13,7 @@
- name: ospf_bfd
case: ospf_bfd/test.py
- name: route_pref_ospf
case: route_pref_ospf/test.py
@@ -22,3 +22,6 @@
- name: route_pref_255
case: route_pref_255/test.py
- name: ospf_default_route_advertise
case: ospf_default_route_advertise/test.py
+19 -4
View File
@@ -56,7 +56,22 @@ def config_target1(target, data, link):
target.put_config_dict("ietf-routing", {
"routing": {
"control-plane-protocols": {
"control-plane-protocol": [{
"control-plane-protocol": [
{
"type": "infix-routing:static",
"name": "default",
"static-routes": {
"ipv4": {
"route": [{
"destination-prefix": "192.168.33.1/32",
"next-hop": {
"special-next-hop": "blackhole"
}
}]
}
}
},
{
"type": "infix-routing:ospfv2",
"name": "default",
"ospf": {
@@ -74,6 +89,7 @@ def config_target1(target, data, link):
"interfaces":
{
"interface": [{
"enabled": True,
"name": link,
"hello-interval": 1,
"dead-interval": 3
@@ -132,9 +148,6 @@ def config_target2(target, link):
"ospf": {
"redistribute": {
"redistribute": [{
"protocol": "static"
},
{
"protocol": "connected"
}]
},
@@ -143,6 +156,7 @@ def config_target2(target, link):
"area-id": "0.0.0.0",
"interfaces":{
"interface": [{
"enabled": True,
"name": link,
"hello-interval": 1,
"dead-interval": 3
@@ -174,6 +188,7 @@ with infamy.Test() as test:
print("Waiting for OSPF routes..")
until(lambda: route.ipv4_route_exist(R1, "192.168.200.1/32", proto="ietf-ospf:ospfv2"), attempts=200)
until(lambda: route.ipv4_route_exist(R2, "192.168.100.1/32", proto="ietf-ospf:ospfv2"), attempts=200)
until(lambda: route.ipv4_route_exist(R2, "192.168.33.1/32", proto="ietf-ospf:ospfv2"), attempts=200)
with test.step("Test connectivity from PC:data to 192.168.200.1"):
_, hport0 = env.ltop.xlate("PC", "data")
@@ -0,0 +1,57 @@
=== OSPF Default route advertise
==== Description
Verify _default-route-advertising_ in OSPF, sometimes called 'redistribute origin'. Verify both
always (regardless if a local default route exist or not) and only redistribute
when local default route exist.
The test is performed by setting a default route on R1 to 192.168.10.2, and setting
_default-route-advertising_ in OSPF, this will result that R2 will see a default route.
When set interface R1:data down, OSPF will no longer redistribute default route to R2,
unless _always_ is set for _default-route-advertising_.
....
+-------------------+ Area 0 +------------------+
| R1 |.1 192.168.50.0/24 .2| R2 |
| 192.169.100.1/32 +------------------------+ 192.168.200.1/32|
| 10.10.10.10/32 |R1:link R2:link | |
+--------------+----+ +---+--------------+
R1:data |.1 R2:data |.1
| |
| 192.168.10.0/24 | 192.168.20.0/24
| |
host:data1 |.2 host:data2 |.2
+-----+---------------------------------+-------+
| |
| host |
| |
+-----------------------------------------------+
....
==== Topology
ifdef::topdoc[]
image::../../test/case/ietf_routing/ospf_default_route_advertise/topology.svg[OSPF Default route advertise topology]
endif::topdoc[]
ifndef::topdoc[]
ifdef::testgroup[]
image::ospf_default_route_advertise/topology.svg[OSPF Default route advertise topology]
endif::testgroup[]
ifndef::testgroup[]
image::topology.svg[OSPF Default route advertise topology]
endif::testgroup[]
endif::topdoc[]
==== Test sequence
. Set up topology and attach to target DUTs
. Configure targets
. Verify R2 has a default route and 192.168.100.1/32 from OSPF
. Verify connectivity from PC:data2 to 10.10.10.10
. Disable link PC:data1 <--> R1:data (take default gateway down)
. Verify R2 does not have a default route but a 192.168.100.1/32 from OSPF
. Verify no connectivity from PC:data2 to 10.10.10.10
. Enable redistribute default route 'always' on R1
. Wait for all neighbors to peer
. Verify R2 has a default route and 192.168.100.1/32 from OSPF
. Verify connectivity from PC:data2 to 10.10.10.10
<<<
+323
View File
@@ -0,0 +1,323 @@
#!/usr/bin/env python3
"""
OSPF Default route advertise
Verify _default-route-advertising_ in OSPF, sometimes called 'redistribute origin'. Verify both
always (regardless if a local default route exist or not) and only redistribute
when local default route exist.
The test is performed by setting a default route on R1 to 192.168.10.2, and setting
_default-route-advertising_ in OSPF, this will result that R2 will see a default route.
When set interface R1:data down, OSPF will no longer redistribute default route to R2,
unless _always_ is set for _default-route-advertising_.
....
+-------------------+ Area 0 +------------------+
| R1 |.1 192.168.50.0/24 .2| R2 |
| 192.169.100.1/32 +------------------------+ 192.168.200.1/32|
| 10.10.10.10/32 |R1:link R2:link | |
+--------------+----+ +---+--------------+
R1:data |.1 R2:data |.1
| |
| 192.168.10.0/24 | 192.168.20.0/24
| |
host:data1 |.2 host:data2 |.2
+-----+---------------------------------+-------+
| |
| host |
| |
+-----------------------------------------------+
....
"""
import infamy
import infamy.route as route
from infamy.util import until, parallel
def config_target1(target, data, link):
target.put_config_dicts({
"ietf-interfaces": {
"interfaces": {
"interface": [
{
"name": "dummy0",
"enabled": True,
"type": "infix-if-type:dummy",
"ipv4": {
"address": [{
"ip": "10.10.10.10",
"prefix-length": 32
}]
}
},
{
"name": data,
"enabled": True,
"ipv4": {
"forwarding": True,
"address": [{
"ip": "192.168.10.1",
"prefix-length": 24
}]}
},
{
"name": link,
"enabled": True,
"ipv4": {
"forwarding": True,
"address": [{
"ip": "192.168.50.1",
"prefix-length": 24
}]
}
},
{
"name": "lo",
"enabled": True,
"ipv4": {
"address": [{
"ip": "192.168.100.1",
"prefix-length": 32
}]
}
}
]
}
},
"ietf-routing": {
"routing": {
"control-plane-protocols": {
"control-plane-protocol": [
{
"type": "infix-routing:static",
"name": "default",
"static-routes": {
"ipv4": {
"route": [
{
"destination-prefix": "0.0.0.0/0",
"next-hop": {
"next-hop-address": "192.168.10.2"
}
}]
}
}
},
{
"type": "infix-routing:ospfv2",
"name": "default",
"ospf": {
"explicit-router-id": "1.1.1.1",
"default-route-advertise": {
"enabled": True
},
"areas": {
"area": [{
"area-id": "0.0.0.0",
"interfaces":
{
"interface": [{
"name": link,
"enabled": True,
"hello-interval": 1,
"dead-interval": 3
},
{
"name": "lo",
"enabled": True
}]
},
}]
}
}
}
]
}
}
}
})
def config_target2(target, data, link):
target.put_config_dicts({
"ietf-interfaces": {
"interfaces": {
"interface": [
{
"name": link,
"enabled": True,
"ipv4": {
"forwarding": True,
"address": [{
"ip": "192.168.50.2",
"prefix-length": 24
}]
}
},
{
"name": data,
"enabled": True,
"ipv4": {
"forwarding": True,
"address": [{
"ip": "192.168.20.1",
"prefix-length": 24
}]
}
},
{
"name": "lo",
"enabled": True,
"forwarding": True,
"ipv4": {
"address": [{
"ip": "192.168.200.1",
"prefix-length": 32
}]
}
}
]
}
},
"ietf-routing": {
"routing": {
"control-plane-protocols": {
"control-plane-protocol": [
{
"type": "infix-routing:ospfv2",
"name": "default",
"ospf": {
"explicit-router-id": "2.2.2.2",
"areas": {
"area": [{
"area-id": "0.0.0.0",
"interfaces":{
"interface": [{
"enabled": True,
"name": link,
"hello-interval": 1,
"dead-interval": 3
},
{
"name": data,
"passive": True,
"enabled": True
},
{
"enabled": True,
"name": "lo"
}]
}
}]
}
}
}
]
}
}
}
})
def disable_interface(target, iface):
target.put_config_dicts({
"ietf-interfaces": {
"interfaces": {
"interface": [
{
"name": iface,
"enabled": False,
}
]
}
}
})
def set_redistribute_default_always(target):
target.put_config_dicts({
"ietf-routing": {
"routing": {
"control-plane-protocols": {
"control-plane-protocol": [
{
"type": "infix-routing:ospfv2",
"name": "default",
"ospf": {
"default-route-advertise": {
"enabled": True,
"always": True
}
}
}]
}
}
}
})
with infamy.Test() as test:
with test.step("Set up topology and attach to target DUTs"):
env = infamy.Env()
R1 = env.attach("R1", "mgmt")
R2 = env.attach("R2", "mgmt")
with test.step("Configure targets"):
_, R1data = env.ltop.xlate("R1", "data")
_, R2data = env.ltop.xlate("R2", "data")
_, R2link = env.ltop.xlate("R2", "link")
_, R1link= env.ltop.xlate("R1", "link")
parallel(config_target1(R1, R1data, R1link),
config_target2(R2, R2data, R2link))
with test.step("Verify R2 has a default route and 192.168.100.1/32 from OSPF"):
print("Waiting for OSPF routes...")
until(lambda: route.ipv4_route_exist(R2, "0.0.0.0/0", proto="ietf-ospf:ospfv2"), attempts=200)
until(lambda: route.ipv4_route_exist(R2, "192.168.100.1/32", proto="ietf-ospf:ospfv2"), attempts=200)
until(lambda: route.ipv4_route_exist(R1, "192.168.200.1/32", proto="ietf-ospf:ospfv2"), attempts=200)
with test.step("Verify connectivity from PC:data2 to 10.10.10.10"):
_, hport0 = env.ltop.xlate("PC", "data2")
with infamy.IsolatedMacVlan(hport0) as ns0:
ns0.addip("192.168.20.2")
ns0.addroute("0.0.0.0/0", "192.168.20.1")
#breakpoint()
ns0.must_reach("10.10.10.10")
with test.step("Disable link PC:data1 <--> R1:data (take default gateway down)"):
disable_interface(R1, R1data)
with test.step("Verify R2 does not have a default route but a 192.168.100.1/32 from OSPF"):
until(lambda: route.ipv4_route_exist(R2, "192.168.100.1/32", proto="ietf-ospf:ospfv2"), attempts=200)
until(lambda: route.ipv4_route_exist(R1, "192.168.200.1/32", proto="ietf-ospf:ospfv2"), attempts=200)
until(lambda: route.ipv4_route_exist(R2, "0.0.0.0/0", proto="ietf-ospf:ospfv2") == False, attempts=200)
with test.step("Verify no connectivity from PC:data2 to 10.10.10.10"):
_, hport0 = env.ltop.xlate("PC", "data2")
with infamy.IsolatedMacVlan(hport0) as ns0:
ns0.addip("192.168.20.2")
ns0.addroute("0.0.0.0/0", "192.168.20.1")
ns0.must_not_reach("10.10.10.10")
with test.step("Enable redistribute default route 'always' on R1"):
set_redistribute_default_always(R1)
with test.step("Wait for all neighbors to peer"):
until(lambda: route.ospf_get_neighbor(R1, "0.0.0.0", R1link, "2.2.2.2"), attempts=200)
until(lambda: route.ospf_get_neighbor(R2, "0.0.0.0", R2link, "1.1.1.1"), attempts=200)
with test.step("Verify R2 has a default route and 192.168.100.1/32 from OSPF"):
print("Waiting for OSPF routes...")
until(lambda: route.ipv4_route_exist(R2, "192.168.100.1/32", proto="ietf-ospf:ospfv2"), attempts=200)
until(lambda: route.ipv4_route_exist(R1, "192.168.200.1/32", proto="ietf-ospf:ospfv2"), attempts=200)
until(lambda: route.ipv4_route_exist(R2, "0.0.0.0/0", proto="ietf-ospf:ospfv2"), attempts=200)
with test.step("Verify connectivity from PC:data2 to 10.10.10.10"):
_, hport0 = env.ltop.xlate("PC", "data2")
with infamy.IsolatedMacVlan(hport0) as ns0:
ns0.addip("192.168.20.2")
ns0.addroute("0.0.0.0/0", "192.168.20.1")
ns0.must_reach("10.10.10.10")
test.succeed()
@@ -0,0 +1,33 @@
graph "2x2" {
layout="neato";
overlap="false";
esep="+20";
size=10
node [shape=record, fontname="DejaVu Sans Mono, Book"];
edge [color="cornflowerblue", penwidth="2", fontname="DejaVu Serif, Book"];
PC [
label="PC | { <mgmt1> mgmt1 | <data1> data1 | <data2> data2 | <mgmt2> mgmt2 }",
pos="20,80!",
kind="controller",
];
R1 [
label="{ <mgmt> mgmt | <data> data | <link> link } | R1 \n 192.168.100.1/32 \n 10.10.10.10/32\n(lo)",
pos="250,85!",
kind="infix",
];
R2 [
label="{ <link> link | <data> data | <mgmt> mgmt } | R2 \n 192.168.200.1/32 \n(lo)",
pos="250,30!",
kind="infix",
];
PC:mgmt1 -- R1:mgmt [kind=mgmt, color="lightgray"]
PC:mgmt2 -- R2:mgmt [kind=mgmt, color="lightgray"]
PC:data1 -- R1:data [color="black", headlabel="192.168.10.1/24", taillabel="192.168.10.2/24", fontcolor="black"]
PC:data2 -- R2:data [color="black", headlabel="192.168.20.1/24", taillabel="192.168.20.2/24", fontcolor="black"]
R1:link -- R2:link [headlabel="192.168.50.2/24", taillabel="192.168.50.1/24", labeldistance=1, fontcolor="black", color="black"]
}
@@ -0,0 +1,86 @@
<?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: 2x2 Pages: 1 -->
<svg width="663pt" height="199pt"
viewBox="0.00 0.00 662.87 198.60" 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 194.6)">
<title>2x2</title>
<polygon fill="white" stroke="transparent" points="-4,4 -4,-194.6 658.87,-194.6 658.87,4 -4,4"/>
<!-- PC -->
<g id="node1" class="node">
<title>PC</title>
<polygon fill="none" stroke="black" points="0,-98.1 0,-190.1 91,-190.1 91,-98.1 0,-98.1"/>
<text text-anchor="middle" x="16.5" y="-140.4" font-family="DejaVu Sans Mono, Book" font-size="14.00">PC</text>
<polyline fill="none" stroke="black" points="33,-98.1 33,-190.1 "/>
<text text-anchor="middle" x="62" y="-174.9" font-family="DejaVu Sans Mono, Book" font-size="14.00">mgmt1</text>
<polyline fill="none" stroke="black" points="33,-167.1 91,-167.1 "/>
<text text-anchor="middle" x="62" y="-151.9" font-family="DejaVu Sans Mono, Book" font-size="14.00">data1</text>
<polyline fill="none" stroke="black" points="33,-144.1 91,-144.1 "/>
<text text-anchor="middle" x="62" y="-128.9" font-family="DejaVu Sans Mono, Book" font-size="14.00">data2</text>
<polyline fill="none" stroke="black" points="33,-121.1 91,-121.1 "/>
<text text-anchor="middle" x="62" y="-105.9" font-family="DejaVu Sans Mono, Book" font-size="14.00">mgmt2</text>
</g>
<!-- R1 -->
<g id="node2" class="node">
<title>R1</title>
<polygon fill="none" stroke="black" points="439.87,-120.51 439.87,-189.51 654.87,-189.51 654.87,-120.51 439.87,-120.51"/>
<text text-anchor="middle" x="464.87" y="-174.31" font-family="DejaVu Sans Mono, Book" font-size="14.00">mgmt</text>
<polyline fill="none" stroke="black" points="439.87,-166.51 489.87,-166.51 "/>
<text text-anchor="middle" x="464.87" y="-151.31" font-family="DejaVu Sans Mono, Book" font-size="14.00">data</text>
<polyline fill="none" stroke="black" points="439.87,-143.51 489.87,-143.51 "/>
<text text-anchor="middle" x="464.87" y="-128.31" font-family="DejaVu Sans Mono, Book" font-size="14.00">link</text>
<polyline fill="none" stroke="black" points="489.87,-120.51 489.87,-189.51 "/>
<text text-anchor="middle" x="572.37" y="-173.81" font-family="DejaVu Sans Mono, Book" font-size="14.00">R1 </text>
<text text-anchor="middle" x="572.37" y="-158.81" font-family="DejaVu Sans Mono, Book" font-size="14.00"> 192.168.100.1/32 </text>
<text text-anchor="middle" x="572.37" y="-143.81" font-family="DejaVu Sans Mono, Book" font-size="14.00"> 10.10.10.10/32</text>
<text text-anchor="middle" x="572.37" y="-128.81" font-family="DejaVu Sans Mono, Book" font-size="14.00">(lo)</text>
</g>
<!-- PC&#45;&#45;R1 -->
<g id="edge1" class="edge">
<title>PC:mgmt1&#45;&#45;R1:mgmt</title>
<path fill="none" stroke="lightgray" stroke-width="2" d="M91.5,-179.1C91.5,-179.1 439.37,-178.01 439.37,-178.01"/>
</g>
<!-- PC&#45;&#45;R1 -->
<g id="edge3" class="edge">
<title>PC:data1&#45;&#45;R1:data</title>
<path fill="none" stroke="black" stroke-width="2" d="M91.5,-156.1C91.5,-156.1 439.37,-155.01 439.37,-155.01"/>
<text text-anchor="middle" x="380.37" y="-158.81" font-family="DejaVu Serif, Book" font-size="14.00">192.168.10.1/24</text>
<text text-anchor="middle" x="150.5" y="-159.9" font-family="DejaVu Serif, Book" font-size="14.00">192.168.10.2/24</text>
</g>
<!-- R2 -->
<g id="node3" class="node">
<title>R2</title>
<polygon fill="none" stroke="black" points="439.87,-0.5 439.87,-69.5 654.87,-69.5 654.87,-0.5 439.87,-0.5"/>
<text text-anchor="middle" x="464.87" y="-54.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">link</text>
<polyline fill="none" stroke="black" points="439.87,-46.5 489.87,-46.5 "/>
<text text-anchor="middle" x="464.87" y="-31.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">data</text>
<polyline fill="none" stroke="black" points="439.87,-23.5 489.87,-23.5 "/>
<text text-anchor="middle" x="464.87" y="-8.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">mgmt</text>
<polyline fill="none" stroke="black" points="489.87,-0.5 489.87,-69.5 "/>
<text text-anchor="middle" x="572.37" y="-46.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">R2 </text>
<text text-anchor="middle" x="572.37" y="-31.3" font-family="DejaVu Sans Mono, Book" font-size="14.00"> 192.168.200.1/32 </text>
<text text-anchor="middle" x="572.37" y="-16.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">(lo)</text>
</g>
<!-- PC&#45;&#45;R2 -->
<g id="edge2" class="edge">
<title>PC:mgmt2&#45;&#45;R2:mgmt</title>
<path fill="none" stroke="lightgray" stroke-width="2" d="M91.5,-109.1C91.5,-109.1 439.37,-12 439.37,-12"/>
</g>
<!-- PC&#45;&#45;R2 -->
<g id="edge4" class="edge">
<title>PC:data2&#45;&#45;R2:data</title>
<path fill="none" stroke="black" stroke-width="2" d="M91.5,-132.1C91.5,-132.1 439.37,-35 439.37,-35"/>
<text text-anchor="middle" x="380.37" y="-38.8" font-family="DejaVu Serif, Book" font-size="14.00">192.168.20.1/24</text>
<text text-anchor="middle" x="150.5" y="-135.9" font-family="DejaVu Serif, Book" font-size="14.00">192.168.20.2/24</text>
</g>
<!-- R1&#45;&#45;R2 -->
<g id="edge5" class="edge">
<title>R1:link&#45;&#45;R2:link</title>
<path fill="none" stroke="black" stroke-width="2" d="M464.37,-120.01C464.37,-120.01 464.37,-70 464.37,-70"/>
<text text-anchor="middle" x="468.59" y="-75.36" font-family="DejaVu Serif, Book" font-size="14.00">192.168.50.2/24</text>
<text text-anchor="middle" x="460.14" y="-107.25" font-family="DejaVu Serif, Book" font-size="14.00">192.168.50.1/24</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.5 KiB