diff options
Diffstat (limited to 'tests/topotests/ospf_netns_vrf')
22 files changed, 606 insertions, 0 deletions
diff --git a/tests/topotests/ospf_netns_vrf/__init__.py b/tests/topotests/ospf_netns_vrf/__init__.py new file mode 100755 index 0000000..e69de29 --- /dev/null +++ b/tests/topotests/ospf_netns_vrf/__init__.py diff --git a/tests/topotests/ospf_netns_vrf/r1/ospfd.conf b/tests/topotests/ospf_netns_vrf/r1/ospfd.conf new file mode 100644 index 0000000..e1e2bfb --- /dev/null +++ b/tests/topotests/ospf_netns_vrf/r1/ospfd.conf @@ -0,0 +1,13 @@ +! +hostname r1 +password zebra +log file /tmp/r1-ospfd.log +! +router ospf vrf r1-ospf-cust1 + ospf router-id 10.0.255.1 + redistribute kernel + redistribute connected + redistribute static + network 10.0.1.0/24 area 0 + network 10.0.3.0/24 area 0 +! diff --git a/tests/topotests/ospf_netns_vrf/r1/ospfroute.txt b/tests/topotests/ospf_netns_vrf/r1/ospfroute.txt new file mode 100644 index 0000000..d617ab3 --- /dev/null +++ b/tests/topotests/ospf_netns_vrf/r1/ospfroute.txt @@ -0,0 +1,18 @@ +VRF Name: r1-ospf-cust1 +============ OSPF network routing table ============ +N 10.0.1.0/24 [10] area: 0.0.0.0 + directly attached to r1-eth0 +N 10.0.2.0/24 [20] area: 0.0.0.0 + via 10.0.3.3, r1-eth1 +N 10.0.3.0/24 [10] area: 0.0.0.0 + directly attached to r1-eth1 +N 10.0.10.0/24 [20] area: 0.0.0.0 + via 10.0.3.1, r1-eth1 + +============ OSPF router routing table ============= +R 10.0.255.2 [10] area: 0.0.0.0, ASBR + via 10.0.3.3, r1-eth1 +R 10.0.255.3 [10] area: 0.0.0.0, ASBR + via 10.0.3.1, r1-eth1 + +============ OSPF external routing table =========== diff --git a/tests/topotests/ospf_netns_vrf/r1/ospfroute_down.txt b/tests/topotests/ospf_netns_vrf/r1/ospfroute_down.txt new file mode 100644 index 0000000..4f7fd69 --- /dev/null +++ b/tests/topotests/ospf_netns_vrf/r1/ospfroute_down.txt @@ -0,0 +1,14 @@ +VRF Name: r1-ospf-cust1 +============ OSPF network routing table ============ +N 10.0.1.0/24 [10] area: 0.0.0.0 + directly attached to r1-eth0 +N 10.0.2.0/24 [20] area: 0.0.0.0 + via 10.0.3.3, r1-eth1 +N 10.0.3.0/24 [10] area: 0.0.0.0 + directly attached to r1-eth1 + +============ OSPF router routing table ============= +R 10.0.255.2 [10] area: 0.0.0.0, ASBR + via 10.0.3.3, r1-eth1 + +============ OSPF external routing table =========== diff --git a/tests/topotests/ospf_netns_vrf/r1/zebra.conf b/tests/topotests/ospf_netns_vrf/r1/zebra.conf new file mode 100644 index 0000000..56d7a97 --- /dev/null +++ b/tests/topotests/ospf_netns_vrf/r1/zebra.conf @@ -0,0 +1,17 @@ +! debug zebra kernel +! debug zebra dplane detail +! debug zebra rib +! debug zebra event +! +hostname r1 +password zebra +log file /tmp/r1-zebra.log +! +interface r1-eth0 vrf r1-ospf-cust1 + ip address 10.0.1.1/24 +! +interface r1-eth1 vrf r1-ospf-cust1 + ip address 10.0.3.2/24 +! +ip forwarding +! diff --git a/tests/topotests/ospf_netns_vrf/r1/zebraroute.txt b/tests/topotests/ospf_netns_vrf/r1/zebraroute.txt new file mode 100644 index 0000000..979af20 --- /dev/null +++ b/tests/topotests/ospf_netns_vrf/r1/zebraroute.txt @@ -0,0 +1,8 @@ +VRF r1-ospf-cust1: +O 10.0.1.0/24 [110/10] is directly connected, r1-eth0, weight 1, XX:XX:XX +C>* 10.0.1.0/24 is directly connected, r1-eth0, XX:XX:XX +O>* 10.0.2.0/24 [110/20] via 10.0.3.3, r1-eth1, weight 1, XX:XX:XX +O 10.0.3.0/24 [110/10] is directly connected, r1-eth1, weight 1, XX:XX:XX +C>* 10.0.3.0/24 is directly connected, r1-eth1, XX:XX:XX +O>* 10.0.10.0/24 [110/20] via 10.0.3.1, r1-eth1, weight 1, XX:XX:XX + diff --git a/tests/topotests/ospf_netns_vrf/r1/zebraroutedown.txt b/tests/topotests/ospf_netns_vrf/r1/zebraroutedown.txt new file mode 100644 index 0000000..ec99fad --- /dev/null +++ b/tests/topotests/ospf_netns_vrf/r1/zebraroutedown.txt @@ -0,0 +1,7 @@ +VRF r1-ospf-cust1: +O 10.0.1.0/24 [110/10] is directly connected, r1-eth0, weight 1, XX:XX:XX +C>* 10.0.1.0/24 is directly connected, r1-eth0, XX:XX:XX +O>* 10.0.2.0/24 [110/20] via 10.0.3.3, r1-eth1, weight 1, XX:XX:XX +O 10.0.3.0/24 [110/10] is directly connected, r1-eth1, weight 1, XX:XX:XX +C>* 10.0.3.0/24 is directly connected, r1-eth1, XX:XX:XX + diff --git a/tests/topotests/ospf_netns_vrf/r2/ospfd.conf b/tests/topotests/ospf_netns_vrf/r2/ospfd.conf new file mode 100644 index 0000000..c198427 --- /dev/null +++ b/tests/topotests/ospf_netns_vrf/r2/ospfd.conf @@ -0,0 +1,14 @@ +! +hostname r2 +password zebra +log file /tmp/r2-ospfd.log +! +! +router ospf vrf r2-ospf-cust1 + ospf router-id 10.0.255.2 + redistribute kernel + redistribute connected + redistribute static + network 10.0.2.0/24 area 0 + network 10.0.3.0/24 area 0 +! diff --git a/tests/topotests/ospf_netns_vrf/r2/ospfroute.txt b/tests/topotests/ospf_netns_vrf/r2/ospfroute.txt new file mode 100644 index 0000000..89763ff --- /dev/null +++ b/tests/topotests/ospf_netns_vrf/r2/ospfroute.txt @@ -0,0 +1,18 @@ +VRF Name: r2-ospf-cust1 +============ OSPF network routing table ============ +N 10.0.1.0/24 [20] area: 0.0.0.0 + via 10.0.3.2, r2-eth1 +N 10.0.2.0/24 [10] area: 0.0.0.0 + directly attached to r2-eth0 +N 10.0.3.0/24 [10] area: 0.0.0.0 + directly attached to r2-eth1 +N 10.0.10.0/24 [20] area: 0.0.0.0 + via 10.0.3.1, r2-eth1 + +============ OSPF router routing table ============= +R 10.0.255.1 [10] area: 0.0.0.0, ASBR + via 10.0.3.2, r2-eth1 +R 10.0.255.3 [10] area: 0.0.0.0, ASBR + via 10.0.3.1, r2-eth1 + +============ OSPF external routing table =========== diff --git a/tests/topotests/ospf_netns_vrf/r2/ospfroute_down.txt b/tests/topotests/ospf_netns_vrf/r2/ospfroute_down.txt new file mode 100644 index 0000000..d946f02 --- /dev/null +++ b/tests/topotests/ospf_netns_vrf/r2/ospfroute_down.txt @@ -0,0 +1,14 @@ +VRF Name: r2-ospf-cust1 +============ OSPF network routing table ============ +N 10.0.1.0/24 [20] area: 0.0.0.0 + via 10.0.3.2, r2-eth1 +N 10.0.2.0/24 [10] area: 0.0.0.0 + directly attached to r2-eth0 +N 10.0.3.0/24 [10] area: 0.0.0.0 + directly attached to r2-eth1 + +============ OSPF router routing table ============= +R 10.0.255.1 [10] area: 0.0.0.0, ASBR + via 10.0.3.2, r2-eth1 + +============ OSPF external routing table =========== diff --git a/tests/topotests/ospf_netns_vrf/r2/zebra.conf b/tests/topotests/ospf_netns_vrf/r2/zebra.conf new file mode 100644 index 0000000..6ff72d1 --- /dev/null +++ b/tests/topotests/ospf_netns_vrf/r2/zebra.conf @@ -0,0 +1,13 @@ +! +hostname r2 +password zebra +log file /tmp/r2-zebra.log +! +interface r2-eth0 vrf r2-ospf-cust1 + ip address 10.0.2.1/24 +! +interface r2-eth1 vrf r2-ospf-cust1 + ip address 10.0.3.3/24 +! +ip forwarding +! diff --git a/tests/topotests/ospf_netns_vrf/r2/zebraroute.txt b/tests/topotests/ospf_netns_vrf/r2/zebraroute.txt new file mode 100644 index 0000000..df66e92 --- /dev/null +++ b/tests/topotests/ospf_netns_vrf/r2/zebraroute.txt @@ -0,0 +1,8 @@ +VRF r2-ospf-cust1: +O>* 10.0.1.0/24 [110/20] via 10.0.3.2, r2-eth1, weight 1, XX:XX:XX +O 10.0.2.0/24 [110/10] is directly connected, r2-eth0, weight 1, XX:XX:XX +C>* 10.0.2.0/24 is directly connected, r2-eth0, XX:XX:XX +O 10.0.3.0/24 [110/10] is directly connected, r2-eth1, weight 1, XX:XX:XX +C>* 10.0.3.0/24 is directly connected, r2-eth1, XX:XX:XX +O>* 10.0.10.0/24 [110/20] via 10.0.3.1, r2-eth1, weight 1, XX:XX:XX + diff --git a/tests/topotests/ospf_netns_vrf/r2/zebraroutedown.txt b/tests/topotests/ospf_netns_vrf/r2/zebraroutedown.txt new file mode 100644 index 0000000..4afc354 --- /dev/null +++ b/tests/topotests/ospf_netns_vrf/r2/zebraroutedown.txt @@ -0,0 +1,7 @@ +VRF r2-ospf-cust1: +O>* 10.0.1.0/24 [110/20] via 10.0.3.2, r2-eth1, weight 1, XX:XX:XX +O 10.0.2.0/24 [110/10] is directly connected, r2-eth0, weight 1, XX:XX:XX +C>* 10.0.2.0/24 is directly connected, r2-eth0, XX:XX:XX +O 10.0.3.0/24 [110/10] is directly connected, r2-eth1, weight 1, XX:XX:XX +C>* 10.0.3.0/24 is directly connected, r2-eth1, XX:XX:XX + diff --git a/tests/topotests/ospf_netns_vrf/r3/ospfd.conf b/tests/topotests/ospf_netns_vrf/r3/ospfd.conf new file mode 100644 index 0000000..b73d547 --- /dev/null +++ b/tests/topotests/ospf_netns_vrf/r3/ospfd.conf @@ -0,0 +1,15 @@ +! +hostname r3 +password zebra +log file /tmp/r3-ospfd.log +! +! +router ospf vrf r3-ospf-cust1 + ospf router-id 10.0.255.3 + redistribute kernel + redistribute connected + redistribute static + network 10.0.3.0/24 area 0 + network 10.0.10.0/24 area 0 + network 172.16.0.0/24 area 1 +! diff --git a/tests/topotests/ospf_netns_vrf/r3/ospfroute.txt b/tests/topotests/ospf_netns_vrf/r3/ospfroute.txt new file mode 100644 index 0000000..917702b --- /dev/null +++ b/tests/topotests/ospf_netns_vrf/r3/ospfroute.txt @@ -0,0 +1,18 @@ +VRF Name: r3-ospf-cust1 +============ OSPF network routing table ============ +N 10.0.1.0/24 [20] area: 0.0.0.0 + via 10.0.3.2, r3-eth0 +N 10.0.2.0/24 [20] area: 0.0.0.0 + via 10.0.3.3, r3-eth0 +N 10.0.3.0/24 [10] area: 0.0.0.0 + directly attached to r3-eth0 +N 10.0.10.0/24 [10] area: 0.0.0.0 + directly attached to r3-eth1 + +============ OSPF router routing table ============= +R 10.0.255.1 [10] area: 0.0.0.0, ASBR + via 10.0.3.2, r3-eth0 +R 10.0.255.2 [10] area: 0.0.0.0, ASBR + via 10.0.3.3, r3-eth0 + +============ OSPF external routing table =========== diff --git a/tests/topotests/ospf_netns_vrf/r3/ospfroute_down.txt b/tests/topotests/ospf_netns_vrf/r3/ospfroute_down.txt new file mode 100644 index 0000000..966185e --- /dev/null +++ b/tests/topotests/ospf_netns_vrf/r3/ospfroute_down.txt @@ -0,0 +1,8 @@ +VRF Name: r3-ospf-cust1 +============ OSPF network routing table ============ +N 10.0.10.0/24 [10] area: 0.0.0.0 + directly attached to r3-eth1 + +============ OSPF router routing table ============= + +============ OSPF external routing table =========== diff --git a/tests/topotests/ospf_netns_vrf/r3/zebra.conf b/tests/topotests/ospf_netns_vrf/r3/zebra.conf new file mode 100644 index 0000000..1534150 --- /dev/null +++ b/tests/topotests/ospf_netns_vrf/r3/zebra.conf @@ -0,0 +1,13 @@ +! +hostname r3 +password zebra +log file /tmp/r3-zebra.log +! +interface r3-eth0 vrf r3-ospf-cust1 + ip address 10.0.3.1/24 +! +interface r3-eth1 vrf r3-ospf-cust1 + ip address 10.0.10.1/24 +! +ip forwarding +! diff --git a/tests/topotests/ospf_netns_vrf/r3/zebraroute.txt b/tests/topotests/ospf_netns_vrf/r3/zebraroute.txt new file mode 100644 index 0000000..b435c2e --- /dev/null +++ b/tests/topotests/ospf_netns_vrf/r3/zebraroute.txt @@ -0,0 +1,8 @@ +VRF r3-ospf-cust1: +O>* 10.0.1.0/24 [110/20] via 10.0.3.2, r3-eth0, weight 1, XX:XX:XX +O>* 10.0.2.0/24 [110/20] via 10.0.3.3, r3-eth0, weight 1, XX:XX:XX +O 10.0.3.0/24 [110/10] is directly connected, r3-eth0, weight 1, XX:XX:XX +C>* 10.0.3.0/24 is directly connected, r3-eth0, XX:XX:XX +O 10.0.10.0/24 [110/10] is directly connected, r3-eth1, weight 1, XX:XX:XX +C>* 10.0.10.0/24 is directly connected, r3-eth1, XX:XX:XX + diff --git a/tests/topotests/ospf_netns_vrf/r3/zebraroutedown.txt b/tests/topotests/ospf_netns_vrf/r3/zebraroutedown.txt new file mode 100644 index 0000000..f30a4be --- /dev/null +++ b/tests/topotests/ospf_netns_vrf/r3/zebraroutedown.txt @@ -0,0 +1,4 @@ +VRF r3-ospf-cust1: +O 10.0.10.0/24 [110/10] is directly connected, r3-eth1, weight 1, XX:XX:XX +C>* 10.0.10.0/24 is directly connected, r3-eth1, XX:XX:XX + diff --git a/tests/topotests/ospf_netns_vrf/test_ospf_netns_vrf.dot b/tests/topotests/ospf_netns_vrf/test_ospf_netns_vrf.dot new file mode 100644 index 0000000..789fdd7 --- /dev/null +++ b/tests/topotests/ospf_netns_vrf/test_ospf_netns_vrf.dot @@ -0,0 +1,78 @@ +## Color coding: +######################### +## Main FRR: #f08080 red +## Switches: #d0e0d0 gray +## RIP: #19e3d9 Cyan +## RIPng: #fcb314 dark yellow +## OSPFv2: #32b835 Green +## OSPFv3: #19e3d9 Cyan +## ISIS IPv4 #fcb314 dark yellow +## ISIS IPv6 #9a81ec purple +## BGP IPv4 #eee3d3 beige +## BGP IPv6 #fdff00 yellow +##### Colors (see http://www.color-hex.com/) + +graph ospf_topo1 { + label="ospf topo1"; + + # Routers + r1 [ + label="r1\nrtr-id 10.0.255.1/32", + shape=doubleoctagon, + fillcolor="#f08080", + style=filled, + ]; + r2 [ + label="r2\nrtr-id 10.0.255.2/32", + shape=doubleoctagon, + fillcolor="#f08080", + style=filled, + ]; + r3 [ + label="r3\nrtr-id 10.0.255.3/32", + shape=doubleoctagon, + fillcolor="#f08080", + style=filled, + ]; + + # Switches + s1 [ + label="s1\n10.0.1.0/24\n2001:db8:1::/64", + shape=oval, + fillcolor="#d0e0d0", + style=filled, + ]; + s2 [ + label="s2\n10.0.2.0/24\n2001:db8:2::/64", + shape=oval, + fillcolor="#d0e0d0", + style=filled, + ]; + s3 [ + label="s3\n10.0.3.0/24\n2001:db8:3::/64", + shape=oval, + fillcolor="#d0e0d0", + style=filled, + ]; + s4 [ + label="s4\n10.0.10.0/24\n2001:db8:100::/64", + shape=oval, + fillcolor="#d0e0d0", + style=filled, + ]; + + # Connections + subgraph cluster0 { + label="area 0" + + r1 -- s1 [label="eth0\n.1\n::1"]; + r1 -- s3 [label="eth1\n.2\n::2"]; + + r2 -- s2 [label="eth0\n.1\n::1"]; + r2 -- s3 [label="eth1\n.3\n::3"]; + + r3 -- s3 [label="eth0\n.1\n::1"]; + r3 -- s4 [label="eth1\n.1\n::1"]; + } + +} diff --git a/tests/topotests/ospf_netns_vrf/test_ospf_netns_vrf.jpg b/tests/topotests/ospf_netns_vrf/test_ospf_netns_vrf.jpg Binary files differnew file mode 100644 index 0000000..85f2e52 --- /dev/null +++ b/tests/topotests/ospf_netns_vrf/test_ospf_netns_vrf.jpg diff --git a/tests/topotests/ospf_netns_vrf/test_ospf_netns_vrf.py b/tests/topotests/ospf_netns_vrf/test_ospf_netns_vrf.py new file mode 100644 index 0000000..2716f63 --- /dev/null +++ b/tests/topotests/ospf_netns_vrf/test_ospf_netns_vrf.py @@ -0,0 +1,311 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: ISC + +# +# test_ospf_netns_vrf.py +# Part of NetDEF Topology Tests +# +# Copyright (c) 2017 by +# Network Device Education Foundation, Inc. ("NetDEF") +# + +""" +test_ospf_netns_vrf.py: Test OSPF with Network Namespace VRFs. +""" + +import os +import sys +from functools import partial +import pytest + +# Save the Current Working Directory to find configuration files. +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) + +# pylint: disable=C0413 +# Import topogen and topotest helpers +from lib import topotest +from lib.topogen import Topogen, TopoRouter, get_topogen +from lib.topolog import logger + +# Required to instantiate the topology builder class. + +pytestmark = [pytest.mark.ospfd] + + +def build_topo(tgen): + "Build function" + + # Create 3 routers + for routern in range(1, 4): + tgen.add_router("r{}".format(routern)) + + # Create a empty network for router 1 + switch = tgen.add_switch("s1") + switch.add_link(tgen.gears["r1"]) + + # Create a empty network for router 2 + switch = tgen.add_switch("s2") + switch.add_link(tgen.gears["r2"]) + + # Interconect router 1, 2 and 3 + switch = tgen.add_switch("s3") + switch.add_link(tgen.gears["r1"]) + switch.add_link(tgen.gears["r2"]) + switch.add_link(tgen.gears["r3"]) + + # Create empty netowrk for router3 + switch = tgen.add_switch("s4") + switch.add_link(tgen.gears["r3"]) + + +def setup_module(mod): + "Sets up the pytest environment" + tgen = Topogen(build_topo, mod.__name__) + tgen.start_topology() + + router_list = tgen.routers() + + # check for zebra capability + for rname, router in router_list.items(): + if router.check_capability(TopoRouter.RD_ZEBRA, "--vrfwnetns") == False: + return pytest.skip( + "Skipping OSPF VRF NETNS feature. VRF NETNS backend not available on FRR" + ) + + if os.system("ip netns list") != 0: + return pytest.skip( + "Skipping OSPF VRF NETNS Test. NETNS not available on System" + ) + + logger.info("Testing with VRF Namespace support") + + for rname, router in router_list.items(): + # create VRF rx-ospf-cust1 and link rx-eth{0,1} to rx-ospf-cust1 + ns = "{}-ospf-cust1".format(rname) + router.net.add_netns(ns) + router.net.set_intf_netns(rname + "-eth0", ns, up=True) + router.net.set_intf_netns(rname + "-eth1", ns, up=True) + + router.load_config( + TopoRouter.RD_ZEBRA, + os.path.join(CWD, "{}/zebra.conf".format(rname)), + "--vrfwnetns", + ) + router.load_config( + TopoRouter.RD_OSPF, os.path.join(CWD, "{}/ospfd.conf".format(rname)) + ) + + # Initialize all routers. + tgen.start_router() + for router in router_list.values(): + if router.has_version("<", "4.0"): + tgen.set_error("unsupported version") + + +def teardown_module(mod): + "Teardown the pytest environment" + tgen = get_topogen() + + # Move interfaces out of vrf namespace and delete the namespace + router_list = tgen.routers() + for rname, router in router_list.items(): + tgen.net[rname].reset_intf_netns(rname + "-eth0") + tgen.net[rname].reset_intf_netns(rname + "-eth1") + tgen.net[rname].delete_netns(rname + "-ospf-cust1") + tgen.stop_topology() + + +# Shared test function to validate expected output. +def compare_show_ip_route_vrf(rname, expected): + """ + Calls 'show ip ospf vrf [rname]-ospf-cust1 route' for router `rname` and compare the obtained + result with the expected output. + """ + tgen = get_topogen() + vrf_name = "{0}-ospf-cust1".format(rname) + current = topotest.ip4_route_zebra(tgen.gears[rname], vrf_name) + ret = topotest.difflines( + current, expected, title1="Current output", title2="Expected output" + ) + return ret + + +def test_ospf_convergence(): + "Test OSPF daemon convergence" + tgen = get_topogen() + + if tgen.routers_have_failure(): + pytest.skip("skipped because of router(s) failure") + + for rname, router in tgen.routers().items(): + logger.info('Waiting for router "%s" convergence', rname) + + # Load expected results from the command + reffile = os.path.join(CWD, "{}/ospfroute.txt".format(rname)) + expected = open(reffile).read() + + # Run test function until we get an result. Wait at most 60 seconds. + test_func = partial( + topotest.router_output_cmp, + router, + "show ip ospf vrf {0}-ospf-cust1 route".format(rname), + expected, + ) + result, diff = topotest.run_and_expect(test_func, "", count=160, wait=0.5) + assertmsg = "OSPF did not converge on {}:\n{}".format(rname, diff) + assert result, assertmsg + + +def test_ospf_kernel_route(): + "Test OSPF kernel route installation" + tgen = get_topogen() + + if tgen.routers_have_failure(): + pytest.skip("skipped because of router(s) failure") + + rlist = tgen.routers().values() + for router in rlist: + logger.info('Checking OSPF IPv4 kernel routes in "%s"', router.name) + reffile = os.path.join(CWD, "{}/zebraroute.txt".format(router.name)) + expected = open(reffile).read() + # Run test function until we get an result. Wait at most 60 seconds. + test_func = partial(compare_show_ip_route_vrf, router.name, expected) + result, diff = topotest.run_and_expect(test_func, "", count=140, wait=0.5) + assertmsg = 'OSPF IPv4 route mismatch in router "{}": {}'.format( + router.name, diff + ) + assert result, assertmsg + + +def test_ospf_json(): + "Test 'show ip ospf json' output for coherency." + tgen = get_topogen() + + if tgen.routers_have_failure(): + pytest.skip("skipped because of router(s) failure") + + for rname, router in tgen.routers().items(): + logger.info( + 'Comparing router "%s" "show ip ospf vrf %s-ospf-cust1 json" output', + router.name, + router.name, + ) + expected = { + "{}-ospf-cust1".format(router.name): { + "vrfName": "{}-ospf-cust1".format(router.name), + "routerId": "10.0.255.{}".format(rname[1:]), + "tosRoutesOnly": True, + "rfc2328Conform": True, + "spfScheduleDelayMsecs": 0, + "holdtimeMinMsecs": 50, + "holdtimeMaxMsecs": 5000, + "lsaMinIntervalMsecs": 5000, + "lsaMinArrivalMsecs": 1000, + "writeMultiplier": 20, + "refreshTimerMsecs": 10000, + "asbrRouter": "injectingExternalRoutingInformation", + "attachedAreaCounter": 1, + "areas": {}, + } + } + # Area specific additional checks + if router.name == "r1" or router.name == "r2" or router.name == "r3": + expected["{}-ospf-cust1".format(router.name)]["areas"]["0.0.0.0"] = { + "areaIfActiveCounter": 2, + "areaIfTotalCounter": 2, + "authentication": "authenticationNone", + "backbone": True, + "lsaAsbrNumber": 0, + "lsaNetworkNumber": 1, + "lsaNssaNumber": 0, + "lsaNumber": 4, + "lsaOpaqueAreaNumber": 0, + "lsaOpaqueLinkNumber": 0, + "lsaRouterNumber": 3, + "lsaSummaryNumber": 0, + "nbrFullAdjacentCounter": 2, + } + + test_func = partial( + topotest.router_json_cmp, + router, + "show ip ospf vrf {0}-ospf-cust1 json".format(rname), + expected, + ) + _, diff = topotest.run_and_expect(test_func, None, count=10, wait=0.5) + assertmsg = '"{}" JSON output mismatches'.format(rname) + assert diff is None, assertmsg + + +def test_ospf_link_down(): + "Test OSPF convergence after a link goes down" + tgen = get_topogen() + + if tgen.routers_have_failure(): + pytest.skip("skipped because of router(s) failure") + + # Simulate a network down event on router3 switch3 interface. + router3 = tgen.gears["r3"] + topotest.interface_set_status( + router3, "r3-eth0", ifaceaction=False, vrf_name="r3-ospf-cust1" + ) + + # Expect convergence on all routers + for rname, router in tgen.routers().items(): + logger.info('Waiting for router "%s" convergence after link failure', rname) + # Load expected results from the command + reffile = os.path.join(CWD, "{}/ospfroute_down.txt".format(rname)) + expected = open(reffile).read() + + # Run test function until we get an result. Wait at most 60 seconds. + test_func = partial( + topotest.router_output_cmp, + router, + "show ip ospf vrf {0}-ospf-cust1 route".format(rname), + expected, + ) + result, diff = topotest.run_and_expect(test_func, "", count=140, wait=0.5) + assertmsg = "OSPF did not converge on {}:\n{}".format(rname, diff) + assert result, assertmsg + + +def test_ospf_link_down_kernel_route(): + "Test OSPF kernel route installation" + tgen = get_topogen() + + if tgen.routers_have_failure(): + pytest.skip("skipped because of router(s) failure") + + rlist = tgen.routers().values() + for router in rlist: + logger.info( + 'Checking OSPF IPv4 kernel routes in "%s" after link down', router.name + ) + + str = "{0}-ospf-cust1".format(router.name) + reffile = os.path.join(CWD, "{}/zebraroutedown.txt".format(router.name)) + expected = open(reffile).read() + # Run test function until we get an result. Wait at most 60 seconds. + test_func = partial(compare_show_ip_route_vrf, router.name, expected) + result, diff = topotest.run_and_expect(test_func, "", count=140, wait=0.5) + assertmsg = ( + 'OSPF IPv4 route mismatch in router "{}" after link down: {}'.format( + router.name, diff + ) + ) + assert result, assertmsg + + +def test_memory_leak(): + "Run the memory leak test and report results." + tgen = get_topogen() + if not tgen.is_memleak_enabled(): + pytest.skip("Memory leak test/report is disabled") + + tgen.report_memory_leaks() + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) |