diff options
Diffstat (limited to 'tests')
135 files changed, 5362 insertions, 389 deletions
diff --git a/tests/lib/script1.lua b/tests/lib/script1.lua index e9ebc29bd9..6361c960a7 100644 --- a/tests/lib/script1.lua +++ b/tests/lib/script1.lua @@ -1 +1,54 @@ -a = a + b + +-- Positive testing + +function foo(a, b) + a = a + 1 + b = b + 1 + return { + a = a, + b = b, + } +end + +function bar(a, b) + a = a + 1 + b = b + 1 + c = 303 + return { + b = b, + c = c, + } +end + +function fact(n) + -- outer function must return a table + -- inner functions can be used to recurse or as helpers + function helper(m) + if m == 0 then + return 1 + else + return m * helper(m - 1) + end + end + return { + ans = helper(n) + } +end + +-- Negative testing + +function bad_return1() +end + +function bad_return2() + return 123 +end + +function bad_return3() + return {} +end + +function bad_return4() + error("Something bad!") +end + diff --git a/tests/lib/test_frrscript.c b/tests/lib/test_frrscript.c index bd75cc5552..7b23045978 100644 --- a/tests/lib/test_frrscript.c +++ b/tests/lib/test_frrscript.c @@ -20,18 +20,85 @@ #include <zebra.h> #include "lib/frrscript.h" +#include "lib/frrlua.h" int main(int argc, char **argv) { frrscript_init("./lib"); + struct frrscript *fs = frrscript_new("script1"); + int result; + + /* Positive testing */ - struct frrscript *fs = frrscript_load("script1", NULL); long long a = 100, b = 200; - int result = frrscript_call(fs, ("a", &a), ("b", &b)); + result = frrscript_load(fs, "foo", NULL); + assert(result == 0); + result = frrscript_call(fs, "foo", ("a", &a), ("b", &b)); + assert(result == 0); + assert(a == 101); + assert(b == 201); + + a = 100, b = 200; + + result = frrscript_load(fs, "bar", NULL); + assert(result == 0); + result = frrscript_call(fs, "bar", ("a", &a), ("b", &b)); + assert(result == 0); + long long *cptr = frrscript_get_result(fs, "bar", "c", lua_tointegerp); + + /* a should not occur in the returned table in script */ + assert(a == 100); + assert(b == 201); + assert(*cptr == 303); + XFREE(MTYPE_SCRIPT_RES, cptr); + + long long n = 5; + + result = frrscript_load(fs, "fact", NULL); assert(result == 0); - assert(a == 300); - assert(b == 200); + result = frrscript_call(fs, "fact", ("n", &n)); + assert(result == 0); + long long *ansptr = + frrscript_get_result(fs, "fact", "ans", lua_tointegerp); + assert(*ansptr == 120); + XFREE(MTYPE_SCRIPT_RES, ansptr); + + /* Negative testing */ + + /* Function does not exist in script file*/ + result = frrscript_load(fs, "does_not_exist", NULL); + assert(result == 1); + + /* Function was not (successfully) loaded */ + result = frrscript_call(fs, "does_not_exist", ("a", &a), ("b", &b)); + assert(result == 1); + + /* Get result from a function that was not loaded */ + long long *llptr = + frrscript_get_result(fs, "does_not_exist", "c", lua_tointegerp); + assert(llptr == NULL); + + /* Function returns void */ + result = frrscript_call(fs, "bad_return1"); + assert(result == 1); + + /* Function returns number */ + result = frrscript_call(fs, "bad_return2"); + assert(result == 1); + + /* Get non-existent result from a function */ + result = frrscript_call(fs, "bad_return3"); + assert(result == 1); + long long *cllptr = + frrscript_get_result(fs, "bad_return3", "c", lua_tointegerp); + assert(cllptr == NULL); + + /* Function throws exception */ + result = frrscript_call(fs, "bad_return4"); + assert(result == 1); + + frrscript_delete(fs); return 0; } diff --git a/tests/topotests/bgp-evpn-overlay-index-gateway/test_bgp_evpn_overlay_index_gateway.py b/tests/topotests/bgp-evpn-overlay-index-gateway/test_bgp_evpn_overlay_index_gateway.py index fbce2809e0..6728f76004 100755 --- a/tests/topotests/bgp-evpn-overlay-index-gateway/test_bgp_evpn_overlay_index_gateway.py +++ b/tests/topotests/bgp-evpn-overlay-index-gateway/test_bgp_evpn_overlay_index_gateway.py @@ -77,6 +77,9 @@ from lib.common_config import ( # Required to instantiate the topology builder class. from mininet.topo import Topo +pytestmark = [pytest.mark.bgpd] + + #Global variables PES = ['PE1', 'PE2'] HOSTS = ['host1', 'host2'] diff --git a/tests/topotests/bgp_aggregate_address_topo1/test_bgp_aggregate_address_topo1.py b/tests/topotests/bgp_aggregate_address_topo1/test_bgp_aggregate_address_topo1.py index 089b1acb1c..9f26978259 100644 --- a/tests/topotests/bgp_aggregate_address_topo1/test_bgp_aggregate_address_topo1.py +++ b/tests/topotests/bgp_aggregate_address_topo1/test_bgp_aggregate_address_topo1.py @@ -42,6 +42,8 @@ from lib.topogen import Topogen, TopoRouter, get_topogen from lib.topolog import logger from mininet.topo import Topo +pytestmark = [pytest.mark.bgpd] + class BgpAggregateAddressTopo1(Topo): def build(self, *_args, **_opts): diff --git a/tests/topotests/bgp_basic_functionality_topo1/test_bgp_basic_functionality.py b/tests/topotests/bgp_basic_functionality_topo1/test_bgp_basic_functionality.py index 485a76c6b2..4753c49397 100644 --- a/tests/topotests/bgp_basic_functionality_topo1/test_bgp_basic_functionality.py +++ b/tests/topotests/bgp_basic_functionality_topo1/test_bgp_basic_functionality.py @@ -1135,9 +1135,9 @@ def test_bgp_with_loopback_with_same_subnet_p1(request): protocol = "bgp" for addr_type in ADDR_TYPES: result = verify_fib_routes(tgen, addr_type, dut, input_dict_r1) - assert result is not True, "Testcase {} : Failed \n".format(tc_name) + assert result is not True, "Testcase {} : Failed \n" "Expected behavior: routes should not present in fib \n" - "Error: {}".format(result) + "Error: {}".format(tc_name, result) step("Verify Ipv4 and Ipv6 network installed in r3 RIB but not in FIB") input_dict_r3 = { @@ -1152,9 +1152,9 @@ def test_bgp_with_loopback_with_same_subnet_p1(request): protocol = "bgp" for addr_type in ADDR_TYPES: result = verify_fib_routes(tgen, addr_type, dut, input_dict_r1) - assert result is not True, "Testcase {} : Failed \n".format(tc_name) + assert result is not True, "Testcase {} : Failed \n" "Expected behavior: routes should not present in fib \n" - "Error: {}".format(result) + "Error: {}".format(tc_name, result) write_test_footer(tc_name) diff --git a/tests/topotests/bgp_community_alias/test_bgp-community-alias.py b/tests/topotests/bgp_community_alias/test_bgp-community-alias.py index c41ba810f1..6aadff1cfa 100644 --- a/tests/topotests/bgp_community_alias/test_bgp-community-alias.py +++ b/tests/topotests/bgp_community_alias/test_bgp-community-alias.py @@ -40,6 +40,8 @@ from lib.topogen import Topogen, TopoRouter, get_topogen from lib.topolog import logger from mininet.topo import Topo +pytestmark = [pytest.mark.bgpd] + class TemplateTopo(Topo): def build(self, *_args, **_opts): diff --git a/tests/topotests/bgp_community_change_update/test_bgp_community_change_update.py b/tests/topotests/bgp_community_change_update/test_bgp_community_change_update.py index 95e63c617e..9f449d7979 100644 --- a/tests/topotests/bgp_community_change_update/test_bgp_community_change_update.py +++ b/tests/topotests/bgp_community_change_update/test_bgp_community_change_update.py @@ -59,7 +59,7 @@ from mininet.topo import Topo from lib.common_config import step from time import sleep -pytestmark = [pytest.mark.bgpd, pytest.mark.bgpd] +pytestmark = [pytest.mark.bgpd] class TemplateTopo(Topo): diff --git a/tests/topotests/bgp_conditional_advertisement/test_bgp_conditional_advertisement.py b/tests/topotests/bgp_conditional_advertisement/test_bgp_conditional_advertisement.py index 0e31ab1995..44f54c7b51 100644 --- a/tests/topotests/bgp_conditional_advertisement/test_bgp_conditional_advertisement.py +++ b/tests/topotests/bgp_conditional_advertisement/test_bgp_conditional_advertisement.py @@ -139,6 +139,8 @@ from lib.topogen import Topogen, TopoRouter, get_topogen from lib.topolog import logger from mininet.topo import Topo +pytestmark = [pytest.mark.bgpd] + class BgpConditionalAdvertisementTopo(Topo): def build(self, *_args, **_opts): diff --git a/tests/topotests/bgp_default_afi_safi/test_bgp-default-afi-safi.py b/tests/topotests/bgp_default_afi_safi/test_bgp-default-afi-safi.py index 28117b7fe4..6ed7023044 100644 --- a/tests/topotests/bgp_default_afi_safi/test_bgp-default-afi-safi.py +++ b/tests/topotests/bgp_default_afi_safi/test_bgp-default-afi-safi.py @@ -47,6 +47,8 @@ from lib.topolog import logger from mininet.topo import Topo from lib.common_config import step +pytestmark = [pytest.mark.bgpd] + class TemplateTopo(Topo): def build(self, *_args, **_opts): diff --git a/tests/topotests/bgp_default_route/test_bgp_default-originate.py b/tests/topotests/bgp_default_route/test_bgp_default-originate.py index 19632162b4..6fbdfbe78a 100644 --- a/tests/topotests/bgp_default_route/test_bgp_default-originate.py +++ b/tests/topotests/bgp_default_route/test_bgp_default-originate.py @@ -38,6 +38,8 @@ from lib.topogen import Topogen, TopoRouter, get_topogen from lib.topolog import logger from mininet.topo import Topo +pytestmark = [pytest.mark.bgpd] + class TemplateTopo(Topo): def build(self, *_args, **_opts): diff --git a/tests/topotests/bgp_default_route_route_map_match/test_bgp_default-originate_route-map_match.py b/tests/topotests/bgp_default_route_route_map_match/test_bgp_default-originate_route-map_match.py index 089c9a964e..e7e3512b17 100644 --- a/tests/topotests/bgp_default_route_route_map_match/test_bgp_default-originate_route-map_match.py +++ b/tests/topotests/bgp_default_route_route_map_match/test_bgp_default-originate_route-map_match.py @@ -38,6 +38,8 @@ from lib.topogen import Topogen, TopoRouter, get_topogen from lib.topolog import logger from mininet.topo import Topo +pytestmark = [pytest.mark.bgpd] + class TemplateTopo(Topo): def build(self, *_args, **_opts): diff --git a/tests/topotests/bgp_default_route_route_map_match2/test_bgp_default-originate_route-map_match2.py b/tests/topotests/bgp_default_route_route_map_match2/test_bgp_default-originate_route-map_match2.py index 42a6b6edf6..5852ac268b 100644 --- a/tests/topotests/bgp_default_route_route_map_match2/test_bgp_default-originate_route-map_match2.py +++ b/tests/topotests/bgp_default_route_route_map_match2/test_bgp_default-originate_route-map_match2.py @@ -41,6 +41,8 @@ from lib.topolog import logger from mininet.topo import Topo from lib.common_config import step +pytestmark = [pytest.mark.bgpd] + class TemplateTopo(Topo): def build(self, *_args, **_opts): diff --git a/tests/topotests/bgp_default_route_route_map_match_set/test_bgp_default-originate_route-map_match_set.py b/tests/topotests/bgp_default_route_route_map_match_set/test_bgp_default-originate_route-map_match_set.py index 12d1d01bfb..e2fa89fccb 100644 --- a/tests/topotests/bgp_default_route_route_map_match_set/test_bgp_default-originate_route-map_match_set.py +++ b/tests/topotests/bgp_default_route_route_map_match_set/test_bgp_default-originate_route-map_match_set.py @@ -40,6 +40,9 @@ from lib.topolog import logger from mininet.topo import Topo +pytestmark = [pytest.mark.bgpd] + + class TemplateTopo(Topo): def build(self, *_args, **_opts): tgen = get_topogen(self) diff --git a/tests/topotests/bgp_default_route_route_map_set/test_bgp_default-originate_route-map_set.py b/tests/topotests/bgp_default_route_route_map_set/test_bgp_default-originate_route-map_set.py index 2622c33f5b..be87dc61cf 100644 --- a/tests/topotests/bgp_default_route_route_map_set/test_bgp_default-originate_route-map_set.py +++ b/tests/topotests/bgp_default_route_route_map_set/test_bgp_default-originate_route-map_set.py @@ -38,6 +38,8 @@ from lib.topogen import Topogen, TopoRouter, get_topogen from lib.topolog import logger from mininet.topo import Topo +pytestmark = [pytest.mark.bgpd] + class TemplateTopo(Topo): def build(self, *_args, **_opts): diff --git a/tests/topotests/bgp_distance_change/test_bgp_distance_change.py b/tests/topotests/bgp_distance_change/test_bgp_distance_change.py index f338d52e70..bf26714087 100644 --- a/tests/topotests/bgp_distance_change/test_bgp_distance_change.py +++ b/tests/topotests/bgp_distance_change/test_bgp_distance_change.py @@ -49,6 +49,8 @@ from lib.topogen import Topogen, TopoRouter, get_topogen from lib.topolog import logger from mininet.topo import Topo +pytestmark = [pytest.mark.bgpd] + class TemplateTopo(Topo): def build(self, *_args, **_opts): diff --git a/tests/topotests/bgp_dont_capability_negogiate/__init__.py b/tests/topotests/bgp_dont_capability_negogiate/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/topotests/bgp_dont_capability_negogiate/__init__.py diff --git a/tests/topotests/bgp_dont_capability_negogiate/r1/bgpd.conf b/tests/topotests/bgp_dont_capability_negogiate/r1/bgpd.conf new file mode 100644 index 0000000000..b429efe076 --- /dev/null +++ b/tests/topotests/bgp_dont_capability_negogiate/r1/bgpd.conf @@ -0,0 +1,6 @@ +! +router bgp 65001 + no bgp ebgp-requires-policy + neighbor 192.168.1.2 remote-as external + neighbor 192.168.1.2 dont-capability-negotiate +! diff --git a/tests/topotests/bgp_dont_capability_negogiate/r1/zebra.conf b/tests/topotests/bgp_dont_capability_negogiate/r1/zebra.conf new file mode 100644 index 0000000000..b29940f46a --- /dev/null +++ b/tests/topotests/bgp_dont_capability_negogiate/r1/zebra.conf @@ -0,0 +1,4 @@ +! +int r1-eth0 + ip address 192.168.1.1/24 +! diff --git a/tests/topotests/bgp_dont_capability_negogiate/r2/bgpd.conf b/tests/topotests/bgp_dont_capability_negogiate/r2/bgpd.conf new file mode 100644 index 0000000000..4af2cd6a80 --- /dev/null +++ b/tests/topotests/bgp_dont_capability_negogiate/r2/bgpd.conf @@ -0,0 +1,7 @@ +router bgp 65002 + no bgp ebgp-requires-policy + neighbor 192.168.1.1 remote-as external + address-family ipv4 unicast + redistribute connected + exit-address-family +! diff --git a/tests/topotests/bgp_dont_capability_negogiate/r2/zebra.conf b/tests/topotests/bgp_dont_capability_negogiate/r2/zebra.conf new file mode 100644 index 0000000000..dc15cf756a --- /dev/null +++ b/tests/topotests/bgp_dont_capability_negogiate/r2/zebra.conf @@ -0,0 +1,7 @@ +! +int lo + ip address 172.16.16.1/32 +! +int r2-eth0 + ip address 192.168.1.2/24 +! diff --git a/tests/topotests/bgp_dont_capability_negogiate/test_bgp_dont_capability_negotiate.py b/tests/topotests/bgp_dont_capability_negogiate/test_bgp_dont_capability_negotiate.py new file mode 100644 index 0000000000..398fa57ba9 --- /dev/null +++ b/tests/topotests/bgp_dont_capability_negogiate/test_bgp_dont_capability_negotiate.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python + +# Copyright (c) 2021 by +# Donatas Abraitis <donatas.abraitis@gmail.com> +# +# 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 if BGP connection is established if at least one peer +sets `dont-capability-negotiate`. +""" + +import os +import sys +import json +import time +import pytest +import functools + +pytestmark = pytest.mark.bgpd + +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) + +# pylint: disable=C0413 +from lib import topotest +from lib.topogen import Topogen, TopoRouter, get_topogen +from lib.topolog import logger +from mininet.topo import Topo + +pytestmark = [pytest.mark.bgpd] + + +class TemplateTopo(Topo): + def build(self, *_args, **_opts): + tgen = get_topogen(self) + + for routern in range(1, 3): + tgen.add_router("r{}".format(routern)) + + switch = tgen.add_switch("s1") + switch.add_link(tgen.gears["r1"]) + switch.add_link(tgen.gears["r2"]) + + +def setup_module(mod): + tgen = Topogen(TemplateTopo, mod.__name__) + tgen.start_topology() + + router_list = tgen.routers() + + for i, (rname, router) in enumerate(router_list.items(), 1): + router.load_config( + TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)) + ) + router.load_config( + TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname)) + ) + + tgen.start_router() + + +def teardown_module(mod): + tgen = get_topogen() + tgen.stop_topology() + + +def test_bgp_dont_capability_negotiate(): + tgen = get_topogen() + + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + router = tgen.gears["r1"] + + def _bgp_converge(router): + output = json.loads(router.vtysh_cmd("show bgp ipv4 unicast summary json")) + expected = { + "peers": { + "192.168.1.2": { + "pfxRcd": 2, + "pfxSnt": 2, + "state": "Established", + "peerState": "OK", + } + } + } + return topotest.json_cmp(output, expected) + + test_func = functools.partial(_bgp_converge, router) + success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5) + assert result is None, "Can't converge with dont-capability-negotiate" + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tests/topotests/bgp_ebgp_common_subnet_nexthop_unchanged/test_bgp-ebgp-common-subnet-nexthop-unchanged.py b/tests/topotests/bgp_ebgp_common_subnet_nexthop_unchanged/test_bgp-ebgp-common-subnet-nexthop-unchanged.py index 3b99065fe0..6db2697e75 100644 --- a/tests/topotests/bgp_ebgp_common_subnet_nexthop_unchanged/test_bgp-ebgp-common-subnet-nexthop-unchanged.py +++ b/tests/topotests/bgp_ebgp_common_subnet_nexthop_unchanged/test_bgp-ebgp-common-subnet-nexthop-unchanged.py @@ -51,6 +51,8 @@ from lib.topogen import Topogen, TopoRouter, get_topogen from lib.topolog import logger from mininet.topo import Topo +pytestmark = [pytest.mark.bgpd] + class TemplateTopo(Topo): def build(self, *_args, **_opts): diff --git a/tests/topotests/bgp_ebgp_requires_policy/test_bgp_ebgp_requires_policy.py b/tests/topotests/bgp_ebgp_requires_policy/test_bgp_ebgp_requires_policy.py index fa155dd5fe..2731d37fb0 100644 --- a/tests/topotests/bgp_ebgp_requires_policy/test_bgp_ebgp_requires_policy.py +++ b/tests/topotests/bgp_ebgp_requires_policy/test_bgp_ebgp_requires_policy.py @@ -57,6 +57,8 @@ from lib.topogen import Topogen, TopoRouter, get_topogen from lib.topolog import logger from mininet.topo import Topo +pytestmark = [pytest.mark.bgpd] + class TemplateTopo(Topo): def build(self, *_args, **_opts): diff --git a/tests/topotests/bgp_evpn_mh/test_evpn_mh.py b/tests/topotests/bgp_evpn_mh/test_evpn_mh.py index f389632b1e..2dcf70f14a 100644 --- a/tests/topotests/bgp_evpn_mh/test_evpn_mh.py +++ b/tests/topotests/bgp_evpn_mh/test_evpn_mh.py @@ -50,6 +50,9 @@ from lib.topolog import logger # Required to instantiate the topology builder class. from mininet.topo import Topo +pytestmark = [pytest.mark.bgpd, pytest.mark.pimd] + + ##################################################### ## ## Network Topology Definition @@ -594,14 +597,23 @@ def test_evpn_ead_update(): def ping_anycast_gw(tgen): - local_host = tgen.gears["hostd11"] - remote_host = tgen.gears["hostd21"] - # ping the anycast gw from the local and remote hosts to populate # the mac address on the PEs - cmd_str = "arping -I torbond -c 1 45.0.0.1" - local_host.run(cmd_str) - remote_host.run(cmd_str) + script_path = os.path.abspath(os.path.join(CWD, "../lib/scapy_sendpkt.py")) + intf = "torbond" + ipaddr = "45.0.0.1" + ping_cmd = [ + script_path, + "--imports=Ether,ARP", + "--interface=" + intf, + "'Ether(dst=\"ff:ff:ff:ff:ff:ff\")/ARP(pdst=\"{}\")'".format(ipaddr) + ] + for name in ("hostd11", "hostd21"): + host = tgen.net[name] + stdout = host.cmd(ping_cmd) + stdout = stdout.strip() + if stdout: + host.logger.debug("%s: arping on %s for %s returned: %s", name, intf, ipaddr, stdout) def check_mac(dut, vni, mac, m_type, esi, intf, ping_gw=False, tgen=None): diff --git a/tests/topotests/bgp_evpn_rt5/test_bgp_evpn.py b/tests/topotests/bgp_evpn_rt5/test_bgp_evpn.py index 36605d44f0..59024f7b71 100644 --- a/tests/topotests/bgp_evpn_rt5/test_bgp_evpn.py +++ b/tests/topotests/bgp_evpn_rt5/test_bgp_evpn.py @@ -46,6 +46,7 @@ from lib.topolog import logger # Required to instantiate the topology builder class. from mininet.topo import Topo +pytestmark = [pytest.mark.bgpd] class BGPEVPNTopo(Topo): "Test topology builder" diff --git a/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1.py b/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1.py index ee57b9c479..330ae5e437 100644 --- a/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1.py +++ b/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1.py @@ -139,6 +139,9 @@ from lib.common_config import ( required_linux_kernel_version, ) +pytestmark = [pytest.mark.bgpd] + + # Reading the data from JSON File for topology and configuration creation jsonFile = "{}/bgp_gr_topojson_topo1.json".format(CWD) try: diff --git a/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2.py b/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2.py index b6f8bf4cd9..e7ce216042 100644 --- a/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2.py +++ b/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2.py @@ -138,6 +138,9 @@ from lib.common_config import ( required_linux_kernel_version, ) +pytestmark = [pytest.mark.bgpd] + + # Reading the data from JSON File for topology and configuration creation jsonFile = "{}/bgp_gr_topojson_topo2.json".format(CWD) try: diff --git a/tests/topotests/bgp_gshut/test_bgp_gshut.py b/tests/topotests/bgp_gshut/test_bgp_gshut.py index fe945a4565..77f86a0bb8 100644 --- a/tests/topotests/bgp_gshut/test_bgp_gshut.py +++ b/tests/topotests/bgp_gshut/test_bgp_gshut.py @@ -75,6 +75,8 @@ from lib.topogen import Topogen, TopoRouter, get_topogen from lib.topolog import logger from mininet.topo import Topo +pytestmark = [pytest.mark.bgpd] + class TemplateTopo(Topo): def build(self, *_args, **_opts): diff --git a/tests/topotests/bgp_gshut_topo1/test_ebgp_gshut_topo1.py b/tests/topotests/bgp_gshut_topo1/test_ebgp_gshut_topo1.py index 868aec9f3e..fcfeaab613 100644 --- a/tests/topotests/bgp_gshut_topo1/test_ebgp_gshut_topo1.py +++ b/tests/topotests/bgp_gshut_topo1/test_ebgp_gshut_topo1.py @@ -75,6 +75,9 @@ from lib.bgp import ( ) from lib.topojson import build_topo_from_json, build_config_from_json +pytestmark = [pytest.mark.bgpd, pytest.mark.staticd] + + # Reading the data from JSON File for topology and configuration creation jsonFile = "{}/ebgp_gshut_topo1.json".format(CWD) try: diff --git a/tests/topotests/bgp_gshut_topo1/test_ibgp_gshut_topo1.py b/tests/topotests/bgp_gshut_topo1/test_ibgp_gshut_topo1.py index 69f4916374..d83e9e25a1 100644 --- a/tests/topotests/bgp_gshut_topo1/test_ibgp_gshut_topo1.py +++ b/tests/topotests/bgp_gshut_topo1/test_ibgp_gshut_topo1.py @@ -75,6 +75,9 @@ from lib.bgp import ( ) from lib.topojson import build_topo_from_json, build_config_from_json +pytestmark = [pytest.mark.bgpd, pytest.mark.staticd] + + # Reading the data from JSON File for topology and configuration creation jsonFile = "{}/ibgp_gshut_topo1.json".format(CWD) try: diff --git a/tests/topotests/bgp_large_community/test_bgp_large_community_topo_1.py b/tests/topotests/bgp_large_community/test_bgp_large_community_topo_1.py index 31fbdcd4b5..69eba23e0f 100644 --- a/tests/topotests/bgp_large_community/test_bgp_large_community_topo_1.py +++ b/tests/topotests/bgp_large_community/test_bgp_large_community_topo_1.py @@ -73,6 +73,9 @@ from lib.topolog import logger from lib.bgp import verify_bgp_convergence, create_router_bgp, clear_bgp_and_verify from lib.topojson import build_topo_from_json, build_config_from_json +pytestmark = [pytest.mark.bgpd] + + # Save the Current Working Directory to find configuration files. CWD = os_path.dirname(os_path.realpath(__file__)) sys.path.append(os_path.join(CWD, "../")) diff --git a/tests/topotests/bgp_large_community/test_bgp_large_community_topo_2.py b/tests/topotests/bgp_large_community/test_bgp_large_community_topo_2.py index 84d9c48f35..b033c7e5cd 100644 --- a/tests/topotests/bgp_large_community/test_bgp_large_community_topo_2.py +++ b/tests/topotests/bgp_large_community/test_bgp_large_community_topo_2.py @@ -97,6 +97,9 @@ from lib.topolog import logger from lib.bgp import verify_bgp_convergence, create_router_bgp, clear_bgp_and_verify from lib.topojson import build_topo_from_json, build_config_from_json +pytestmark = [pytest.mark.bgpd] + + # Reading the data from JSON File for topology and configuration creation jsonFile = "{}/bgp_large_community_topo_2.json".format(CWD) diff --git a/tests/topotests/bgp_link_bw_ip/test_bgp_linkbw_ip.py b/tests/topotests/bgp_link_bw_ip/test_bgp_linkbw_ip.py index f09ff20651..3fcc3bec9a 100644 --- a/tests/topotests/bgp_link_bw_ip/test_bgp_linkbw_ip.py +++ b/tests/topotests/bgp_link_bw_ip/test_bgp_linkbw_ip.py @@ -46,6 +46,9 @@ from lib.topolog import logger # Required to instantiate the topology builder class. from mininet.topo import Topo +pytestmark = [pytest.mark.bgpd] + + """ This topology is for validating one of the primary use cases for weighted ECMP (a.k.a. Unequal cost multipath) using BGP link-bandwidth: diff --git a/tests/topotests/bgp_listen_on_multiple_addresses/test_bgp_listen_on_multiple_addresses.py b/tests/topotests/bgp_listen_on_multiple_addresses/test_bgp_listen_on_multiple_addresses.py index a3ca1408e2..a7959fe61b 100755 --- a/tests/topotests/bgp_listen_on_multiple_addresses/test_bgp_listen_on_multiple_addresses.py +++ b/tests/topotests/bgp_listen_on_multiple_addresses/test_bgp_listen_on_multiple_addresses.py @@ -50,11 +50,14 @@ sys.path.append(os.path.join(CWD, "../")) from lib.topogen import Topogen, get_topogen from lib.topojson import build_topo_from_json, build_config_from_json +from lib.topojson import linux_intf_config_from_json from lib.common_config import start_topology from lib.topotest import router_json_cmp, run_and_expect from mininet.topo import Topo from functools import partial +pytestmark = [pytest.mark.bgpd] + LISTEN_ADDRESSES = { "r1": ["10.0.0.1"], @@ -94,6 +97,9 @@ def setup_module(mod): ) start_topology(tgen) + + linux_intf_config_from_json(tgen, topo) + build_config_from_json(tgen, topo) diff --git a/tests/topotests/bgp_local_as_private_remove/test_bgp_local_as_private_remove.py b/tests/topotests/bgp_local_as_private_remove/test_bgp_local_as_private_remove.py index 32e7a4df61..7c5ed87dd0 100644 --- a/tests/topotests/bgp_local_as_private_remove/test_bgp_local_as_private_remove.py +++ b/tests/topotests/bgp_local_as_private_remove/test_bgp_local_as_private_remove.py @@ -43,6 +43,8 @@ from lib.topogen import Topogen, TopoRouter, get_topogen from lib.topolog import logger from mininet.topo import Topo +pytestmark = [pytest.mark.bgpd] + class TemplateTopo(Topo): def build(self, *_args, **_opts): diff --git a/tests/topotests/bgp_maximum_prefix_invalid_update/test_bgp_maximum_prefix_invalid_update.py b/tests/topotests/bgp_maximum_prefix_invalid_update/test_bgp_maximum_prefix_invalid_update.py index 8494653dfe..0fde32a68b 100644 --- a/tests/topotests/bgp_maximum_prefix_invalid_update/test_bgp_maximum_prefix_invalid_update.py +++ b/tests/topotests/bgp_maximum_prefix_invalid_update/test_bgp_maximum_prefix_invalid_update.py @@ -47,6 +47,8 @@ from lib.topogen import Topogen, TopoRouter, get_topogen from lib.topolog import logger from mininet.topo import Topo +pytestmark = [pytest.mark.bgpd] + class TemplateTopo(Topo): def build(self, *_args, **_opts): diff --git a/tests/topotests/bgp_maximum_prefix_out/test_bgp_maximum_prefix_out.py b/tests/topotests/bgp_maximum_prefix_out/test_bgp_maximum_prefix_out.py index b99664e700..5c93910788 100644 --- a/tests/topotests/bgp_maximum_prefix_out/test_bgp_maximum_prefix_out.py +++ b/tests/topotests/bgp_maximum_prefix_out/test_bgp_maximum_prefix_out.py @@ -43,6 +43,8 @@ from lib.topogen import Topogen, TopoRouter, get_topogen from lib.topolog import logger from mininet.topo import Topo +pytestmark = [pytest.mark.bgpd] + class TemplateTopo(Topo): def build(self, *_args, **_opts): diff --git a/tests/topotests/bgp_multi_vrf_topo1/test_bgp_multi_vrf_topo1.py b/tests/topotests/bgp_multi_vrf_topo1/test_bgp_multi_vrf_topo1.py index 7ea5a24fd7..c9a93bd75f 100644 --- a/tests/topotests/bgp_multi_vrf_topo1/test_bgp_multi_vrf_topo1.py +++ b/tests/topotests/bgp_multi_vrf_topo1/test_bgp_multi_vrf_topo1.py @@ -145,6 +145,7 @@ from lib.bgp import ( ) from lib.topojson import build_topo_from_json, build_config_from_json +pytestmark = [pytest.mark.bgpd, pytest.mark.staticd] # Reading the data from JSON File for topology creation jsonFile = "{}/bgp_multi_vrf_topo1.json".format(CWD) diff --git a/tests/topotests/bgp_multiview_topo1/test_bgp_multiview_topo1.py b/tests/topotests/bgp_multiview_topo1/test_bgp_multiview_topo1.py index d8815a0d39..01e90fb4b8 100644 --- a/tests/topotests/bgp_multiview_topo1/test_bgp_multiview_topo1.py +++ b/tests/topotests/bgp_multiview_topo1/test_bgp_multiview_topo1.py @@ -81,6 +81,10 @@ from functools import partial sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from lib import topotest + +pytestmark = [pytest.mark.bgpd] + + fatal_error = "" diff --git a/tests/topotests/bgp_path_attributes_topo1/test_bgp_path_attributes.py b/tests/topotests/bgp_path_attributes_topo1/test_bgp_path_attributes.py index a9541a55c5..a591c2f3f4 100644 --- a/tests/topotests/bgp_path_attributes_topo1/test_bgp_path_attributes.py +++ b/tests/topotests/bgp_path_attributes_topo1/test_bgp_path_attributes.py @@ -94,6 +94,9 @@ from lib.bgp import ( ) from lib.topojson import build_topo_from_json, build_config_from_json +pytestmark = [pytest.mark.bgpd, pytest.mark.staticd] + + # Reading the data from JSON File for topology creation jsonFile = "{}/bgp_path_attributes.json".format(CWD) diff --git a/tests/topotests/bgp_peer_type_multipath_relax/test_bgp_peer-type_multipath-relax.py b/tests/topotests/bgp_peer_type_multipath_relax/test_bgp_peer-type_multipath-relax.py index 39a0beeb11..743fcf7b3a 100755 --- a/tests/topotests/bgp_peer_type_multipath_relax/test_bgp_peer-type_multipath-relax.py +++ b/tests/topotests/bgp_peer_type_multipath_relax/test_bgp_peer-type_multipath-relax.py @@ -73,6 +73,8 @@ from lib.topogen import Topogen, TopoRouter, get_topogen from lib.topolog import logger from mininet.topo import Topo +pytestmark = [pytest.mark.bgpd, pytest.mark.staticd] + class PeerTypeRelaxTopo(Topo): def build(self, *_args, **_opts): diff --git a/tests/topotests/bgp_prefix_list_topo1/test_prefix_lists.py b/tests/topotests/bgp_prefix_list_topo1/test_prefix_lists.py index 22952f645c..10dee0f77b 100644 --- a/tests/topotests/bgp_prefix_list_topo1/test_prefix_lists.py +++ b/tests/topotests/bgp_prefix_list_topo1/test_prefix_lists.py @@ -73,6 +73,9 @@ from lib.topolog import logger from lib.bgp import verify_bgp_convergence, create_router_bgp, clear_bgp_and_verify from lib.topojson import build_topo_from_json, build_config_from_json +pytestmark = [pytest.mark.bgpd] + + # Reading the data from JSON File for topology creation jsonFile = "{}/prefix_lists.json".format(CWD) diff --git a/tests/topotests/bgp_prefix_sid/test_bgp_prefix_sid.py b/tests/topotests/bgp_prefix_sid/test_bgp_prefix_sid.py index ceac84709b..fffe135b77 100644 --- a/tests/topotests/bgp_prefix_sid/test_bgp_prefix_sid.py +++ b/tests/topotests/bgp_prefix_sid/test_bgp_prefix_sid.py @@ -41,6 +41,8 @@ from lib.topogen import Topogen, TopoRouter, get_topogen from lib.topolog import logger from mininet.topo import Topo +pytestmark = [pytest.mark.bgpd] + class TemplateTopo(Topo): def build(self, **_opts): diff --git a/tests/topotests/bgp_prefix_sid2/test_bgp_prefix_sid2.py b/tests/topotests/bgp_prefix_sid2/test_bgp_prefix_sid2.py index 25362530d4..703dcd7e2d 100755 --- a/tests/topotests/bgp_prefix_sid2/test_bgp_prefix_sid2.py +++ b/tests/topotests/bgp_prefix_sid2/test_bgp_prefix_sid2.py @@ -41,6 +41,8 @@ from lib.topogen import Topogen, TopoRouter, get_topogen from lib.topolog import logger from mininet.topo import Topo +pytestmark = [pytest.mark.bgpd] + class TemplateTopo(Topo): def build(self, **_opts): diff --git a/tests/topotests/bgp_reject_as_sets/test_bgp_reject_as_sets.py b/tests/topotests/bgp_reject_as_sets/test_bgp_reject_as_sets.py index d514dccd4a..c644d2104f 100644 --- a/tests/topotests/bgp_reject_as_sets/test_bgp_reject_as_sets.py +++ b/tests/topotests/bgp_reject_as_sets/test_bgp_reject_as_sets.py @@ -50,6 +50,8 @@ from lib.topogen import Topogen, TopoRouter, get_topogen from lib.topolog import logger from mininet.topo import Topo +pytestmark = [pytest.mark.bgpd] + class TemplateTopo(Topo): def build(self, *_args, **_opts): diff --git a/tests/topotests/bgp_route_aggregation/test_bgp_aggregation.py b/tests/topotests/bgp_route_aggregation/test_bgp_aggregation.py index 0467bf1bfb..ecf1ed521c 100644 --- a/tests/topotests/bgp_route_aggregation/test_bgp_aggregation.py +++ b/tests/topotests/bgp_route_aggregation/test_bgp_aggregation.py @@ -70,6 +70,9 @@ from lib.bgp import ( ) from lib.topojson import build_topo_from_json, build_config_from_json +pytestmark = [pytest.mark.bgpd, pytest.mark.staticd] + + # Reading the data from JSON File for topology and configuration creation jsonFile = "{}/bgp_aggregation.json".format(CWD) try: diff --git a/tests/topotests/bgp_route_map/test_route_map_topo1.py b/tests/topotests/bgp_route_map/test_route_map_topo1.py index 74172501db..7de56849c8 100644 --- a/tests/topotests/bgp_route_map/test_route_map_topo1.py +++ b/tests/topotests/bgp_route_map/test_route_map_topo1.py @@ -67,6 +67,9 @@ from lib.bgp import ( ) from lib.topojson import build_topo_from_json, build_config_from_json +pytestmark = [pytest.mark.bgpd, pytest.mark.staticd] + + ################################# # TOPOLOGY ################################# diff --git a/tests/topotests/bgp_route_map/test_route_map_topo2.py b/tests/topotests/bgp_route_map/test_route_map_topo2.py index 958eceba62..230a89ace1 100644 --- a/tests/topotests/bgp_route_map/test_route_map_topo2.py +++ b/tests/topotests/bgp_route_map/test_route_map_topo2.py @@ -149,6 +149,9 @@ from lib.bgp import ( ) from lib.topojson import build_topo_from_json, build_config_from_json +pytestmark = [pytest.mark.bgpd, pytest.mark.staticd] + + # Reading the data from JSON File for topology and configuration creation jsonFile = "{}/bgp_route_map_topo2.json".format(CWD) diff --git a/tests/topotests/bgp_rr_ibgp/test_bgp_rr_ibgp_topo1.py b/tests/topotests/bgp_rr_ibgp/test_bgp_rr_ibgp_topo1.py index 6a604765ca..664c9dc91a 100644 --- a/tests/topotests/bgp_rr_ibgp/test_bgp_rr_ibgp_topo1.py +++ b/tests/topotests/bgp_rr_ibgp/test_bgp_rr_ibgp_topo1.py @@ -49,6 +49,9 @@ from lib.topolog import logger # Required to instantiate the topology builder class. from mininet.topo import Topo +pytestmark = [pytest.mark.bgpd] + + ##################################################### ## ## Network Topology Definition diff --git a/tests/topotests/bgp_set_local_preference_add_subtract/test_bgp_set_local-preference_add_subtract.py b/tests/topotests/bgp_set_local_preference_add_subtract/test_bgp_set_local-preference_add_subtract.py index af64648951..b4af911d91 100644 --- a/tests/topotests/bgp_set_local_preference_add_subtract/test_bgp_set_local-preference_add_subtract.py +++ b/tests/topotests/bgp_set_local_preference_add_subtract/test_bgp_set_local-preference_add_subtract.py @@ -44,6 +44,8 @@ from lib.topogen import Topogen, TopoRouter, get_topogen from lib.topolog import logger from mininet.topo import Topo +pytestmark = [pytest.mark.bgpd] + class TemplateTopo(Topo): def build(self, *_args, **_opts): diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/test_bgp_srv6l3vpn_to_bgp_vrf.py b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/test_bgp_srv6l3vpn_to_bgp_vrf.py index 2d80c66b0b..3251484514 100755 --- a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/test_bgp_srv6l3vpn_to_bgp_vrf.py +++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/test_bgp_srv6l3vpn_to_bgp_vrf.py @@ -39,6 +39,8 @@ from lib.topolog import logger from lib.common_config import required_linux_kernel_version from mininet.topo import Topo +pytestmark = [pytest.mark.bgpd] + class Topology(Topo): """ diff --git a/tests/topotests/bgp_suppress_fib/test_bgp_suppress_fib.py b/tests/topotests/bgp_suppress_fib/test_bgp_suppress_fib.py index c75055c26f..476f6b556b 100644 --- a/tests/topotests/bgp_suppress_fib/test_bgp_suppress_fib.py +++ b/tests/topotests/bgp_suppress_fib/test_bgp_suppress_fib.py @@ -40,6 +40,8 @@ from lib.topogen import Topogen, TopoRouter, get_topogen from lib.topolog import logger from mininet.topo import Topo +pytestmark = [pytest.mark.bgpd] + class TemplateTopo(Topo): def build(self, *_args, **_opts): diff --git a/tests/topotests/bgp_tcp_mss/test_bgp_tcp_mss.py b/tests/topotests/bgp_tcp_mss/test_bgp_tcp_mss.py index 7500c3b3ad..cb1d28cc06 100644 --- a/tests/topotests/bgp_tcp_mss/test_bgp_tcp_mss.py +++ b/tests/topotests/bgp_tcp_mss/test_bgp_tcp_mss.py @@ -51,6 +51,8 @@ from lib.topogen import Topogen, TopoRouter, get_topogen from lib.topolog import logger from mininet.topo import Topo +pytestmark = [pytest.mark.bgpd] + class TemplateTopo(Topo): def build(self, *_args, **_opts): diff --git a/tests/topotests/bgp_update_delay/test_bgp_update_delay.py b/tests/topotests/bgp_update_delay/test_bgp_update_delay.py index 71bd58bf73..2972a25f38 100644 --- a/tests/topotests/bgp_update_delay/test_bgp_update_delay.py +++ b/tests/topotests/bgp_update_delay/test_bgp_update_delay.py @@ -73,6 +73,8 @@ from lib.topogen import Topogen, TopoRouter, get_topogen from lib.topolog import logger from mininet.topo import Topo +pytestmark = [pytest.mark.bgpd] + class TemplateTopo(Topo): def build(self, *_args, **_opts): diff --git a/tests/topotests/bgp_vrf_dynamic_route_leak/test_bgp_vrf_dynamic_route_leak_topo1.py b/tests/topotests/bgp_vrf_dynamic_route_leak/test_bgp_vrf_dynamic_route_leak_topo1.py index 83682fb36d..d6f1058a98 100644 --- a/tests/topotests/bgp_vrf_dynamic_route_leak/test_bgp_vrf_dynamic_route_leak_topo1.py +++ b/tests/topotests/bgp_vrf_dynamic_route_leak/test_bgp_vrf_dynamic_route_leak_topo1.py @@ -81,6 +81,9 @@ from lib.bgp import ( ) from lib.topojson import build_topo_from_json, build_config_from_json +pytestmark = [pytest.mark.bgpd, pytest.mark.staticd] + + # Reading the data from JSON File for topology creation jsonFile = "{}/bgp_vrf_dynamic_route_leak_topo1.json".format(CWD) try: diff --git a/tests/topotests/bgp_vrf_dynamic_route_leak/test_bgp_vrf_dynamic_route_leak_topo2.py b/tests/topotests/bgp_vrf_dynamic_route_leak/test_bgp_vrf_dynamic_route_leak_topo2.py index 6e7495d929..f701529b52 100644 --- a/tests/topotests/bgp_vrf_dynamic_route_leak/test_bgp_vrf_dynamic_route_leak_topo2.py +++ b/tests/topotests/bgp_vrf_dynamic_route_leak/test_bgp_vrf_dynamic_route_leak_topo2.py @@ -78,6 +78,9 @@ from lib.bgp import ( ) from lib.topojson import build_topo_from_json, build_config_from_json +pytestmark = [pytest.mark.bgpd, pytest.mark.staticd] + + # Reading the data from JSON File for topology creation jsonFile = "{}/bgp_vrf_dynamic_route_leak_topo2.json".format(CWD) try: diff --git a/tests/topotests/bgp_vrf_lite_ipv6_rtadv/test_bgp_vrf_lite_ipv6_rtadv.py b/tests/topotests/bgp_vrf_lite_ipv6_rtadv/test_bgp_vrf_lite_ipv6_rtadv.py index a17819f747..57ba87e887 100644 --- a/tests/topotests/bgp_vrf_lite_ipv6_rtadv/test_bgp_vrf_lite_ipv6_rtadv.py +++ b/tests/topotests/bgp_vrf_lite_ipv6_rtadv/test_bgp_vrf_lite_ipv6_rtadv.py @@ -47,6 +47,8 @@ from lib.common_config import required_linux_kernel_version # Required to instantiate the topology builder class. from mininet.topo import Topo +pytestmark = [pytest.mark.bgpd] + class BGPIPV6RTADVVRFTopo(Topo): "Test topology builder" diff --git a/tests/topotests/bgp_vrf_netns/test_bgp_vrf_netns_topo.py b/tests/topotests/bgp_vrf_netns/test_bgp_vrf_netns_topo.py index 30bb9595b7..9889e1cdd5 100644 --- a/tests/topotests/bgp_vrf_netns/test_bgp_vrf_netns_topo.py +++ b/tests/topotests/bgp_vrf_netns/test_bgp_vrf_netns_topo.py @@ -44,6 +44,9 @@ from lib.topolog import logger # Required to instantiate the topology builder class. from mininet.topo import Topo +pytestmark = [pytest.mark.bgpd] + + total_ebgp_peers = 1 CustomizeVrfWithNetns = True diff --git a/tests/topotests/bgp_vrf_route_leak_basic/test_bgp-vrf-route-leak-basic.py b/tests/topotests/bgp_vrf_route_leak_basic/test_bgp-vrf-route-leak-basic.py index 71f64e9b70..fcec0c23af 100644 --- a/tests/topotests/bgp_vrf_route_leak_basic/test_bgp-vrf-route-leak-basic.py +++ b/tests/topotests/bgp_vrf_route_leak_basic/test_bgp-vrf-route-leak-basic.py @@ -41,6 +41,8 @@ from lib.topolog import logger from mininet.topo import Topo +pytestmark = [pytest.mark.bgpd] + class BGPVRFTopo(Topo): def build(self, *_args, **_opts): diff --git a/tests/topotests/evpn_pim_1/leaf1/pimd.conf b/tests/topotests/evpn_pim_1/leaf1/pimd.conf index 293e252086..d85f33d1fc 100644 --- a/tests/topotests/evpn_pim_1/leaf1/pimd.conf +++ b/tests/topotests/evpn_pim_1/leaf1/pimd.conf @@ -2,6 +2,7 @@ debug pim events debug pim nht debug pim zebra ip pim rp 192.168.100.1 +ip pim join-prune-interval 5 ! int lo ip pim diff --git a/tests/topotests/evpn_pim_1/leaf2/pimd.conf b/tests/topotests/evpn_pim_1/leaf2/pimd.conf index 08d5a19a2a..d775b800b3 100644 --- a/tests/topotests/evpn_pim_1/leaf2/pimd.conf +++ b/tests/topotests/evpn_pim_1/leaf2/pimd.conf @@ -1,4 +1,5 @@ ip pim rp 192.168.100.1 +ip pim join-prune-interval 5 ! int lo ip pim diff --git a/tests/topotests/evpn_pim_1/spine/pimd.conf b/tests/topotests/evpn_pim_1/spine/pimd.conf index 56adda5cc4..12c6d6f85c 100644 --- a/tests/topotests/evpn_pim_1/spine/pimd.conf +++ b/tests/topotests/evpn_pim_1/spine/pimd.conf @@ -1,4 +1,5 @@ ip pim rp 192.168.100.1 +ip pim join-prune-interval 5 ! int lo ip pim diff --git a/tests/topotests/evpn_pim_1/test_evpn_pim_topo1.py b/tests/topotests/evpn_pim_1/test_evpn_pim_topo1.py index 260a197aca..b1f5daef1e 100644 --- a/tests/topotests/evpn_pim_1/test_evpn_pim_topo1.py +++ b/tests/topotests/evpn_pim_1/test_evpn_pim_topo1.py @@ -49,6 +49,9 @@ from lib.topolog import logger # Required to instantiate the topology builder class. from mininet.topo import Topo +pytestmark = [pytest.mark.bgpd, pytest.mark.bgpd] + + ##################################################### ## ## Network Topology Definition diff --git a/tests/topotests/evpn_type5_test_topo1/test_evpn_type5_chaos_topo1.py b/tests/topotests/evpn_type5_test_topo1/test_evpn_type5_chaos_topo1.py index 46e21857c8..09d66baa79 100644 --- a/tests/topotests/evpn_type5_test_topo1/test_evpn_type5_chaos_topo1.py +++ b/tests/topotests/evpn_type5_test_topo1/test_evpn_type5_chaos_topo1.py @@ -85,6 +85,9 @@ from lib.bgp import ( ) from lib.topojson import build_topo_from_json, build_config_from_json +pytestmark = [pytest.mark.bgpd, pytest.mark.staticd] + + # Reading the data from JSON File for topology creation jsonFile = "{}/evpn_type5_chaos_topo1.json".format(CWD) try: diff --git a/tests/topotests/evpn_type5_test_topo1/test_evpn_type5_topo1.py b/tests/topotests/evpn_type5_test_topo1/test_evpn_type5_topo1.py index 1a399ab32e..521f2335b4 100644 --- a/tests/topotests/evpn_type5_test_topo1/test_evpn_type5_topo1.py +++ b/tests/topotests/evpn_type5_test_topo1/test_evpn_type5_topo1.py @@ -91,6 +91,9 @@ from lib.bgp import ( ) from lib.topojson import build_topo_from_json, build_config_from_json +pytestmark = [pytest.mark.bgpd, pytest.mark.staticd] + + # Reading the data from JSON File for topology creation jsonFile = "{}/evpn_type5_topo1.json".format(CWD) try: diff --git a/tests/topotests/isis_lsp_bits_topo1/test_isis_lsp_bits_topo1.py b/tests/topotests/isis_lsp_bits_topo1/test_isis_lsp_bits_topo1.py index 27dc1073c6..70dcff035f 100755 --- a/tests/topotests/isis_lsp_bits_topo1/test_isis_lsp_bits_topo1.py +++ b/tests/topotests/isis_lsp_bits_topo1/test_isis_lsp_bits_topo1.py @@ -84,6 +84,9 @@ from lib.topolog import logger # Required to instantiate the topology builder class. from mininet.topo import Topo +pytestmark = [pytest.mark.isisd] + + # Global multi-dimensional dictionary containing all expected outputs outputs = {} diff --git a/tests/topotests/isis_rlfa_topo1/test_isis_rlfa_topo1.py b/tests/topotests/isis_rlfa_topo1/test_isis_rlfa_topo1.py index 9ad41c5934..ded1a4cc22 100755 --- a/tests/topotests/isis_rlfa_topo1/test_isis_rlfa_topo1.py +++ b/tests/topotests/isis_rlfa_topo1/test_isis_rlfa_topo1.py @@ -82,7 +82,7 @@ from lib.topolog import logger # Required to instantiate the topology builder class. from mininet.topo import Topo -pytestmark = [pytest.mark.isisd] +pytestmark = [pytest.mark.isisd, pytest.mark.ldpd] # Global multi-dimensional dictionary containing all expected outputs outputs = {} diff --git a/tests/topotests/isis_snmp/test_isis_snmp.py b/tests/topotests/isis_snmp/test_isis_snmp.py index 04e043847d..2cd07299b0 100755 --- a/tests/topotests/isis_snmp/test_isis_snmp.py +++ b/tests/topotests/isis_snmp/test_isis_snmp.py @@ -82,6 +82,8 @@ from lib.snmptest import SnmpTester # Required to instantiate the topology builder class. from mininet.topo import Topo +pytestmark = [pytest.mark.isisd, pytest.mark.ldpd, pytest.mark.snmp] + class TemplateTopo(Topo): "Test topology builder" diff --git a/tests/topotests/ldp_snmp/test_ldp_snmp_topo1.py b/tests/topotests/ldp_snmp/test_ldp_snmp_topo1.py index f47d906157..8052316d73 100644 --- a/tests/topotests/ldp_snmp/test_ldp_snmp_topo1.py +++ b/tests/topotests/ldp_snmp/test_ldp_snmp_topo1.py @@ -81,6 +81,7 @@ from lib.snmptest import SnmpTester # Required to instantiate the topology builder class. from mininet.topo import Topo +pytestmark = [pytest.mark.ldpd, pytest.mark.isisd, pytest.mark.snmp] class TemplateTopo(Topo): "Test topology builder" diff --git a/tests/topotests/ldp_sync_isis_topo1/test_ldp_sync_isis_topo1.py b/tests/topotests/ldp_sync_isis_topo1/test_ldp_sync_isis_topo1.py index 331e6fafd4..44b34c485f 100644 --- a/tests/topotests/ldp_sync_isis_topo1/test_ldp_sync_isis_topo1.py +++ b/tests/topotests/ldp_sync_isis_topo1/test_ldp_sync_isis_topo1.py @@ -80,6 +80,8 @@ from lib.topolog import logger # Required to instantiate the topology builder class. from mininet.topo import Topo +pytestmark = [pytest.mark.isisd, pytest.mark.ldpd] + class TemplateTopo(Topo): "Test topology builder" diff --git a/tests/topotests/lib/common_config.py b/tests/topotests/lib/common_config.py index 6a02e50127..07bb5153ab 100644 --- a/tests/topotests/lib/common_config.py +++ b/tests/topotests/lib/common_config.py @@ -1859,7 +1859,7 @@ def create_interfaces_cfg(tgen, topo, build=False): ) if "ospf6" in data: interface_data += _create_interfaces_ospf_cfg( - "ospf6", c_data, data, ospf_keywords + "ospf6", c_data, data, ospf_keywords + ["area"] ) result = create_common_configuration( diff --git a/tests/topotests/lib/ospf.py b/tests/topotests/lib/ospf.py index dc9fe0fcca..40da7c8fbe 100644 --- a/tests/topotests/lib/ospf.py +++ b/tests/topotests/lib/ospf.py @@ -28,6 +28,7 @@ from time import sleep from lib.topolog import logger from lib.topotest import frr_unicode from ipaddress import IPv6Address + # Import common_config to use commomnly used APIs from lib.common_config import ( create_common_configuration, @@ -89,8 +90,7 @@ def create_router_ospf(tgen, topo, input_dict=None, build=False, load_config=Tru logger.debug("Router %s: 'ospf' not present in input_dict", router) continue - result = __create_ospf_global( - tgen, input_dict, router, build, load_config) + result = __create_ospf_global(tgen, input_dict, router, build, load_config) if result is True: ospf_data = input_dict[router]["ospf"] @@ -100,7 +100,8 @@ def create_router_ospf(tgen, topo, input_dict=None, build=False, load_config=Tru continue result = __create_ospf_global( - tgen, input_dict, router, build, load_config, ospf='ospf6') + tgen, input_dict, router, build, load_config, ospf="ospf6" + ) if result is True: ospf_data = input_dict[router]["ospf6"] @@ -172,7 +173,6 @@ def __create_ospf_global( config_data.append(cmd) - # router id router_id = ospf_data.setdefault("router_id", None) del_router_id = ospf_data.setdefault("del_router_id", False) @@ -187,8 +187,7 @@ def __create_ospf_global( if del_log_adj_changes: config_data.append("no log-adjacency-changes detail") if log_adj_changes: - config_data.append("log-adjacency-changes {}".format( - log_adj_changes)) + config_data.append("log-adjacency-changes {}".format(log_adj_changes)) # aggregation timer aggr_timer = ospf_data.setdefault("aggr_timer", None) @@ -196,8 +195,7 @@ def __create_ospf_global( if del_aggr_timer: config_data.append("no aggregation timer") if aggr_timer: - config_data.append("aggregation timer {}".format( - aggr_timer)) + config_data.append("aggregation timer {}".format(aggr_timer)) # maximum path information ecmp_data = ospf_data.setdefault("maximum-paths", {}) @@ -245,12 +243,13 @@ def __create_ospf_global( cmd = "no {}".format(cmd) config_data.append(cmd) - #def route information + # def route information def_rte_data = ospf_data.setdefault("default-information", {}) if def_rte_data: if "originate" not in def_rte_data: - logger.debug("Router %s: 'originate key' not present in " - "input_dict", router) + logger.debug( + "Router %s: 'originate key' not present in " "input_dict", router + ) else: cmd = "default-information originate" @@ -261,12 +260,10 @@ def __create_ospf_global( cmd = cmd + " metric {}".format(def_rte_data["metric"]) if "metric-type" in def_rte_data: - cmd = cmd + " metric-type {}".format(def_rte_data[ - "metric-type"]) + cmd = cmd + " metric-type {}".format(def_rte_data["metric-type"]) if "route-map" in def_rte_data: - cmd = cmd + " route-map {}".format(def_rte_data[ - "route-map"]) + cmd = cmd + " route-map {}".format(def_rte_data["route-map"]) del_action = def_rte_data.setdefault("delete", False) if del_action: @@ -288,19 +285,19 @@ def __create_ospf_global( config_data.append(cmd) try: - if "area" in input_dict[router]['links'][neighbor][ - 'ospf6']: + if "area" in input_dict[router]["links"][neighbor]["ospf6"]: iface = input_dict[router]["links"][neighbor]["interface"] cmd = "interface {} area {}".format( - iface, input_dict[router]['links'][neighbor][ - 'ospf6']['area']) - if input_dict[router]['links'][neighbor].setdefault( - "delete", False): + iface, + input_dict[router]["links"][neighbor]["ospf6"]["area"], + ) + if input_dict[router]["links"][neighbor].setdefault( + "delete", False + ): cmd = "no {}".format(cmd) config_data.append(cmd) except KeyError: - pass - + pass # summary information summary_data = ospf_data.setdefault("summary-address", {}) @@ -420,6 +417,7 @@ def config_ospf_interface(tgen, topo, input_dict=None, build=False, load_config= True or False """ logger.debug("Enter lib config_ospf_interface") + result = False if not input_dict: input_dict = deepcopy(topo) else: @@ -502,7 +500,7 @@ def config_ospf_interface(tgen, topo, input_dict=None, build=False, load_config= # interface ospf mtu if data_ospf_mtu: cmd = "ip ospf mtu-ignore" - if 'del_action' in ospf_data: + if "del_action" in ospf_data: cmd = "no {}".format(cmd) config_data.append(cmd) @@ -543,8 +541,7 @@ def clear_ospf(tgen, router, ospf=None): version = "ip" cmd = "clear {} ospf interface".format(version) - logger.info( - "Clearing ospf process on router %s.. using command '%s'", router, cmd) + logger.info("Clearing ospf process on router %s.. using command '%s'", router, cmd) run_frr_cmd(rnode, cmd) logger.debug("Exiting lib API: clear_ospf()") @@ -774,7 +771,7 @@ def verify_ospf_neighbor(tgen, topo, dut=None, input_dict=None, lan=False, expec ################################ # Verification procs ################################ -@retry(retry_timeout=20) +@retry(retry_timeout=50) def verify_ospf6_neighbor(tgen, topo, dut=None, input_dict=None, lan=False): """ This API is to verify ospf neighborship by running @@ -825,105 +822,133 @@ def verify_ospf6_neighbor(tgen, topo, dut=None, input_dict=None, lan=False): if input_dict: for router, rnode in tgen.routers().items(): - if 'ospf6' not in topo['routers'][router]: + if "ospf6" not in topo["routers"][router]: continue if dut is not None and dut != router: continue logger.info("Verifying OSPF neighborship on router %s:", router) - show_ospf_json = run_frr_cmd(rnode, - "show ipv6 ospf neighbor json", isjson=True) + show_ospf_json = run_frr_cmd( + rnode, "show ipv6 ospf neighbor json", isjson=True + ) # Verifying output dictionary show_ospf_json is empty or not if not bool(show_ospf_json): errormsg = "OSPF6 is not running" return errormsg ospf_data_list = input_dict[router]["ospf6"] - ospf_nbr_list = ospf_data_list['neighbors'] + ospf_nbr_list = ospf_data_list["neighbors"] for ospf_nbr, nbr_data in ospf_nbr_list.items(): - data_ip = data_rid = topo['routers'][ospf_nbr]['ospf6']['router_id'] + + try: + data_ip = data_rid = topo["routers"][ospf_nbr]["ospf6"]["router_id"] + except KeyError: + data_ip = data_rid = topo["routers"][nbr_data["nbr"]]["ospf6"][ + "router_id" + ] + if ospf_nbr in data_ip: nbr_details = nbr_data[ospf_nbr] elif lan: - for switch in topo['switches']: - if 'ospf6' in topo['switches'][switch]['links'][router]: + for switch in topo["switches"]: + if "ospf6" in topo["switches"][switch]["links"][router]: neighbor_ip = data_ip else: continue else: - neighbor_ip = data_ip[router]['ipv6'].split("/")[0] + neighbor_ip = data_ip[router]["ipv6"].split("/")[0] nh_state = None neighbor_ip = neighbor_ip.lower() nbr_rid = data_rid - get_index_val = dict((d['neighborId'], dict( \ - d, index=index)) for (index, d) in enumerate( \ - show_ospf_json['neighbors'])) + get_index_val = dict( + (d["neighborId"], dict(d, index=index)) + for (index, d) in enumerate(show_ospf_json["neighbors"]) + ) try: - nh_state = get_index_val.get(neighbor_ip)['state'] - intf_state = get_index_val.get(neighbor_ip)['ifState'] + nh_state = get_index_val.get(neighbor_ip)["state"] + intf_state = get_index_val.get(neighbor_ip)["ifState"] except TypeError: - errormsg = "[DUT: {}] OSPF peer {} missing,from "\ - "{} ".format(router, - nbr_rid, ospf_nbr) + errormsg = "[DUT: {}] OSPF peer {} missing,from " "{} ".format( + router, nbr_rid, ospf_nbr + ) return errormsg - nbr_state = nbr_data.setdefault("state",None) - nbr_role = nbr_data.setdefault("role",None) + nbr_state = nbr_data.setdefault("state", None) + nbr_role = nbr_data.setdefault("role", None) if nbr_state: if nbr_state == nh_state: - logger.info("[DUT: {}] OSPF6 Nbr is {}:{} State {}".format - (router, ospf_nbr, nbr_rid, nh_state)) + logger.info( + "[DUT: {}] OSPF6 Nbr is {}:{} State {}".format( + router, ospf_nbr, nbr_rid, nh_state + ) + ) result = True else: - errormsg = ("[DUT: {}] OSPF6 is not Converged, neighbor" - " state is {} , Expected state is {}".format(router, - nh_state, nbr_state)) + errormsg = ( + "[DUT: {}] OSPF6 is not Converged, neighbor" + " state is {} , Expected state is {}".format( + router, nh_state, nbr_state + ) + ) return errormsg if nbr_role: if nbr_role == intf_state: - logger.info("[DUT: {}] OSPF6 Nbr is {}: {} Role {}".format( - router, ospf_nbr, nbr_rid, nbr_role)) + logger.info( + "[DUT: {}] OSPF6 Nbr is {}: {} Role {}".format( + router, ospf_nbr, nbr_rid, nbr_role + ) + ) else: - errormsg = ("[DUT: {}] OSPF6 is not Converged with rid" - "{}, role is {}, Expected role is {}".format(router, - nbr_rid, intf_state, nbr_role)) + errormsg = ( + "[DUT: {}] OSPF6 is not Converged with rid" + "{}, role is {}, Expected role is {}".format( + router, nbr_rid, intf_state, nbr_role + ) + ) return errormsg continue else: for router, rnode in tgen.routers().items(): - if 'ospf6' not in topo['routers'][router]: + if "ospf6" not in topo["routers"][router]: continue if dut is not None and dut != router: continue logger.info("Verifying OSPF6 neighborship on router %s:", router) - show_ospf_json = run_frr_cmd(rnode, - "show ipv6 ospf neighbor json", isjson=True) + show_ospf_json = run_frr_cmd( + rnode, "show ipv6 ospf neighbor json", isjson=True + ) # Verifying output dictionary show_ospf_json is empty or not if not bool(show_ospf_json): errormsg = "OSPF6 is not running" return errormsg ospf_data_list = topo["routers"][router]["ospf6"] - ospf_neighbors = ospf_data_list['neighbors'] + ospf_neighbors = ospf_data_list["neighbors"] total_peer = 0 total_peer = len(ospf_neighbors.keys()) no_of_ospf_nbr = 0 - ospf_nbr_list = ospf_data_list['neighbors'] + ospf_nbr_list = ospf_data_list["neighbors"] no_of_peer = 0 for ospf_nbr, nbr_data in ospf_nbr_list.items(): - data_ip = data_rid = topo['routers'][ospf_nbr]['ospf6']['router_id'] + try: + data_ip = data_rid = topo["routers"][ospf_nbr]["ospf6"]["router_id"] + except KeyError: + data_ip = data_rid = topo["routers"][nbr_data["nbr"]]["ospf6"][ + "router_id" + ] + if ospf_nbr in data_ip: nbr_details = nbr_data[ospf_nbr] elif lan: - for switch in topo['switches']: - if 'ospf6' in topo['switches'][switch]['links'][router]: + for switch in topo["switches"]: + if "ospf6" in topo["switches"][switch]["links"][router]: neighbor_ip = data_ip else: continue @@ -933,26 +958,27 @@ def verify_ospf6_neighbor(tgen, topo, dut=None, input_dict=None, lan=False): nh_state = None neighbor_ip = neighbor_ip.lower() nbr_rid = data_rid - get_index_val = dict((d['neighborId'], dict( \ - d, index=index)) for (index, d) in enumerate( \ - show_ospf_json['neighbors'])) + get_index_val = dict( + (d["neighborId"], dict(d, index=index)) + for (index, d) in enumerate(show_ospf_json["neighbors"]) + ) try: - nh_state = get_index_val.get(neighbor_ip)['state'] - intf_state = get_index_val.get(neighbor_ip)['ifState'] + nh_state = get_index_val.get(neighbor_ip)["state"] + intf_state = get_index_val.get(neighbor_ip)["ifState"] except TypeError: - errormsg = "[DUT: {}] OSPF peer {} missing,from "\ - "{} ".format(router, - nbr_rid, ospf_nbr) + errormsg = "[DUT: {}] OSPF peer {} missing,from " "{} ".format( + router, nbr_rid, ospf_nbr + ) return errormsg - if nh_state == 'Full': + if nh_state == "Full": no_of_peer += 1 if no_of_peer == total_peer: logger.info("[DUT: {}] OSPF6 is Converged".format(router)) result = True else: - errormsg = ("[DUT: {}] OSPF6 is not Converged".format(router)) + errormsg = "[DUT: {}] OSPF6 is not Converged".format(router) return errormsg logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name)) @@ -1491,7 +1517,7 @@ def verify_ospf_database(tgen, topo, dut, input_dict, expected=True): @retry(retry_timeout=20) -def verify_ospf_summary(tgen, topo, dut, input_dict, expected=True): +def verify_ospf_summary(tgen, topo, dut, input_dict, ospf=None, expected=True): """ This API is to verify ospf routes by running show ip ospf interface command. @@ -1502,7 +1528,6 @@ def verify_ospf_summary(tgen, topo, dut, input_dict, expected=True): * `topo` : topology descriptions * `dut`: device under test * `input_dict` : Input dict data, required when configuring from testcase - * `expected` : expected results from API, by-default True Usage ----- @@ -1522,18 +1547,30 @@ def verify_ospf_summary(tgen, topo, dut, input_dict, expected=True): True or False (Error Message) """ - logger.debug("Entering lib API: verify_ospf_summary()") + logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name)) result = False router = dut logger.info("Verifying OSPF summary on router %s:", router) - if "ospf" not in topo["routers"][dut]: - errormsg = "[DUT: {}] OSPF is not configured on the router.".format(router) - return errormsg - rnode = tgen.routers()[dut] - show_ospf_json = run_frr_cmd(rnode, "show ip ospf summary detail json", isjson=True) + + if ospf: + if 'ospf6' not in topo['routers'][dut]: + errormsg = "[DUT: {}] OSPF6 is not configured on the router.".format( + router) + return errormsg + + show_ospf_json = run_frr_cmd(rnode, "show ipv6 ospf summary detail json", + isjson=True) + else: + if 'ospf' not in topo['routers'][dut]: + errormsg = "[DUT: {}] OSPF is not configured on the router.".format( + router) + return errormsg + + show_ospf_json = run_frr_cmd(rnode, "show ip ospf summary detail json", + isjson=True) # Verifying output dictionary show_ospf_json is empty or not if not bool(show_ospf_json): @@ -1542,35 +1579,31 @@ def verify_ospf_summary(tgen, topo, dut, input_dict, expected=True): # To find neighbor ip type ospf_summary_data = input_dict + + if ospf: + show_ospf_json = show_ospf_json['default'] + for ospf_summ, summ_data in ospf_summary_data.items(): if ospf_summ not in show_ospf_json: continue - summary = ospf_summary_data[ospf_summ]["Summary address"] + summary = ospf_summary_data[ospf_summ]['Summary address'] + if summary in show_ospf_json: for summ in summ_data: if summ_data[summ] == show_ospf_json[summary][summ]: - logger.info( - "[DUT: %s] OSPF summary %s:%s is %s", - router, - summary, - summ, - summ_data[summ], - ) + logger.info("[DUT: %s] OSPF summary %s:%s is %s", + router, summary, summ, summ_data[summ]) result = True else: - errormsg = ( - "[DUT: {}] OSPF summary {}:{} is %s, " - "Expected is {}".format( - router, summary, summ, show_ospf_json[summary][summ] - ) - ) + errormsg = ("[DUT: {}] OSPF summary {} : {} is {}, " + "Expected is {}".format(router, summary, summ,show_ospf_json[ + summary][summ], summ_data[summ] )) return errormsg - logger.debug("Exiting API: verify_ospf_summary()") + logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name)) return result - @retry(retry_timeout=30) def verify_ospf6_rib(tgen, dut, input_dict, next_hop=None, tag=None, metric=None, fib=None): @@ -1627,31 +1660,34 @@ def verify_ospf6_rib(tgen, dut, input_dict, next_hop=None, found_routes = [] missing_routes = [] - if "static_routes" in input_dict[routerInput] or \ - "prefix" in input_dict[routerInput]: + if ( + "static_routes" in input_dict[routerInput] + or "prefix" in input_dict[routerInput] + ): if "prefix" in input_dict[routerInput]: static_routes = input_dict[routerInput]["prefix"] else: static_routes = input_dict[routerInput]["static_routes"] - for static_route in static_routes: cmd = "{}".format(command) cmd = "{} json".format(cmd) - ospf_rib_json = run_frr_cmd(rnode, cmd, isjson=True) + ospf_rib_json = run_frr_cmd(rnode, cmd, isjson=True) # Fix for PR 2644182 try: - ospf_rib_json = ospf_rib_json['routes'] + ospf_rib_json = ospf_rib_json["routes"] except KeyError: pass # Verifying output dictionary ospf_rib_json is not empty if bool(ospf_rib_json) is False: - errormsg = "[DUT: {}] No routes found in OSPF6 route " \ + errormsg = ( + "[DUT: {}] No routes found in OSPF6 route " "table".format(router) + ) return errormsg network = static_route["network"] @@ -1659,7 +1695,6 @@ def verify_ospf6_rib(tgen, dut, input_dict, next_hop=None, _tag = static_route.setdefault("tag", None) _rtype = static_route.setdefault("routeType", None) - # Generating IPs for verification ip_list = generate_ips(network, no_of_ip) st_found = False @@ -1668,7 +1703,7 @@ def verify_ospf6_rib(tgen, dut, input_dict, next_hop=None, st_rt = str(ipaddress.ip_network(frr_unicode(st_rt))) _addr_type = validate_ip_address(st_rt) - if _addr_type != 'ipv6': + if _addr_type != "ipv6": continue if st_rt in ospf_rib_json: @@ -1681,17 +1716,26 @@ def verify_ospf6_rib(tgen, dut, input_dict, next_hop=None, next_hop = [next_hop] for mnh in range(0, len(ospf_rib_json[st_rt])): - if 'fib' in ospf_rib_json[st_rt][ - mnh]["nextHops"][0]: - found_hops.append([rib_r[ - "ip"] for rib_r in ospf_rib_json[ - st_rt][mnh]["nextHops"]]) + if ( + "fib" + in ospf_rib_json[st_rt][mnh]["nextHops"][0] + ): + found_hops.append( + [ + rib_r["ip"] + for rib_r in ospf_rib_json[st_rt][mnh][ + "nextHops" + ] + ] + ) if found_hops[0]: - missing_list_of_nexthops = \ - set(found_hops[0]).difference(next_hop) - additional_nexthops_in_required_nhs = \ - set(next_hop).difference(found_hops[0]) + missing_list_of_nexthops = set( + found_hops[0] + ).difference(next_hop) + additional_nexthops_in_required_nhs = set( + next_hop + ).difference(found_hops[0]) if additional_nexthops_in_required_nhs: logger.info( @@ -1699,13 +1743,18 @@ def verify_ospf6_rib(tgen, dut, input_dict, next_hop=None, "%s is not active for route %s in " "RIB of router %s\n", additional_nexthops_in_required_nhs, - st_rt, dut) + st_rt, + dut, + ) errormsg = ( "Nexthop {} is not active" " for route {} in RIB of router" " {}\n".format( - additional_nexthops_in_required_nhs, - st_rt, dut)) + additional_nexthops_in_required_nhs, + st_rt, + dut, + ) + ) return errormsg else: nh_found = True @@ -1713,98 +1762,118 @@ def verify_ospf6_rib(tgen, dut, input_dict, next_hop=None, elif next_hop and fib is None: if type(next_hop) is not list: next_hop = [next_hop] - found_hops = [rib_r['nextHop'] for rib_r in - ospf_rib_json[st_rt][ - "nextHops"]] + found_hops = [ + rib_r["nextHop"] + for rib_r in ospf_rib_json[st_rt]["nextHops"] + ] if found_hops: - missing_list_of_nexthops = \ - set(found_hops).difference(next_hop) - additional_nexthops_in_required_nhs = \ - set(next_hop).difference(found_hops) + missing_list_of_nexthops = set( + found_hops + ).difference(next_hop) + additional_nexthops_in_required_nhs = set( + next_hop + ).difference(found_hops) if additional_nexthops_in_required_nhs: logger.info( - "Missing nexthop %s for route"\ - " %s in RIB of router %s\n", \ - additional_nexthops_in_required_nhs, \ - st_rt, dut) - errormsg=("Nexthop {} is Missing for "\ - "route {} in RIB of router {}\n".format( + "Missing nexthop %s for route" + " %s in RIB of router %s\n", additional_nexthops_in_required_nhs, - st_rt, dut)) + st_rt, + dut, + ) + errormsg = ( + "Nexthop {} is Missing for " + "route {} in RIB of router {}\n".format( + additional_nexthops_in_required_nhs, + st_rt, + dut, + ) + ) return errormsg else: nh_found = True if _rtype: - if "destinationType" not in ospf_rib_json[ - st_rt]: - errormsg = ("[DUT: {}]: destinationType missing" - "for route {} in OSPF RIB \n".\ - format(dut, st_rt)) + if "destinationType" not in ospf_rib_json[st_rt]: + errormsg = ( + "[DUT: {}]: destinationType missing" + "for route {} in OSPF RIB \n".format(dut, st_rt) + ) return errormsg - elif _rtype != ospf_rib_json[st_rt][ - "destinationType"]: - errormsg = ("[DUT: {}]: destinationType mismatch" - "for route {} in OSPF RIB \n".\ - format(dut, st_rt)) + elif _rtype != ospf_rib_json[st_rt]["destinationType"]: + errormsg = ( + "[DUT: {}]: destinationType mismatch" + "for route {} in OSPF RIB \n".format(dut, st_rt) + ) return errormsg else: - logger.info("DUT: {}]: Found destinationType {}" - "for route {}".\ - format(dut, _rtype, st_rt)) + logger.info( + "DUT: {}]: Found destinationType {}" + "for route {}".format(dut, _rtype, st_rt) + ) if tag: - if "tag" not in ospf_rib_json[ - st_rt]: - errormsg = ("[DUT: {}]: tag is not" - " present for" - " route {} in RIB \n".\ - format(dut, st_rt - )) + if "tag" not in ospf_rib_json[st_rt]: + errormsg = ( + "[DUT: {}]: tag is not" + " present for" + " route {} in RIB \n".format(dut, st_rt) + ) return errormsg - if _tag != ospf_rib_json[ - st_rt]["tag"]: - errormsg = ("[DUT: {}]: tag value {}" - " is not matched for" - " route {} in RIB \n".\ - format(dut, _tag, st_rt, - )) + if _tag != ospf_rib_json[st_rt]["tag"]: + errormsg = ( + "[DUT: {}]: tag value {}" + " is not matched for" + " route {} in RIB \n".format( + dut, + _tag, + st_rt, + ) + ) return errormsg if metric is not None: - if "type2cost" not in ospf_rib_json[ - st_rt]: - errormsg = ("[DUT: {}]: metric is" - " not present for" - " route {} in RIB \n".\ - format(dut, st_rt)) + if "type2cost" not in ospf_rib_json[st_rt]: + errormsg = ( + "[DUT: {}]: metric is" + " not present for" + " route {} in RIB \n".format(dut, st_rt) + ) return errormsg - if metric != ospf_rib_json[ - st_rt]["type2cost"]: - errormsg = ("[DUT: {}]: metric value " - "{} is not matched for " - "route {} in RIB \n".\ - format(dut, metric, st_rt, - )) + if metric != ospf_rib_json[st_rt]["type2cost"]: + errormsg = ( + "[DUT: {}]: metric value " + "{} is not matched for " + "route {} in RIB \n".format( + dut, + metric, + st_rt, + ) + ) return errormsg else: missing_routes.append(st_rt) if nh_found: - logger.info("[DUT: {}]: Found next_hop {} for all OSPF" - " routes in RIB".format(router, next_hop)) + logger.info( + "[DUT: {}]: Found next_hop {} for all OSPF" + " routes in RIB".format(router, next_hop) + ) if len(missing_routes) > 0: - errormsg = ("[DUT: {}]: Missing route in RIB, " - "routes: {}".\ - format(dut, missing_routes)) + errormsg = "[DUT: {}]: Missing route in RIB, " "routes: {}".format( + dut, missing_routes + ) return errormsg if found_routes: - logger.info("[DUT: %s]: Verified routes in RIB, found" - " routes are: %s\n", dut, found_routes) + logger.info( + "[DUT: %s]: Verified routes in RIB, found" " routes are: %s\n", + dut, + found_routes, + ) result = True logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name)) @@ -1855,15 +1924,16 @@ def verify_ospf6_interface(tgen, topo, dut=None,lan=False, input_dict=None): result = False for router, rnode in tgen.routers().iteritems(): - if 'ospf6' not in topo['routers'][router]: + if "ospf6" not in topo["routers"][router]: continue if dut is not None and dut != router: continue logger.info("Verifying OSPF interface on router %s:", router) - show_ospf_json = run_frr_cmd(rnode, "show ipv6 ospf interface json", - isjson=True) + show_ospf_json = run_frr_cmd( + rnode, "show ipv6 ospf interface json", isjson=True + ) # Verifying output dictionary show_ospf_json is empty or not if not bool(show_ospf_json): @@ -1873,32 +1943,49 @@ def verify_ospf6_interface(tgen, topo, dut=None,lan=False, input_dict=None): # To find neighbor ip type ospf_intf_data = input_dict[router]["links"] for ospf_intf, intf_data in ospf_intf_data.items(): - intf = topo['routers'][router]['links'][ospf_intf]['interface'] - if intf in show_ospf_json: - for intf_attribute in intf_data['ospf6']: - if intf_data['ospf6'][intf_attribute] is not list: - if intf_data['ospf6'][intf_attribute] == show_ospf_json[ - intf][intf_attribute]: - logger.info("[DUT: %s] OSPF6 interface %s: %s is %s", - router, intf, intf_attribute, intf_data['ospf6'][ - intf_attribute]) - elif intf_data['ospf6'][intf_attribute] is list: + intf = topo["routers"][router]["links"][ospf_intf]["interface"] + if intf in show_ospf_json: + for intf_attribute in intf_data["ospf6"]: + if intf_data["ospf6"][intf_attribute] is not list: + if ( + intf_data["ospf6"][intf_attribute] + == show_ospf_json[intf][intf_attribute] + ): + logger.info( + "[DUT: %s] OSPF6 interface %s: %s is %s", + router, + intf, + intf_attribute, + intf_data["ospf6"][intf_attribute], + ) + elif intf_data["ospf6"][intf_attribute] is list: for addr_list in len(show_ospf_json[intf][intf_attribute]): - if show_ospf_json[intf][intf_attribute][addr_list][ - 'address'].split('/')[0] == intf_data['ospf6'][ - 'internetAddress'][0]['address']: - break + if ( + show_ospf_json[intf][intf_attribute][addr_list][ + "address" + ].split("/")[0] + == intf_data["ospf6"]["internetAddress"][0]["address"] + ): + break else: - errormsg= "[DUT: {}] OSPF6 interface {}: {} is {}, \ - Expected is {}".format(router, intf, intf_attribute, - intf_data['ospf6'][intf_attribute], intf_data['ospf6'][ - intf_attribute]) + errormsg = "[DUT: {}] OSPF6 interface {}: {} is {}, \ + Expected is {}".format( + router, + intf, + intf_attribute, + intf_data["ospf6"][intf_attribute], + intf_data["ospf6"][intf_attribute], + ) return errormsg else: - errormsg= "[DUT: {}] OSPF6 interface {}: {} is {}, \ - Expected is {}".format(router, intf, intf_attribute, - intf_data['ospf6'][intf_attribute], intf_data['ospf6'][ - intf_attribute]) + errormsg = "[DUT: {}] OSPF6 interface {}: {} is {}, \ + Expected is {}".format( + router, + intf, + intf_attribute, + intf_data["ospf6"][intf_attribute], + intf_data["ospf6"][intf_attribute], + ) return errormsg result = True logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name)) @@ -1956,16 +2043,14 @@ def verify_ospf6_database(tgen, topo, dut, input_dict): router = dut logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name)) - if 'ospf' not in topo['routers'][dut]: - errormsg = "[DUT: {}] OSPF is not configured on the router.".format( - dut) + if "ospf" not in topo["routers"][dut]: + errormsg = "[DUT: {}] OSPF is not configured on the router.".format(dut) return errormsg rnode = tgen.routers()[dut] logger.info("Verifying OSPF interface on router %s:", dut) - show_ospf_json = run_frr_cmd(rnode, "show ip ospf database json", - isjson=True) + show_ospf_json = run_frr_cmd(rnode, "show ip ospf database json", isjson=True) # Verifying output dictionary show_ospf_json is empty or not if not bool(show_ospf_json): errormsg = "OSPF is not running" @@ -1973,167 +2058,209 @@ def verify_ospf6_database(tgen, topo, dut, input_dict): # for inter and inter lsa's ospf_db_data = input_dict.setdefault("areas", None) - ospf_external_lsa = input_dict.setdefault( - 'asExternalLinkStates', None) + ospf_external_lsa = input_dict.setdefault("asExternalLinkStates", None) if ospf_db_data: - for ospf_area, area_lsa in ospf_db_data.items(): - if ospf_area in show_ospf_json['areas']: - if 'routerLinkStates' in area_lsa: - for lsa in area_lsa['routerLinkStates']: - for rtrlsa in show_ospf_json['areas'][ospf_area][ - 'routerLinkStates']: - if lsa['lsaId'] == rtrlsa['lsaId'] and \ - lsa['advertisedRouter'] == rtrlsa[ - 'advertisedRouter']: - result = True - break - if result: - logger.info( - "[DUT: %s] OSPF LSDB area %s:Router " - "LSA %s", router, ospf_area, lsa) + for ospf_area, area_lsa in ospf_db_data.items(): + if ospf_area in show_ospf_json["areas"]: + if "routerLinkStates" in area_lsa: + for lsa in area_lsa["routerLinkStates"]: + for rtrlsa in show_ospf_json["areas"][ospf_area][ + "routerLinkStates" + ]: + if ( + lsa["lsaId"] == rtrlsa["lsaId"] + and lsa["advertisedRouter"] + == rtrlsa["advertisedRouter"] + ): + result = True break - else: - errormsg = \ - "[DUT: {}] OSPF LSDB area {}: expected" \ + if result: + logger.info( + "[DUT: %s] OSPF LSDB area %s:Router " "LSA %s", + router, + ospf_area, + lsa, + ) + break + else: + errormsg = ( + "[DUT: {}] OSPF LSDB area {}: expected" " Router LSA is {}".format(router, ospf_area, lsa) - return errormsg + ) + return errormsg - if 'networkLinkStates' in area_lsa: - for lsa in area_lsa['networkLinkStates']: - for netlsa in show_ospf_json['areas'][ospf_area][ - 'networkLinkStates']: - if lsa in show_ospf_json['areas'][ospf_area][ - 'networkLinkStates']: - if lsa['lsaId'] == netlsa['lsaId'] and \ - lsa['advertisedRouter'] == netlsa[ - 'advertisedRouter']: - result = True - break - if result: - logger.info( - "[DUT: %s] OSPF LSDB area %s:Network " - "LSA %s", router, ospf_area, lsa) - break - else: - errormsg = \ - "[DUT: {}] OSPF LSDB area {}: expected" \ + if "networkLinkStates" in area_lsa: + for lsa in area_lsa["networkLinkStates"]: + for netlsa in show_ospf_json["areas"][ospf_area][ + "networkLinkStates" + ]: + if ( + lsa + in show_ospf_json["areas"][ospf_area][ + "networkLinkStates" + ] + ): + if ( + lsa["lsaId"] == netlsa["lsaId"] + and lsa["advertisedRouter"] + == netlsa["advertisedRouter"] + ): + result = True + break + if result: + logger.info( + "[DUT: %s] OSPF LSDB area %s:Network " "LSA %s", + router, + ospf_area, + lsa, + ) + break + else: + errormsg = ( + "[DUT: {}] OSPF LSDB area {}: expected" " Network LSA is {}".format(router, ospf_area, lsa) - return errormsg + ) + return errormsg - if 'summaryLinkStates' in area_lsa: - for lsa in area_lsa['summaryLinkStates']: - for t3lsa in show_ospf_json['areas'][ospf_area][ - 'summaryLinkStates']: - if lsa['lsaId'] == t3lsa['lsaId'] and \ - lsa['advertisedRouter'] == t3lsa[ - 'advertisedRouter']: - result = True - break - if result: - logger.info( - "[DUT: %s] OSPF LSDB area %s:Summary " - "LSA %s", router, ospf_area, lsa) + if "summaryLinkStates" in area_lsa: + for lsa in area_lsa["summaryLinkStates"]: + for t3lsa in show_ospf_json["areas"][ospf_area][ + "summaryLinkStates" + ]: + if ( + lsa["lsaId"] == t3lsa["lsaId"] + and lsa["advertisedRouter"] == t3lsa["advertisedRouter"] + ): + result = True break - else: - errormsg = \ - "[DUT: {}] OSPF LSDB area {}: expected" \ + if result: + logger.info( + "[DUT: %s] OSPF LSDB area %s:Summary " "LSA %s", + router, + ospf_area, + lsa, + ) + break + else: + errormsg = ( + "[DUT: {}] OSPF LSDB area {}: expected" " Summary LSA is {}".format(router, ospf_area, lsa) - return errormsg + ) + return errormsg - if 'nssaExternalLinkStates' in area_lsa: - for lsa in area_lsa['nssaExternalLinkStates']: - for t7lsa in show_ospf_json['areas'][ospf_area][ - 'nssaExternalLinkStates']: - if lsa['lsaId'] == t7lsa['lsaId'] and \ - lsa['advertisedRouter'] == t7lsa[ - 'advertisedRouter']: - result = True - break - if result: - logger.info( - "[DUT: %s] OSPF LSDB area %s:Type7 " - "LSA %s", router, ospf_area, lsa) + if "nssaExternalLinkStates" in area_lsa: + for lsa in area_lsa["nssaExternalLinkStates"]: + for t7lsa in show_ospf_json["areas"][ospf_area][ + "nssaExternalLinkStates" + ]: + if ( + lsa["lsaId"] == t7lsa["lsaId"] + and lsa["advertisedRouter"] == t7lsa["advertisedRouter"] + ): + result = True break - else: - errormsg = \ - "[DUT: {}] OSPF LSDB area {}: expected" \ + if result: + logger.info( + "[DUT: %s] OSPF LSDB area %s:Type7 " "LSA %s", + router, + ospf_area, + lsa, + ) + break + else: + errormsg = ( + "[DUT: {}] OSPF LSDB area {}: expected" " Type7 LSA is {}".format(router, ospf_area, lsa) - return errormsg + ) + return errormsg - if 'asbrSummaryLinkStates' in area_lsa: - for lsa in area_lsa['asbrSummaryLinkStates']: - for t4lsa in show_ospf_json['areas'][ospf_area][ - 'asbrSummaryLinkStates']: - if lsa['lsaId'] == t4lsa['lsaId'] and \ - lsa['advertisedRouter'] == t4lsa[ - 'advertisedRouter']: - result = True - break - if result: - logger.info( - "[DUT: %s] OSPF LSDB area %s:ASBR Summary " - "LSA %s", router, ospf_area, lsa) + if "asbrSummaryLinkStates" in area_lsa: + for lsa in area_lsa["asbrSummaryLinkStates"]: + for t4lsa in show_ospf_json["areas"][ospf_area][ + "asbrSummaryLinkStates" + ]: + if ( + lsa["lsaId"] == t4lsa["lsaId"] + and lsa["advertisedRouter"] == t4lsa["advertisedRouter"] + ): result = True - else: - errormsg = \ - "[DUT: {}] OSPF LSDB area {}: expected" \ - " ASBR Summary LSA is {}".format( - router, ospf_area, lsa) - return errormsg + break + if result: + logger.info( + "[DUT: %s] OSPF LSDB area %s:ASBR Summary " "LSA %s", + router, + ospf_area, + lsa, + ) + result = True + else: + errormsg = ( + "[DUT: {}] OSPF LSDB area {}: expected" + " ASBR Summary LSA is {}".format(router, ospf_area, lsa) + ) + return errormsg - if 'linkLocalOpaqueLsa' in area_lsa: - for lsa in area_lsa['linkLocalOpaqueLsa']: - try: - for lnklsa in show_ospf_json['areas'][ospf_area][ - 'linkLocalOpaqueLsa']: - if lsa['lsaId'] in lnklsa['lsaId'] and \ - 'linkLocalOpaqueLsa' in show_ospf_json[ - 'areas'][ospf_area]: - logger.info(( - "[DUT: FRR] OSPF LSDB area %s:Opaque-LSA" - "%s", ospf_area, lsa)) - result = True - else: - errormsg = ("[DUT: FRR] OSPF LSDB area: {} " - "expected Opaque-LSA is {}, Found is {}".format( - ospf_area, lsa, show_ospf_json)) - raise ValueError (errormsg) - return errormsg - except KeyError: - errormsg = ("[DUT: FRR] linkLocalOpaqueLsa Not " - "present") - return errormsg + if "linkLocalOpaqueLsa" in area_lsa: + for lsa in area_lsa["linkLocalOpaqueLsa"]: + try: + for lnklsa in show_ospf_json["areas"][ospf_area][ + "linkLocalOpaqueLsa" + ]: + if ( + lsa["lsaId"] in lnklsa["lsaId"] + and "linkLocalOpaqueLsa" + in show_ospf_json["areas"][ospf_area] + ): + logger.info( + ( + "[DUT: FRR] OSPF LSDB area %s:Opaque-LSA" + "%s", + ospf_area, + lsa, + ) + ) + result = True + else: + errormsg = ( + "[DUT: FRR] OSPF LSDB area: {} " + "expected Opaque-LSA is {}, Found is {}".format( + ospf_area, lsa, show_ospf_json + ) + ) + raise ValueError(errormsg) + return errormsg + except KeyError: + errormsg = "[DUT: FRR] linkLocalOpaqueLsa Not " "present" + return errormsg if ospf_external_lsa: - for lsa in ospf_external_lsa: - try: - for t5lsa in show_ospf_json['asExternalLinkStates']: - if lsa['lsaId'] == t5lsa['lsaId'] and \ - lsa['advertisedRouter'] == t5lsa[ - 'advertisedRouter']: - result = True - break - except KeyError: - result = False - if result: - logger.info( - "[DUT: %s] OSPF LSDB:External LSA %s", - router, lsa) - result = True - else: - errormsg = \ - "[DUT: {}] OSPF LSDB : expected" \ - " External LSA is {}".format(router, lsa) - return errormsg + for lsa in ospf_external_lsa: + try: + for t5lsa in show_ospf_json["asExternalLinkStates"]: + if ( + lsa["lsaId"] == t5lsa["lsaId"] + and lsa["advertisedRouter"] == t5lsa["advertisedRouter"] + ): + result = True + break + except KeyError: + result = False + if result: + logger.info("[DUT: %s] OSPF LSDB:External LSA %s", router, lsa) + result = True + else: + errormsg = ( + "[DUT: {}] OSPF LSDB : expected" + " External LSA is {}".format(router, lsa) + ) + return errormsg logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name)) return result - -def config_ospf6_interface (tgen, topo, input_dict=None, build=False, - load_config=True): +def config_ospf6_interface(tgen, topo, input_dict=None, build=False, load_config=True): """ API to configure ospf on router. @@ -2180,17 +2307,17 @@ def config_ospf6_interface (tgen, topo, input_dict=None, build=False, "input_dict, passed input_dict %s", router, str(input_dict)) continue - ospf_data = input_dict[router]['links'][lnk]['ospf6'] + ospf_data = input_dict[router]["links"][lnk]["ospf6"] data_ospf_area = ospf_data.setdefault("area", None) - data_ospf_auth = ospf_data.setdefault("authentication", None) + data_ospf_auth = ospf_data.setdefault("hash-algo", None) data_ospf_dr_priority = ospf_data.setdefault("priority", None) data_ospf_cost = ospf_data.setdefault("cost", None) data_ospf_mtu = ospf_data.setdefault("mtu_ignore", None) try: - intf = topo['routers'][router]['links'][lnk]['interface'] + intf = topo["routers"][router]["links"][lnk]["interface"] except KeyError: - intf = topo['switches'][router]['links'][lnk]['interface'] + intf = topo["switches"][router]["links"][lnk]["interface"] # interface cmd = "interface {}".format(intf) @@ -2201,34 +2328,50 @@ def config_ospf6_interface (tgen, topo, input_dict=None, build=False, cmd = "ipv6 ospf area {}".format(data_ospf_area) config_data.append(cmd) + # interface ospf auth + if data_ospf_auth: + cmd = "ipv6 ospf6 authentication" + + if "del_action" in ospf_data: + cmd = "no {}".format(cmd) + + if "hash-algo" in ospf_data: + cmd = "{} key-id {} hash-algo {} key {}".format( + cmd, + ospf_data["key-id"], + ospf_data["hash-algo"], + ospf_data["key"], + ) + if "del_action" in ospf_data: + cmd = "no {}".format(cmd) + config_data.append(cmd) + # interface ospf dr priority if data_ospf_dr_priority: - cmd = "ipv6 ospf priority {}".format( - ospf_data["priority"]) - if 'del_action' in ospf_data: + cmd = "ipv6 ospf priority {}".format(ospf_data["priority"]) + if "del_action" in ospf_data: cmd = "no {}".format(cmd) config_data.append(cmd) # interface ospf cost if data_ospf_cost: - cmd = "ipv6 ospf cost {}".format( - ospf_data["cost"]) - if 'del_action' in ospf_data: + cmd = "ipv6 ospf cost {}".format(ospf_data["cost"]) + if "del_action" in ospf_data: cmd = "no {}".format(cmd) config_data.append(cmd) # interface ospf mtu if data_ospf_mtu: cmd = "ipv6 ospf mtu-ignore" - if 'del_action' in ospf_data: + if "del_action" in ospf_data: cmd = "no {}".format(cmd) config_data.append(cmd) if build: return config_data else: - result = create_common_configuration(tgen, router, config_data, - "interface_config", - build=build) + result = create_common_configuration( + tgen, router, config_data, "interface_config", build=build + ) logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name)) return result diff --git a/tests/topotests/lib/scapy_sendpkt.py b/tests/topotests/lib/scapy_sendpkt.py new file mode 100755 index 0000000000..0bb6a72092 --- /dev/null +++ b/tests/topotests/lib/scapy_sendpkt.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 eval: (blacken-mode 1) -*- +# +# July 29 2021, Christian Hopps <chopps@labn.net> +# +# Copyright (c) 2021, LabN Consulting, L.L.C. ("LabN") +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# +import argparse +import logging +import re +import sys + +from scapy.all import conf, srp + +conf.verb = 0 + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("-i", "--interface", help="interface to send packet on.") + parser.add_argument("-I", "--imports", help="scapy symbols to import") + parser.add_argument( + "-t", "--timeout", type=float, default=2.0, help="timeout for reply receipts" + ) + parser.add_argument("pktdef", help="scapy packet definition to send") + args = parser.parse_args() + + if args.imports: + i = args.imports.replace("\n", "").strip() + if not re.match("[a-zA-Z0-9_ \t,]", i): + logging.critical('Invalid imports specified: "%s"', i) + sys.exit(1) + exec("from scapy.all import " + i, globals(), locals()) + + ans, unans = srp(eval(args.pktdef), iface=args.interface, timeout=args.timeout) + if not ans: + sys.exit(2) + for pkt in ans: + print(pkt.answer.show(dump=True)) + + +if __name__ == "__main__": + main() diff --git a/tests/topotests/lib/topojson.py b/tests/topotests/lib/topojson.py index fcc6c19868..1ae482a265 100644 --- a/tests/topotests/lib/topojson.py +++ b/tests/topotests/lib/topojson.py @@ -293,6 +293,24 @@ def build_topo_from_json(tgen, topo): ) +def linux_intf_config_from_json(tgen, topo): + """Configure interfaces from linux based on topo.""" + routers = topo["routers"] + for rname in routers: + router = tgen.gears[rname] + links = routers[rname]["links"] + for rrname in links: + link = links[rrname] + if rrname == "lo": + lname = "lo" + else: + lname = link["interface"] + if "ipv4" in link: + router.run("ip addr add {} dev {}".format(link["ipv4"], lname)) + if "ipv6" in link: + router.run("ip -6 addr add {} dev {}".format(link["ipv6"], lname)) + + def build_config_from_json(tgen, topo, save_bkup=True): """ Reads initial configuraiton from JSON for each router, builds diff --git a/tests/topotests/msdp_mesh_topo1/r1/pimd.conf b/tests/topotests/msdp_mesh_topo1/r1/pimd.conf index 30cecee9e1..c2ffed4762 100644 --- a/tests/topotests/msdp_mesh_topo1/r1/pimd.conf +++ b/tests/topotests/msdp_mesh_topo1/r1/pimd.conf @@ -10,6 +10,7 @@ interface r1-eth1 ip igmp ! ip pim rp 10.254.254.1 +ip pim join-prune-interval 5 ip msdp timers 10 20 3 ip msdp mesh-group mg-1 source 10.254.254.1 ip msdp mesh-group mg-1 member 10.254.254.2 diff --git a/tests/topotests/msdp_mesh_topo1/r2/pimd.conf b/tests/topotests/msdp_mesh_topo1/r2/pimd.conf index a51c6d58c7..1719a17007 100644 --- a/tests/topotests/msdp_mesh_topo1/r2/pimd.conf +++ b/tests/topotests/msdp_mesh_topo1/r2/pimd.conf @@ -9,6 +9,7 @@ interface r2-eth1 ip pim ! ip pim rp 10.254.254.2 +ip pim join-prune-interval 5 ip msdp timers 10 20 3 ip msdp mesh-group mg-1 source 10.254.254.2 ip msdp mesh-group mg-1 member 10.254.254.1 diff --git a/tests/topotests/msdp_mesh_topo1/r3/pimd.conf b/tests/topotests/msdp_mesh_topo1/r3/pimd.conf index 663f78620e..2748a55d83 100644 --- a/tests/topotests/msdp_mesh_topo1/r3/pimd.conf +++ b/tests/topotests/msdp_mesh_topo1/r3/pimd.conf @@ -9,6 +9,7 @@ interface r3-eth1 ip pim ip igmp ! +ip pim join-prune-interval 5 ip pim rp 10.254.254.3 ip msdp timers 10 20 3 ip msdp mesh-group mg-1 source 10.254.254.3 diff --git a/tests/topotests/msdp_topo1/r1/pimd.conf b/tests/topotests/msdp_topo1/r1/pimd.conf index fc289031f4..4274315271 100644 --- a/tests/topotests/msdp_topo1/r1/pimd.conf +++ b/tests/topotests/msdp_topo1/r1/pimd.conf @@ -19,3 +19,4 @@ ip msdp timers 10 20 3 ip msdp peer 192.168.0.2 source 192.168.0.1 ip msdp peer 192.168.1.2 source 192.168.1.1 ip pim rp 10.254.254.1 +ip pim join-prune-interval 5 diff --git a/tests/topotests/msdp_topo1/r2/pimd.conf b/tests/topotests/msdp_topo1/r2/pimd.conf index ffa80b12d3..a4a69bf05c 100644 --- a/tests/topotests/msdp_topo1/r2/pimd.conf +++ b/tests/topotests/msdp_topo1/r2/pimd.conf @@ -15,3 +15,4 @@ ip msdp timers 10 20 3 ip msdp peer 192.168.0.1 source 192.168.0.2 ip msdp peer 192.168.2.2 source 192.168.2.1 ip pim rp 10.254.254.2 +ip pim join-prune-interval 5 diff --git a/tests/topotests/msdp_topo1/r3/pimd.conf b/tests/topotests/msdp_topo1/r3/pimd.conf index ab12f0573a..db94447c76 100644 --- a/tests/topotests/msdp_topo1/r3/pimd.conf +++ b/tests/topotests/msdp_topo1/r3/pimd.conf @@ -15,3 +15,4 @@ ip msdp timers 10 20 3 ip msdp peer 192.168.1.1 source 192.168.1.2 ip msdp peer 192.168.3.2 source 192.168.3.1 ip pim rp 10.254.254.3 +ip pim join-prune-interval 5 diff --git a/tests/topotests/msdp_topo1/r4/pimd.conf b/tests/topotests/msdp_topo1/r4/pimd.conf index b2e05cb3cb..e9bb59054c 100644 --- a/tests/topotests/msdp_topo1/r4/pimd.conf +++ b/tests/topotests/msdp_topo1/r4/pimd.conf @@ -19,3 +19,4 @@ ip msdp timers 10 20 3 ip msdp peer 192.168.2.1 source 192.168.2.2 ip msdp peer 192.168.3.1 source 192.168.3.2 ip pim rp 10.254.254.4 +ip pim join-prune-interval 5 diff --git a/tests/topotests/multicast_pim_bsm_topo1/test_mcast_pim_bsmp_01.py b/tests/topotests/multicast_pim_bsm_topo1/test_mcast_pim_bsmp_01.py index cd398a5111..827dde69ec 100644 --- a/tests/topotests/multicast_pim_bsm_topo1/test_mcast_pim_bsmp_01.py +++ b/tests/topotests/multicast_pim_bsm_topo1/test_mcast_pim_bsmp_01.py @@ -113,6 +113,9 @@ from lib.pim import ( from lib.topolog import logger from lib.topojson import build_topo_from_json, build_config_from_json +pytestmark = [pytest.mark.pimd, pytest.mark.staticd] + + # Reading the data from JSON File for topology creation jsonFile = "{}/mcast_pim_bsmp_01.json".format(CWD) try: diff --git a/tests/topotests/multicast_pim_bsm_topo2/test_mcast_pim_bsmp_02.py b/tests/topotests/multicast_pim_bsm_topo2/test_mcast_pim_bsmp_02.py index 60bd6de35d..98af4433ab 100644 --- a/tests/topotests/multicast_pim_bsm_topo2/test_mcast_pim_bsmp_02.py +++ b/tests/topotests/multicast_pim_bsm_topo2/test_mcast_pim_bsmp_02.py @@ -104,8 +104,7 @@ from lib.pim import ( from lib.topolog import logger from lib.topojson import build_topo_from_json, build_config_from_json - -pytestmark = [pytest.mark.pimd] +pytestmark = [pytest.mark.pimd, pytest.mark.staticd] # Reading the data from JSON File for topology creation diff --git a/tests/topotests/multicast_pim_sm_topo1/test_multicast_pim_sm_topo1.py b/tests/topotests/multicast_pim_sm_topo1/test_multicast_pim_sm_topo1.py index b880e0e462..99a6e5bacf 100755 --- a/tests/topotests/multicast_pim_sm_topo1/test_multicast_pim_sm_topo1.py +++ b/tests/topotests/multicast_pim_sm_topo1/test_multicast_pim_sm_topo1.py @@ -107,6 +107,9 @@ from lib.pim import ( from lib.topolog import logger from lib.topojson import build_topo_from_json, build_config_from_json +pytestmark = [pytest.mark.pimd] + + # Reading the data from JSON File for topology creation jsonFile = "{}/multicast_pim_sm_topo1.json".format(CWD) try: diff --git a/tests/topotests/multicast_pim_sm_topo2/test_multicast_pim_sm_topo2.py b/tests/topotests/multicast_pim_sm_topo2/test_multicast_pim_sm_topo2.py index ad3b77b843..f30902c1b2 100755 --- a/tests/topotests/multicast_pim_sm_topo2/test_multicast_pim_sm_topo2.py +++ b/tests/topotests/multicast_pim_sm_topo2/test_multicast_pim_sm_topo2.py @@ -102,6 +102,9 @@ from lib.pim import ( from lib.topolog import logger from lib.topojson import build_topo_from_json, build_config_from_json +pytestmark = [pytest.mark.pimd] + + # Reading the data from JSON File for topology creation jsonFile = "{}/multicast_pim_sm_topo2.json".format(CWD) try: diff --git a/tests/topotests/multicast_pim_static_rp_topo1/test_multicast_pim_static_rp.py b/tests/topotests/multicast_pim_static_rp_topo1/test_multicast_pim_static_rp.py index d73e8dc9e8..736cb1659c 100755 --- a/tests/topotests/multicast_pim_static_rp_topo1/test_multicast_pim_static_rp.py +++ b/tests/topotests/multicast_pim_static_rp_topo1/test_multicast_pim_static_rp.py @@ -153,6 +153,9 @@ from lib.pim import ( clear_ip_mroute_verify, ) +pytestmark = [pytest.mark.pimd, pytest.mark.staticd] + + # Reading the data from JSON File for topology and configuration creation jsonFile = "{}/multicast_pim_static_rp.json".format(CWD) try: diff --git a/tests/topotests/nhrp_topo/test_nhrp_topo.py b/tests/topotests/nhrp_topo/test_nhrp_topo.py index 1687961f34..f59e3ae1b9 100644 --- a/tests/topotests/nhrp_topo/test_nhrp_topo.py +++ b/tests/topotests/nhrp_topo/test_nhrp_topo.py @@ -45,6 +45,8 @@ from lib.topolog import logger # Required to instantiate the topology builder class. from mininet.topo import Topo +pytestmark = [pytest.mark.nhrpd] + class NHRPTopo(Topo): "Test topology builder" @@ -115,7 +117,7 @@ def setup_module(mod): ) # Initialize all routers. - logger.info('Launching BGP, NHRP') + logger.info('Launching NHRP') for name in router_list: router = tgen.gears[name] router.start() diff --git a/tests/topotests/ospf6_topo1/test_ospf6_topo1.py b/tests/topotests/ospf6_topo1/test_ospf6_topo1.py index bbd18a57ff..8a6544734a 100644 --- a/tests/topotests/ospf6_topo1/test_ospf6_topo1.py +++ b/tests/topotests/ospf6_topo1/test_ospf6_topo1.py @@ -91,6 +91,9 @@ from lib.topogen import Topogen, TopoRouter, get_topogen from lib.topolog import logger import platform +pytestmark = [pytest.mark.ospfd] + + ##################################################### ## ## Network Topology Definition diff --git a/tests/topotests/ospf6_topo1_vrf/test_ospf6_topo1_vrf.py b/tests/topotests/ospf6_topo1_vrf/test_ospf6_topo1_vrf.py index b158099d9a..61a80cc9ec 100755 --- a/tests/topotests/ospf6_topo1_vrf/test_ospf6_topo1_vrf.py +++ b/tests/topotests/ospf6_topo1_vrf/test_ospf6_topo1_vrf.py @@ -94,6 +94,9 @@ from lib.topolog import logger from lib.topotest import iproute2_is_vrf_capable from lib.common_config import required_linux_kernel_version +pytestmark = [pytest.mark.ospfd] + + ##################################################### ## ## Network Topology Definition diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_asbr_summary_topo1.py b/tests/topotests/ospf_basic_functionality/test_ospf_asbr_summary_topo1.py index 41960ac79f..e61a6b5905 100644 --- a/tests/topotests/ospf_basic_functionality/test_ospf_asbr_summary_topo1.py +++ b/tests/topotests/ospf_basic_functionality/test_ospf_asbr_summary_topo1.py @@ -70,6 +70,9 @@ from lib.ospf import ( verify_ospf_summary, ) +pytestmark = [pytest.mark.ospfd, pytest.mark.staticd] + + # Global variables topo = None # Reading the data from JSON File for topology creation diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_asbr_summary_type7_lsa.py b/tests/topotests/ospf_basic_functionality/test_ospf_asbr_summary_type7_lsa.py index 393eb19a53..db177360b4 100644 --- a/tests/topotests/ospf_basic_functionality/test_ospf_asbr_summary_type7_lsa.py +++ b/tests/topotests/ospf_basic_functionality/test_ospf_asbr_summary_type7_lsa.py @@ -70,6 +70,9 @@ from lib.ospf import ( verify_ospf_summary, ) +pytestmark = [pytest.mark.ospfd, pytest.mark.staticd] + + # Global variables topo = None # Reading the data from JSON File for topology creation diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_authentication.py b/tests/topotests/ospf_basic_functionality/test_ospf_authentication.py index a7f2893eab..bdba8fd8e4 100644 --- a/tests/topotests/ospf_basic_functionality/test_ospf_authentication.py +++ b/tests/topotests/ospf_basic_functionality/test_ospf_authentication.py @@ -56,6 +56,9 @@ from lib.topojson import build_topo_from_json, build_config_from_json from lib.ospf import verify_ospf_neighbor, config_ospf_interface, clear_ospf from ipaddress import IPv4Address +pytestmark = [pytest.mark.ospfd] + + # Global variables topo = None # Reading the data from JSON File for topology creation diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_ecmp.py b/tests/topotests/ospf_basic_functionality/test_ospf_ecmp.py index 49ecaac9f7..5c57f8be25 100644 --- a/tests/topotests/ospf_basic_functionality/test_ospf_ecmp.py +++ b/tests/topotests/ospf_basic_functionality/test_ospf_ecmp.py @@ -68,6 +68,9 @@ from lib.ospf import ( redistribute_ospf, ) +pytestmark = [pytest.mark.ospfd, pytest.mark.staticd] + + topo = None # Reading the data from JSON File for topology creation diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_ecmp_lan.py b/tests/topotests/ospf_basic_functionality/test_ospf_ecmp_lan.py index 47c6c45e39..96f781c150 100644 --- a/tests/topotests/ospf_basic_functionality/test_ospf_ecmp_lan.py +++ b/tests/topotests/ospf_basic_functionality/test_ospf_ecmp_lan.py @@ -70,6 +70,9 @@ from lib.ospf import ( ) from ipaddress import IPv4Address +pytestmark = [pytest.mark.ospfd, pytest.mark.staticd] + + # Global variables topo = None # Reading the data from JSON File for topology creation diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_lan.py b/tests/topotests/ospf_basic_functionality/test_ospf_lan.py index d9b90a132a..c89a663380 100644 --- a/tests/topotests/ospf_basic_functionality/test_ospf_lan.py +++ b/tests/topotests/ospf_basic_functionality/test_ospf_lan.py @@ -71,6 +71,9 @@ from lib.ospf import ( ) from ipaddress import IPv4Address +pytestmark = [pytest.mark.ospfd, pytest.mark.staticd] + + # Global variables topo = None # Reading the data from JSON File for topology creation diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_nssa.py b/tests/topotests/ospf_basic_functionality/test_ospf_nssa.py index 3644bff3dc..0af83548b9 100644 --- a/tests/topotests/ospf_basic_functionality/test_ospf_nssa.py +++ b/tests/topotests/ospf_basic_functionality/test_ospf_nssa.py @@ -63,6 +63,9 @@ sys.path.append(os.path.join(CWD, "../lib/")) # pylint: disable=C0413 # Import topogen and topotest helpers +pytestmark = [pytest.mark.ospfd, pytest.mark.staticd] + + # Global variables topo = None # Reading the data from JSON File for topology creation diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_p2mp.py b/tests/topotests/ospf_basic_functionality/test_ospf_p2mp.py index be18ba5a78..0172f589c5 100644 --- a/tests/topotests/ospf_basic_functionality/test_ospf_p2mp.py +++ b/tests/topotests/ospf_basic_functionality/test_ospf_p2mp.py @@ -68,6 +68,9 @@ from lib.ospf import ( verify_ospf_database, ) +pytestmark = [pytest.mark.ospfd, pytest.mark.staticd] + + # Global variables topo = None diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_routemaps.py b/tests/topotests/ospf_basic_functionality/test_ospf_routemaps.py index 0848f6c94a..bc6c248ad2 100644 --- a/tests/topotests/ospf_basic_functionality/test_ospf_routemaps.py +++ b/tests/topotests/ospf_basic_functionality/test_ospf_routemaps.py @@ -65,6 +65,9 @@ from lib.ospf import ( redistribute_ospf, ) +pytestmark = [pytest.mark.ospfd, pytest.mark.staticd] + + # Global variables topo = None # Reading the data from JSON File for topology creation diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py b/tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py index f17346d5b1..0e2fef4a22 100644 --- a/tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py +++ b/tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py @@ -66,6 +66,9 @@ from lib.ospf import ( verify_ospf_interface, ) +pytestmark = [pytest.mark.ospfd, pytest.mark.staticd] + + # Global variables topo = None diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_single_area.py b/tests/topotests/ospf_basic_functionality/test_ospf_single_area.py index e94680d974..a595bc0491 100644 --- a/tests/topotests/ospf_basic_functionality/test_ospf_single_area.py +++ b/tests/topotests/ospf_basic_functionality/test_ospf_single_area.py @@ -69,6 +69,7 @@ from lib.ospf import ( verify_ospf_database, ) +pytestmark = [pytest.mark.ospfd, pytest.mark.staticd] # Global variables topo = None diff --git a/tests/topotests/ospf_dual_stack/test_ospf_dual_stack.py b/tests/topotests/ospf_dual_stack/test_ospf_dual_stack.py index 5e7802fa04..b5f535cd06 100644 --- a/tests/topotests/ospf_dual_stack/test_ospf_dual_stack.py +++ b/tests/topotests/ospf_dual_stack/test_ospf_dual_stack.py @@ -42,6 +42,9 @@ from lib.ospf import ( verify_ospf_database, ) +pytestmark = [pytest.mark.ospfd, pytest.mark.staticd] + + # Global variables topo = None diff --git a/tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.py b/tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.py index 76e50beb5c..a22fbf458a 100644 --- a/tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.py +++ b/tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.py @@ -50,6 +50,8 @@ from lib.topogen import Topogen, TopoRouter, get_topogen # Required to instantiate the topology builder class. from mininet.topo import Topo +pytestmark = [pytest.mark.ospfd] + class NetworkTopo(Topo): "OSPF topology builder" diff --git a/tests/topotests/ospf_tilfa_topo1/test_ospf_tilfa_topo1.py b/tests/topotests/ospf_tilfa_topo1/test_ospf_tilfa_topo1.py index 489690471c..b3da6e2a1a 100644 --- a/tests/topotests/ospf_tilfa_topo1/test_ospf_tilfa_topo1.py +++ b/tests/topotests/ospf_tilfa_topo1/test_ospf_tilfa_topo1.py @@ -71,6 +71,8 @@ from lib.topolog import logger # Required to instantiate the topology builder class. from mininet.topo import Topo +pytestmark = [pytest.mark.ospfd] + class TemplateTopo(Topo): "Test topology builder" diff --git a/tests/topotests/ospf_topo2/test_ospf_topo2.py b/tests/topotests/ospf_topo2/test_ospf_topo2.py index 6451f5fb32..8b8d5d6e9f 100644 --- a/tests/topotests/ospf_topo2/test_ospf_topo2.py +++ b/tests/topotests/ospf_topo2/test_ospf_topo2.py @@ -46,6 +46,8 @@ from lib.topolog import logger # Required to instantiate the topology builder class. from mininet.topo import Topo +pytestmark = [pytest.mark.ospfd] + class OSPFTopo(Topo): "Test topology builder" diff --git a/tests/topotests/ospfv3_basic_functionality/ospfv3_asbr_summary_topo1.json b/tests/topotests/ospfv3_basic_functionality/ospfv3_asbr_summary_topo1.json new file mode 100644 index 0000000000..74a0de489f --- /dev/null +++ b/tests/topotests/ospfv3_basic_functionality/ospfv3_asbr_summary_topo1.json @@ -0,0 +1,198 @@ +{ + "address_types": [ + "ipv6" + ], + "ipv6base": "fd00::", + "ipv6mask": 64, + "link_ip_start": { + "ipv6": "fd00::", + "v6mask": 64 + }, + "lo_prefix": { + "ipv6": "2001:db8:f::", + "v6mask": 128 + }, + "routers": { + "r0": { + "links": { + "lo": { + "ipv6": "auto", + "type": "loopback" + }, + "r1": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r2": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r3": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4, + "network": "point-to-point" + } + }, + "r3-link0": { + "ipv6": "auto", + "description": "DummyIntftoR3" + } + }, + "ospf6": { + "router_id": "100.1.1.0", + "neighbors": { + "r1": {}, + "r2": {}, + "r3": {} + } + } + }, + "r1": { + "links": { + "lo": { + "ipv6": "auto", + "type": "loopback" + }, + "r0": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r2": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r3": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r3-link0": { + "ipv6": "auto", + "description": "DummyIntftoR3" + } + }, + "ospf6": { + "router_id": "100.1.1.1", + "neighbors": { + "r0": {}, + "r2": {}, + "r3": {} + } + } + }, + "r2": { + "links": { + "lo": { + "ipv6": "auto", + "type": "loopback" + }, + "r0": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r1": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r3": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + } + }, + "ospf6": { + "router_id": "100.1.1.2", + "neighbors": { + "r1": {}, + "r0": {}, + "r3": {} + } + } + }, + "r3": { + "links": { + "lo": { + "ipv6": "auto", + "type": "loopback" + }, + "r0": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4, + "network": "point-to-point" + } + }, + "r0-link0": { + "ipv6": "auto", + "description": "DummyIntftoR0" + }, + "r1": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r2": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r1-link0": { + "ipv6": "auto", + "description": "DummyIntftoR1", + "ospf6": { + "area": "0.0.0.0" + } + } + }, + "ospf6": { + "router_id": "100.1.1.3", + "neighbors": { + "r0": {}, + "r1": {}, + "r2": {} + } + } + } + } +}
\ No newline at end of file diff --git a/tests/topotests/ospfv3_basic_functionality/ospfv3_ecmp.json b/tests/topotests/ospfv3_basic_functionality/ospfv3_ecmp.json new file mode 100644 index 0000000000..c928093925 --- /dev/null +++ b/tests/topotests/ospfv3_basic_functionality/ospfv3_ecmp.json @@ -0,0 +1,347 @@ +{ + "address_types": [ + "ipv6" + ], + "ipv6base": "fd00::", + "ipv6mask": 64, + "link_ip_start": { + "ipv6": "fd00::", + "v6mask": 64 + }, + "lo_prefix": { + "ipv6": "2001:db8:f::", + "v6mask": 128 + }, + "routers": { + "r0": { + "links": { + "lo": { + "ipv6": "auto", + "type": "loopback" + }, + "r1": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r1-link1": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r1-link2": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r1-link3": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r1-link4": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r1-link5": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r1-link6": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r1-link7": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r2": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r3": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4, + "network": "point-to-point" + } + } + }, + "ospf6": { + "router_id": "100.1.1.0", + "neighbors": { + "r1": {}, + "r1-link1": { + "nbr": "r1" + }, + "r1-link2": { + "nbr": "r1" + }, + "r1-link3": { + "nbr": "r1" + }, + "r1-link4": { + "nbr": "r1" + }, + "r1-link5": { + "nbr": "r1" + }, + "r1-link6": { + "nbr": "r1" + }, + "r1-link7": { + "nbr": "r1" + }, + "r2": {}, + "r3": {} + } + } + }, + "r1": { + "links": { + "lo": { + "ipv6": "auto", + "type": "loopback" + }, + "r0": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r0-link1": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r0-link2": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r0-link3": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r0-link4": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r0-link5": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r0-link6": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r0-link7": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r2": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r3": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r3-link0": { + "ipv6": "auto", + "description": "DummyIntftoR3" + } + }, + "ospf6": { + "router_id": "100.1.1.1", + "neighbors": { + "r0": {}, + "r0-link1": { + "nbr": "r0" + }, + "r0-link2": { + "nbr": "r0" + }, + "r0-link3": { + "nbr": "r0" + }, + "r0-link4": { + "nbr": "r0" + }, + "r0-link5": { + "nbr": "r0" + }, + "r0-link6": { + "nbr": "r0" + }, + "r0-link7": { + "nbr": "r0" + }, + "r2": {}, + "r3": {} + } + } + }, + "r2": { + "links": { + "lo": { + "ipv6": "auto", + "type": "loopback" + }, + "r0": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r1": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r3": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + } + }, + "ospf6": { + "router_id": "100.1.1.2", + "neighbors": { + "r1": {}, + "r0": {}, + "r3": {} + } + } + }, + "r3": { + "links": { + "lo": { + "ipv6": "auto", + "type": "loopback" + }, + "r0": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4, + "network": "point-to-point" + } + }, + "r1": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r2": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r1-link0": { + "ipv6": "auto", + "description": "DummyIntftoR1", + "ospf": { + "area": "0.0.0.0" + }, + "ospf6": { + "area": "0.0.0.0" + } + } + }, + "ospf6": { + "router_id": "100.1.1.3", + "neighbors": { + "r0": {}, + "r1": {}, + "r2": {} + } + } + } + } +}
\ No newline at end of file diff --git a/tests/topotests/ospfv3_basic_functionality/ospfv3_routemaps.json b/tests/topotests/ospfv3_basic_functionality/ospfv3_routemaps.json new file mode 100644 index 0000000000..226f84f320 --- /dev/null +++ b/tests/topotests/ospfv3_basic_functionality/ospfv3_routemaps.json @@ -0,0 +1,137 @@ +{ + "address_types": ["ipv6"], + "ipv6base": "fd00::", + "ipv6mask": 64, + "link_ip_start": {"ipv6": "fd00::", "v6mask": 64}, + "lo_prefix": {"ipv6": "2001:db8:f::", "v6mask": 128}, + "routers": { + "r0": { + "links": { + "r1": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r2": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r3": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + } + }, + "ospf6": { + "router_id": "100.1.1.0", + "neighbors": {"r1": {}, "r2": {}, "r3": {}} + } + }, + "r1": { + "links": { + "r0": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r2": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r3": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + } + }, + "ospf6": { + "router_id": "100.1.1.1", + "neighbors": {"r0": {}, "r2": {}, "r3": {}} + } + }, + "r2": { + "links": { + "r0": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r1": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r3": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + } + }, + "ospf6": { + "router_id": "100.1.1.2", + "neighbors": {"r1": {}, "r0": {}, "r3": {}} + } + }, + "r3": { + "links": { + "r0": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r1": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r2": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + } + }, + "ospf6": { + "router_id": "100.1.1.3", + "neighbors": {"r0": {}, "r1": {}, "r2": {}} + } + } + } +} diff --git a/tests/topotests/ospfv3_basic_functionality/test_ospfv3_asbr_summary_topo1.py b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_asbr_summary_topo1.py new file mode 100644 index 0000000000..6a4b60fbed --- /dev/null +++ b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_asbr_summary_topo1.py @@ -0,0 +1,1928 @@ +#!/usr/bin/python + +# +# Copyright (c) 2021 by VMware, Inc. ("VMware") +# Used Copyright (c) 2018 by Network Device Education Foundation, Inc. +# ("NetDEF") in this file. +# +# 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 VMWARE DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE 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. +# + + +"""OSPF Summarisation Functionality Automation.""" +import os +import sys +import time +import pytest +import json +from copy import deepcopy +from ipaddress import IPv4Address +from lib.topotest import frr_unicode + +# Save the Current Working Directory to find configuration files. +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) +sys.path.append(os.path.join(CWD, "../lib/")) + +# pylint: disable=C0413 +# Import topogen and topotest helpers +from mininet.topo import Topo +from lib.topogen import Topogen, get_topogen +import ipaddress +from time import sleep + +# Import topoJson from lib, to create topology and initial configuration +from lib.common_config import ( + start_topology, + write_test_header, + kill_router_daemons, + write_test_footer, + reset_config_on_routers, + stop_router, + start_router, + verify_rib, + create_static_routes, + step, + start_router_daemons, + create_route_maps, + shutdown_bringup_interface, + create_prefix_lists, + create_route_maps, + create_interfaces_cfg, + topo_daemons, +) +from lib.topolog import logger +from lib.topojson import build_topo_from_json, build_config_from_json +from lib.ospf import ( + verify_ospf6_neighbor, + clear_ospf, + verify_ospf6_rib, + create_router_ospf, + verify_ospf_summary, +) + + +# Global variables +topo = None +# Reading the data from JSON File for topology creation +jsonFile = "{}/ospfv3_asbr_summary_topo1.json".format(CWD) +try: + with open(jsonFile, "r") as topoJson: + topo = json.load(topoJson) +except IOError: + assert False, "Could not read file {}".format(jsonFile) + +NETWORK = { + "ipv4": [ + "11.0.20.1/32", + "11.0.20.2/32", + "11.0.20.3/32", + "11.0.20.4/32", + "11.0.20.5/32", + ], + "ipv6": [ + "2011:0:20::1/128", + "2011:0:20::2/128", + "2011:0:20::3/128", + "2011:0:20::4/128", + "2011:0:20::5/128", + ], +} +NETWORK_11 = { + "ipv4": ["11.0.20.6/32", "11.0.20.7/32"], + "ipv6": ["2011:0:20::6/128", "2011:0:20::7/128"], +} + +NETWORK2 = { + "ipv4": [ + "12.0.20.1/32", + "12.0.20.2/32", + "12.0.20.3/32", + "12.0.20.4/32", + "12.0.20.5/32", + ], + "ipv6": [ + "2012:0:20::1/128", + "2012:0:20::2/128", + "2012:0:20::3/128", + "2012:0:20::4/128", + "2012:0:20::5/128", + ], +} +SUMMARY = { + "ipv4": ["11.0.0.0/8", "12.0.0.0/8", "11.0.0.0/24"], + "ipv6": ["2011::/32", "2012::/32", "2011::/64", "2011::/24"], +} +""" +TOPOOLOGY = + Please view in a fixed-width font such as Courier. + +---+ A0 +---+ + +R1 +------------+R2 | + +-+-+- +--++ + | -- -- | + | -- A0 -- | + A0| ---- | + | ---- | A0 + | -- -- | + | -- -- | + +-+-+- +-+-+ + +R0 +-------------+R3 | + +---+ A0 +---+ + +TESTCASES = +1. OSPF summarisation functionality. +2. OSPF summarisation with advertise and no advertise option +3. OSPF summarisation with route map modification of metric type. +4. OSPF CLI Show verify ospf ASBR summary config and show commands behaviours. +5. OSPF summarisation Chaos. +""" + + +class CreateTopo(Topo): + """ + Test topology builder. + + * `Topo`: Topology object + """ + + def build(self, *_args, **_opts): + """Build function.""" + tgen = get_topogen(self) + + # Building topology from json file + build_topo_from_json(tgen, topo) + + +def setup_module(mod): + """ + Sets up the pytest environment + + * `mod`: module name + """ + global topo + testsuite_run_time = time.asctime(time.localtime(time.time())) + logger.info("Testsuite start time: {}".format(testsuite_run_time)) + logger.info("=" * 40) + + logger.info("Running setup_module to create topology") + + # This function initiates the topology build with Topogen... + tgen = Topogen(CreateTopo, mod.__name__) + # ... and here it calls Mininet initialization functions. + + # get list of daemons needs to be started for this suite. + daemons = topo_daemons(tgen, topo) + + # Starting topology, create tmp files which are loaded to routers + # to start deamons and then start routers + start_topology(tgen, daemons) + + # Creating configuration from JSON + build_config_from_json(tgen, topo) + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + # Api call verify whether OSPF is converged + ospf_covergence = verify_ospf6_neighbor(tgen, topo) + assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format( + ospf_covergence + ) + + logger.info("Running setup_module() done") + + +def teardown_module(mod): + """ + Teardown the pytest environment. + + * `mod`: module name + """ + + logger.info("Running teardown_module to delete topology") + + tgen = get_topogen() + + # Stop toplogy and Remove tmp files + tgen.stop_topology() + + logger.info( + "Testsuite end time: {}".format(time.asctime(time.localtime(time.time()))) + ) + logger.info("=" * 40) + + +def red_static(dut, config=True): + """ + Local 'def' for Redstribute static routes inside ospf. + + Parameters + ---------- + * `dut` : DUT on which configs have to be made. + * `config` : True or False, True by default for configure, set False for + unconfiguration. + """ + global topo + tgen = get_topogen() + if config: + ospf_red = {dut: {"ospf6": {"redistribute": [{"redist_type": "static"}]}}} + else: + ospf_red = { + dut: { + "ospf6": {"redistribute": [{"redist_type": "static", "delete": True}]} + } + } + result = create_router_ospf(tgen, topo, ospf_red) + assert result is True, "Testcase : Failed \n Error: {}".format(result) + + +def red_connected(dut, config=True): + """ + Local 'def' for Redstribute connected routes inside ospf + + Parameters + ---------- + * `dut` : DUT on which configs have to be made. + * `config` : True or False, True by default for configure, set False for + unconfiguration. + """ + global topo + tgen = get_topogen() + if config: + ospf_red = {dut: {"ospf6": {"redistribute": [{"redist_type": "connected"}]}}} + else: + ospf_red = { + dut: { + "ospf6": { + "redistribute": [{"redist_type": "connected", "delete": True}] + } + } + } + result = create_router_ospf(tgen, topo, ospf_red) + assert result is True, "Testcase: Failed \n Error: {}".format(result) + + +# ################################## +# Test cases start here. +# ################################## + +def test_ospfv3_type5_summary_tc42_p0(request): + """OSPF summarisation functionality.""" + tc_name = request.node.name + write_test_header(tc_name) + tgen = get_topogen() + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + global topo + step("Bring up the base config as per the topology") + reset_config_on_routers(tgen) + + protocol = 'ospf' + + step( + "Configure 5 static routes from the same network on R0" + "5 static routes from different networks and redistribute in R0") + input_dict_static_rtes = { + "r0": { + "static_routes": [ + { + "network": NETWORK["ipv6"], + "next_hop": "blackhole" + }, + { + "network": NETWORK2["ipv6"], + "next_hop": "blackhole" + } + ] + } + } + result = create_static_routes(tgen, input_dict_static_rtes) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + dut = 'r0' + red_static(dut) + + step("Verify that routes are learnt on R1.") + dut = 'r1' + + result = verify_ospf6_rib(tgen, dut, input_dict_static_rtes) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + result = verify_rib(tgen, "ipv6", dut, + input_dict_static_rtes, protocol=protocol) + assert result is True, "Testcase {} : Failed" \ + "Error: Routes is missing in RIB".format(tc_name) + + step( + "Configure External Route summary in R0 to summarise 5" + " routes to one route. with aggregate timer as 6 sec") + + ospf_summ_r1 = { + "r0": { + "ospf6": { + "summary-address": [{ + "prefix": SUMMARY["ipv6"][0].split('/')[0], + "mask": "32" + }], + "aggr_timer": 6 + } + } + } + result = create_router_ospf(tgen, topo, ospf_summ_r1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + step( + "Verify that external routes are summarised to configured summary " + "address on R0 after 5 secs of delay timer expiry and only one " + "route is sent to R1.") + input_dict_summary = { + "r0": { + "static_routes": [{"network": SUMMARY["ipv6"][0]}] + } + } + dut = 'r1' + + result = verify_ospf6_rib(tgen, dut, input_dict_summary) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + result = verify_rib(tgen, "ipv6", dut, + input_dict_summary, protocol=protocol) + assert result is True, "Testcase {} : Failed" \ + "Error: Routes is missing in RIB".format(tc_name) + + step("Verify that show ip ospf summary should show the summaries.") + input_dict = { + SUMMARY["ipv6"][0]: { + "Summary address": SUMMARY["ipv6"][0], + "Metric-type": "E2", + "Metric": 20, + "Tag": 0, + "External route count": 5 + } + } + dut = 'r0' + result = verify_ospf_summary(tgen, topo, dut, input_dict, ospf='ospf6') + assert result is True, "Testcase {} : Failed" \ + "Error: Summary missing in OSPF DB".format(tc_name) + + step( + "Verify that originally advertised routes are withdraw from there" + " peer.") + input_dict = { + "r0": { + "static_routes": [ + { + "network": NETWORK["ipv6"], + "next_hop": "blackhole" + } + ] + } + } + dut = 'r1' + result = verify_ospf6_rib(tgen, dut, input_dict, expected=False) + assert result is not True, "Testcase {} : Failed \n Error: "\ + "Routes still present in OSPF RIB {}".format(tc_name, result) + + result = verify_rib(tgen, "ipv6", dut, input_dict, protocol=protocol, + expected=False) + assert result is not True, "Testcase {} : Failed" \ + "Error: Routes still present in RIB".format(tc_name) + + step("Delete the configured summary") + ospf_summ_r1 = { + "r0": { + "ospf6": { + "summary-address": [{ + "prefix": SUMMARY["ipv6"][0].split('/')[0], + "mask": "32", + "del_aggr_timer": True, + "delete": True + }] + } + } + } + result = create_router_ospf(tgen, topo, ospf_summ_r1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + step("Verify that summary lsa is withdrawn from R1 and deleted from R0.") + dut = 'r1' + result = verify_ospf6_rib(tgen, dut, input_dict, expected=False) + assert result is not True, "Testcase {} : Failed \n Error: "\ + "Routes still present in OSPF RIB {}".format(tc_name, result) + + result = verify_rib(tgen, "ipv6", dut, + input_dict_summary, protocol=protocol, expected=False) + assert result is not True, "Testcase {} : Failed" \ + "Error: Summary Route still present in RIB".format(tc_name) + + step("show ip ospf summary should not have any summary address.") + input_dict = { + SUMMARY["ipv6"][0]: { + "Summary address": SUMMARY["ipv6"][0], + "Metric-type": "E2", + "Metric": 20, + "Tag": 0, + "External route count": 5 + } + } + dut = 'r0' + result = verify_ospf_summary(tgen, topo, dut, input_dict, ospf='ospf6', expected=False) + assert result is not True, "Testcase {} : Failed" \ + "Error: Summary still present in DB".format(tc_name) + + dut = 'r1' + step("All 5 routes are advertised after deletion of configured summary.") + + result = verify_ospf6_rib(tgen, dut, input_dict_static_rtes) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + result = verify_rib(tgen, "ipv6", dut, + input_dict_static_rtes, protocol=protocol) + assert result is True, "Testcase {} : Failed" \ + "Error: Routes is missing in RIB".format(tc_name) + + step("configure the summary again and delete static routes .") + ospf_summ_r1 = { + "r0": { + "ospf6": { + "summary-address": [{ + "prefix": SUMMARY["ipv6"][0].split('/')[0], + "mask": "32" + }] + } + } + } + result = create_router_ospf(tgen, topo, ospf_summ_r1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + input_dict = { + SUMMARY["ipv6"][0]: { + "Summary address": SUMMARY["ipv6"][0], + "Metric-type": "E2", + "Metric": 20, + "Tag": 0, + "External route count": 5 + } + } + dut = 'r0' + result = verify_ospf_summary(tgen, topo, dut, input_dict, ospf='ospf6') + assert result is True, "Testcase {} : Failed" \ + "Error: Summary missing in OSPF DB".format(tc_name) + + input_dict = { + "r0": { + "static_routes": [ + { + "network": NETWORK["ipv6"], + "next_hop": "blackhole", + "delete": True + } + ] + } + } + result = create_static_routes(tgen, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + input_dict_summary = { + "r0": { + "static_routes": [{"network": SUMMARY["ipv6"][0]}] + } + } + step("Verify that summary route is withdrawn from R1.") + + dut = 'r1' + result = verify_ospf6_rib(tgen, dut, input_dict_summary, expected=False) + assert result is not True, "Testcase {} : Failed \n Error: "\ + "Routes still present in OSPF RIB {}".format(tc_name, result) + + result = verify_rib(tgen, "ipv6", dut, + input_dict_summary, protocol=protocol, expected=False) + assert result is not True, "Testcase {} : Failed" \ + "Error: Routes still present in RIB".format(tc_name) + + step("Add back static routes.") + input_dict_static_rtes = { + "r0": { + "static_routes": [ + { + "network": NETWORK["ipv6"], + "next_hop": "blackhole" + } + ] + } + } + result = create_static_routes(tgen, input_dict_static_rtes) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + step( + "Verify that external routes are summarised to configured summary" + " address on R0 and only one route is sent to R1.") + dut = 'r1' + + result = verify_ospf6_rib(tgen, dut, input_dict_static_rtes, expected=False) + assert result is not True, "Testcase {} : Failed \n Error: "\ + "Routes still present in OSPF RIB {}".format(tc_name, result) + + result = verify_rib( + tgen, "ipv6", dut, input_dict_static_rtes, + protocol=protocol, expected=False) + assert result is not True, "Testcase {} : Failed" \ + "Error: Routes still present in RIB".format(tc_name) + + input_dict_summary = { + "r0": { + "static_routes": [{"network": SUMMARY["ipv6"][0]}] + } + } + dut = 'r1' + + result = verify_ospf6_rib(tgen, dut, input_dict_summary) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + result = verify_rib(tgen, "ipv6", dut, + input_dict_summary, protocol=protocol) + assert result is True, "Testcase {} : Failed" \ + "Error: Routes is missing in RIB".format(tc_name) + + step("Verify that show ip ospf summary should show configure summaries.") + + input_dict = { + SUMMARY["ipv6"][0]: { + "Summary address": SUMMARY["ipv6"][0], + "Metric-type": "E2", + "Metric": 20, + "Tag": 0, + "External route count": 5 + } + } + dut = 'r0' + result = verify_ospf_summary(tgen, topo, dut, input_dict, ospf='ospf6') + assert result is True, "Testcase {} : Failed" \ + "Error: Summary missing in OSPF DB".format(tc_name) + + step("Configure new static route which is matching configured summary.") + input_dict_static_rtes = { + "r0": { + "static_routes": [ + { + "network": NETWORK_11["ipv6"], + "next_hop": "blackhole" + } + ] + } + } + result = create_static_routes(tgen, input_dict_static_rtes) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + # step("verify that summary lsa is not refreshed.") + # show ip ospf database command is not working, waiting for DEV fix. + + step("Delete one of the static route.") + input_dict_static_rtes = { + "r0": { + "static_routes": [ + { + "network": NETWORK_11["ipv6"], + "next_hop": "blackhole", + "delete": True + } + ] + } + } + result = create_static_routes(tgen, input_dict_static_rtes) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + # step("verify that summary lsa is not refreshed.") + # show ip ospf database command is not working, waiting for DEV fix. + + # step("Verify that deleted static route is removed from ospf LSDB.") + # show ip ospf database command is not working, waiting for DEV fix. + + step( + "Configure redistribute connected and configure ospf external" + " summary address to summarise the connected routes.") + + dut = 'r0' + red_connected(dut) + clear_ospf(tgen, dut, ospf='ospf6') + + ip = topo['routers']['r0']['links']['r3']['ipv6'] + + ip_net = str(ipaddress.ip_interface(u'{}'.format(ip)).network) + ospf_summ_r1 = { + "r0": { + "ospf6": { + "summary-address": [{ + "prefix": ip_net.split('/')[0], + "mask": "8" + }] + } + } + } + result = create_router_ospf(tgen, topo, ospf_summ_r1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + step( + "Verify that external routes are summarised to configured " + "summary address on R0 and only one route is sent to R1.") + + input_dict_summary = { + "r0": { + "static_routes": [{"network": "fd00::/64"}] + } + } + dut = 'r1' + result = verify_ospf6_rib(tgen, dut, input_dict_summary) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + result = verify_rib(tgen, "ipv6", dut, + input_dict_summary, protocol=protocol) + assert result is True, "Testcase {} : Failed" \ + "Error: Routes is missing in RIB".format(tc_name) + + step("Shut one of the interface") + intf = topo['routers']['r0']['links']['r3-link0']['interface'] + shutdown_bringup_interface(tgen, dut, intf, False) + + # step("verify that summary lsa is not refreshed.") + # show ip ospf database command is not working, waiting for DEV fix. + + # step("Verify that deleted connected route is removed from ospf LSDB.") + # show ip ospf database command is not working, waiting for DEV fix. + + step("Un do shut the interface") + shutdown_bringup_interface(tgen, dut, intf, True) + + # step("verify that summary lsa is not refreshed.") + # show ip ospf database command is not working, waiting for DEV fix. + + # step("Verify that deleted connected route is removed from ospf LSDB.") + # show ip ospf database command is not working, waiting for DEV fix. + + step("Delete OSPF process.") + ospf_del = { + "r0": { + "ospf6": { + "delete": True + } + } + } + result = create_router_ospf(tgen, topo, ospf_del) + assert result is True, "Testcase : Failed \n Error: {}".format(result) + + step("Reconfigure ospf process with summary") + reset_config_on_routers(tgen) + + input_dict_static_rtes = { + "r0": { + "static_routes": [ + { + "network": NETWORK["ipv6"], + "next_hop": "blackhole" + }, + { + "network": NETWORK2["ipv6"], + "next_hop": "blackhole" + } + ] + } + } + result = create_static_routes(tgen, input_dict_static_rtes) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + dut = 'r0' + red_static(dut) + red_connected(dut) + ospf_summ_r1 = { + "r0": { + "ospf6": { + "summary-address": [{ + "prefix": SUMMARY["ipv6"][0].split('/')[0], + "mask": "32" + }] + } + } + } + result = create_router_ospf(tgen, topo, ospf_summ_r1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + step( + "Verify that external routes are summarised to configured summary " + "address on R0 and only one route is sent to R1.") + + input_dict = { + SUMMARY["ipv6"][0]: { + "Summary address": SUMMARY["ipv6"][0], + "Metric-type": "E2", + "Metric": 20, + "Tag": 0, + "External route count": 5 + } + } + dut = 'r0' + result = verify_ospf_summary(tgen, topo, dut, input_dict, ospf='ospf6') + assert result is True, "Testcase {} : Failed" \ + "Error: Summary missing in OSPF DB".format(tc_name) + + + input_dict_summary = { + "r0": { + "static_routes": [{"network": SUMMARY["ipv6"][0]}] + } + } + + dut = 'r1' + result = verify_ospf6_rib(tgen, dut, input_dict_summary) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + result = verify_rib(tgen, "ipv6", dut, + input_dict_summary, protocol=protocol) + assert result is True, "Testcase {} : Failed" \ + "Error: Routes is missing in RIB".format(tc_name) + + ospf_summ_r1 = { + "r0": { + "ospf6": { + "summary-address": [{ + "prefix": SUMMARY["ipv6"][0].split('/')[0], + "mask": "32" + }] + } + } + } + result = create_router_ospf(tgen, topo, ospf_summ_r1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + # step("verify that summary lsa is not refreshed.") + # show ip ospf database command is not working, waiting for DEV fix. + + step("Delete the redistribute command in ospf.") + dut = 'r0' + red_connected(dut, config=False) + red_static(dut, config=False) + + step("Verify that summary route is withdrawn from the peer.") + + dut = 'r1' + result = verify_ospf6_rib(tgen, dut, input_dict_summary, expected=False) + assert result is not True, "Testcase {} : Failed \n Error: "\ + "Routes still present in OSPF RIB {}".format(tc_name, result) + + result = verify_rib(tgen, "ipv6", dut, + input_dict_summary, protocol=protocol, expected=False) + assert result is not True, "Testcase {} : Failed" \ + "Error: Routes still present in RIB".format(tc_name) + + ospf_summ_r1 = { + "r0": { + "ospf6": { + "summary-address": [{ + "prefix": SUMMARY["ipv6"][0].split('/')[0], + "mask": "32", + "metric": "1234" + }] + } + } + } + result = create_router_ospf(tgen, topo, ospf_summ_r1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + write_test_footer(tc_name) + + +def test_ospfv3_type5_summary_tc46_p0(request): + """OSPF summarisation with advertise and no advertise option""" + tc_name = request.node.name + write_test_header(tc_name) + tgen = get_topogen() + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + global topo + step("Bring up the base config as per the topology") + step("Configure OSPF on all the routers of the topology.") + reset_config_on_routers(tgen) + + protocol = 'ospf' + + step( + "Configure 5 static routes from the same network on R0" + "5 static routes from different networks and redistribute in R0") + input_dict_static_rtes = { + "r0": { + "static_routes": [ + { + "network": NETWORK["ipv6"], + "next_hop": "blackhole" + }, + { + "network": NETWORK2["ipv6"], + "next_hop": "blackhole" + } + ] + } + } + result = create_static_routes(tgen, input_dict_static_rtes) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + dut = 'r0' + red_static(dut) + + step("Verify that routes are learnt on R1.") + dut = 'r1' + + result = verify_ospf6_rib(tgen, dut, input_dict_static_rtes) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + result = verify_rib(tgen, "ipv6", dut, + input_dict_static_rtes, protocol=protocol) + assert result is True, "Testcase {} : Failed" \ + "Error: Routes is missing in RIB".format(tc_name) + + step( + "Configure External Route summary in R0 to summarise 5" + " routes to one route with no advertise option.") + ospf_summ_r1 = { + "r0": { + "ospf6": { + "summary-address": [{ + "prefix": SUMMARY["ipv6"][0].split('/')[0], + "mask": "32", + "advertise": False + }] + } + } + } + result = create_router_ospf(tgen, topo, ospf_summ_r1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + step( + "Verify that external routes are summarised to configured summary" + " address on R0 and summary route is not advertised to neighbor as" + " no advertise is configured..") + + input_dict_summary = { + "r0": { + "static_routes": [{"network": SUMMARY["ipv6"][0]}] + } + } + dut = 'r1' + + result = verify_ospf6_rib(tgen, dut, input_dict_summary, expected=False) + assert result is not True, "Testcase {} : Failed \n Error: "\ + "Routes still present in OSPF RIB {}".format(tc_name, result) + + result = verify_rib(tgen, "ipv6", dut, input_dict_summary, + protocol=protocol, expected=False) + assert result is not True, "Testcase {} : Failed" \ + "Error: Routes still present in RIB".format(tc_name) + + step( + "Verify that show ip ospf summary should show the " + "configured summaries.") + input_dict = { + SUMMARY["ipv6"][0]: { + "Summary address": SUMMARY["ipv6"][0], + "External route count": 5 + } + } + dut = 'r0' + result = verify_ospf_summary(tgen, topo, dut, input_dict, ospf='ospf6') + assert result is True, "Testcase {} : Failed" \ + "Error: Summary missing in OSPF DB".format(tc_name) + + step("Delete the configured summary") + ospf_summ_r1 = { + "r0": { + "ospf6": { + "summary-address": [{ + "prefix": SUMMARY["ipv6"][0].split('/')[0], + "mask": "32", + "delete": True + }] + } + } + } + result = create_router_ospf(tgen, topo, ospf_summ_r1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + step("Summary has 5 sec delay timer, sleep 5 secs...") + sleep(5) + + step("Verify that summary lsa is withdrawn from R1 and deleted from R0.") + dut = 'r1' + result = verify_ospf6_rib(tgen, dut, input_dict, expected=False) + assert result is not True, "Testcase {} : Failed \n Error: "\ + "Routes still present in OSPF RIB {}".format(tc_name, result) + + result = verify_rib(tgen, "ipv6", dut, + input_dict_summary, protocol=protocol, expected=False) + assert result is not True, "Testcase {} : Failed" \ + "Error: Summary Route still present in RIB".format(tc_name) + + step("show ip ospf summary should not have any summary address.") + input_dict = { + SUMMARY["ipv6"][0]: { + "Summary address": SUMMARY["ipv6"][0], + "Metric-type": "E2", + "Metric": 20, + "Tag": 1234, + "External route count": 5 + } + } + dut = 'r0' + result = verify_ospf_summary(tgen, topo, dut, input_dict, ospf='ospf6', expected=False) + assert result is not True, "Testcase {} : Failed" \ + "Error: Summary still present in DB".format(tc_name) + + step("Reconfigure summary with no advertise.") + ospf_summ_r1 = { + "r0": { + "ospf6": { + "summary-address": [{ + "prefix": SUMMARY["ipv6"][0].split('/')[0], + "mask": "32", + "advertise": False + }] + } + } + } + result = create_router_ospf(tgen, topo, ospf_summ_r1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + step( + "Verify that external routes are summarised to configured summary" + " address on R0 and summary route is not advertised to neighbor as" + " no advertise is configured..") + + input_dict_summary = { + "r0": { + "static_routes": [{"network": SUMMARY["ipv6"][0]}] + } + } + dut = 'r1' + + result = verify_ospf6_rib(tgen, dut, input_dict_summary, expected=False) + assert result is not True, "Testcase {} : Failed \n Error: "\ + "Routes still present in OSPF RIB {}".format(tc_name, result) + + result = verify_rib(tgen, "ipv6", dut, input_dict_summary, + protocol=protocol, expected=False) + assert result is not True, "Testcase {} : Failed" \ + "Error: Routes still present in RIB".format(tc_name) + + step( + "Verify that show ip ospf summary should show the " + "configured summaries.") + input_dict = { + SUMMARY["ipv6"][0]: { + "Summary address": SUMMARY["ipv6"][0], + "External route count": 5 + } + } + dut = 'r0' + result = verify_ospf_summary(tgen, topo, dut, input_dict, ospf='ospf6') + assert result is True, "Testcase {} : Failed" \ + "Error: Summary missing in OSPF DB".format(tc_name) + + step( + "Change summary address from no advertise to advertise " + "(summary-address 10.0.0.0 255.255.0.0)") + + ospf_summ_r1 = { + "r0": { + "ospf6": { + "summary-address": [{ + "prefix": SUMMARY["ipv6"][0].split('/')[0], + "mask": "32", + "advertise": False + }] + } + } + } + result = create_router_ospf(tgen, topo, ospf_summ_r1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + ospf_summ_r1 = { + "r0": { + "ospf6": { + "summary-address": [{ + "prefix": SUMMARY["ipv6"][0].split('/')[0], + "mask": "32" + }] + } + } + } + result = create_router_ospf(tgen, topo, ospf_summ_r1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + step( + "Verify that external routes are summarised to configured summary " + "address on R0 after 5 secs of delay timer expiry and only one " + "route is sent to R1.") + input_dict_summary = { + "r0": { + "static_routes": [{"network": SUMMARY["ipv6"][0]}] + } + } + dut = 'r1' + + result = verify_ospf6_rib(tgen, dut, input_dict_summary) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + result = verify_rib(tgen, "ipv6", dut, + input_dict_summary, protocol=protocol) + assert result is True, "Testcase {} : Failed" \ + "Error: Routes is missing in RIB".format(tc_name) + + step("Verify that show ip ospf summary should show the summaries.") + input_dict = { + SUMMARY["ipv6"][0]: { + "Summary address": SUMMARY["ipv6"][0], + "Metric-type": "E2", + "Metric": 20, + "Tag": 0, + "External route count": 5 + } + } + dut = 'r0' + result = verify_ospf_summary(tgen, topo, dut, input_dict, ospf='ospf6') + assert result is True, "Testcase {} : Failed" \ + "Error: Summary missing in OSPF DB".format(tc_name) + + step( + "Verify that originally advertised routes are withdraw from there" + " peer.") + input_dict = { + "r0": { + "static_routes": [ + { + "network": NETWORK["ipv6"], + "next_hop": "blackhole" + } + ] + } + } + dut = 'r1' + result = verify_ospf6_rib(tgen, dut, input_dict, expected=False) + assert result is not True, "Testcase {} : Failed \n Error: "\ + "Routes still present in OSPF RIB {}".format(tc_name, result) + + result = verify_rib(tgen, "ipv6", dut, input_dict, protocol=protocol, + expected=False) + assert result is not True, "Testcase {} : Failed" \ + "Error: Routes is present in RIB".format(tc_name) + + write_test_footer(tc_name) + + +def test_ospfv3_type5_summary_tc48_p0(request): + """OSPF summarisation with route map modification of metric type.""" + tc_name = request.node.name + write_test_header(tc_name) + tgen = get_topogen() + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + global topo + step("Bring up the base config as per the topology") + reset_config_on_routers(tgen) + + protocol = 'ospf' + + step( + "Configure 5 static routes from the same network on R0" + "5 static routes from different networks and redistribute in R0") + input_dict_static_rtes = { + "r0": { + "static_routes": [ + { + "network": NETWORK["ipv6"], + "next_hop": "blackhole" + }, + { + "network": NETWORK2["ipv6"], + "next_hop": "blackhole" + } + ] + } + } + result = create_static_routes(tgen, input_dict_static_rtes) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + dut = 'r0' + red_static(dut) + + step("Verify that routes are learnt on R1.") + dut = 'r1' + + result = verify_ospf6_rib(tgen, dut, input_dict_static_rtes) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + result = verify_rib(tgen, "ipv6", dut, + input_dict_static_rtes, protocol=protocol) + assert result is True, "Testcase {} : Failed" \ + "Error: Routes is missing in RIB".format(tc_name) + + step( + "Configure External Route summary in R0 to summarise 5" + " routes to one route.") + + ospf_summ_r1 = { + "r0": { + "ospf6": { + "summary-address": [{ + "prefix": SUMMARY["ipv6"][0].split('/')[0], + "mask": "32" + }] + } + } + } + result = create_router_ospf(tgen, topo, ospf_summ_r1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + step( + "Verify that external routes are summarised to configured summary " + "address on R0 after 5 secs of delay timer expiry and only one " + "route is sent to R1.") + input_dict_summary = { + "r0": { + "static_routes": [{"network": SUMMARY["ipv6"][0]}] + } + } + dut = 'r1' + + result = verify_ospf6_rib(tgen, dut, input_dict_summary) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + result = verify_rib(tgen, "ipv6", dut, + input_dict_summary, protocol=protocol) + assert result is True, "Testcase {} : Failed" \ + "Error: Routes is missing in RIB".format(tc_name) + + step("Verify that show ip ospf summary should show the summaries.") + input_dict = { + SUMMARY["ipv6"][0]: { + "Summary address": SUMMARY["ipv6"][0], + "Metric-type": "E2", + "Metric": 20, + "Tag": 0, + "External route count": 5 + } + } + dut = 'r0' + result = verify_ospf_summary(tgen, topo, dut, input_dict, ospf='ospf6') + assert result is True, "Testcase {} : Failed" \ + "Error: Summary missing in OSPF DB".format(tc_name) + + step( + "Verify that originally advertised routes are withdraw from there" + " peer.") + input_dict = { + "r0": { + "static_routes": [ + { + "network": NETWORK["ipv6"], + "next_hop": "blackhole" + } + ] + } + } + dut = 'r1' + result = verify_ospf6_rib(tgen, dut, input_dict, expected=False) + assert result is not True, "Testcase {} : Failed \n Error: "\ + "Routes still present in OSPF RIB {}".format(tc_name, result) + + result = verify_rib(tgen, "ipv6", dut, input_dict, protocol=protocol, + expected=False) + assert result is not True, "Testcase {} : Failed" \ + "Error: Routes still present in RIB".format(tc_name) + + step( + "Configure route map and & rule to permit configured summary address," + " redistribute static & connected routes with the route map.") + step("Configure prefixlist to permit the static routes, add to route map.") + # Create ip prefix list + pfx_list = { + "r0": { + "prefix_lists": { + "ipv6": { + "pf_list_1_ipv6": [ + { + "seqid": 10, + "network": "any", + "action": "permit" + } + ] + } + } + } + } + result = create_prefix_lists(tgen, pfx_list) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + + routemaps = { + "r0": { + "route_maps": { + "rmap_ipv6": [{ + "action": "permit", + "seq_id": '1', + "match": { + "ipv6": { + "prefix_lists": + "pf_list_1_ipv6" + } + } + }] + } + } + } + result = create_route_maps(tgen, routemaps) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + ospf_red_r1 = { + "r0": { + "ospf6": { + "redistribute": [{ + "redist_type": "static", + "route_map": "rmap_ipv6" + }] + } + } + } + result = create_router_ospf(tgen, topo, ospf_red_r1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + step( + "Verify that external routes are summarised to configured" + "summary address on R0 and only one route is sent to R1. Verify that " + "show ip ospf summary should show the configure summaries.") + + input_dict_summary = { + "r0": { + "static_routes": [{"network": SUMMARY["ipv6"][0]}] + } + } + dut = 'r1' + + result = verify_ospf6_rib(tgen, dut, input_dict_summary) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + result = verify_rib(tgen, "ipv6", dut, + input_dict_summary, protocol=protocol) + assert result is True, "Testcase {} : Failed" \ + "Error: Routes is missing in RIB".format(tc_name) + + input_dict = { + SUMMARY["ipv6"][0]: { + "Summary address": SUMMARY["ipv6"][0], + "Metric-type": "E2", + "Metric": 20, + "Tag": 0, + "External route count": 5 + } + } + dut = 'r0' + result = verify_ospf_summary(tgen, topo, dut, input_dict, ospf='ospf6') + assert result is True, "Testcase {} : Failed" \ + "Error: Summary missing in OSPF DB".format(tc_name) + + step("Configure metric type as 1 in route map.") + + + routemaps = { + "r0": { + "route_maps": { + "rmap_ipv6": [{ + "seq_id": '1', + "action": "permit", + "set":{ + "metric-type": "type-1" + } + }] + } + } + } + result = create_route_maps(tgen, routemaps) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + step( + "Verify that external routes(static / connected) are summarised" + " to configured summary address with metric type 2.") + input_dict = { + SUMMARY["ipv6"][0]: { + "Summary address": SUMMARY["ipv6"][0], + "Metric-type": "E2", + "Metric": 20, + "Tag": 0, + "External route count": 5 + } + } + dut = 'r0' + result = verify_ospf_summary(tgen, topo, dut, input_dict, ospf='ospf6') + assert result is True, "Testcase {} : Failed" \ + "Error: Summary missing in OSPF DB".format(tc_name) + + step("Un configure metric type from route map.") + + routemaps = { + "r0": { + "route_maps": { + "rmap_ipv6": [{ + "action": "permit", + "seq_id": '1', + "set":{ + "metric-type": "type-1", + "delete": True + } + }] + } + } + } + result = create_route_maps(tgen, routemaps) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + step( + "Verify that external routes(static / connected) are summarised" + " to configured summary address with metric type 2.") + input_dict = { + SUMMARY["ipv6"][0]: { + "Summary address": SUMMARY["ipv6"][0], + "Metric-type": "E2", + "Metric": 20, + "Tag": 0, + "External route count": 5 + } + } + dut = 'r0' + result = verify_ospf_summary(tgen, topo, dut, input_dict, ospf='ospf6') + assert result is True, "Testcase {} : Failed" \ + "Error: Summary missing in OSPF DB".format(tc_name) + + step("Change rule from permit to deny in prefix list.") + pfx_list = { + "r0": { + "prefix_lists": { + "ipv6": { + "pf_list_1_ipv6": [ + { + "seqid": 10, + "network": "any", + "action": "deny" + } + ] + } + } + } + } + result = create_prefix_lists(tgen, pfx_list) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + step( + "Verify that previously originated summary lsa " + "is withdrawn from the neighbor.") + input_dict_summary = { + "r0": { + "static_routes": [{"network": SUMMARY["ipv6"][0]}] + } + } + dut = 'r1' + + step("summary route has delay of 5 secs, wait for 5 secs") + + sleep(5) + + result = verify_ospf6_rib(tgen, dut, input_dict_summary, expected=False) + assert result is not True, "Testcase {} : Failed \n Error: "\ + "Routes still present in OSPF RIB {}".format(tc_name, result) + + result = verify_rib(tgen, "ipv6", dut, + input_dict_summary, protocol=protocol, expected=False) + assert result is not True, "Testcase {} : Failed" \ + "Error: Routes still present in RIB".format(tc_name) + + write_test_footer(tc_name) + + +def test_ospfv3_type5_summary_tc51_p2(request): + """OSPF CLI Show. + + verify ospf ASBR summary config and show commands behaviours. + """ + tc_name = request.node.name + write_test_header(tc_name) + tgen = get_topogen() + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + global topo + step("Bring up the base config as per the topology") + reset_config_on_routers(tgen) + + step("Configure all the supported OSPF ASBR summary commands on DUT.") + ospf_summ_r1 = { + "r0": { + "ospf6": { + "summary-address": [{ + "prefix": SUMMARY["ipv6"][0].split('/')[0], + "mask": "32", + "tag": 4294967295 + }, + { + "prefix": SUMMARY["ipv6"][0].split('/')[0], + "mask": "16", + "advertise": True + }, + { + "prefix": SUMMARY["ipv6"][0].split('/')[0], + "mask": "24", + "advertise": False + }, + { + "prefix": SUMMARY["ipv6"][0].split('/')[0], + "mask": "24", + "advertise": False + }, + ] + } + } + } + result = create_router_ospf(tgen, topo, ospf_summ_r1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + + step("Configure and re configure all the commands 10 times in a loop.") + + for itrate in range(0,10): + ospf_summ_r1 = { + "r0": { + "ospf6": { + "summary-address": [{ + "prefix": SUMMARY["ipv6"][0].split('/')[0], + "mask": "8", + "tag": 4294967295 + }, + { + "prefix": SUMMARY["ipv6"][0].split('/')[0], + "mask": "16", + "advertise": True + }, + { + "prefix": SUMMARY["ipv6"][0].split('/')[0], + "mask": "24", + "advertise": False + }, + { + "prefix": SUMMARY["ipv6"][0].split('/')[0], + "mask": "24", + "advertise": False + }, + ] + } + } + } + result = create_router_ospf(tgen, topo, ospf_summ_r1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + ospf_summ_r1 = { + "r0": { + "ospf6": { + "summary-address": [{ + "prefix": SUMMARY["ipv6"][0].split('/')[0], + "mask": "8", + "tag": 4294967295, + "delete": True + }, + { + "prefix": SUMMARY["ipv6"][0].split('/')[0], + "mask": "16", + "advertise": True, + "delete": True + }, + { + "prefix": SUMMARY["ipv6"][0].split('/')[0], + "mask": "24", + "advertise": False, + "delete": True + }, + { + "prefix": SUMMARY["ipv6"][0].split('/')[0], + "mask": "24", + "advertise": False, + "delete": True + }, + ] + } + } + } + result = create_router_ospf(tgen, topo, ospf_summ_r1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + step("Verify the show commands") + + input_dict = { + SUMMARY["ipv6"][3]: { + "Summary address": SUMMARY["ipv6"][3], + "Metric-type": "E2", + "Metric": 20, + "Tag": 0, + "External route count": 0 + } + } + dut = 'r0' + result = verify_ospf_summary(tgen, topo, dut, input_dict, ospf='ospf6') + assert result is True, "Testcase {} : Failed" \ + "Error: Summary missing in OSPF DB".format(tc_name) + + write_test_footer(tc_name) + + +def test_ospfv3_type5_summary_tc49_p2(request): + """OSPF summarisation Chaos.""" + tc_name = request.node.name + write_test_header(tc_name) + tgen = get_topogen() + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + global topo + step("Bring up the base config as per the topology") + reset_config_on_routers(tgen) + + protocol = 'ospf' + + step( + "Configure 5 static routes from the same network on R0" + "5 static routes from different networks and redistribute in R0") + input_dict_static_rtes = { + "r0": { + "static_routes": [ + { + "network": NETWORK["ipv6"], + "next_hop": "blackhole" + }, + { + "network": NETWORK2["ipv6"], + "next_hop": "blackhole" + } + ] + } + } + result = create_static_routes(tgen, input_dict_static_rtes) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + dut = 'r0' + red_static(dut) + + step("Verify that routes are learnt on R1.") + dut = 'r1' + + result = verify_ospf6_rib(tgen, dut, input_dict_static_rtes) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + result = verify_rib(tgen, "ipv6", dut, + input_dict_static_rtes, protocol=protocol) + assert result is True, "Testcase {} : Failed" \ + "Error: Routes is missing in RIB".format(tc_name) + + step( + "Configure External Route summary in R0 to summarise 5" + " routes to one route.") + + ospf_summ_r1 = { + "r0": { + "ospf6": { + "summary-address": [{ + "prefix": SUMMARY["ipv6"][0].split('/')[0], + "mask": "32" + }] + } + } + } + result = create_router_ospf(tgen, topo, ospf_summ_r1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + step( + "Verify that external routes are summarised to configured summary " + "address on R0 after 5 secs of delay timer expiry and only one " + "route is sent to R1.") + input_dict_summary = { + "r0": { + "static_routes": [{"network": SUMMARY["ipv6"][0]}] + } + } + dut = 'r1' + + result = verify_ospf6_rib(tgen, dut, input_dict_summary) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + result = verify_rib(tgen, "ipv6", dut, + input_dict_summary, protocol=protocol) + assert result is True, "Testcase {} : Failed" \ + "Error: Routes is missing in RIB".format(tc_name) + + step("Verify that show ip ospf summary should show the summaries.") + input_dict = { + SUMMARY["ipv6"][0]: { + "Summary address": SUMMARY["ipv6"][0], + "Metric-type": "E2", + "Metric": 20, + "Tag": 0, + "External route count": 5 + } + } + dut = 'r0' + result = verify_ospf_summary(tgen, topo, dut, input_dict, ospf='ospf6') + assert result is True, "Testcase {} : Failed" \ + "Error: Summary missing in OSPF DB".format(tc_name) + + step( + "Verify that originally advertised routes are withdraw from there" + " peer.") + input_dict = { + "r0": { + "static_routes": [ + { + "network": NETWORK["ipv6"], + "next_hop": "blackhole" + } + ] + } + } + dut = 'r1' + result = verify_ospf6_rib(tgen, dut, input_dict, expected=False) + assert result is not True, "Testcase {} : Failed \n Error: "\ + "Routes still present in OSPF RIB {}".format(tc_name, result) + + result = verify_rib(tgen, "ipv6", dut, input_dict, protocol=protocol, + expected=False) + assert result is not True, "Testcase {} : Failed" \ + "Error: Routes still present in RIB".format(tc_name) + + step('Reload the FRR router') + # stop/start -> restart FRR router and verify + stop_router(tgen, 'r0') + start_router(tgen, 'r0') + + step( + "Verify that external routes are summarised to configured summary " + "address on R0 after 5 secs of delay timer expiry and only one " + "route is sent to R1.") + input_dict_summary = { + "r0": { + "static_routes": [{"network": SUMMARY["ipv6"][0]}] + } + } + dut = 'r1' + + result = verify_ospf6_rib(tgen, dut, input_dict_summary) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + result = verify_rib(tgen, "ipv6", dut, + input_dict_summary, protocol=protocol) + assert result is True, "Testcase {} : Failed" \ + "Error: Routes is missing in RIB".format(tc_name) + + step("Verify that show ip ospf summary should show the summaries.") + input_dict = { + SUMMARY["ipv6"][0]: { + "Summary address": SUMMARY["ipv6"][0], + "Metric-type": "E2", + "Metric": 20, + "Tag": 0, + "External route count": 5 + } + } + dut = 'r0' + result = verify_ospf_summary(tgen, topo, dut, input_dict, ospf='ospf6') + assert result is True, "Testcase {} : Failed" \ + "Error: Summary missing in OSPF DB".format(tc_name) + + step( + "Verify that originally advertised routes are withdraw from there" + " peer.") + input_dict = { + "r0": { + "static_routes": [ + { + "network": NETWORK["ipv6"], + "next_hop": "blackhole" + } + ] + } + } + dut = 'r1' + result = verify_ospf6_rib(tgen, dut, input_dict, expected=False) + assert result is not True, "Testcase {} : Failed \n Error: "\ + "Routes still present in OSPF RIB {}".format(tc_name, result) + + result = verify_rib(tgen, "ipv6", dut, input_dict, protocol=protocol, + expected=False) + assert result is not True, "Testcase {} : Failed" \ + "Error: Routes still present in RIB".format(tc_name) + + step("Kill OSPF6d daemon on R0.") + kill_router_daemons(tgen, "r0", ["ospf6d"]) + + step("Bring up OSPF6d daemon on R0.") + start_router_daemons(tgen, "r0", ["ospf6d"]) + + step("Verify OSPF neighbors are up after bringing back ospf6d in R0") + # Api call verify whether OSPF is converged + ospf_covergence = verify_ospf6_neighbor(tgen, topo) + assert ospf_covergence is True, ("setup_module :Failed \n Error:" + " {}".format(ospf_covergence)) + + step( + "Verify that external routes are summarised to configured summary " + "address on R0 after 5 secs of delay timer expiry and only one " + "route is sent to R1.") + input_dict_summary = { + "r0": { + "static_routes": [{"network": SUMMARY["ipv6"][0]}] + } + } + dut = 'r1' + + result = verify_ospf6_rib(tgen, dut, input_dict_summary) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + result = verify_rib(tgen, "ipv6", dut, + input_dict_summary, protocol=protocol) + assert result is True, "Testcase {} : Failed" \ + "Error: Routes is missing in RIB".format(tc_name) + + step("Verify that show ip ospf summary should show the summaries.") + input_dict = { + SUMMARY["ipv6"][0]: { + "Summary address": SUMMARY["ipv6"][0], + "Metric-type": "E2", + "Metric": 20, + "Tag": 0, + "External route count": 5 + } + } + dut = 'r0' + result = verify_ospf_summary(tgen, topo, dut, input_dict, ospf='ospf6') + assert result is True, "Testcase {} : Failed" \ + "Error: Summary missing in OSPF DB".format(tc_name) + + step( + "Verify that originally advertised routes are withdraw from there" + " peer.") + input_dict = { + "r0": { + "static_routes": [ + { + "network": NETWORK["ipv6"], + "next_hop": "blackhole" + } + ] + } + } + dut = 'r1' + result = verify_ospf6_rib(tgen, dut, input_dict, expected=False) + assert result is not True, "Testcase {} : Failed \n Error: "\ + "Routes still present in OSPF RIB {}".format(tc_name, result) + + result = verify_rib(tgen, "ipv6", dut, input_dict, protocol=protocol, + expected=False) + assert result is not True, "Testcase {} : Failed" \ + "Error: Routes still present in RIB".format(tc_name) + + step("restart zebrad") + kill_router_daemons(tgen, "r0", ["zebra"]) + + step("Bring up zebra daemon on R0.") + start_router_daemons(tgen, "r0", ["zebra"]) + + step( + "Verify that external routes are summarised to configured summary " + "address on R0 after 5 secs of delay timer expiry and only one " + "route is sent to R1.") + input_dict_summary = { + "r0": { + "static_routes": [{"network": SUMMARY["ipv6"][0]}] + } + } + dut = 'r1' + + result = verify_ospf6_rib(tgen, dut, input_dict_summary) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result) + + result = verify_rib(tgen, "ipv6", dut, + input_dict_summary, protocol=protocol) + assert result is True, "Testcase {} : Failed" \ + "Error: Routes is missing in RIB".format(tc_name) + + step("Verify that show ip ospf summary should show the summaries.") + input_dict = { + SUMMARY["ipv6"][0]: { + "Summary address": SUMMARY["ipv6"][0], + "Metric-type": "E2", + "Metric": 20, + "Tag": 0, + "External route count": 5 + } + } + dut = 'r0' + result = verify_ospf_summary(tgen, topo, dut, input_dict, ospf='ospf6') + assert result is True, "Testcase {} : Failed" \ + "Error: Summary missing in OSPF DB".format(tc_name) + + step( + "Verify that originally advertised routes are withdraw from there" + " peer.") + input_dict = { + "r0": { + "static_routes": [ + { + "network": NETWORK["ipv6"], + "next_hop": "blackhole" + } + ] + } + } + dut = 'r1' + result = verify_ospf6_rib(tgen, dut, input_dict, expected=False) + assert result is not True, "Testcase {} : Failed \n Error: "\ + "Routes still present in OSPF RIB {}".format(tc_name, result) + + result = verify_rib(tgen, "ipv6", dut, input_dict, protocol=protocol, + expected=False) + assert result is not True, "Testcase {} : Failed" \ + "Error: Routes still present in RIB".format(tc_name) + + write_test_footer(tc_name) + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tests/topotests/ospfv3_basic_functionality/test_ospfv3_ecmp.py b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_ecmp.py new file mode 100644 index 0000000000..50c5144b3f --- /dev/null +++ b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_ecmp.py @@ -0,0 +1,523 @@ +#!/usr/bin/python + +# +# Copyright (c) 2021 by VMware, Inc. ("VMware") +# Used Copyright (c) 2018 by Network Device Education Foundation, Inc. +# ("NetDEF") in this file. +# +# 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 VMWARE DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE 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. +# + + +"""OSPF Basic Functionality Automation.""" +import os +import sys +import time +import pytest +import json +from copy import deepcopy +from ipaddress import IPv4Address +from lib.topotest import frr_unicode + +# Save the Current Working Directory to find configuration files. +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) +sys.path.append(os.path.join(CWD, "../lib/")) + +# pylint: disable=C0413 +# Import topogen and topotest helpers +from mininet.topo import Topo +from lib.topogen import Topogen, get_topogen +import ipaddress + +# Import topoJson from lib, to create topology and initial configuration +from lib.common_config import ( + start_topology, + write_test_header, + write_test_footer, + reset_config_on_routers, + verify_rib, + create_static_routes, + step, + create_route_maps, + shutdown_bringup_interface, + create_interfaces_cfg, + topo_daemons, + get_frr_ipv6_linklocal, +) +from lib.topolog import logger +from lib.topojson import build_topo_from_json, build_config_from_json + +from lib.ospf import ( + verify_ospf6_neighbor, + config_ospf_interface, + clear_ospf, + verify_ospf6_rib, + create_router_ospf, + verify_ospf6_interface, + verify_ospf6_database, + config_ospf6_interface, +) + +from ipaddress import IPv6Address + +pytestmark = [pytest.mark.ospfd, pytest.mark.staticd] + + +# Global variables +topo = None + +# Reading the data from JSON File for topology creation +jsonFile = "{}/ospfv3_ecmp.json".format(CWD) +try: + with open(jsonFile, "r") as topoJson: + topo = json.load(topoJson) +except IOError: + assert False, "Could not read file {}".format(jsonFile) + +NETWORK = { + "ipv4": [ + "11.0.20.1/32", + "11.0.20.2/32", + "11.0.20.3/32", + "11.0.20.4/32", + "11.0.20.5/32", + ], + "ipv6": ["2::1/128", "2::2/128", "2::3/128", "2::4/128", "2::5/128"], +} +""" +TOPOLOGY : + Please view in a fixed-width font such as Courier. + +---+ A1 +---+ + +R1 +------------+R2 | + +-+-+- +--++ + | -- -- | + | -- A0 -- | + A0| ---- | + | ---- | A2 + | -- -- | + | -- -- | + +-+-+- +-+-+ + +R0 +-------------+R3 | + +---+ A3 +---+ + +TESTCASES : +1. Verify OSPF ECMP with max path configured as 8 (ECMPconfigured at FRR level) +2. Verify OSPF ECMP with max path configured as 2 (Edge having 2 uplink ports) + """ + + +class CreateTopo(Topo): + """ + Test topology builder. + + * `Topo`: Topology object + """ + + def build(self, *_args, **_opts): + """Build function.""" + tgen = get_topogen(self) + + # Building topology from json file + build_topo_from_json(tgen, topo) + + +def setup_module(mod): + """ + Sets up the pytest environment + + * `mod`: module name + """ + global topo + testsuite_run_time = time.asctime(time.localtime(time.time())) + logger.info("Testsuite start time: {}".format(testsuite_run_time)) + logger.info("=" * 40) + + logger.info("Running setup_module to create topology") + + # This function initiates the topology build with Topogen... + tgen = Topogen(CreateTopo, mod.__name__) + # ... and here it calls Mininet initialization functions. + + # get list of daemons needs to be started for this suite. + daemons = topo_daemons(tgen, topo) + + # Starting topology, create tmp files which are loaded to routers + # to start deamons and then start routers + start_topology(tgen, daemons) + + # Creating configuration from JSON + build_config_from_json(tgen, topo) + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + ospf_covergence = verify_ospf6_neighbor(tgen, topo) + assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format( + ospf_covergence + ) + + logger.info("Running setup_module() done") + + +def teardown_module(mod): + """ + Teardown the pytest environment. + + * `mod`: module name + """ + + logger.info("Running teardown_module to delete topology") + + tgen = get_topogen() + + # Stop toplogy and Remove tmp files + tgen.stop_topology() + + logger.info( + "Testsuite end time: {}".format(time.asctime(time.localtime(time.time()))) + ) + logger.info("=" * 40) + + +def red_static(dut, config=True): + """Local def for Redstribute static routes inside ospf.""" + global topo + tgen = get_topogen() + if config: + ospf_red = {dut: {"ospf6": {"redistribute": [{"redist_type": "static"}]}}} + else: + ospf_red = { + dut: { + "ospf6": {"redistribute": [{"redist_type": "static", "delete": True}]} + } + } + result = create_router_ospf(tgen, topo, ospf_red) + assert result is True, "Testcase : Failed \n Error: {}".format(result) + + +def red_connected(dut, config=True): + """Local def for Redstribute connected routes inside ospf.""" + global topo + tgen = get_topogen() + if config: + ospf_red = {dut: {"ospf6": {"redistribute": [{"redist_type": "connected"}]}}} + else: + ospf_red = { + dut: { + "ospf6": { + "redistribute": [{"redist_type": "connected", "del_action": True}] + } + } + } + result = create_router_ospf(tgen, topo, ospf_red) + assert result is True, "Testcase: Failed \n Error: {}".format(result) + + +def get_llip(onrouter, intf): + """ + API to get the link local ipv6 address of a perticular interface + + Parameters + ---------- + * `fromnode`: Source node + * `tonode` : interface for which link local ip needs to be returned. + + Usage + ----- + result = get_llip('r1', 'r2-link0') + + Returns + ------- + 1) link local ipv6 address from the interface. + 2) errormsg - when link local ip not found. + """ + tgen = get_topogen() + intf = topo["routers"][onrouter]["links"][intf]["interface"] + llip = get_frr_ipv6_linklocal(tgen, onrouter, intf) + if llip: + logger.info("llip ipv6 address to be set as NH is %s", llip) + return llip + return None + + +def get_glipv6(onrouter, intf): + """ + API to get the global ipv6 address of a perticular interface + + Parameters + ---------- + * `onrouter`: Source node + * `intf` : interface for which link local ip needs to be returned. + + Usage + ----- + result = get_glipv6('r1', 'r2-link0') + + Returns + ------- + 1) global ipv6 address from the interface. + 2) errormsg - when link local ip not found. + """ + glipv6 = (topo["routers"][onrouter]["links"][intf]["ipv6"]).split("/")[0] + if glipv6: + logger.info("Global ipv6 address to be set as NH is %s", glipv6) + return glipv6 + return None + + +# ################################## +# Test cases start here. +# ################################## + + +def test_ospfv3_ecmp_tc16_p0(request): + """ + Verify OSPF ECMP. + + Verify OSPF ECMP with max path configured as 8 (ECMP + configured at FRR level) + """ + tc_name = request.node.name + write_test_header(tc_name) + tgen = get_topogen() + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + global topo + step("Bring up the base config as per the topology") + step("Configure 8 interfaces between R1 and R2 and enable ospf in area 0.") + + reset_config_on_routers(tgen) + + step("Verify that OSPF is up with 8 neighborship sessions.") + dut = "r1" + ospf_covergence = verify_ospf6_neighbor(tgen, topo, dut=dut) + assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format( + ospf_covergence + ) + + step("Configure a static route in R0 and redistribute in OSPF.") + + input_dict = { + "r0": { + "static_routes": [ + { + "network": NETWORK["ipv6"][0], + "no_of_ip": 5, + "next_hop": "Null0", + } + ] + } + } + result = create_static_routes(tgen, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + dut = "r0" + red_static(dut) + + llip = get_llip("r0", "r1-link1") + assert llip is not None, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Verify that route in R2 in stalled with 8 next hops.") + nh = [] + for item in range(1, 7): + nh.append(llip) + + llip = get_llip("r0", "r1") + assert llip is not None, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + nh2 = llip + + nh.append(nh2) + + dut = "r1" + result = verify_ospf6_rib(tgen, dut, input_dict, next_hop=nh) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + protocol = "ospf" + result = verify_rib(tgen, "ipv6", dut, input_dict, protocol=protocol, next_hop=nh) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("shut no shut all the interfaces on the remote router - R2") + dut = "r1" + for intfr in range(1, 7): + intf = topo["routers"]["r1"]["links"]["r0-link{}".format(intfr)]["interface"] + shutdown_bringup_interface(tgen, dut, intf, False) + + result = verify_ospf6_rib(tgen, dut, input_dict, next_hop=nh, expected=False) + assert ( + result is not True + ), "Testcase {} : Failed \n Route present in OSPF RIB. Error: {}".format( + tc_name, result + ) + + protocol = "ospf" + result = verify_rib( + tgen, "ipv6", dut, input_dict, protocol=protocol, next_hop=nh, expected=False + ) + assert ( + result is not True + ), "Testcase {} : Failed \n Route present in RIB. Error: {}".format(tc_name, result) + + for intfr in range(1, 7): + intf = topo["routers"]["r1"]["links"]["r0-link{}".format(intfr)]["interface"] + shutdown_bringup_interface(tgen, dut, intf, True) + + result = verify_ospf6_rib(tgen, dut, input_dict, next_hop=nh) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + protocol = "ospf" + result = verify_rib(tgen, "ipv6", dut, input_dict, protocol=protocol, next_hop=nh) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("shut no shut on all the interfaces on DUT (r1)") + for intfr in range(1, 7): + intf = topo["routers"]["r1"]["links"]["r0-link{}".format(intfr)]["interface"] + shutdown_bringup_interface(tgen, dut, intf, False) + + for intfr in range(1, 7): + intf = topo["routers"]["r1"]["links"]["r0-link{}".format(intfr)]["interface"] + shutdown_bringup_interface(tgen, dut, intf, True) + + step( + "Verify that all the neighbours are up and routes are installed" + " with 8 next hop in ospf and ip route tables on R1." + ) + + step("Verify that OSPF is up with 8 neighborship sessions.") + dut = "r1" + ospf_covergence = verify_ospf6_neighbor(tgen, topo, dut=dut) + assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format( + ospf_covergence + ) + + dut = "r1" + result = verify_ospf6_rib(tgen, dut, input_dict, next_hop=nh) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + protocol = "ospf" + result = verify_rib(tgen, "ipv6", dut, input_dict, protocol=protocol, next_hop=nh) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + write_test_footer(tc_name) + + +def test_ospfv3_ecmp_tc17_p0(request): + """ + Verify OSPF ECMP. + + Verify OSPF ECMP with max path configured as 2 (Edge having 2 uplink ports) + """ + tc_name = request.node.name + write_test_header(tc_name) + tgen = get_topogen() + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + global topo + step("Bring up the base config as per the topology") + step("Configure 2 interfaces between R1 and R2 & enable ospf in area 0.") + + reset_config_on_routers(tgen) + + step("Verify that OSPF is up with 2 neighborship sessions.") + dut = "r1" + ospf_covergence = verify_ospf6_neighbor(tgen, topo, dut=dut) + assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format( + ospf_covergence + ) + + step("Configure a static route in R0 and redistribute in OSPF.") + + input_dict = { + "r0": { + "static_routes": [ + { + "network": NETWORK["ipv6"][0], + "no_of_ip": 5, + "next_hop": "Null0", + } + ] + } + } + result = create_static_routes(tgen, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + dut = "r0" + red_static(dut) + + step("Verify that route in R2 in stalled with 2 next hops.") + + llip = get_llip("r0", "r1-link1") + assert llip is not None, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + nh1 = llip + + llip = get_llip("r0", "r1") + assert llip is not None, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + nh2 = llip + + nh = [nh1, nh2] + + dut = "r1" + result = verify_ospf6_rib(tgen, dut, input_dict, next_hop=nh) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + protocol = "ospf" + result = verify_rib(tgen, "ipv6", dut, input_dict, protocol=protocol, next_hop=nh) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Configure ECMP value as 1.") + max_path = {"r1": {"ospf6": {"maximum-paths": 1}}} + result = create_router_ospf(tgen, topo, max_path) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + result = verify_rib(tgen, "ipv6", dut, input_dict, protocol=protocol, next_hop=nh2) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + dut = "r1" + max_path = {"r1": {"ospf6": {"maximum-paths": 2}}} + result = create_router_ospf(tgen, topo, max_path) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + result = verify_rib(tgen, "ipv6", dut, input_dict, protocol=protocol, next_hop=nh) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Configure cost on R0 as 100") + r0_ospf_cost = {"r0": {"links": {"r1": {"ospf6": {"cost": 100}}}}} + result = config_ospf6_interface(tgen, topo, r0_ospf_cost) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + dut = "r1" + result = verify_ospf6_rib(tgen, dut, input_dict, next_hop=nh) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + protocol = "ospf" + result = verify_rib(tgen, "ipv6", dut, input_dict, protocol=protocol, next_hop=nh) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + write_test_footer(tc_name) + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tests/topotests/ospfv3_basic_functionality/test_ospfv3_routemaps.py b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_routemaps.py new file mode 100644 index 0000000000..d8cf3bd02d --- /dev/null +++ b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_routemaps.py @@ -0,0 +1,875 @@ +#!/usr/bin/python + +# +# Copyright (c) 2021 by VMware, Inc. ("VMware") +# Used Copyright (c) 2018 by Network Device Education Foundation, Inc. +# ("NetDEF") in this file. +# +# 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 VMWARE DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE 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. +# + + +"""OSPF Basic Functionality Automation.""" +import os +import sys +import time +import pytest +import json +from copy import deepcopy +from ipaddress import IPv4Address +from lib.topotest import frr_unicode + +# Save the Current Working Directory to find configuration files. +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) +sys.path.append(os.path.join(CWD, "../lib/")) + +# pylint: disable=C0413 +# Import topogen and topotest helpers +from mininet.topo import Topo +from lib.topogen import Topogen, get_topogen +import ipaddress + +# Import topoJson from lib, to create topology and initial configuration +from lib.common_config import ( + start_topology, + write_test_header, + write_test_footer, + reset_config_on_routers, + create_prefix_lists, + verify_rib, + create_static_routes, + step, + create_route_maps, + verify_prefix_lists, + get_frr_ipv6_linklocal, + topo_daemons, +) +from lib.topolog import logger +from lib.topojson import build_topo_from_json, build_config_from_json + +from lib.ospf import ( + verify_ospf6_neighbor, + config_ospf_interface, + clear_ospf, + verify_ospf6_rib, + create_router_ospf, + verify_ospf6_interface, + verify_ospf6_database, + config_ospf6_interface, +) + +from ipaddress import IPv6Address + +pytestmark = [pytest.mark.ospfd, pytest.mark.staticd] + + +# Global variables +topo = None + +# Reading the data from JSON File for topology creation +jsonFile = "{}/ospfv3_routemaps.json".format(CWD) +try: + with open(jsonFile, "r") as topoJson: + topo = json.load(topoJson) +except IOError: + assert False, "Could not read file {}".format(jsonFile) + +NETWORK = { + "ipv4": [ + "11.0.20.1/32", + "11.0.20.2/32", + "11.0.20.3/32", + "11.0.20.4/32", + "11.0.20.5/32", + ], + "ipv6": ["2::1/128", "2::2/128", "2::3/128", "2::4/128", "2::5/128"], +} + +routerids = ["100.1.1.0", "100.1.1.1", "100.1.1.2", "100.1.1.3"] + +""" +TOPOOLOGY = + Please view in a fixed-width font such as Courier. + +---+ A1 +---+ + +R1 +------------+R2 | + +-+-+- +--++ + | -- -- | + | -- A0 -- | + A0| ---- | + | ---- | A2 + | -- -- | + | -- -- | + +-+-+- +-+-+ + +R0 +-------------+R3 | + +---+ A3 +---+ + +TESTCASES = +2. Verify OSPF route map support functionality when route map is not + configured at system level but configured in OSPF +4. Verify OSPF route map support functionality + when route map actions are toggled. +5. Verify OSPF route map support functionality with multiple sequence + numbers in a single route-map for different match/set clauses. +6. Verify OSPF route map support functionality when we add/remove route-maps + with multiple set clauses and without any match statement.(Set only) +7. Verify OSPF route map support functionality when we + add/remove route-maps with multiple match clauses and without + any set statement.(Match only) +8. Verify OSPF route map applied to ospf redistribution with ipv6 prefix list + """ + + +class CreateTopo(Topo): + """ + Test topology builder. + + * `Topo`: Topology object + """ + + def build(self, *_args, **_opts): + """Build function.""" + tgen = get_topogen(self) + + # Building topology from json file + build_topo_from_json(tgen, topo) + + +def setup_module(mod): + """ + Sets up the pytest environment + + * `mod`: module name + """ + global topo + testsuite_run_time = time.asctime(time.localtime(time.time())) + logger.info("Testsuite start time: {}".format(testsuite_run_time)) + logger.info("=" * 40) + + logger.info("Running setup_module to create topology") + + # This function initiates the topology build with Topogen... + tgen = Topogen(CreateTopo, mod.__name__) + # ... and here it calls Mininet initialization functions. + + # get list of daemons needs to be started for this suite. + daemons = topo_daemons(tgen, topo) + + # Starting topology, create tmp files which are loaded to routers + # to start deamons and then start routers + start_topology(tgen, daemons) + + # Creating configuration from JSON + build_config_from_json(tgen, topo) + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + ospf_covergence = verify_ospf6_neighbor(tgen, topo) + assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format( + ospf_covergence + ) + + logger.info("Running setup_module() done") + + +def teardown_module(mod): + """ + Teardown the pytest environment. + + * `mod`: module name + """ + + logger.info("Running teardown_module to delete topology") + + tgen = get_topogen() + + # Stop toplogy and Remove tmp files + tgen.stop_topology() + + logger.info( + "Testsuite end time: {}".format(time.asctime(time.localtime(time.time()))) + ) + logger.info("=" * 40) + + +# ################################## +# Test cases start here. +# ################################## + + +def test_ospfv3_routemaps_functionality_tc20_p0(request): + """ + OSPF route map support functionality. + + Verify OSPF route map support functionality when route map is not + configured at system level but configured in OSPF + + """ + tc_name = request.node.name + write_test_header(tc_name) + tgen = get_topogen() + global topo + step("Bring up the base config as per the topology") + + reset_config_on_routers(tgen) + + step("Create static routes(10.0.20.1/32 and 10.0.20.2/32) in R0") + # Create Static routes + input_dict = { + "r0": { + "static_routes": [ + { + "network": NETWORK["ipv6"][0], + "no_of_ip": 5, + "next_hop": "Null0", + } + ] + } + } + result = create_static_routes(tgen, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Redistribute to ospf using route map ( non existent route map)") + ospf_red_r1 = { + "r0": { + "ospf6": { + "redistribute": [{"redist_type": "static", "route_map": "rmap_ipv6"}] + } + } + } + result = create_router_ospf(tgen, topo, ospf_red_r1) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step( + "Verify that routes are not allowed in OSPF even tough no " + "matching routing map is configured." + ) + + dut = "r1" + protocol = "ospf" + result = verify_ospf6_rib(tgen, dut, input_dict) + assert ( + result is not True + ), "Testcase {} : Failed \n Route found in the RIB, Error: {}".format( + tc_name, result + ) + + result = verify_rib(tgen, "ipv6", dut, input_dict, protocol=protocol) + assert ( + result is not True + ), "Testcase {} : Failed \n Route found in the RIB, Error: {}".format( + tc_name, result + ) + + step( + "configure the route map with the same name that is used " + "in the ospf with deny rule." + ) + + # Create route map + routemaps = {"r0": {"route_maps": {"rmap_ipv6": [{"action": "deny"}]}}} + result = create_route_maps(tgen, routemaps) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("verify that now route map is activated & routes are denied in OSPF.") + dut = "r1" + protocol = "ospf" + result = verify_ospf6_rib(tgen, dut, input_dict, expected=False) + assert ( + result is not True + ), "Testcase {} : Failed \n Route found in the RIB, Error: {}".format( + tc_name, result + ) + + result = verify_rib( + tgen, "ipv6", dut, input_dict, protocol=protocol, expected=False + ) + assert ( + result is not True + ), "Testcase {} : Failed \n Route found in the RIB, Error: {}".format( + tc_name, result + ) + + # Create route map + routemaps = {"r0": {"route_maps": {"rmap_ipv6": [{"action": "deny"}]}}} + result = create_route_maps(tgen, routemaps) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("verify that now route map is activated & routes are denied in OSPF.") + dut = "r1" + protocol = "ospf" + result = verify_ospf6_rib(tgen, dut, input_dict, expected=False) + assert ( + result is not True + ), "Testcase {} : Failed \n Route found in the RIB, Error: {}".format( + tc_name, result + ) + + result = verify_rib( + tgen, "ipv6", dut, input_dict, protocol=protocol, expected=False + ) + assert ( + result is not True + ), "Testcase {} : Failed \n Route found in the RIB, Error: {}".format( + tc_name, result + ) + + step("Delete the route map.") + # Create route map + routemaps = { + "r0": {"route_maps": {"rmap_ipv6": [{"action": "deny", "delete": True}]}} + } + result = create_route_maps(tgen, routemaps) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step( + "Verify that routes are allowed in OSPF even tough " + "no matching routing map is configured." + ) + dut = "r1" + protocol = "ospf" + result = verify_ospf6_rib(tgen, dut, input_dict, expected=False) + assert ( + result is not True + ), "Testcase {} : Failed \n Route found in the RIB, Error: {}".format( + tc_name, result + ) + + result = verify_rib( + tgen, "ipv6", dut, input_dict, protocol=protocol, expected=False + ) + assert ( + result is not True + ), "Testcase {} : Failed \n Route found in the RIB, Error: {}".format( + tc_name, result + ) + + write_test_footer(tc_name) + + +def test_ospfv3_routemaps_functionality_tc25_p0(request): + """ + OSPF route map support functionality. + + Verify OSPF route map support functionality + when route map actions are toggled. + + """ + tc_name = request.node.name + write_test_header(tc_name) + tgen = get_topogen() + global topo + step("Bring up the base config as per the topology") + + reset_config_on_routers(tgen) + + step( + "Create static routes(10.0.20.1/32) in R1 and redistribute " + "to OSPF using route map." + ) + + # Create Static routes + input_dict = { + "r0": { + "static_routes": [ + { + "network": NETWORK["ipv6"][0], + "no_of_ip": 5, + "next_hop": "Null0", + } + ] + } + } + result = create_static_routes(tgen, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + ospf_red_r0 = { + "r0": { + "ospf6": { + "redistribute": [{"redist_type": "static", "route_map": "rmap_ipv6"}] + } + } + } + result = create_router_ospf(tgen, topo, ospf_red_r0) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + step("Configure route map with permit rule") + # Create route map + routemaps = {"r0": {"route_maps": {"rmap_ipv6": [{"action": "permit"}]}}} + result = create_route_maps(tgen, routemaps) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Verify that route is advertised to R1.") + dut = "r1" + protocol = "ospf" + result = verify_ospf6_rib(tgen, dut, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + result = verify_rib(tgen, "ipv6", dut, input_dict, protocol=protocol) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + step("Configure route map with deny rule") + # Create route map + routemaps = { + "r0": {"route_maps": {"rmap_ipv6": [{"seq_id": 10, "action": "deny"}]}} + } + result = create_route_maps(tgen, routemaps) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + # Api call verify whether OSPF is converged + ospf_covergence = verify_ospf6_neighbor(tgen, topo) + assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format( + ospf_covergence + ) + + step("Verify that route is not advertised to R1.") + dut = "r1" + protocol = "ospf" + result = verify_ospf6_rib(tgen, dut, input_dict, expected=False) + assert ( + result is not True + ), "Testcase {} : Failed \n Route found in the RIB, Error: {}".format( + tc_name, result + ) + + result = verify_rib( + tgen, "ipv6", dut, input_dict, protocol=protocol, expected=False + ) + assert ( + result is not True + ), "Testcase {} : Failed \n Route found in the RIB, Error: {}".format( + tc_name, result + ) + + write_test_footer(tc_name) + + +def test_ospfv3_routemaps_functionality_tc22_p0(request): + """ + OSPF Route map - Multiple sequence numbers. + + Verify OSPF route map support functionality with multiple sequence + numbers in a single route-map for different match/set clauses. + + """ + tc_name = request.node.name + write_test_header(tc_name) + tgen = get_topogen() + global topo + step("Bring up the base config as per the topology") + + reset_config_on_routers(tgen) + + step( + "Configure route map with seq number 10 to with ip prefix" + " permitting route 10.0.20.1/32 in R1" + ) + step( + "Configure route map with seq number 20 to with ip prefix" + " permitting route 10.0.20.2/32 in R1" + ) + + # Create route map + input_dict_3 = { + "r0": { + "route_maps": { + "rmap_ipv6": [ + { + "action": "permit", + "seq_id": "10", + "match": {"ipv6": {"prefix_lists": "pf_list_1_ipv6"}}, + }, + { + "action": "permit", + "seq_id": "20", + "match": {"ipv6": {"prefix_lists": "pf_list_2_ipv4"}}, + }, + ] + } + } + } + result = create_route_maps(tgen, input_dict_3) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + # Create ip prefix list + input_dict_2 = { + "r0": { + "prefix_lists": { + "ipv4": { + "pf_list_1_ipv6": [ + {"seqid": 10, "network": NETWORK["ipv6"][0], "action": "permit"} + ] + } + } + } + } + result = create_prefix_lists(tgen, input_dict_2) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + # Create ip prefix list + input_dict_2 = { + "r0": { + "prefix_lists": { + "ipv4": { + "pf_list_2_ipv4": [ + {"seqid": 10, "network": NETWORK["ipv6"][1], "action": "permit"} + ] + } + } + } + } + result = create_prefix_lists(tgen, input_dict_2) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Configure static routes 10.0.20.1/32 and 10.0.20.2 in R1") + # Create Static routes + input_dict = { + "r0": { + "static_routes": [ + { + "network": NETWORK["ipv6"][0], + "no_of_ip": 5, + "next_hop": "Null0", + } + ] + } + } + result = create_static_routes(tgen, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Configure redistribute static route with route map.") + ospf_red_r0 = { + "r0": { + "ospf6": { + "redistribute": [{"redist_type": "static", "route_map": "rmap_ipv6"}] + } + } + } + result = create_router_ospf(tgen, topo, ospf_red_r0) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + input_dict = { + "r0": { + "static_routes": [ + { + "network": NETWORK["ipv6"][0], + "no_of_ip": 2, + "next_hop": "Null0", + } + ] + } + } + result = create_static_routes(tgen, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Verify that both routes are learned in R1 and R2") + dut = "r1" + protocol = "ospf" + result = verify_ospf6_rib(tgen, dut, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + result = verify_rib(tgen, "ipv6", dut, input_dict, protocol=protocol) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + dut = "r2" + protocol = "ospf" + result = verify_ospf6_rib(tgen, dut, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + result = verify_rib(tgen, "ipv6", dut, input_dict, protocol=protocol) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Change route map with seq number 20 to deny.") + # Create route map + input_dict_3 = { + "r0": { + "route_maps": { + "rmap_ipv6": [ + { + "action": "deny", + "seq_id": "20", + "match": {"ipv6": {"prefix_lists": "pf_list_2_ipv4"}}, + } + ] + } + } + } + result = create_route_maps(tgen, input_dict_3) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step( + "Verify the route 10.0.20.2/32 is withdrawn and not present " + "in the routing table of R0 and R1." + ) + + input_dict = { + "r0": {"static_routes": [{"network": NETWORK["ipv6"][1], "next_hop": "Null0"}]} + } + + dut = "r1" + protocol = "ospf" + result = verify_ospf6_rib(tgen, dut, input_dict, expected=False) + assert ( + result is not True + ), "Testcase {} : Failed \n Route found in the RIB, Error: {}".format( + tc_name, result + ) + + result = verify_rib( + tgen, "ipv6", dut, input_dict, protocol=protocol, expected=False + ) + assert ( + result is not True + ), "Testcase {} : Failed \n Route found in the RIB, Error: {}".format( + tc_name, result + ) + + dut = "r2" + protocol = "ospf" + result = verify_ospf6_rib(tgen, dut, input_dict, expected=False) + assert ( + result is not True + ), "Testcase {} : Failed \n Route found in the RIB, Error: {}".format( + tc_name, result + ) + + result = verify_rib( + tgen, "ipv6", dut, input_dict, protocol=protocol, expected=False + ) + assert ( + result is not True + ), "Testcase {} : Failed \n Route found in the RIB, Error: {}".format( + tc_name, result + ) + + write_test_footer(tc_name) + + +def test_ospfv3_routemaps_functionality_tc24_p0(request): + """ + OSPF Route map - Multiple set clauses. + + Verify OSPF route map support functionality when we + add/remove route-maps with multiple match clauses and without + any set statement.(Match only) + + """ + tc_name = request.node.name + write_test_header(tc_name) + tgen = get_topogen() + global topo + step("Bring up the base config as per the topology") + + reset_config_on_routers(tgen) + + step( + "Create static routes(10.0.20.1/32) in R1 and redistribute to " + "OSPF using route map." + ) + # Create Static routes + input_dict = { + "r0": { + "static_routes": [ + { + "network": NETWORK["ipv6"][0], + "no_of_ip": 1, + "next_hop": "Null0", + } + ] + } + } + result = create_static_routes(tgen, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + ospf_red_r0 = { + "r0": { + "ospf6": { + "redistribute": [{"redist_type": "static", "route_map": "rmap_ipv6"}] + } + } + } + result = create_router_ospf(tgen, topo, ospf_red_r0) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + # Create ip prefix list + pfx_list = { + "r0": { + "prefix_lists": { + "ipv6": { + "pf_list_1_ipv6": [ + {"seqid": 10, "network": "any", "action": "permit"} + ] + } + } + } + } + result = create_prefix_lists(tgen, pfx_list) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("verify that prefix-list is created in R0.") + result = verify_prefix_lists(tgen, pfx_list) + assert ( + result is not True + ), "Testcase {} : Failed \n Prefix list not " "present. Error: {}".format( + tc_name, result + ) + + # Create route map + routemaps = { + "r0": { + "route_maps": { + "rmap_ipv6": [ + { + "action": "permit", + "match": {"ipv6": {"prefix_lists": "pf_list_1_ipv6"}}, + } + ] + } + } + } + result = create_route_maps(tgen, routemaps) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Verify that metric falls back to original metric for ospf routes.") + dut = "r1" + protocol = "ospf" + + result = verify_ospf6_rib(tgen, dut, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + result = verify_rib(tgen, "ipv6", dut, input_dict, protocol=protocol) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step( + "Create static routes(10.0.20.1/32) in R1 and redistribute to " + "OSPF using route map." + ) + # Create Static routes + input_dict = { + "r0": { + "static_routes": [ + { + "network": NETWORK["ipv6"][1], + "no_of_ip": 1, + "next_hop": "Null0", + "tag": 1000, + } + ] + } + } + result = create_static_routes(tgen, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + # Create ip prefix list + pfx_list = { + "r0": { + "prefix_lists": { + "ipv6": { + "pf_list_1_ipv6": [ + {"seqid": 10, "network": "any", "action": "permit"} + ] + } + } + } + } + result = create_prefix_lists(tgen, pfx_list) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("verify that prefix-list is created in R0.") + result = verify_prefix_lists(tgen, pfx_list) + assert ( + result is not True + ), "Testcase {} : Failed \n Prefix list not " "present. Error: {}".format( + tc_name, result + ) + + # Create route map + routemaps = { + "r0": { + "route_maps": { + "rmap_ipv6": [{"action": "permit", "match": {"ipv6": {"tag": "1000"}}}] + } + } + } + result = create_route_maps(tgen, routemaps) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Verify that metric falls back to original metric for ospf routes.") + dut = "r1" + protocol = "ospf" + + result = verify_ospf6_rib(tgen, dut, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + result = verify_rib(tgen, "ipv6", dut, input_dict, protocol=protocol) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Delete the match clause with tag in route map") + # Create route map + routemaps = { + "r0": { + "route_maps": { + "rmap_ipv6": [ + { + "action": "permit", + "match": {"ipv6": {"tag": "1000", "delete": True}}, + } + ] + } + } + } + result = create_route_maps(tgen, routemaps) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Verify that metric falls back to original metric for ospf routes.") + dut = "r1" + protocol = "ospf" + + result = verify_ospf6_rib(tgen, dut, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + result = verify_rib(tgen, "ipv6", dut, input_dict, protocol=protocol) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Delete the match clause with metric in route map.") + + # Create route map + routemaps = { + "r0": { + "route_maps": { + "rmap_ipv6": [ + { + "action": "permit", + "match": {"ipv6": {"prefix_lists": "pf_list_1_ipv6"}}, + } + ] + } + } + } + result = create_route_maps(tgen, routemaps) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + result = verify_ospf6_rib(tgen, dut, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + result = verify_rib(tgen, "ipv6", dut, input_dict, protocol=protocol) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + write_test_footer(tc_name) + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tests/topotests/ospfv3_basic_functionality/test_ospfv3_rte_calc.py b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_rte_calc.py index 4aa71bfb16..860f17ba67 100644 --- a/tests/topotests/ospfv3_basic_functionality/test_ospfv3_rte_calc.py +++ b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_rte_calc.py @@ -74,6 +74,9 @@ from lib.ospf import ( from ipaddress import IPv6Address +pytestmark = [pytest.mark.ospfd, pytest.mark.staticd] + + # Global variables topo = None @@ -281,6 +284,233 @@ def red_connected(dut, config=True): # ################################## # Test cases start here. # ################################## +def test_ospfv3_redistribution_tc5_p0(request): + """Test OSPF intra area route calculations.""" + tc_name = request.node.name + write_test_header(tc_name) + tgen = get_topogen() + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + global topo + step("Bring up the base config.") + reset_config_on_routers(tgen) + + step("Verify that OSPF neighbors are FULL.") + ospf_covergence = verify_ospf6_neighbor(tgen, topo) + assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format( + ospf_covergence + ) + + step("verify intra area route is calculated for r0-r3 interface ip in R1") + ip = topo["routers"]["r0"]["links"]["r3"]["ipv6"] + ip_net = str(ipaddress.ip_interface(u"{}".format(ip)).network) + + llip = get_llip("r0", "r1") + assert llip is not None, "Testcase {} : Failed \n Error: {}".format(tc_name, llip) + + nh = llip + input_dict = { + "r1": {"static_routes": [{"network": ip_net, "no_of_ip": 1, "routeType": "N"}]} + } + + dut = "r1" + result = verify_ospf6_rib(tgen, dut, input_dict, next_hop=nh) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + protocol = "ospf" + result = verify_rib(tgen, "ipv6", dut, input_dict, protocol=protocol, next_hop=nh) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Delete the ip address on newly configured loopback of R0") + topo1 = { + "r0": { + "links": { + "r3": { + "ipv6": topo["routers"]["r0"]["links"]["r3"]["ipv6"], + "interface": topo["routers"]["r0"]["links"]["r3"]["interface"], + "delete": True, + } + } + } + } + + result = create_interfaces_cfg(tgen, topo1) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + dut = "r1" + result = verify_ospf6_rib(tgen, dut, input_dict, next_hop=nh, expected=False) + assert ( + result is not True + ), "Testcase {} : Failed \n Route present in RIB. Error: {}".format(tc_name, result) + + protocol = "ospf" + result = verify_rib( + tgen, "ipv6", dut, input_dict, protocol=protocol, next_hop=nh, expected=False + ) + assert ( + result is not True + ), "Testcase {} : Failed \n Route present in RIB. Error: {}".format(tc_name, result) + + step("Add back the deleted ip address on newly configured interface of R0") + topo1 = { + "r0": { + "links": { + "r3": { + "ipv6": topo["routers"]["r0"]["links"]["r3"]["ipv6"], + "interface": topo["routers"]["r0"]["links"]["r3"]["interface"], + } + } + } + } + + result = create_interfaces_cfg(tgen, topo1) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + dut = "r1" + result = verify_ospf6_rib(tgen, dut, input_dict, next_hop=nh) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + protocol = "ospf" + result = verify_rib(tgen, "ipv6", dut, input_dict, protocol=protocol, next_hop=nh) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Shut no shut interface on R0") + dut = "r0" + intf = topo["routers"]["r0"]["links"]["r3"]["interface"] + shutdown_bringup_interface(tgen, dut, intf, False) + + step("un shut the OSPF interface on R0") + dut = "r0" + shutdown_bringup_interface(tgen, dut, intf, True) + + dut = "r1" + result = verify_ospf6_rib(tgen, dut, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + protocol = "ospf" + result = verify_rib(tgen, "ipv6", dut, input_dict, protocol=protocol, next_hop=nh) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + write_test_footer(tc_name) + + +def test_ospfv3_redistribution_tc6_p0(request): + """Test OSPF inter area route calculations.""" + tc_name = request.node.name + write_test_header(tc_name) + tgen = get_topogen() + + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + global topo + step("Bring up the base config.") + reset_config_on_routers(tgen) + + step("Verify that OSPF neighbors are FULL.") + ospf_covergence = verify_ospf6_neighbor(tgen, topo) + assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format( + ospf_covergence + ) + + step("verify intra area route is calculated for r0-r3 interface ip in R1") + ip = topo["routers"]["r0"]["links"]["r3"]["ipv6"] + ip_net = str(ipaddress.ip_interface(u"{}".format(ip)).network) + llip = get_llip("r0", "r1") + assert llip is not None, "Testcase {} : Failed \n Error: {}".format(tc_name, llip) + nh = llip + input_dict = { + "r1": {"static_routes": [{"network": ip_net, "no_of_ip": 1, "routeType": "N"}]} + } + + dut = "r1" + result = verify_ospf6_rib(tgen, dut, input_dict, next_hop=nh) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + protocol = "ospf" + result = verify_rib(tgen, "ipv6", dut, input_dict, protocol=protocol, next_hop=nh) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Delete the ip address on newly configured loopback of R0") + topo1 = { + "r0": { + "links": { + "r3": { + "ipv6": topo["routers"]["r0"]["links"]["r3"]["ipv6"], + "interface": topo["routers"]["r0"]["links"]["r3"]["interface"], + "delete": True, + } + } + } + } + + result = create_interfaces_cfg(tgen, topo1) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + dut = "r1" + result = verify_ospf6_rib(tgen, dut, input_dict, next_hop=nh, expected=False) + assert ( + result is not True + ), "Testcase {} : Failed \n Route present in RIB. Error: {}".format(tc_name, result) + + protocol = "ospf" + result = verify_rib( + tgen, "ipv6", dut, input_dict, protocol=protocol, next_hop=nh, expected=False + ) + assert ( + result is not True + ), "Testcase {} : Failed \n Route present in RIB. Error: {}".format(tc_name, result) + + step("Add back the deleted ip address on newly configured interface of R0") + topo1 = { + "r0": { + "links": { + "r3": { + "ipv6": topo["routers"]["r0"]["links"]["r3"]["ipv6"], + "interface": topo["routers"]["r0"]["links"]["r3"]["interface"], + } + } + } + } + + result = create_interfaces_cfg(tgen, topo1) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + dut = "r1" + result = verify_ospf6_rib(tgen, dut, input_dict, next_hop=nh) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + protocol = "ospf" + result = verify_rib(tgen, "ipv6", dut, input_dict, protocol=protocol, next_hop=nh) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Shut no shut interface on R0") + dut = "r0" + intf = topo["routers"]["r0"]["links"]["r3"]["interface"] + shutdown_bringup_interface(tgen, dut, intf, False) + + step("Verify that intraroute calculated for R1 intf on R0 is deleted.") + dut = "r1" + + step("un shut the OSPF interface on R0") + dut = "r0" + shutdown_bringup_interface(tgen, dut, intf, True) + + dut = "r1" + result = verify_ospf6_rib(tgen, dut, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + protocol = "ospf" + result = verify_rib(tgen, "ipv6", dut, input_dict, protocol=protocol, next_hop=nh) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + write_test_footer(tc_name) + + def test_ospfv3_cost_tc52_p0(request): """OSPF Cost - verifying ospf interface cost functionality""" tc_name = request.node.name @@ -368,7 +598,6 @@ def test_ospfv3_cost_tc52_p0(request): write_test_footer(tc_name) - if __name__ == "__main__": args = ["-s"] + sys.argv[1:] sys.exit(pytest.main(args)) diff --git a/tests/topotests/ospfv3_basic_functionality/test_ospfv3_single_area.py b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_single_area.py index a84f1a1eb6..0c1c51c78a 100644 --- a/tests/topotests/ospfv3_basic_functionality/test_ospfv3_single_area.py +++ b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_single_area.py @@ -54,7 +54,7 @@ from lib.common_config import ( create_route_maps, shutdown_bringup_interface, create_interfaces_cfg, - topo_daemons, + topo_daemons ) from lib.topolog import logger from lib.topojson import build_topo_from_json, build_config_from_json @@ -72,6 +72,9 @@ from lib.ospf import ( from ipaddress import IPv6Address +pytestmark = [pytest.mark.ospfd, pytest.mark.staticd] + + # Global variables topo = None diff --git a/tests/topotests/pim_acl/r1/pimd.conf b/tests/topotests/pim_acl/r1/pimd.conf index 72d28c9b02..a148c73146 100644 --- a/tests/topotests/pim_acl/r1/pimd.conf +++ b/tests/topotests/pim_acl/r1/pimd.conf @@ -13,6 +13,7 @@ ip pim rp 192.168.0.12 prefix-list rp-pl-2 ip pim rp 192.168.0.13 prefix-list rp-pl-3 ip pim rp 192.168.0.14 prefix-list rp-pl-4 ip pim rp 192.168.0.15 prefix-list rp-pl-5 +ip pim join-prune-interval 5 ! interface r1-eth0 ip igmp diff --git a/tests/topotests/pim_acl/r11/pimd.conf b/tests/topotests/pim_acl/r11/pimd.conf index 05cd5ac911..b1d45205da 100644 --- a/tests/topotests/pim_acl/r11/pimd.conf +++ b/tests/topotests/pim_acl/r11/pimd.conf @@ -7,6 +7,7 @@ debug pim zebra debug pim bsm ! ip pim rp 192.168.0.11 239.100.0.0/28 +ip pim join-prune-interval 5 ! interface lo ip pim diff --git a/tests/topotests/pim_acl/r12/pimd.conf b/tests/topotests/pim_acl/r12/pimd.conf index cedde73c59..ba9e7d902f 100644 --- a/tests/topotests/pim_acl/r12/pimd.conf +++ b/tests/topotests/pim_acl/r12/pimd.conf @@ -7,6 +7,7 @@ debug pim zebra debug pim bsm ! ip pim rp 192.168.0.12 239.100.0.17/32 +ip pim join-prune-interval 5 ! interface lo ip pim diff --git a/tests/topotests/pim_acl/r13/pimd.conf b/tests/topotests/pim_acl/r13/pimd.conf index 2dab0cabec..2ff1743574 100644 --- a/tests/topotests/pim_acl/r13/pimd.conf +++ b/tests/topotests/pim_acl/r13/pimd.conf @@ -7,6 +7,7 @@ debug pim zebra debug pim bsm ! ip pim rp 192.168.0.13 239.100.0.32/27 +ip pim join-prune-interval 5 ! interface lo ip pim diff --git a/tests/topotests/pim_acl/r14/pimd.conf b/tests/topotests/pim_acl/r14/pimd.conf index c6b949af16..1324a9e40b 100644 --- a/tests/topotests/pim_acl/r14/pimd.conf +++ b/tests/topotests/pim_acl/r14/pimd.conf @@ -8,6 +8,7 @@ debug pim bsm ! ip pim rp 192.168.0.14 239.100.0.96/28 ip pim rp 192.168.0.14 239.100.0.128/25 +ip pim join-prune-interval 5 ! interface lo ip pim diff --git a/tests/topotests/pim_acl/r15/pimd.conf b/tests/topotests/pim_acl/r15/pimd.conf index 85c9c51e1e..f47e78c221 100644 --- a/tests/topotests/pim_acl/r15/pimd.conf +++ b/tests/topotests/pim_acl/r15/pimd.conf @@ -7,6 +7,7 @@ debug pim zebra debug pim bsm ! ip pim rp 192.168.0.15 239.100.0.64/28 +ip pim join-prune-interval 5 ! interface lo ip pim diff --git a/tests/topotests/pim_acl/test_pim_acl.py b/tests/topotests/pim_acl/test_pim_acl.py index 848f7fa8ed..77917a0239 100755 --- a/tests/topotests/pim_acl/test_pim_acl.py +++ b/tests/topotests/pim_acl/test_pim_acl.py @@ -121,7 +121,7 @@ from lib.topolog import logger # Required to instantiate the topology builder class. from mininet.topo import Topo -pytestmark = [pytest.mark.pimd] +pytestmark = [pytest.mark.pimd, pytest.mark.ospfd] # diff --git a/tests/topotests/pim_basic/r1/pimd.conf b/tests/topotests/pim_basic/r1/pimd.conf index f64a46deb3..737019fa51 100644 --- a/tests/topotests/pim_basic/r1/pimd.conf +++ b/tests/topotests/pim_basic/r1/pimd.conf @@ -15,3 +15,4 @@ interface lo ip pim ! ip pim rp 10.254.0.3 +ip pim join-prune-interval 5 diff --git a/tests/topotests/pim_basic/rp/pimd.conf b/tests/topotests/pim_basic/rp/pimd.conf index 6e35c97971..fd26bc4d71 100644 --- a/tests/topotests/pim_basic/rp/pimd.conf +++ b/tests/topotests/pim_basic/rp/pimd.conf @@ -6,6 +6,7 @@ interface rp-eth0 interface lo ip pim ! +ip pim join-prune-interval 5 ip pim rp 10.254.0.3 ip pim register-accept-list ACCEPT diff --git a/tests/topotests/pim_basic_topo2/r2/pimd.conf b/tests/topotests/pim_basic_topo2/r2/pimd.conf index 0b32ded19a..9f389deb11 100644 --- a/tests/topotests/pim_basic_topo2/r2/pimd.conf +++ b/tests/topotests/pim_basic_topo2/r2/pimd.conf @@ -10,3 +10,4 @@ interface r2-eth2 ip pim ip pim bfd ! +ip pim join-prune-interval 5 diff --git a/tests/topotests/pim_igmp_vrf/r1/pimd.conf b/tests/topotests/pim_igmp_vrf/r1/pimd.conf index 6ee264d3d0..f04c255de9 100644 --- a/tests/topotests/pim_igmp_vrf/r1/pimd.conf +++ b/tests/topotests/pim_igmp_vrf/r1/pimd.conf @@ -24,3 +24,4 @@ interface r1-eth2 interface r1-eth3 ip pim ! +ip pim join-prune-interval 5 diff --git a/tests/topotests/pim_igmp_vrf/r11/pimd.conf b/tests/topotests/pim_igmp_vrf/r11/pimd.conf index 05cd5ac911..b1d45205da 100644 --- a/tests/topotests/pim_igmp_vrf/r11/pimd.conf +++ b/tests/topotests/pim_igmp_vrf/r11/pimd.conf @@ -7,6 +7,7 @@ debug pim zebra debug pim bsm ! ip pim rp 192.168.0.11 239.100.0.0/28 +ip pim join-prune-interval 5 ! interface lo ip pim diff --git a/tests/topotests/pim_igmp_vrf/r12/pimd.conf b/tests/topotests/pim_igmp_vrf/r12/pimd.conf index 531aec61ed..5cb76efa22 100644 --- a/tests/topotests/pim_igmp_vrf/r12/pimd.conf +++ b/tests/topotests/pim_igmp_vrf/r12/pimd.conf @@ -7,6 +7,7 @@ debug pim zebra debug pim bsm ! ip pim rp 192.168.0.12 239.100.0.0/28 +ip pim join-prune-interval 5 ! interface lo ip pim diff --git a/tests/topotests/pim_igmp_vrf/test_pim_vrf.py b/tests/topotests/pim_igmp_vrf/test_pim_vrf.py index 298adef9c6..cb207cb810 100755 --- a/tests/topotests/pim_igmp_vrf/test_pim_vrf.py +++ b/tests/topotests/pim_igmp_vrf/test_pim_vrf.py @@ -111,7 +111,7 @@ from lib.common_config import ( # Required to instantiate the topology builder class. from mininet.topo import Topo -pytestmark = [pytest.mark.pimd] +pytestmark = [pytest.mark.ospfd, pytest.mark.pimd] # diff --git a/tests/topotests/route_scale/test_route_scale.py b/tests/topotests/route_scale/test_route_scale.py index bbd6ef8d60..469ad42d64 100644 --- a/tests/topotests/route_scale/test_route_scale.py +++ b/tests/topotests/route_scale/test_route_scale.py @@ -48,6 +48,9 @@ from lib.common_config import shutdown_bringup_interface # Required to instantiate the topology builder class. from mininet.topo import Topo +pytestmark = [pytest.mark.sharpd] + + ##################################################### ## ## Network Topology Definition diff --git a/tests/topotests/simple_snmp_test/test_simple_snmp.py b/tests/topotests/simple_snmp_test/test_simple_snmp.py index 5647e2b663..bdb44816b6 100755 --- a/tests/topotests/simple_snmp_test/test_simple_snmp.py +++ b/tests/topotests/simple_snmp_test/test_simple_snmp.py @@ -90,6 +90,16 @@ def setup_module(mod): r1 = tgen.gears["r1"] + r1.run("ip addr add 192.168.12.12/24 dev r1-eth0") + r1.run("ip -6 addr add 2000:1:1:12::12/64 dev r1-eth0") + r1.run("ip addr add 192.168.13.13/24 dev r1-eth1") + r1.run("ip -6 addr add 2000:1:1:13::13/64 dev r1-eth1") + r1.run("ip addr add 192.168.14.14/24 dev r1-eth2") + r1.run("ip -6 addr add 2000:1:1:14::14/64 dev r1-eth2") + r1.run("ip addr add 1.1.1.1/32 dev lo") + r1.run("ip -6 addr add 2000:1:1:1::1/128 dev lo") + r1.run("ip addr show") + router_list = tgen.routers() # For all registred routers, load the zebra configuration file diff --git a/tests/topotests/srv6_locator/test_srv6_locator.py b/tests/topotests/srv6_locator/test_srv6_locator.py index a7416ce085..04b0d8db97 100755 --- a/tests/topotests/srv6_locator/test_srv6_locator.py +++ b/tests/topotests/srv6_locator/test_srv6_locator.py @@ -43,6 +43,8 @@ from lib.topogen import Topogen, TopoRouter, get_topogen from lib.topolog import logger from mininet.topo import Topo +pytestmark = [pytest.mark.bgpd, pytest.mark.sharpd] + def open_json_file(filename): try: diff --git a/tests/topotests/static_routing_with_ebgp/test_static_routes_topo4_ebgp.py b/tests/topotests/static_routing_with_ebgp/test_static_routes_topo4_ebgp.py index 812b39797f..626de6b422 100644 --- a/tests/topotests/static_routing_with_ebgp/test_static_routes_topo4_ebgp.py +++ b/tests/topotests/static_routing_with_ebgp/test_static_routes_topo4_ebgp.py @@ -72,6 +72,9 @@ from lib.bgp import ( ) from lib.topojson import build_topo_from_json, build_config_from_json +pytestmark = [pytest.mark.bgpd, pytest.mark.staticd] + + # Reading the data from JSON File for topology creation jsonFile = "{}/static_routes_topo4_ebgp.json".format(CWD) try: diff --git a/tests/topotests/zebra_netlink/test_zebra_netlink.py b/tests/topotests/zebra_netlink/test_zebra_netlink.py index 94baf8438f..cf08ee9639 100644 --- a/tests/topotests/zebra_netlink/test_zebra_netlink.py +++ b/tests/topotests/zebra_netlink/test_zebra_netlink.py @@ -47,6 +47,9 @@ from lib.common_config import shutdown_bringup_interface # Required to instantiate the topology builder class. from mininet.topo import Topo +pytestmark = [pytest.mark.sharpd] + + ##################################################### ## ## Network Topology Definition diff --git a/tests/topotests/zebra_opaque/test_zebra_opaque.py b/tests/topotests/zebra_opaque/test_zebra_opaque.py index cc52fbd1a7..2339b0f5b0 100644 --- a/tests/topotests/zebra_opaque/test_zebra_opaque.py +++ b/tests/topotests/zebra_opaque/test_zebra_opaque.py @@ -38,6 +38,8 @@ from lib.topogen import Topogen, TopoRouter, get_topogen from lib.topolog import logger from mininet.topo import Topo +pytestmark = [pytest.mark.bgpd] + class TemplateTopo(Topo): def build(self, *_args, **_opts): diff --git a/tests/topotests/zebra_rib/test_zebra_rib.py b/tests/topotests/zebra_rib/test_zebra_rib.py index 9fcf7b6820..56d112b7c3 100644 --- a/tests/topotests/zebra_rib/test_zebra_rib.py +++ b/tests/topotests/zebra_rib/test_zebra_rib.py @@ -46,6 +46,8 @@ from time import sleep # Required to instantiate the topology builder class. from mininet.topo import Topo +pytestmark = [pytest.mark.sharpd] + class ZebraTopo(Topo): "Test topology builder" @@ -124,7 +126,7 @@ def test_zebra_kernel_admin_distance(): "show ip route 4.5.{}.0 json".format(i), expected, ) - _, result = topotest.run_and_expect(test_func, None, count=2, wait=0.5) + _, result = topotest.run_and_expect(test_func, None, count=20, wait=0.5) assertmsg = '"r1" JSON output mismatches' assert result is None, assertmsg # tgen.mininet_cli() @@ -145,7 +147,7 @@ def test_zebra_kernel_override(): test_func = partial( topotest.router_json_cmp, r1, "show ip route 4.5.1.0 json", expected ) - _, result = topotest.run_and_expect(test_func, None, count=2, wait=0.5) + _, result = topotest.run_and_expect(test_func, None, count=20, wait=0.5) assert result is None, '"r1" JSON output mismatches' logger.info( @@ -158,7 +160,7 @@ def test_zebra_kernel_override(): test_func = partial( topotest.router_json_cmp, r1, "show ip route 4.5.1.0 json", expected ) - _, result = topotest.run_and_expect(test_func, None, count=2, wait=0.5) + _, result = topotest.run_and_expect(test_func, None, count=20, wait=0.5) assert result is None, '"r1" JSON output mismatches' diff --git a/tests/topotests/zebra_seg6_route/test_zebra_seg6_route.py b/tests/topotests/zebra_seg6_route/test_zebra_seg6_route.py index e83b2c1007..a83c6d6ec0 100755 --- a/tests/topotests/zebra_seg6_route/test_zebra_seg6_route.py +++ b/tests/topotests/zebra_seg6_route/test_zebra_seg6_route.py @@ -43,6 +43,8 @@ from lib.topolog import logger from lib.common_config import shutdown_bringup_interface from mininet.topo import Topo +pytestmark = [pytest.mark.sharpd] + def open_json_file(filename): try: diff --git a/tests/topotests/zebra_seg6local_route/test_zebra_seg6local_route.py b/tests/topotests/zebra_seg6local_route/test_zebra_seg6local_route.py index 1c9d208fef..6cdb77b94b 100755 --- a/tests/topotests/zebra_seg6local_route/test_zebra_seg6local_route.py +++ b/tests/topotests/zebra_seg6local_route/test_zebra_seg6local_route.py @@ -43,6 +43,8 @@ from lib.topolog import logger from lib.common_config import shutdown_bringup_interface from mininet.topo import Topo +pytestmark = [pytest.mark.sharpd] + def open_json_file(filename): try: |
