summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/lib/script1.lua55
-rw-r--r--tests/lib/test_frrscript.c75
-rwxr-xr-xtests/topotests/bgp-evpn-overlay-index-gateway/test_bgp_evpn_overlay_index_gateway.py3
-rw-r--r--tests/topotests/bgp_aggregate_address_topo1/test_bgp_aggregate_address_topo1.py2
-rw-r--r--tests/topotests/bgp_basic_functionality_topo1/test_bgp_basic_functionality.py8
-rw-r--r--tests/topotests/bgp_community_alias/test_bgp-community-alias.py2
-rw-r--r--tests/topotests/bgp_community_change_update/test_bgp_community_change_update.py2
-rw-r--r--tests/topotests/bgp_conditional_advertisement/test_bgp_conditional_advertisement.py2
-rw-r--r--tests/topotests/bgp_default_afi_safi/test_bgp-default-afi-safi.py2
-rw-r--r--tests/topotests/bgp_default_route/test_bgp_default-originate.py2
-rw-r--r--tests/topotests/bgp_default_route_route_map_match/test_bgp_default-originate_route-map_match.py2
-rw-r--r--tests/topotests/bgp_default_route_route_map_match2/test_bgp_default-originate_route-map_match2.py2
-rw-r--r--tests/topotests/bgp_default_route_route_map_match_set/test_bgp_default-originate_route-map_match_set.py3
-rw-r--r--tests/topotests/bgp_default_route_route_map_set/test_bgp_default-originate_route-map_set.py2
-rw-r--r--tests/topotests/bgp_distance_change/test_bgp_distance_change.py2
-rw-r--r--tests/topotests/bgp_dont_capability_negogiate/__init__.py0
-rw-r--r--tests/topotests/bgp_dont_capability_negogiate/r1/bgpd.conf6
-rw-r--r--tests/topotests/bgp_dont_capability_negogiate/r1/zebra.conf4
-rw-r--r--tests/topotests/bgp_dont_capability_negogiate/r2/bgpd.conf7
-rw-r--r--tests/topotests/bgp_dont_capability_negogiate/r2/zebra.conf7
-rw-r--r--tests/topotests/bgp_dont_capability_negogiate/test_bgp_dont_capability_negotiate.py110
-rw-r--r--tests/topotests/bgp_ebgp_common_subnet_nexthop_unchanged/test_bgp-ebgp-common-subnet-nexthop-unchanged.py2
-rw-r--r--tests/topotests/bgp_ebgp_requires_policy/test_bgp_ebgp_requires_policy.py2
-rw-r--r--tests/topotests/bgp_evpn_mh/test_evpn_mh.py24
-rw-r--r--tests/topotests/bgp_evpn_rt5/test_bgp_evpn.py1
-rw-r--r--tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1.py3
-rw-r--r--tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2.py3
-rw-r--r--tests/topotests/bgp_gshut/test_bgp_gshut.py2
-rw-r--r--tests/topotests/bgp_gshut_topo1/test_ebgp_gshut_topo1.py3
-rw-r--r--tests/topotests/bgp_gshut_topo1/test_ibgp_gshut_topo1.py3
-rw-r--r--tests/topotests/bgp_large_community/test_bgp_large_community_topo_1.py3
-rw-r--r--tests/topotests/bgp_large_community/test_bgp_large_community_topo_2.py3
-rw-r--r--tests/topotests/bgp_link_bw_ip/test_bgp_linkbw_ip.py3
-rwxr-xr-xtests/topotests/bgp_listen_on_multiple_addresses/test_bgp_listen_on_multiple_addresses.py6
-rw-r--r--tests/topotests/bgp_local_as_private_remove/test_bgp_local_as_private_remove.py2
-rw-r--r--tests/topotests/bgp_maximum_prefix_invalid_update/test_bgp_maximum_prefix_invalid_update.py2
-rw-r--r--tests/topotests/bgp_maximum_prefix_out/test_bgp_maximum_prefix_out.py2
-rw-r--r--tests/topotests/bgp_multi_vrf_topo1/test_bgp_multi_vrf_topo1.py1
-rw-r--r--tests/topotests/bgp_multiview_topo1/test_bgp_multiview_topo1.py4
-rw-r--r--tests/topotests/bgp_path_attributes_topo1/test_bgp_path_attributes.py3
-rwxr-xr-xtests/topotests/bgp_peer_type_multipath_relax/test_bgp_peer-type_multipath-relax.py2
-rw-r--r--tests/topotests/bgp_prefix_list_topo1/test_prefix_lists.py3
-rw-r--r--tests/topotests/bgp_prefix_sid/test_bgp_prefix_sid.py2
-rwxr-xr-xtests/topotests/bgp_prefix_sid2/test_bgp_prefix_sid2.py2
-rw-r--r--tests/topotests/bgp_reject_as_sets/test_bgp_reject_as_sets.py2
-rw-r--r--tests/topotests/bgp_route_aggregation/test_bgp_aggregation.py3
-rw-r--r--tests/topotests/bgp_route_map/test_route_map_topo1.py3
-rw-r--r--tests/topotests/bgp_route_map/test_route_map_topo2.py3
-rw-r--r--tests/topotests/bgp_rr_ibgp/test_bgp_rr_ibgp_topo1.py3
-rw-r--r--tests/topotests/bgp_set_local_preference_add_subtract/test_bgp_set_local-preference_add_subtract.py2
-rwxr-xr-xtests/topotests/bgp_srv6l3vpn_to_bgp_vrf/test_bgp_srv6l3vpn_to_bgp_vrf.py2
-rw-r--r--tests/topotests/bgp_suppress_fib/test_bgp_suppress_fib.py2
-rw-r--r--tests/topotests/bgp_tcp_mss/test_bgp_tcp_mss.py2
-rw-r--r--tests/topotests/bgp_update_delay/test_bgp_update_delay.py2
-rw-r--r--tests/topotests/bgp_vrf_dynamic_route_leak/test_bgp_vrf_dynamic_route_leak_topo1.py3
-rw-r--r--tests/topotests/bgp_vrf_dynamic_route_leak/test_bgp_vrf_dynamic_route_leak_topo2.py3
-rw-r--r--tests/topotests/bgp_vrf_lite_ipv6_rtadv/test_bgp_vrf_lite_ipv6_rtadv.py2
-rw-r--r--tests/topotests/bgp_vrf_netns/test_bgp_vrf_netns_topo.py3
-rw-r--r--tests/topotests/bgp_vrf_route_leak_basic/test_bgp-vrf-route-leak-basic.py2
-rw-r--r--tests/topotests/evpn_pim_1/leaf1/pimd.conf1
-rw-r--r--tests/topotests/evpn_pim_1/leaf2/pimd.conf1
-rw-r--r--tests/topotests/evpn_pim_1/spine/pimd.conf1
-rw-r--r--tests/topotests/evpn_pim_1/test_evpn_pim_topo1.py3
-rw-r--r--tests/topotests/evpn_type5_test_topo1/test_evpn_type5_chaos_topo1.py3
-rw-r--r--tests/topotests/evpn_type5_test_topo1/test_evpn_type5_topo1.py3
-rwxr-xr-xtests/topotests/isis_lsp_bits_topo1/test_isis_lsp_bits_topo1.py3
-rwxr-xr-xtests/topotests/isis_rlfa_topo1/test_isis_rlfa_topo1.py2
-rwxr-xr-xtests/topotests/isis_snmp/test_isis_snmp.py2
-rw-r--r--tests/topotests/ldp_snmp/test_ldp_snmp_topo1.py1
-rw-r--r--tests/topotests/ldp_sync_isis_topo1/test_ldp_sync_isis_topo1.py2
-rw-r--r--tests/topotests/lib/common_config.py2
-rw-r--r--tests/topotests/lib/ospf.py865
-rwxr-xr-xtests/topotests/lib/scapy_sendpkt.py61
-rw-r--r--tests/topotests/lib/topojson.py18
-rw-r--r--tests/topotests/msdp_mesh_topo1/r1/pimd.conf1
-rw-r--r--tests/topotests/msdp_mesh_topo1/r2/pimd.conf1
-rw-r--r--tests/topotests/msdp_mesh_topo1/r3/pimd.conf1
-rw-r--r--tests/topotests/msdp_topo1/r1/pimd.conf1
-rw-r--r--tests/topotests/msdp_topo1/r2/pimd.conf1
-rw-r--r--tests/topotests/msdp_topo1/r3/pimd.conf1
-rw-r--r--tests/topotests/msdp_topo1/r4/pimd.conf1
-rw-r--r--tests/topotests/multicast_pim_bsm_topo1/test_mcast_pim_bsmp_01.py3
-rw-r--r--tests/topotests/multicast_pim_bsm_topo2/test_mcast_pim_bsmp_02.py3
-rwxr-xr-xtests/topotests/multicast_pim_sm_topo1/test_multicast_pim_sm_topo1.py3
-rwxr-xr-xtests/topotests/multicast_pim_sm_topo2/test_multicast_pim_sm_topo2.py3
-rwxr-xr-xtests/topotests/multicast_pim_static_rp_topo1/test_multicast_pim_static_rp.py3
-rw-r--r--tests/topotests/nhrp_topo/test_nhrp_topo.py4
-rw-r--r--tests/topotests/ospf6_topo1/test_ospf6_topo1.py3
-rwxr-xr-xtests/topotests/ospf6_topo1_vrf/test_ospf6_topo1_vrf.py3
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_asbr_summary_topo1.py3
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_asbr_summary_type7_lsa.py3
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_authentication.py3
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_ecmp.py3
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_ecmp_lan.py3
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_lan.py3
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_nssa.py3
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_p2mp.py3
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_routemaps.py3
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py3
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_single_area.py1
-rw-r--r--tests/topotests/ospf_dual_stack/test_ospf_dual_stack.py3
-rw-r--r--tests/topotests/ospf_suppress_fa/test_ospf_suppress_fa.py2
-rw-r--r--tests/topotests/ospf_tilfa_topo1/test_ospf_tilfa_topo1.py2
-rw-r--r--tests/topotests/ospf_topo2/test_ospf_topo2.py2
-rw-r--r--tests/topotests/ospfv3_basic_functionality/ospfv3_asbr_summary_topo1.json198
-rw-r--r--tests/topotests/ospfv3_basic_functionality/ospfv3_ecmp.json347
-rw-r--r--tests/topotests/ospfv3_basic_functionality/ospfv3_routemaps.json137
-rw-r--r--tests/topotests/ospfv3_basic_functionality/test_ospfv3_asbr_summary_topo1.py1928
-rw-r--r--tests/topotests/ospfv3_basic_functionality/test_ospfv3_ecmp.py523
-rw-r--r--tests/topotests/ospfv3_basic_functionality/test_ospfv3_routemaps.py875
-rw-r--r--tests/topotests/ospfv3_basic_functionality/test_ospfv3_rte_calc.py231
-rw-r--r--tests/topotests/ospfv3_basic_functionality/test_ospfv3_single_area.py5
-rw-r--r--tests/topotests/pim_acl/r1/pimd.conf1
-rw-r--r--tests/topotests/pim_acl/r11/pimd.conf1
-rw-r--r--tests/topotests/pim_acl/r12/pimd.conf1
-rw-r--r--tests/topotests/pim_acl/r13/pimd.conf1
-rw-r--r--tests/topotests/pim_acl/r14/pimd.conf1
-rw-r--r--tests/topotests/pim_acl/r15/pimd.conf1
-rwxr-xr-xtests/topotests/pim_acl/test_pim_acl.py2
-rw-r--r--tests/topotests/pim_basic/r1/pimd.conf1
-rw-r--r--tests/topotests/pim_basic/rp/pimd.conf1
-rw-r--r--tests/topotests/pim_basic_topo2/r2/pimd.conf1
-rw-r--r--tests/topotests/pim_igmp_vrf/r1/pimd.conf1
-rw-r--r--tests/topotests/pim_igmp_vrf/r11/pimd.conf1
-rw-r--r--tests/topotests/pim_igmp_vrf/r12/pimd.conf1
-rwxr-xr-xtests/topotests/pim_igmp_vrf/test_pim_vrf.py2
-rw-r--r--tests/topotests/route_scale/test_route_scale.py3
-rwxr-xr-xtests/topotests/simple_snmp_test/test_simple_snmp.py10
-rwxr-xr-xtests/topotests/srv6_locator/test_srv6_locator.py2
-rw-r--r--tests/topotests/static_routing_with_ebgp/test_static_routes_topo4_ebgp.py3
-rw-r--r--tests/topotests/zebra_netlink/test_zebra_netlink.py3
-rw-r--r--tests/topotests/zebra_opaque/test_zebra_opaque.py2
-rw-r--r--tests/topotests/zebra_rib/test_zebra_rib.py8
-rwxr-xr-xtests/topotests/zebra_seg6_route/test_zebra_seg6_route.py2
-rwxr-xr-xtests/topotests/zebra_seg6local_route/test_zebra_seg6local_route.py2
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: