From 4436ba8d46516851a0e2924a9fd043b6de7d812d Mon Sep 17 00:00:00 2001 From: ckishimo Date: Thu, 5 Nov 2020 05:32:03 -0800 Subject: [PATCH] ospfd: add topotest for suppress-fa feature Signed-off-by: ckishimo --- tests/topotests/ospf_suppress_fa/__init__.py | 0 .../topotests/ospf_suppress_fa/r1/ospfd.conf | 9 + .../topotests/ospf_suppress_fa/r1/zebra.conf | 4 + .../topotests/ospf_suppress_fa/r2/ospfd.conf | 16 ++ .../topotests/ospf_suppress_fa/r2/zebra.conf | 7 + .../topotests/ospf_suppress_fa/r3/ospfd.conf | 11 ++ .../topotests/ospf_suppress_fa/r3/zebra.conf | 8 + .../test_ospf_suppress_fa.dot | 66 +++++++ .../test_ospf_suppress_fa.dot.jpg | Bin 0 -> 33501 bytes .../ospf_suppress_fa/test_ospf_suppress_fa.py | 181 ++++++++++++++++++ 10 files changed, 302 insertions(+) create mode 100755 tests/topotests/ospf_suppress_fa/__init__.py create mode 100644 tests/topotests/ospf_suppress_fa/r1/ospfd.conf create mode 100644 tests/topotests/ospf_suppress_fa/r1/zebra.conf create mode 100644 tests/topotests/ospf_suppress_fa/r2/ospfd.conf create mode 100644 tests/topotests/ospf_suppress_fa/r2/zebra.conf create mode 100644 tests/topotests/ospf_suppress_fa/r3/ospfd.conf create mode 100644 tests/topotests/ospf_suppress_fa/r3/zebra.conf create mode 100644 tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.dot create mode 100644 tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.dot.jpg create mode 100644 tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.py diff --git a/tests/topotests/ospf_suppress_fa/__init__.py b/tests/topotests/ospf_suppress_fa/__init__.py new file mode 100755 index 0000000000..e69de29bb2 diff --git a/tests/topotests/ospf_suppress_fa/r1/ospfd.conf b/tests/topotests/ospf_suppress_fa/r1/ospfd.conf new file mode 100644 index 0000000000..c02be35b14 --- /dev/null +++ b/tests/topotests/ospf_suppress_fa/r1/ospfd.conf @@ -0,0 +1,9 @@ +! +interface r1-eth0 + ip ospf network point-to-point + ip ospf hello-interval 2 + ip ospf dead-interval 10 +! +router ospf + network 10.0.12.0/24 area 0 +! diff --git a/tests/topotests/ospf_suppress_fa/r1/zebra.conf b/tests/topotests/ospf_suppress_fa/r1/zebra.conf new file mode 100644 index 0000000000..c1e31fb474 --- /dev/null +++ b/tests/topotests/ospf_suppress_fa/r1/zebra.conf @@ -0,0 +1,4 @@ +! +interface r1-eth0 + ip address 10.0.12.1/24 +! diff --git a/tests/topotests/ospf_suppress_fa/r2/ospfd.conf b/tests/topotests/ospf_suppress_fa/r2/ospfd.conf new file mode 100644 index 0000000000..ebc7d252fd --- /dev/null +++ b/tests/topotests/ospf_suppress_fa/r2/ospfd.conf @@ -0,0 +1,16 @@ +! +interface r2-eth0 + ip ospf network point-to-point + ip ospf hello-interval 2 + ip ospf dead-interval 10 +! +interface r2-eth1 + ip ospf network point-to-point + ip ospf hello-interval 2 + ip ospf dead-interval 10 +! +router ospf + network 10.0.12.0/24 area 0 + network 10.0.23.0/24 area 1 + area 1 nssa +! diff --git a/tests/topotests/ospf_suppress_fa/r2/zebra.conf b/tests/topotests/ospf_suppress_fa/r2/zebra.conf new file mode 100644 index 0000000000..9f1a26349e --- /dev/null +++ b/tests/topotests/ospf_suppress_fa/r2/zebra.conf @@ -0,0 +1,7 @@ +! +interface r2-eth0 + ip address 10.0.12.2/24 +! +interface r2-eth1 + ip address 10.0.23.2/24 +! diff --git a/tests/topotests/ospf_suppress_fa/r3/ospfd.conf b/tests/topotests/ospf_suppress_fa/r3/ospfd.conf new file mode 100644 index 0000000000..08be11a7b7 --- /dev/null +++ b/tests/topotests/ospf_suppress_fa/r3/ospfd.conf @@ -0,0 +1,11 @@ +! +interface r3-eth0 + ip ospf network point-to-point + ip ospf hello-interval 2 + ip ospf dead-interval 10 +! +router ospf + redistribute static + network 10.0.23.0/24 area 1 + area 1 nssa +! diff --git a/tests/topotests/ospf_suppress_fa/r3/zebra.conf b/tests/topotests/ospf_suppress_fa/r3/zebra.conf new file mode 100644 index 0000000000..f76cbf74d2 --- /dev/null +++ b/tests/topotests/ospf_suppress_fa/r3/zebra.conf @@ -0,0 +1,8 @@ +! +ip route 3.3.1.1/32 Null0 +ip route 3.3.2.2/32 Null0 +ip route 3.3.3.3/32 Null0 +! +interface r3-eth0 + ip address 10.0.23.3/24 +! diff --git a/tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.dot b/tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.dot new file mode 100644 index 0000000000..1036658f1a --- /dev/null +++ b/tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.dot @@ -0,0 +1,66 @@ +## 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 suppress-fa"; + + # Routers + r1 [ + label="r1\nrtr-id 10.0.12.1", + shape=doubleoctagon, + fillcolor="#f08080", + style=filled, + ]; + r2 [ + label="r2 (ABR)\nrtr-id 10.0.23.2", + shape=doubleoctagon, + fillcolor="#f08080", + style=filled, + ]; + r3 [ + label="r3 (ASBR)\nrtr-id 10.0.23.3", + shape=doubleoctagon, + fillcolor="#f08080", + style=filled, + ]; + + # Switches + s1 [ + label="s1\n10.0.12.0/24", + shape=oval, + fillcolor="#d0e0d0", + style=filled, + ]; + s2 [ + label="s2\n10.0.23.0/24", + shape=oval, + fillcolor="#d0e0d0", + style=filled, + ]; + + # Connections + subgraph cluster0 { + label="area 0" + r1 -- s1 [label="eth1\n.1"]; + r2 -- s1 [label="eth1\n.2"]; + } + + subgraph cluster1 { + label="area 1\nNSSA" + r2 -- s2 [label="eth2\n.2"]; + r3 -- s2 [label="eth1\n.3"]; + } + + { rank=same; r1; r2; r3; } +} diff --git a/tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.dot.jpg b/tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.dot.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2907d799f51bd65c7d85ffcf5ae0b7a63dd6e3f2 GIT binary patch literal 33501 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 literal 0 HcmV?d00001 diff --git a/tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.py b/tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.py new file mode 100644 index 0000000000..74d609c57e --- /dev/null +++ b/tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.py @@ -0,0 +1,181 @@ +#!/usr/bin/env python + +# +# test_ospf_suppres_fa.py +# Carles Kishimoto +# +# Permission to use, copy, modify, and/or distribute this software +# for any purpose with or without fee is hereby granted, provided +# that the above copyright notice and this permission notice appear +# in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY +# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +# OF THIS SOFTWARE. +# + +""" +test_ospf_suppres_fa.py: Test OSPF suppress-fa feature +- Topology: r1 --- R2 (ABR) --- R3 (redistribute static) + +test_ospf_set_suppress_fa() + 1) R1: Get a dict[LSA_ID] = fwd_addr for all type 5 LSA + 2) R2: Configure: area 1 nssa suppress-fa + 3) R1: Get a dict[LSA_ID] and compare fwd_address with 0.0.0.0 + +test_ospf_unset_suppress_fa() + 4) R2: Configure: no area 1 nssa suppress-fa + 5) R1: Get a dict[LSA_ID] = fwd_addr and compare it with the dict obtained in 1) +""" + +import os +import sys +import re +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 + +# Required to instantiate the topology builder class. +from mininet.topo import Topo + + +class NetworkTopo(Topo): + "OSPF topology builder" + + def build(self, *_args, **_opts): + "Build function" + + tgen = get_topogen(self) + + # Create routers + for router in range(1, 4): + tgen.add_router("r{}".format(router)) + + # R1-R2 backbone area + switch = tgen.add_switch("s1") + switch.add_link(tgen.gears["r1"]) + switch.add_link(tgen.gears["r2"]) + + # R2-R3 NSSA area + switch = tgen.add_switch("s2") + switch.add_link(tgen.gears["r2"]) + switch.add_link(tgen.gears["r3"]) + + +def setup_module(mod): + "Sets up the pytest environment" + + tgen = Topogen(NetworkTopo, mod.__name__) + tgen.start_topology() + + # This is a sample of configuration loading. + router_list = tgen.routers() + + # For all registred routers, load the zebra and ospf configuration file + for rname, router in router_list.items(): + router.load_config( + TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)) + ) + router.load_config( + TopoRouter.RD_OSPF, os.path.join(CWD, "{}/ospfd.conf".format(rname)) + ) + + tgen.start_router() + +def teardown_module(_mod): + "Teardown the pytest environment" + + tgen = get_topogen() + tgen.stop_topology() + +def test_converge_protocols(): + "Wait for protocol convergence" + + tgen = get_topogen() + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + topotest.sleep(10, "Waiting for OSPF convergence") + +def ospf_configure_suppress_fa(router_name, area): + "Configure OSPF suppress-fa in router_name" + + tgen = get_topogen() + router = tgen.gears[router_name] + router.vtysh_cmd("conf t\nrouter ospf\narea {} nssa suppress-fa\nexit\n".format(area)) + +def ospf_unconfigure_suppress_fa(router_name, area): + "Remove OSPF suppress-fa in router_name" + + tgen = get_topogen() + router = tgen.gears[router_name] + router.vtysh_cmd("conf t\nrouter ospf\nno area {} nssa suppress-fa\nexit\n".format(area)) + +def ospf_get_lsa_type5(router_name): + "Return a dict with link state id as key and forwarding addresses as value" + + result = dict() + tgen = get_topogen() + router = tgen.gears[router_name] + cmd = "show ip ospf database external\n" + output = topotest.normalize_text(router.vtysh_cmd(cmd)) + for line in output.splitlines(): + re0 = re.match(r"\s+Link State ID: (\S+) \(External Network Number\)", line) + if re0: + lsa = re0.group(1) + re1 = re.match(r"\s+Forward Address: (\S+)", line) + if re1: + result[lsa] = re1.group(1) + return result + +@pytest.fixture(scope='module', name='original') +def test_ospf_set_suppress_fa(): + "Test OSPF area [x] nssa suppress-fa" + + # Get current forwarding address for each LSA type-5 in r1 + initial = ospf_get_lsa_type5("r1") + + # Configure suppres-fa in r2 area 1 + ospf_configure_suppress_fa("r2", "1") + topotest.sleep(10, "Waiting for OSPF convergence") + + # Check forwarding address on r1 for all statics is 0.0.0.0 + assertmsg = "Forwarding address is not 0.0.0.0 after enabling OSPF suppress-fa" + suppress = ospf_get_lsa_type5("r1") + for prefix in suppress: + assert suppress[prefix] == "0.0.0.0", assertmsg + + # Return the original forwarding addresses so we can compare them + # in the test_ospf_unset_supress_fa + return initial + +def test_ospf_unset_supress_fa(original): + "Test OSPF no area [x] nssa suppress-fa" + + # Remove suppress-fa in r2 area 1 + ospf_unconfigure_suppress_fa("r2", "1") + topotest.sleep(10, "Waiting for OSPF convergence") + + # Check forwarding address is the original value on r1 for all statics + assertmsg = "Forwarding address is not correct after removing OSPF suppress-fa" + restore = ospf_get_lsa_type5("r1") + for prefix in restore: + assert restore[prefix] == original[prefix], assertmsg + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args))