From d1b5fa5b9e47b248a8d9f21238c850c0a08531f4 Mon Sep 17 00:00:00 2001 From: nguggarigoud Date: Mon, 2 Aug 2021 18:18:29 -0700 Subject: [PATCH] tests: adding ospfv3 base cases. Covers basic test case like route map, rte calc. Signed-off-by: nguggarigoud --- tests/topotests/lib/common_config.py | 7 +- tests/topotests/lib/ospf.py | 8 +- tests/topotests/lib/topotest.py | 1 + .../ospfv3_asbr_summary_type7_lsa.json | 202 +++ .../ospfv3_dual_stack.json | 312 +++++ .../ospfv3_ecmp.json | 36 +- .../ospfv3_ecmp_lan.json | 264 ++++ .../ospfv3_lan.json | 140 ++ .../ospfv3_nssa2.json | 197 +++ .../ospfv3_routemaps.json | 59 +- .../ospfv3_rte_calc.json | 17 + .../test_ospfv3_asbr_summary_topo1.py | 1200 +++++++++++++++-- .../test_ospfv3_ecmp_lan.py | 400 ++++++ .../test_ospfv3_nssa2.py | 482 +++++++ .../test_ospfv3_routemaps.py | 416 +++++- .../test_ospfv3_rte_calc.py | 375 +++++- .../test_ospfv3_single_area.py | 957 +++++++++++++ 17 files changed, 4921 insertions(+), 152 deletions(-) create mode 100644 tests/topotests/ospfv3_basic_functionality/ospfv3_asbr_summary_type7_lsa.json create mode 100644 tests/topotests/ospfv3_basic_functionality/ospfv3_dual_stack.json create mode 100644 tests/topotests/ospfv3_basic_functionality/ospfv3_ecmp_lan.json create mode 100644 tests/topotests/ospfv3_basic_functionality/ospfv3_lan.json create mode 100644 tests/topotests/ospfv3_basic_functionality/ospfv3_nssa2.json create mode 100644 tests/topotests/ospfv3_basic_functionality/test_ospfv3_ecmp_lan.py create mode 100644 tests/topotests/ospfv3_basic_functionality/test_ospfv3_nssa2.py diff --git a/tests/topotests/lib/common_config.py b/tests/topotests/lib/common_config.py index c0572fca4c..005896b01c 100644 --- a/tests/topotests/lib/common_config.py +++ b/tests/topotests/lib/common_config.py @@ -2536,6 +2536,7 @@ def create_route_maps(tgen, input_dict, build=False): ipv6_data = set_data.setdefault("ipv6", {}) local_preference = set_data.setdefault("locPrf", None) metric = set_data.setdefault("metric", None) + metric_type = set_data.setdefault("metric-type", None) as_path = set_data.setdefault("path", {}) weight = set_data.setdefault("weight", None) community = set_data.setdefault("community", {}) @@ -2559,7 +2560,11 @@ def create_route_maps(tgen, input_dict, build=False): # Metric if metric: - rmap_data.append("set metric {} \n".format(metric)) + del_comm = set_data.setdefault("delete", None) + if del_comm: + rmap_data.append("no set metric {}".format(metric)) + else: + rmap_data.append("set metric {}".format(metric)) # Origin if origin: diff --git a/tests/topotests/lib/ospf.py b/tests/topotests/lib/ospf.py index 8d2bf12af2..e7ea7d32ba 100644 --- a/tests/topotests/lib/ospf.py +++ b/tests/topotests/lib/ospf.py @@ -1668,7 +1668,7 @@ def verify_ospf6_rib( logger.info("Checking router %s RIB:", router) # Verifying RIB routes - command = "show ipv6 ospf route" + command = "show ipv6 ospf route detail" found_routes = [] missing_routes = [] @@ -1710,6 +1710,8 @@ def verify_ospf6_rib( # Generating IPs for verification ip_list = generate_ips(network, no_of_ip) + if len(ip_list) == 1: + ip_list = [network] st_found = False nh_found = False for st_rt in ip_list: @@ -1846,7 +1848,7 @@ def verify_ospf6_rib( return errormsg if metric is not None: - if "type2cost" not in ospf_rib_json[st_rt]: + if "metricCostE2" not in ospf_rib_json[st_rt]: errormsg = ( "[DUT: {}]: metric is" " not present for" @@ -1854,7 +1856,7 @@ def verify_ospf6_rib( ) return errormsg - if metric != ospf_rib_json[st_rt]["type2cost"]: + if metric != ospf_rib_json[st_rt]["metricCostE2"]: errormsg = ( "[DUT: {}]: metric value " "{} is not matched for " diff --git a/tests/topotests/lib/topotest.py b/tests/topotests/lib/topotest.py index 62b6a8a70e..e786ae02cd 100644 --- a/tests/topotests/lib/topotest.py +++ b/tests/topotests/lib/topotest.py @@ -737,6 +737,7 @@ def proto_name_to_number(protocol): "sharp": "194", "pbr": "195", "static": "196", + "ospf6": "197", }.get( protocol, protocol ) # default return same as input diff --git a/tests/topotests/ospfv3_basic_functionality/ospfv3_asbr_summary_type7_lsa.json b/tests/topotests/ospfv3_basic_functionality/ospfv3_asbr_summary_type7_lsa.json new file mode 100644 index 0000000000..27b36aea17 --- /dev/null +++ b/tests/topotests/ospfv3_basic_functionality/ospfv3_asbr_summary_type7_lsa.json @@ -0,0 +1,202 @@ +{ + "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.2", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r2": { + "ipv6": "auto" + }, + "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", + "area": [ + { + "id": "0.0.0.2", + "type": "nssa" + } + ], + "neighbors": { + "r1": {}, + "r3": {} + } + } + }, + "r1": { + "links": { + "lo": { + "ipv6": "auto", + "type": "loopback" + }, + "r0": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.2", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r2": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.2", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r3": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.2", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r3-link0": { + "ipv6": "auto", + "description": "DummyIntftoR3" + } + }, + "ospf6": { + "router_id": "100.1.1.1", + "area": [ + { + "id": "0.0.0.2", + "type": "nssa" + } + ], + "neighbors": { + "r0": {}, + "r2": {}, + "r3": {} + } + } + }, + "r2": { + "links": { + "lo": { + "ipv6": "auto", + "type": "loopback" + }, + "r0": { + "ipv6": "auto" + }, + "r1": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.2", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r3": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.2", + "hello_interval": 1, + "dead_interval": 4 + } + } + }, + "ospf6": { + "router_id": "100.1.1.2", + "area": [ + { + "id": "0.0.0.2", + "type": "nssa" + } + ], + "neighbors": { + "r1": {}, + "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.2", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r2": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.2", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r1-link0": { + "ipv6": "auto", + "description": "DummyIntftoR1", + "ospf6": { + "area": "0.0.0.3" + } + } + }, + "ospf6": { + "router_id": "100.1.1.3", + "area": [ + { + "id": "0.0.0.2", + "type": "nssa" + } + ], + "neighbors": { + "r0": {}, + "r1": {}, + "r2": {} + } + } + } + } +} \ No newline at end of file diff --git a/tests/topotests/ospfv3_basic_functionality/ospfv3_dual_stack.json b/tests/topotests/ospfv3_basic_functionality/ospfv3_dual_stack.json new file mode 100644 index 0000000000..5555d9291e --- /dev/null +++ b/tests/topotests/ospfv3_basic_functionality/ospfv3_dual_stack.json @@ -0,0 +1,312 @@ +{ + "address_types": [ + "ipv4", + "ipv6" + ], + "ipv4base": "10.0.0.0", + "ipv4mask": 30, + "ipv6base": "fd00::", + "ipv6mask": 64, + "link_ip_start": { + "ipv4": "10.0.0.0", + "v4mask": 30, + "ipv6": "fd00::", + "v6mask": 64 + }, + "lo_prefix": { + "ipv4": "1.0.", + "v4mask": 32, + "ipv6": "2001:db8:f::", + "v6mask": 128 + }, + "routers": { + "r0": { + "links": { + "lo": { + "ipv4": "auto", + "ipv6": "auto", + "type": "loopback" + }, + "r1": { + "ipv4": "auto", + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + }, + "ospf": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r2": { + "ipv4": "auto", + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + }, + "ospf": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r3": { + "ipv4": "auto", + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4, + "network": "point-to-point" + }, + "ospf": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4, + "network": "point-to-point" + } + } + }, + "ospf6": { + "router_id": "100.1.1.0", + "neighbors": { + "r1": {}, + "r2": {}, + "r3": {} + } + }, + "ospf": { + "router_id": "100.1.1.0", + "neighbors": { + "r1": {}, + "r2": {}, + "r3": {} + } + } + }, + "r1": { + "links": { + "lo": { + "ipv4": "auto", + "ipv6": "auto", + "type": "loopback" + }, + "r0": { + "ipv4": "auto", + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + }, + "ospf": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r2": { + "ipv4": "auto", + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + }, + "ospf": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r3": { + "ipv4": "auto", + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + }, + "ospf": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r3-link0": { + "ipv4": "auto", + "ipv6": "auto", + "description": "DummyIntftoR3" + } + }, + "ospf6": { + "router_id": "100.1.1.1", + "neighbors": { + "r0": {}, + "r2": {}, + "r3": {} + } + }, + "ospf": { + "router_id": "100.1.1.1", + "neighbors": { + "r0": {}, + "r2": {}, + "r3": {} + } + } + }, + "r2": { + "links": { + "lo": { + "ipv4": "auto", + "ipv6": "auto", + "type": "loopback" + }, + "r0": { + "ipv4": "auto", + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + }, + "ospf": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r1": { + "ipv4": "auto", + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + }, + "ospf": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r3": { + "ipv4": "auto", + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + }, + "ospf": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + } + }, + "ospf6": { + "router_id": "100.1.1.2", + "neighbors": { + "r1": {}, + "r0": {}, + "r3": {} + } + }, + "ospf": { + "router_id": "100.1.1.2", + "neighbors": { + "r1": {}, + "r0": {}, + "r3": {} + } + } + }, + "r3": { + "links": { + "lo": { + "ipv4": "auto", + "ipv6": "auto", + "type": "loopback" + }, + "r0": { + "ipv4": "auto", + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4, + "network": "point-to-point" + }, + "ospf": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4, + "network": "point-to-point" + } + }, + "r1": { + "ipv4": "auto", + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + }, + "ospf": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r2": { + "ipv4": "auto", + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + }, + "ospf": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r1-link0": { + "ipv4": "auto", + "ipv6": "auto", + "description": "DummyIntftoR1", + "ospf6": { + "area": "0.0.0.0" + }, + "ospf": { + "area": "0.0.0.0" + } + } + }, + "ospf6": { + "router_id": "1.0.4.17", + "neighbors": { + "r0": {}, + "r1": {}, + "r2": {} + } + }, + "ospf": { + "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 index c928093925..22f46e2bf6 100644 --- a/tests/topotests/ospfv3_basic_functionality/ospfv3_ecmp.json +++ b/tests/topotests/ospfv3_basic_functionality/ospfv3_ecmp.json @@ -2,6 +2,7 @@ "address_types": [ "ipv6" ], + "ipv6base": "fd00::", "ipv6mask": 64, "link_ip_start": { @@ -9,6 +10,7 @@ "v6mask": 64 }, "lo_prefix": { + "ipv6": "2001:db8:f::", "v6mask": 128 }, @@ -21,6 +23,7 @@ }, "r1": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -29,6 +32,7 @@ }, "r1-link1": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -37,6 +41,7 @@ }, "r1-link2": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -45,6 +50,7 @@ }, "r1-link3": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -53,6 +59,7 @@ }, "r1-link4": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -61,6 +68,7 @@ }, "r1-link5": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -69,6 +77,7 @@ }, "r1-link6": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -77,6 +86,7 @@ }, "r1-link7": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -85,6 +95,7 @@ }, "r2": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -93,6 +104,7 @@ }, "r3": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -101,6 +113,7 @@ } } }, + "ospf6": { "router_id": "100.1.1.0", "neighbors": { @@ -139,6 +152,7 @@ }, "r0": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -147,6 +161,7 @@ }, "r0-link1": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -155,6 +170,7 @@ }, "r0-link2": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -163,6 +179,7 @@ }, "r0-link3": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -171,6 +188,7 @@ }, "r0-link4": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -179,6 +197,7 @@ }, "r0-link5": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -187,6 +206,7 @@ }, "r0-link6": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -195,6 +215,7 @@ }, "r0-link7": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -203,6 +224,7 @@ }, "r2": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -211,6 +233,7 @@ }, "r3": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -222,6 +245,7 @@ "description": "DummyIntftoR3" } }, + "ospf6": { "router_id": "100.1.1.1", "neighbors": { @@ -260,6 +284,7 @@ }, "r0": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -268,6 +293,7 @@ }, "r1": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -276,6 +302,7 @@ }, "r3": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -283,6 +310,7 @@ } } }, + "ospf6": { "router_id": "100.1.1.2", "neighbors": { @@ -300,6 +328,7 @@ }, "r0": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -309,6 +338,7 @@ }, "r1": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -317,6 +347,7 @@ }, "r2": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -326,14 +357,13 @@ "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": { diff --git a/tests/topotests/ospfv3_basic_functionality/ospfv3_ecmp_lan.json b/tests/topotests/ospfv3_basic_functionality/ospfv3_ecmp_lan.json new file mode 100644 index 0000000000..53b3f49e62 --- /dev/null +++ b/tests/topotests/ospfv3_basic_functionality/ospfv3_ecmp_lan.json @@ -0,0 +1,264 @@ +{ + "address_types": [ + "ipv6" + ], + "ipv6base": "fd00::", + "ipv6mask": 64, + "link_ip_start": { + "ipv6": "fd00::", + "v6mask": 64 + }, + "lo_prefix": { + "ipv6": "2001:db8:f::", + "v6mask": 128 + }, + "switches": { + "s1": { + "links": { + "r0": { + + "ipv6": "auto", + + "ospf6": { + "area": "0.0.0.3", + "hello_interval": 1, + "dead_interval": 4, + "priority": 98 + } + }, + "r1": { + + "ipv6": "auto", + + "ospf6": { + "area": "0.0.0.3", + "hello_interval": 1, + "dead_interval": 4, + "priority": 99 + } + }, + "r2": { + + "ipv6": "auto", + + "ospf6": { + "area": "0.0.0.3", + "hello_interval": 1, + "dead_interval": 4, + "priority": 0 + } + }, + "r3": { + + "ipv6": "auto", + + "ospf6": { + "area": "0.0.0.3", + "hello_interval": 1, + "dead_interval": 4, + "priority": 0 + } + }, + "r4": { + + "ipv6": "auto", + + "ospf6": { + "area": "0.0.0.3", + "hello_interval": 1, + "dead_interval": 4, + "priority": 0 + } + }, + "r5": { + + "ipv6": "auto", + + "ospf6": { + "area": "0.0.0.3", + "hello_interval": 1, + "dead_interval": 4, + "priority": 0 + } + }, + "r6": { + + "ipv6": "auto", + + "ospf6": { + "area": "0.0.0.3", + "hello_interval": 1, + "dead_interval": 4, + "priority": 0 + } + }, + "r7": { + + "ipv6": "auto", + + "ospf6": { + "area": "0.0.0.3", + "hello_interval": 1, + "dead_interval": 4, + "priority": 0 + } + } + } + } + }, + "routers": { + "r0": { + "links": { + "lo": { + + "ipv6": "auto", + "type": "loopback" + } + }, + "ospf6": { + "router_id": "100.1.1.0", + "neighbors": { + "r1": {}, + "r2": {}, + "r3": {}, + "r4": {}, + "r5": {}, + "r6": {}, + "r7": {} + } + } + }, + "r1": { + "links": { + "lo": { + + "ipv6": "auto", + "type": "loopback" + }, + "r3-link0": { + + "ipv6": "auto", + "description": "DummyIntftoR3" + } + }, + "ospf6": { + "router_id": "100.1.1.1", + "neighbors": { + "r0": {}, + "r2": {}, + "r3": {}, + "r4": {}, + "r5": {}, + "r6": {}, + "r7": {} + } + } + }, + "r2": { + "links": { + "lo": { + + "ipv6": "auto", + "type": "loopback" + } + }, + "ospf6": { + "router_id": "100.1.1.2", + "neighbors": { + "r1": {}, + "r0": {} + } + } + }, + "r3": { + "links": { + "lo": { + + "ipv6": "auto", + "type": "loopback" + }, + "r1-link0": { + + "ipv6": "auto", + "description": "DummyIntftoR1" + + } + }, + + "ospf6": { + "router_id": "100.1.1.3", + "neighbors": { + "r0": {}, + "r1": {} + } + } + }, + "r4": { + "links": { + "lo": { + + "ipv6": "auto", + "type": "loopback" + } + }, + + "ospf6": { + "router_id": "100.1.1.4", + "neighbors": { + "r0": {}, + "r1": {} + } + } + }, + "r5": { + "links": { + "lo": { + + "ipv6": "auto", + "type": "loopback" + } + }, + "ospf6": { + "router_id": "100.1.1.5", + "neighbors": { + "r0": {}, + "r1": {} + } + } + }, + "r6": { + "links": { + "lo": { + + "ipv6": "auto", + "type": "loopback" + } + }, + + "ospf6": { + "router_id": "100.1.1.6", + "neighbors": { + "r0": {}, + "r1": {} + } + } + }, + "r7": { + "links": { + "lo": { + + "ipv6": "auto", + "type": "loopback" + } + }, + + "ospf6": { + "router_id": "100.1.1.7", + "neighbors": { + "r0": {}, + "r1": {} + } + } + } + } +} \ No newline at end of file diff --git a/tests/topotests/ospfv3_basic_functionality/ospfv3_lan.json b/tests/topotests/ospfv3_basic_functionality/ospfv3_lan.json new file mode 100644 index 0000000000..3a2fc022e5 --- /dev/null +++ b/tests/topotests/ospfv3_basic_functionality/ospfv3_lan.json @@ -0,0 +1,140 @@ +{ + "address_types": [ + "ipv6" + ], + + "ipv6base": "fd00::", + "ipv6mask": 64, + "link_ip_start": { + + "ipv6": "fd00::", + "v6mask": 64 + }, + "lo_prefix": { + + "ipv6": "2001:db8:f::", + "v6mask": 128 + }, + "switches": { + "s1": { + "links": { + "r0": { + "ipv6": "auto", + + "ospf6": { + "area": "0.0.0.3", + "hello_interval": 1, + "dead_interval": 4, + "priority": 98 + } + }, + "r1": { + "ipv6": "auto", + + "ospf6": { + "area": "0.0.0.3", + "hello_interval": 1, + "dead_interval": 4, + "priority": 99 + } + }, + "r2": { + "ipv6": "auto", + + "ospf6": { + "area": "0.0.0.3", + "hello_interval": 1, + "dead_interval": 4, + "priority": 0 + } + }, + "r3": { + "ipv6": "auto", + + "ospf6": { + "area": "0.0.0.3", + "hello_interval": 1, + "dead_interval": 4, + "priority": 0 + } + } + } + } + }, + "routers": { + "r0": { + "links": { + "lo": { + "ipv6": "auto", + "type": "loopback" + } + }, + + "ospf6": { + "router_id": "100.1.1.0", + "neighbors": { + "r1": {}, + "r2": {}, + "r3": {} + } + } + }, + "r1": { + "links": { + "lo": { + "ipv6": "auto", + "type": "loopback" + }, + "r3-link0": { + "ipv6": "auto", + "description": "DummyIntftoR3" + } + }, + + "ospf6": { + "router_id": "100.1.1.1", + "neighbors": { + "r0": {}, + "r2": {}, + "r3": {} + } + } + }, + "r2": { + "links": { + "lo": { + "ipv6": "auto", + "type": "loopback" + } + }, + + "ospf6": { + "router_id": "100.1.1.2", + "neighbors": { + "r1": {}, + "r0": {} + } + } + }, + "r3": { + "links": { + "lo": { + "ipv6": "auto", + "type": "loopback" + }, + "r1-link0": { + "ipv6": "auto", + "description": "DummyIntftoR1" + } + }, + + "ospf6": { + "router_id": "100.1.1.3", + "neighbors": { + "r0": {}, + "r1": {} + } + } + } + } +} \ No newline at end of file diff --git a/tests/topotests/ospfv3_basic_functionality/ospfv3_nssa2.json b/tests/topotests/ospfv3_basic_functionality/ospfv3_nssa2.json new file mode 100644 index 0000000000..b1432b9bee --- /dev/null +++ b/tests/topotests/ospfv3_basic_functionality/ospfv3_nssa2.json @@ -0,0 +1,197 @@ + +{ + "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" + }, + "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": {}, + "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.2", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r3": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.2", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r3-link0": { + "ipv6": "auto", + "description": "DummyIntftoR3" + } + }, + "ospf6": { + "router_id": "100.1.1.1", + "area": [ + { + "id": "0.0.0.2", + "type": "nssa" + } + ], + "neighbors": { + "r0": {}, + "r2": {}, + "r3": {} + } + } + }, + "r2": { + "links": { + "lo": { + "ipv6": "auto", + "type": "loopback" + }, + "r0": { + "ipv6": "auto" + }, + "r1": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.2", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r3": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.2", + "hello_interval": 1, + "dead_interval": 4 + } + } + }, + "ospf6": { + "router_id": "100.1.1.2", + "area": [ + { + "id": "0.0.0.2", + "type": "nssa" + } + ], + "neighbors": { + "r1": {}, + "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.2", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r2": { + "ipv6": "auto", + "ospf6": { + "area": "0.0.0.2", + "hello_interval": 1, + "dead_interval": 4 + } + }, + "r1-link0": { + "ipv6": "auto", + "description": "DummyIntftoR1", + "ospf6": { + "area": "0.0.0.3" + } + } + }, + "ospf6": { + "router_id": "100.1.1.3", + "area": [ + { + "id": "0.0.0.2", + "type": "nssa" + } + ], + "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 index 226f84f320..a1c7bd72d4 100644 --- a/tests/topotests/ospfv3_basic_functionality/ospfv3_routemaps.json +++ b/tests/topotests/ospfv3_basic_functionality/ospfv3_routemaps.json @@ -1,14 +1,26 @@ { - "address_types": ["ipv6"], + "address_types": [ + "ipv6" + ], + "ipv6base": "fd00::", "ipv6mask": 64, - "link_ip_start": {"ipv6": "fd00::", "v6mask": 64}, - "lo_prefix": {"ipv6": "2001:db8:f::", "v6mask": 128}, + "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, @@ -17,6 +29,7 @@ }, "r2": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -25,6 +38,7 @@ }, "r3": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -32,15 +46,21 @@ } } }, + "ospf6": { "router_id": "100.1.1.0", - "neighbors": {"r1": {}, "r2": {}, "r3": {}} + "neighbors": { + "r1": {}, + "r2": {}, + "r3": {} + } } }, "r1": { "links": { "r0": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -49,6 +69,7 @@ }, "r2": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -57,6 +78,7 @@ }, "r3": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -64,15 +86,21 @@ } } }, + "ospf6": { "router_id": "100.1.1.1", - "neighbors": {"r0": {}, "r2": {}, "r3": {}} + "neighbors": { + "r0": {}, + "r2": {}, + "r3": {} + } } }, "r2": { "links": { "r0": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -81,6 +109,7 @@ }, "r1": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -89,6 +118,7 @@ }, "r3": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -96,15 +126,21 @@ } } }, + "ospf6": { "router_id": "100.1.1.2", - "neighbors": {"r1": {}, "r0": {}, "r3": {}} + "neighbors": { + "r1": {}, + "r0": {}, + "r3": {} + } } }, "r3": { "links": { "r0": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -113,6 +149,7 @@ }, "r1": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -121,6 +158,7 @@ }, "r2": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -128,10 +166,15 @@ } } }, + "ospf6": { "router_id": "100.1.1.3", - "neighbors": {"r0": {}, "r1": {}, "r2": {}} + "neighbors": { + "r0": {}, + "r1": {}, + "r2": {} + } } } } -} +} \ No newline at end of file diff --git a/tests/topotests/ospfv3_basic_functionality/ospfv3_rte_calc.json b/tests/topotests/ospfv3_basic_functionality/ospfv3_rte_calc.json index 3669b3a554..e70481ace9 100644 --- a/tests/topotests/ospfv3_basic_functionality/ospfv3_rte_calc.json +++ b/tests/topotests/ospfv3_basic_functionality/ospfv3_rte_calc.json @@ -5,13 +5,16 @@ "address_types": [ "ipv6" ], + "ipv6base": "fd00::", "ipv6mask": 64, "link_ip_start": { + "ipv6": "fd00::", "v6mask": 64 }, "lo_prefix": { + "ipv6": "2001:db8:f::", "v6mask": 128 }, @@ -24,6 +27,7 @@ }, "r1": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -32,6 +36,7 @@ }, "r2": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -40,6 +45,7 @@ }, "r3": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -47,6 +53,7 @@ } } }, + "ospf6": { "router_id": "100.1.1.0", "neighbors": { @@ -63,6 +70,7 @@ }, "r0": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -71,6 +79,7 @@ }, "r2": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -79,6 +88,7 @@ }, "r3": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -86,6 +96,7 @@ } } }, + "ospf6": { "router_id": "100.1.1.1", "neighbors": { @@ -103,6 +114,7 @@ }, "r0": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -111,6 +123,7 @@ }, "r1": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -119,6 +132,7 @@ }, "r3": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -126,6 +140,7 @@ } } }, + "ospf6": { "router_id": "100.1.1.2", "neighbors": { @@ -146,6 +161,7 @@ }, "r1": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, @@ -154,6 +170,7 @@ }, "r2": { "ipv6": "auto", + "ospf6": { "area": "0.0.0.0", "hello_interval": 1, 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 index 47333fcb39..10c51a6784 100644 --- a/tests/topotests/ospfv3_basic_functionality/test_ospfv3_asbr_summary_topo1.py +++ b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_asbr_summary_topo1.py @@ -56,6 +56,7 @@ from lib.common_config import ( create_prefix_lists, create_route_maps, topo_daemons, + create_interfaces_cfg, ) from lib.topolog import logger from lib.topojson import build_config_from_json @@ -747,6 +748,1084 @@ def test_ospfv3_type5_summary_tc42_p0(request): write_test_footer(tc_name) +def test_ospfv3_type5_summary_tc43_p0(request): + """OSPF summarisation with metric type 2.""" + 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("Change the summary address mask to lower match (ex - 16 to 8)") + ospf_summ_r1 = { + "r0": { + "ospf6": { + "summary-address": [ + {"prefix": SUMMARY["ipv6"][0].split("/")[0], "mask": "16"}, + { + "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) + + sleep(5) + + input_dict = { + "2011::/16": { + "Summary address": "2011::/16", + "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 external routes(static / connected) are summarised" + " to configured summary address with newly configured mask." + ) + + input_dict_summary = {"r0": {"static_routes": [{"network": "2011::0/16"}]}} + 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("Change the summary address mask to higher match (ex - 8 to 24)") + 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 = { + "2011::/32": { + "Summary address": "2011::/32", + "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) + + step( + "Verify that external routes(static / connected) are summarised" + " to configured summary address with newly configured mask." + ) + step("Configure 2 summary address with different mask of same network.") + step( + "Verify that external routes(static / connected) are summarised " + "to configured summary address with highest match." + ) + + input_dict_summary = {"r0": {"static_routes": [{"network": "2011::0/32"}]}} + 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(" Un configure one of the summary address.") + 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) + + sleep(5) + + step( + "Verify that external routes(static / connected) are summarised" + " to configured summary address with newly configured mask." + ) + + input_dict_summary = {"r0": {"static_routes": [{"network": "2011::0/16"}]}} + 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": "16"} + ] + } + } + } + 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(static / connected) are summarised " + "to configured summary address with highest match." + ) + input_dict_summary = {"r0": {"static_routes": [{"network": "2011::0/16"}]}} + 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) + + write_test_footer(tc_name) + + +def ospfv3_type5_summary_tc45_p0(request): + """OSPF summarisation with Tag 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." + ) + ospf_summ_r1 = { + "r0": { + "ospf6": { + "summary-address": [ + { + "prefix": SUMMARY["ipv6"][0].split("/")[0], + "mask": "32", + "tag": "1234", + } + ] + } + } + } + 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 with configured tag." + ) + input_dict_summary = { + "r0": {"static_routes": [{"network": SUMMARY["ipv6"][0], "tag": "1234"}]} + } + 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 with tag.") + 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") + 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", + "tag": "1234", + "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": 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("Configure Min tag value") + ospf_summ_r1 = { + "r0": { + "ospf6": { + "summary-address": [ + {"prefix": SUMMARY["ipv6"][0].split("/")[0], "mask": "32", "tag": 1} + ] + } + } + } + result = create_router_ospf(tgen, topo, ospf_summ_r1) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + input_dict_summary = { + "r0": {"static_routes": [{"network": SUMMARY["ipv6"][0], "tag": "1"}]} + } + 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 with tag.") + input_dict = { + SUMMARY["ipv6"][0]: { + "Summary address": SUMMARY["ipv6"][0], + "Metric-type": "E2", + "Metric": 20, + "Tag": 1, + "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 Max Tag Value") + ospf_summ_r1 = { + "r0": { + "ospf6": { + "summary-address": [ + { + "prefix": SUMMARY["ipv6"][0].split("/")[0], + "mask": "32", + "tag": 4294967295, + } + ] + } + } + } + result = create_router_ospf(tgen, topo, ospf_summ_r1) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + input_dict_summary = { + "r0": {"static_routes": [{"network": SUMMARY["ipv6"][0], "tag": "4294967295"}]} + } + 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 boundary values tags are used for summary route" + " using show ip ospf route command." + ) + input_dict = { + SUMMARY["ipv6"][0]: { + "Summary address": SUMMARY["ipv6"][0], + "Metric-type": "E2", + "Metric": 20, + "Tag": 4294967295, + "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 with different tag.") + input_dict_static_rtes_11 = { + "r0": { + "static_routes": [ + {"network": NETWORK_11["ipv6"], "next_hop": "blackhole", "tag": "88888"} + ] + } + } + result = create_static_routes(tgen, input_dict_static_rtes_11) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("New tag has not been used by summary address.") + + input_dict_summary = { + "r0": {"static_routes": [{"network": SUMMARY["ipv6"][0], "tag": "88888"}]} + } + dut = "r1" + + result = verify_ospf6_rib( + tgen, dut, input_dict_summary, tag="88888", 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, + tag="88888", + expected=False, + ) + assert ( + result is not True + ), "Testcase {} : Failed" "Error: Routes still present in RIB".format(tc_name) + + step( + "Verify that boundary values tags are used for summary route" + " using show ip ospf route command." + ) + input_dict = { + SUMMARY["ipv6"][0]: { + "Summary address": SUMMARY["ipv6"][0], + "Metric-type": "E2", + "Metric": 20, + "Tag": 88888, + "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 missing in OSPF DB".format(tc_name) + + step("Delete the configured summary address") + ospf_summ_r1 = { + "r0": { + "ospf6": { + "summary-address": [ + { + "prefix": SUMMARY["ipv6"][0].split("/")[0], + "mask": "32", + "tag": 4294967295, + "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 6 routes are advertised to neighbour with 5 routes" + " without any tag, 1 route with tag." + ) + + 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("Verify that summary address is flushed from neighbor.") + + 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("Configure summary first & then configure matching static route.") + + input_dict_static_rtes = { + "r0": { + "static_routes": [ + {"network": NETWORK["ipv6"], "next_hop": "blackhole", "delete": True}, + {"network": NETWORK2["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) + + 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_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) + + step("Repeat steps 1 to 10 of summarisation in non Back bone area.") + reset_config_on_routers(tgen) + + step("Change the area id on the interface on R0") + input_dict = { + "r0": { + "links": { + "r1": { + "interface": topo["routers"]["r0"]["links"]["r1"]["interface"], + "ospf6": {"area": "0.0.0.0"}, + "delete": True, + } + } + } + } + + result = create_interfaces_cfg(tgen, input_dict) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + input_dict = { + "r0": { + "links": { + "r1": { + "interface": topo["routers"]["r0"]["links"]["r1"]["interface"], + "ospf6": {"area": "0.0.0.1"}, + } + } + } + } + + result = create_interfaces_cfg(tgen, input_dict) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + step("Change the area id on the interface ") + input_dict = { + "r1": { + "links": { + "r0": { + "interface": topo["routers"]["r1"]["links"]["r0"]["interface"], + "ospf6": {"area": "0.0.0.0"}, + "delete": True, + } + } + } + } + + result = create_interfaces_cfg(tgen, input_dict) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + input_dict = { + "r1": { + "links": { + "r0": { + "interface": topo["routers"]["r1"]["links"]["r0"]["interface"], + "ospf6": {"area": "0.0.0.1"}, + } + } + } + } + + result = create_interfaces_cfg(tgen, input_dict) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + ospf_covergence = verify_ospf6_neighbor(tgen, topo) + assert ospf_covergence is True, "Testcase {} :Failed \n Error: {}".format( + tc_name, ospf_covergence + ) + + 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", + "tag": "1234", + } + ] + } + } + } + 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 with configured tag." + ) + input_dict_summary = { + "r0": {"static_routes": [{"network": SUMMARY["ipv6"][0], "tag": "1234"}]} + } + 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 with tag.") + 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") + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + 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("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("Configure Min tag value") + ospf_summ_r1 = { + "r0": { + "ospf6": { + "summary-address": [ + {"prefix": SUMMARY["ipv6"][0].split("/")[0], "mask": "32", "tag": 1} + ] + } + } + } + result = create_router_ospf(tgen, topo, ospf_summ_r1) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + input_dict_summary = { + "r0": {"static_routes": [{"network": SUMMARY["ipv6"][0], "tag": "1"}]} + } + 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 with tag.") + input_dict = { + SUMMARY["ipv6"][0]: { + "Summary address": SUMMARY["ipv6"][0], + "Metric-type": "E2", + "Metric": 20, + "Tag": 1, + "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 Max Tag Value") + ospf_summ_r1 = { + "r0": { + "ospf6": { + "summary-address": [ + { + "prefix": SUMMARY["ipv6"][0].split("/")[0], + "mask": "32", + "tag": 4294967295, + } + ] + } + } + } + result = create_router_ospf(tgen, topo, ospf_summ_r1) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + input_dict_summary = { + "r0": {"static_routes": [{"network": SUMMARY["ipv6"][0], "tag": "4294967295"}]} + } + 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 boundary values tags are used for summary route" + " using show ip ospf route command." + ) + input_dict = { + SUMMARY["ipv6"][0]: { + "Summary address": SUMMARY["ipv6"][0], + "Metric-type": "E2", + "Metric": 20, + "Tag": 4294967295, + "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 with different tag.") + input_dict_static_rtes_11 = { + "r0": { + "static_routes": [ + {"network": NETWORK_11["ipv6"], "next_hop": "blackhole", "tag": "88888"} + ] + } + } + result = create_static_routes(tgen, input_dict_static_rtes_11) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("New tag has not been used by summary address.") + + input_dict_summary = { + "r0": {"static_routes": [{"network": SUMMARY["ipv6"][0], "tag": "88888"}]} + } + dut = "r1" + + result = verify_ospf6_rib( + tgen, dut, input_dict_summary, tag="88888", 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, + tag="88888", + expected=False, + ) + assert ( + result is not True + ), "Testcase {} : Failed" "Error: Routes still present in RIB".format(tc_name) + + step( + "Verify that boundary values tags are used for summary route" + " using show ip ospf route command." + ) + input_dict = { + SUMMARY["ipv6"][0]: { + "Summary address": SUMMARY["ipv6"][0], + "Metric-type": "E2", + "Metric": 20, + "Tag": 88888, + "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 missing in OSPF DB".format(tc_name) + + step("Delete the configured summary address") + ospf_summ_r1 = { + "r0": { + "ospf6": { + "summary-address": [ + { + "prefix": SUMMARY["ipv6"][0].split("/")[0], + "mask": "32", + "tag": 4294967295, + "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 6 routes are advertised to neighbour with 5 routes" + " without any tag, 1 route with tag." + ) + + 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("Verify that summary address is flushed from neighbor.") + + 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("Configure summary first & then configure matching static route.") + + input_dict_static_rtes = { + "r0": { + "static_routes": [ + {"network": NETWORK["ipv6"], "next_hop": "blackhole", "delete": True}, + {"network": NETWORK2["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) + + 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_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) + + 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 @@ -1657,127 +2736,6 @@ def test_ospfv3_type5_summary_tc49_p2(request): 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) diff --git a/tests/topotests/ospfv3_basic_functionality/test_ospfv3_ecmp_lan.py b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_ecmp_lan.py new file mode 100644 index 0000000000..fe8be0a4b3 --- /dev/null +++ b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_ecmp_lan.py @@ -0,0 +1,400 @@ +#!/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 +import ipaddress + +# 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 lib.topogen import Topogen, get_topogen + +# 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_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 + +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"], +} +MASK = {"ipv6": "32", "ipv6": "128"} + +""" +TOPOOLOGY = + Please view in a fixed-width font such as Courier. + Topo : Broadcast Networks + +---+ +---+ +---+ +---+ + |R0 + +R1 + +R2 + +R3 | + +-+-+ +-+-+ +-+-+ +-+-+ + | | | | + | | | | + --+-----------+--------------+---------------+----- + Ethernet Segment + +TESTCASES = +1. Verify OSPF ECMP with max path configured as 8 + (Edge having 1 uplink port as broadcast network, + connect to 8 TORs - LAN case) + + """ + + +def setup_module(mod): + """ + Sets up the pytest environment + + * `mod`: module name + """ + global topo, switch_name + 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... + json_file = "{}/ospfv3_ecmp_lan.json".format(CWD) + tgen = Topogen(json_file, mod.__name__) + global topo + topo = tgen.json_topo + # ... 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, lan=True) + assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format( + ospf_covergence + ) + + switch_name = [k for k in topo["switches"].keys()][0] + + 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 + + try: + # Stop toplogy and Remove tmp files + tgen.stop_topology() + + except OSError: + # OSError exception is raised when mininet tries to stop switch + # though switch is stopped once but mininet tries to stop same + # switch again, where it ended up with exception + pass + 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_lan_ecmp_tc18_p0(request): + """ + OSPF ECMP. + + Verify OSPF ECMP with max path configured as 8 + (Edge having 1 uplink port as broadcast network, + connect to 8 TORs - LAN case) + + """ + 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 in all the routers on LAN interface.") + + reset_config_on_routers(tgen) + + step("Verify that OSPF is up with 8 neighborship sessions.") + + ospf_covergence = verify_ospf6_neighbor(tgen, topo, lan=True) + assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format( + ospf_covergence + ) + + step( + "Configure a static route in all the routes and " + "redistribute static/connected in OSPF." + ) + + for rtr in topo["routers"]: + input_dict = { + rtr: { + "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 = rtr + red_static(dut) + + step( + "Verify that route in R0 in stalled with 8 hops. " + "Verify ospf route table and ip route table." + ) + + nh = [] + for rtr in topo["routers"]: + llip = get_llip(rtr, switch_name) + assert llip is not None, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + nh.append(llip) + + llip = get_llip("r1", switch_name) + assert llip is not None, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + nh.remove(llip) + dut = "r1" + result = verify_ospf6_rib(tgen, dut, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + protocol = "ospf6" + result = verify_rib(tgen, "ipv6", dut, input_dict, protocol=protocol) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step(" clear ip ospf interface on DUT(r0)") + clear_ospf(tgen, "r0", ospf="ospf6") + + step( + "Verify that after clearing the ospf interface all the " + "neighbours are up and routes are installed with 8 next hop " + "in ospf and ip route tables on R0" + ) + + dut = "r0" + ospf_covergence = verify_ospf6_neighbor(tgen, topo, dut=dut, lan=True) + assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format( + ospf_covergence + ) + + step(" clear ip ospf interface on R2") + clear_ospf(tgen, "r2") + + dut = "r2" + ospf_covergence = verify_ospf6_neighbor(tgen, topo, dut=dut, lan=True) + assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format( + ospf_covergence + ) + + step("Delete static/connected cmd in ospf in all the routes one by one.") + for rtr in topo["routers"]: + input_dict = { + rtr: { + "static_routes": [ + { + "network": NETWORK["ipv6"][0], + "no_of_ip": 5, + "next_hop": "Null0", + "delete": True, + } + ] + } + } + result = create_static_routes(tgen, input_dict) + 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_nssa2.py b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_nssa2.py new file mode 100644 index 0000000000..dc3b915d49 --- /dev/null +++ b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_nssa2.py @@ -0,0 +1,482 @@ +#!/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 +from copy import deepcopy +import ipaddress +from lib.ospf import ( + verify_ospf6_neighbor, + config_ospf6_interface, + clear_ospf, + verify_ospf6_rib, + verify_ospf6_interface, + verify_ospf6_database, + create_router_ospf, +) + +# pylint: disable=C0413 +# Import topogen and topotest helpers +from lib.topogen import Topogen, get_topogen + +from lib.bgp import ( + verify_bgp_convergence, + create_router_bgp, + clear_bgp_and_verify, + verify_bgp_rib, +) +from lib.topolog import logger +from lib.common_config import ( + start_topology, + write_test_header, + write_test_footer, + reset_config_on_routers, + verify_rib, + create_static_routes, + step, + topo_daemons, + create_route_maps, + shutdown_bringup_interface, + create_interfaces_cfg, + check_router_status, +) +from ipaddress import IPv4Address +from lib.topolog import logger +from lib.topojson import build_config_from_json + + +# Save the Current Working Directory to find configuration files. +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) + +pytestmark = [pytest.mark.ospfd, pytest.mark.staticd] + +# Global variables +topo = None +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", + ], +} +""" +TOPOOLOGY = + Please view in a fixed-width font such as Courier. + +---+ A1 +---+ + +R1 +------------+R2 | + +-+-+- +--++ + | -- -- | + | -- A0 -- | + A0| ---- | + | ---- | A2 + | -- -- | + | -- -- | + +-+-+- +-+-+ + +R0 +-------------+R3 | + +---+ A3 +---+ + + + +TESTCASES = +1. OSPF Learning - Verify OSPF can learn different types of LSA and + processes them.[Edge learning different types of LSAs] +2. Verify that ospf non back bone area can be configured as NSSA area +3. Verify that ospf NSSA area DUT is capable receiving & processing + Type7 N2 route. +""" + + +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... + json_file = "{}/ospfv3_nssa2.json".format(CWD) + tgen = Topogen(json_file, mod.__name__) + global topo + topo = tgen.json_topo + # ... 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(): + """Teardown the pytest environment.""" + logger.info("Running teardown_module to delete topology") + + tgen = get_topogen() + + # Stop toplogy and Remove tmp files + tgen.stop_topology() + + +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) + + +# ################################## +# Test cases start here. +# ################################## + + +def test_ospfv3_nssa_tc26_p0(request): + """Verify that ospf non back bone area can be configured as NSSA area""" + 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(): + check_router_status(tgen) + + global topo + step("Bring up the base config as per the topology") + step("Configure ospf area 2 on r0 , r1 & r4, make the area 2 as NSSA area") + + reset_config_on_routers(tgen) + + input_dict = { + "r2": { + "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 static route in R2 ospf.") + dut = "r2" + red_static(dut) + + step("Verify that Type 5 LSA is originated by R2.") + dut = "r0" + protocol = "ospf6" + result = verify_rib(tgen, "ipv6", dut, input_dict, protocol=protocol) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Un configure redistribute command in R4") + dut = "r2" + red_static(dut, config=False) + + input_dict = { + "r1": { + "static_routes": [ + {"network": NETWORK["ipv6"][0], "no_of_ip": 1, "routeType": "Network"} + ] + } + } + + step("Configure area 0 on interface of r2 connecting to r1") + + input_dict = { + "r2": { + "links": { + "r1": { + "interface": topo["routers"]["r2"]["links"]["r1"]["interface"], + "ospf6": {"area": "0.0.0.2"}, + "delete": True, + } + } + } + } + + result = create_interfaces_cfg(tgen, input_dict) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + input_dict = { + "r2": { + "links": { + "r1": { + "interface": topo["routers"]["r2"]["links"]["r1"]["interface"], + "ospf6": {"area": "0.0.0.0"}, + } + } + } + } + + result = create_interfaces_cfg(tgen, input_dict) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + step("verify that ospf neighbor goes down between r2 and r1.") + result = verify_ospf6_neighbor(tgen, topo, dut="r2", expected=False) + assert ( + result is not True + ), "Testcase {} : Failed \n Nbrs are not down" "Error: {}".format(tc_name, result) + + step("Now configure area 0 on interface of r1 connecting to r2.") + + input_dict = { + "r1": { + "links": { + "r2": { + "interface": topo["routers"]["r1"]["links"]["r2"]["interface"], + "ospf6": {"area": "0.0.0.2"}, + "delete": True, + } + } + } + } + + result = create_interfaces_cfg(tgen, input_dict) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + input_dict = { + "r1": { + "links": { + "r2": { + "interface": topo["routers"]["r1"]["links"]["r2"]["interface"], + "ospf6": {"area": "0.0.0.0"}, + } + } + } + } + + result = create_interfaces_cfg(tgen, input_dict) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + step("Verify that ospf neighbour comes up between r2 and r1.") + result = verify_ospf6_neighbor(tgen, topo, dut="r2") + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Configure area 2 on interface of r2 connecting to r1.") + + input_dict = { + "r2": { + "links": { + "r1": { + "interface": topo["routers"]["r2"]["links"]["r1"]["interface"], + "ospf6": {"area": "0.0.0.0"}, + "delete": True, + } + } + } + } + + result = create_interfaces_cfg(tgen, input_dict) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + input_dict = { + "r2": { + "links": { + "r1": { + "interface": topo["routers"]["r2"]["links"]["r1"]["interface"], + "ospf6": {"area": "0.0.0.2"}, + } + } + } + } + + result = create_interfaces_cfg(tgen, input_dict) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + step("verify that ospf neighbor goes down between r2 and r1.") + result = verify_ospf6_neighbor(tgen, topo, dut="r2", expected=False) + assert ( + result is not True + ), "Testcase {} : Failed \n Nbrs are not down" "Error: {}".format(tc_name, result) + + step("Now configure area 2 on interface of r1 connecting to r2.") + + input_dict = { + "r1": { + "links": { + "r2": { + "interface": topo["routers"]["r1"]["links"]["r2"]["interface"], + "ospf6": {"area": "0.0.0.0"}, + "delete": True, + } + } + } + } + + result = create_interfaces_cfg(tgen, input_dict) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + input_dict = { + "r1": { + "links": { + "r2": { + "interface": topo["routers"]["r1"]["links"]["r2"]["interface"], + "ospf6": {"area": "0.0.0.2"}, + } + } + } + } + + result = create_interfaces_cfg(tgen, input_dict) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + step("Verify that ospf neighbour comes up between r2 and r1.") + result = verify_ospf6_neighbor(tgen, topo, dut="r2") + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + write_test_footer(tc_name) + + +# As per internal discussion, this script has to be removed as translator +# function is not supported, for more details kindly check this PR 2565570 +def ospfv3_nssa_tc27_p0(request): + """ + OSPF NSSA. + + Verify that ospf NSSA area DUT is capable receiving & processing + Type7 N2 route. + """ + 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(): + check_router_status(tgen) + + global topo + step("Bring up the base config as per the topology") + step("Configure ospf area 2 on r0 , r1 & r4, make the area 2 as NSSA area") + + reset_config_on_routers(tgen) + + input_dict = { + "r2": { + "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 static route in R2 ospf.") + dut = "r2" + red_static(dut) + + step("Verify that Type 5 LSA is originated by R2.") + dut = "r0" + protocol = "ospf6" + result = verify_rib(tgen, "ipv6", dut, input_dict, protocol=protocol) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Un configure redistribute command in R4") + dut = "r2" + red_static(dut, config=False) + + input_dict = { + "r1": { + "static_routes": [ + {"network": NETWORK["ipv6"][0], "no_of_ip": 1, "routeType": "Network"} + ] + } + } + + dut = "r0" + result = verify_ospf6_rib(tgen, dut, input_dict, expected=False) + assert result is not True, "Testcase {} : Failed \n 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 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 index 461efbe979..d7cf951c5f 100644 --- a/tests/topotests/ospfv3_basic_functionality/test_ospfv3_routemaps.py +++ b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_routemaps.py @@ -178,6 +178,312 @@ def teardown_module(mod): # ################################## +def test_ospfv3_routemaps_functionality_tc19_p0(request): + """ + OSPF Route map - Verify OSPF route map support functionality. + + """ + 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) + + ospf_red_r1 = {"r0": {"ospf6": {"redistribute": [{"redist_type": "static"}]}}} + result = create_router_ospf(tgen, topo, ospf_red_r1) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + dut = "r1" + lsid = NETWORK["ipv6"][0].split("/")[0] + rid = routerids[0] + + 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) + + ospf_red_r1 = { + "r0": { + "ospf6": {"redistribute": [{"redist_type": "static", "del_action": True}]} + } + } + result = create_router_ospf(tgen, topo, ospf_red_r1) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step( + "Create prefix-list in R0 to permit 10.0.20.1/32 prefix &" " deny 10.0.20.2/32" + ) + + # Create ip prefix list + pfx_list = { + "r0": { + "prefix_lists": { + "ipv6": { + "pf_list_1_ipv6": [ + { + "seqid": 10, + "network": NETWORK["ipv6"][0], + "action": "permit", + }, + {"seqid": 11, "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 prefix-list is created in R0.") + result = verify_prefix_lists(tgen, pfx_list) + assert ( + result is not True + ), "Testcase {} : Failed \n, prefix list creation failed. 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( + "Configure route map rmap1 and redistribute static routes to" + " ospf using route map rmap1" + ) + + 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 route map is activated in OSPF.") + + step("Verify that route 10.0.20.1 is allowed and 10.0.20.2 is denied.") + dut = "r1" + input_dict = { + "r0": { + "static_routes": [ + {"network": NETWORK["ipv6"][0], "no_of_ip": 1, "next_hop": "Null0"} + ] + } + } + 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 = "r1" + lsid = NETWORK["ipv6"][1].split("/")[0] + rid = routerids[0] + + step("Change prefix rules to permit 10.0.20.2 and deny 10.0.20.1") + # Create ip prefix list + pfx_list = { + "r0": { + "prefix_lists": { + "ipv6": { + "pf_list_1_ipv6": [ + { + "seqid": 10, + "network": NETWORK["ipv6"][1], + "action": "permit", + }, + {"seqid": 11, "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 route 10.0.20.2 is allowed and 10.0.20.1 is denied.") + dut = "r1" + input_dict = { + "r0": { + "static_routes": [ + {"network": NETWORK["ipv6"][1], "no_of_ip": 1, "next_hop": "Null0"} + ] + } + } + 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) + + input_dict = { + "r0": { + "static_routes": [ + {"network": NETWORK["ipv6"][0], "no_of_ip": 1, "next_hop": "Null0"} + ] + } + } + 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 and reconfigure prefix list.") + # Create ip prefix list + pfx_list = { + "r0": { + "prefix_lists": { + "ipv6": { + "pf_list_1_ipv6": [ + { + "seqid": 10, + "network": NETWORK["ipv6"][1], + "action": "permit", + "delete": True, + }, + { + "seqid": 11, + "network": "any", + "action": "deny", + "delete": True, + }, + ] + } + } + } + } + result = create_prefix_lists(tgen, pfx_list) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + result = verify_prefix_lists(tgen, pfx_list) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + input_dict = { + "r0": { + "static_routes": [ + {"network": NETWORK["ipv6"][0], "no_of_ip": 5, "next_hop": "Null0"} + ] + } + } + 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 + ) + + pfx_list = { + "r0": { + "prefix_lists": { + "ipv6": { + "pf_list_1_ipv6": [ + { + "seqid": 10, + "network": NETWORK["ipv6"][1], + "action": "permit", + }, + {"seqid": 11, "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 route 10.0.20.2 is allowed and 10.0.20.1 is denied.") + dut = "r1" + input_dict = { + "r0": { + "static_routes": [ + {"network": NETWORK["ipv6"][1], "no_of_ip": 1, "next_hop": "Null0"} + ] + } + } + 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) + + input_dict = { + "r0": { + "static_routes": [ + {"network": NETWORK["ipv6"][0], "no_of_ip": 1, "next_hop": "Null0"} + ] + } + } + 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_tc20_p0(request): """ OSPF route map support functionality. @@ -461,7 +767,7 @@ def test_ospfv3_routemaps_functionality_tc22_p0(request): { "action": "permit", "seq_id": "20", - "match": {"ipv6": {"prefix_lists": "pf_list_2_ipv4"}}, + "match": {"ipv6": {"prefix_lists": "pf_list_2_ipv6"}}, }, ] } @@ -474,7 +780,7 @@ def test_ospfv3_routemaps_functionality_tc22_p0(request): input_dict_2 = { "r0": { "prefix_lists": { - "ipv4": { + "ipv6": { "pf_list_1_ipv6": [ {"seqid": 10, "network": NETWORK["ipv6"][0], "action": "permit"} ] @@ -489,8 +795,8 @@ def test_ospfv3_routemaps_functionality_tc22_p0(request): input_dict_2 = { "r0": { "prefix_lists": { - "ipv4": { - "pf_list_2_ipv4": [ + "ipv6": { + "pf_list_2_ipv6": [ {"seqid": 10, "network": NETWORK["ipv6"][1], "action": "permit"} ] } @@ -567,7 +873,7 @@ def test_ospfv3_routemaps_functionality_tc22_p0(request): { "action": "deny", "seq_id": "20", - "match": {"ipv6": {"prefix_lists": "pf_list_2_ipv4"}}, + "match": {"ipv6": {"prefix_lists": "pf_list_2_ipv6"}}, } ] } @@ -624,6 +930,106 @@ def test_ospfv3_routemaps_functionality_tc22_p0(request): write_test_footer(tc_name) +def test_ospfv3_routemaps_functionality_tc23_p0(request): + """ + OSPF Route map - Multiple set clauses. + + Verify OSPF route map support functionality when we add/remove route-maps + with multiple set clauses and without any match statement.(Set 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": 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 set clause (set metric)") + # Create route map + routemaps = { + "r0": { + "route_maps": { + "rmap_ipv6": [ + {"action": "permit", "seq_id": 10, "set": {"metric": 123}} + ] + } + } + } + result = create_route_maps(tgen, routemaps) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Verify that configured metric is applied to ospf routes.") + dut = "r1" + protocol = "ospf" + + result = verify_ospf6_rib(tgen, dut, input_dict, metric=123) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + result = verify_rib(tgen, "ipv6", dut, input_dict, protocol=protocol, metric=123) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("un configure the set clause") + # Create route map + routemaps = { + "r0": { + "route_maps": { + "rmap_ipv6": [ + { + "action": "permit", + "seq_id": 10, + "set": {"metric": 123, "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, metric=20) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + result = verify_rib(tgen, "ipv6", dut, input_dict, protocol=protocol, metric=20) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + write_test_footer(tc_name) + + def test_ospfv3_routemaps_functionality_tc24_p0(request): """ OSPF Route map - Multiple set clauses. 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 d8f659e5a9..21d03fadfb 100644 --- a/tests/topotests/ospfv3_basic_functionality/test_ospfv3_rte_calc.py +++ b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_rte_calc.py @@ -48,17 +48,21 @@ from lib.common_config import ( create_interfaces_cfg, topo_daemons, get_frr_ipv6_linklocal, + check_router_status, + create_static_routes, ) from lib.topolog import logger from lib.topojson import build_config_from_json - +from lib.bgp import create_router_bgp, verify_bgp_convergence from lib.ospf import ( verify_ospf6_neighbor, + clear_ospf, verify_ospf6_rib, + verify_ospf_database, create_router_ospf, - verify_ospf6_interface, config_ospf6_interface, + verify_ospf6_interface, ) @@ -251,6 +255,8 @@ 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 @@ -259,7 +265,7 @@ def test_ospfv3_redistribution_tc5_p0(request): # Don't run this test if we have any failure. if tgen.routers_have_failure(): - pytest.skip(tgen.errors) + check_router_status(tgen) global topo step("Bring up the base config.") @@ -280,7 +286,11 @@ def test_ospfv3_redistribution_tc5_p0(request): nh = llip input_dict = { - "r1": {"static_routes": [{"network": ip_net, "no_of_ip": 1, "routeType": "N"}]} + "r1": { + "static_routes": [ + {"network": ip_net, "no_of_ip": 1, "routeType": "Network"} + ] + } } dut = "r1" @@ -372,7 +382,7 @@ def test_ospfv3_redistribution_tc6_p0(request): # Don't run this test if we have any failure. if tgen.routers_have_failure(): - pytest.skip(tgen.errors) + check_router_status(tgen) global topo step("Bring up the base config.") @@ -380,8 +390,8 @@ def test_ospfv3_redistribution_tc6_p0(request): 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 + assert ospf_covergence is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, ospf_covergence ) step("verify intra area route is calculated for r0-r3 interface ip in R1") @@ -391,7 +401,11 @@ def test_ospfv3_redistribution_tc6_p0(request): 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"}]} + "r1": { + "static_routes": [ + {"network": ip_net, "no_of_ip": 1, "routeType": "Network"} + ] + } } dut = "r1" @@ -460,9 +474,6 @@ def test_ospfv3_redistribution_tc6_p0(request): 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) @@ -478,6 +489,168 @@ def test_ospfv3_redistribution_tc6_p0(request): write_test_footer(tc_name) +def test_ospfv3_redistribution_tc8_p1(request): + """ + Test OSPF redistribution of connected routes. + + Verify OSPF redistribution of connected routes when bgp multi hop + neighbor is configured using ospf routes + + """ + tc_name = request.node.name + write_test_header(tc_name) + tgen = get_topogen() + global topo + step("Bring up the base config.") + step( + "Configure loopback interface on all routers, and redistribut" + "e connected routes into ospf" + ) + if tgen.routers_have_failure(): + check_router_status(tgen) + reset_config_on_routers(tgen) + + step( + "verify that connected routes -loopback is found in all routers" + "advertised/exchaged via ospf" + ) + for rtr in topo["routers"]: + red_static(rtr) + red_connected(rtr) + + for node in topo["routers"]: + input_dict = { + "r0": { + "static_routes": [ + { + "network": topo["routers"][node]["links"]["lo"]["ipv6"], + "no_of_ip": 1, + } + ] + } + } + for rtr in topo["routers"]: + result = verify_rib(tgen, "ipv6", rtr, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step("Configure E BGP multi hop using the loopback addresses.") + as_num = 100 + for node in topo["routers"]: + as_num += 1 + topo["routers"][node].update( + { + "bgp": { + "local_as": as_num, + "address_family": {"ipv6": {"unicast": {"neighbor": {}}}}, + } + } + ) + for node in topo["routers"]: + for rtr in topo["routers"]: + if node is not rtr: + topo["routers"][node]["bgp"]["address_family"]["ipv6"]["unicast"][ + "neighbor" + ].update( + { + rtr: { + "dest_link": { + "lo": {"source_link": "lo", "ebgp_multihop": 2} + } + } + } + ) + + result = create_router_bgp(tgen, topo, topo["routers"]) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + # Modify router id + input_dict = { + "r0": {"bgp": {"router_id": "11.11.11.11"}}, + "r1": {"bgp": {"router_id": "22.22.22.22"}}, + "r2": {"bgp": {"router_id": "33.33.33.33"}}, + "r3": {"bgp": {"router_id": "44.44.44.44"}}, + } + result = create_router_bgp(tgen, topo, input_dict) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + step("Verify that BGP neighbor is ESTABLISHED") + result = verify_bgp_convergence(tgen, topo) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + step( + "Configure couple of static routes in R0 and " + "Redistribute static routes in R1 bgp." + ) + + for rtr in topo["routers"]: + ospf_red = { + rtr: { + "ospf6": {"redistribute": [{"redist_type": "static", "delete": True}]} + } + } + result = create_router_ospf(tgen, topo, ospf_red) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + 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) + + configure_bgp_on_r0 = { + "r0": { + "bgp": { + "address_family": { + "ipv6": {"unicast": {"redistribute": [{"redist_type": "static"}]}} + } + } + } + } + result = create_router_bgp(tgen, topo, configure_bgp_on_r0) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + protocol = "bgp" + for rtr in ["r1", "r2", "r3"]: + result = verify_rib(tgen, "ipv6", rtr, input_dict, protocol=protocol) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step("Clear ospf neighbours in R0") + for rtr in topo["routers"]: + clear_ospf(tgen, rtr) + + step("Verify that OSPF neighbours are reset and forms new adjacencies.") + # 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 BGP neighbours are reset and forms new adjacencies.") + result = verify_bgp_convergence(tgen, topo) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + protocol = "bgp" + for rtr in ["r1", "r2", "r3"]: + result = verify_rib(tgen, "ipv6", rtr, input_dict, protocol=protocol) + 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 @@ -485,6 +658,8 @@ def test_ospfv3_cost_tc52_p0(request): tgen = get_topogen() global topo step("Bring up the base config.") + if tgen.routers_have_failure(): + check_router_status(tgen) reset_config_on_routers(tgen) step( @@ -565,6 +740,184 @@ def test_ospfv3_cost_tc52_p0(request): write_test_footer(tc_name) +def test_ospfv3_def_rte_tc9_p0(request): + """OSPF default route - Verify OSPF default route origination.""" + tc_name = request.node.name + write_test_header(tc_name) + tgen = get_topogen() + global topo + step("Bring up the base config.") + step("Configure OSPF on all the routers of the topology.") + if tgen.routers_have_failure(): + check_router_status(tgen) + reset_config_on_routers(tgen) + + step(" Configure default-information originate always on R0.") + input_dict = {"r0": {"ospf6": {"default-information": {"originate": True}}}} + result = create_router_ospf(tgen, topo, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + dut = "r0" + step(" Configure default-information originate always on R0.") + input_dict = { + "r0": { + "ospf6": { + "default-information": { + "originate": True, + "always": True, + } + } + } + } + result = create_router_ospf(tgen, topo, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Verify that default route is originated in area always.") + dut = "r1" + + step(" Configure default-information originate metric type 1 on R0.") + input_dict = { + "r0": { + "ospf6": { + "default-information": { + "originate": True, + "always": True, + "metric-type": 1, + } + } + } + } + + step( + "Verify that default route is originated in area when external " + "routes are present in R0 with metric type as 1." + ) + dut = "r0" + step( + "Verify that on R1 default route with type 1 is installed" + " (R1 is DUT in this case)" + ) + dut = "r1" + step("Configure default-information originate metric type 2 on R0.") + input_dict = { + "r0": { + "ospf6": { + "default-information": { + "originate": True, + "always": True, + "metric-type": 2, + } + } + } + } + result = create_router_ospf(tgen, topo, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step( + "Verify that default route is originated in area when external" + " routes are present in R0 with metric type as 2." + ) + + dut = "r1" + step(" Configure default-information originate metric 100 on R0") + input_dict = { + "r0": { + "ospf6": { + "default-information": { + "originate": True, + "always": True, + "metric-type": 2, + "metric": 100, + } + } + } + } + result = create_router_ospf(tgen, topo, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Verify that default route is originated with cost as 100 on R0.") + + dut = "r1" + + step("Delete the default-information command") + input_dict = { + "r0": { + "ospf6": { + "default-information": { + "originate": True, + "always": True, + "delete": True, + } + } + } + } + result = create_router_ospf(tgen, topo, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + dut = "r0" + step("Configure default-information originate always on R0.") + input_dict = { + "r0": { + "ospf6": { + "default-information": { + "originate": True, + "always": True, + } + } + } + } + result = create_router_ospf(tgen, topo, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Configure default route originate with active def route in zebra") + input_dict = { + "r0": { + "static_routes": [ + { + "network": "0::0/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) + + input_dict = { + "r0": { + "ospf6": { + "default-information": { + "originate": True, + } + } + } + } + result = create_router_ospf(tgen, topo, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Verify that default route is originated by R0.") + dut = "r1" + + step("Delete static route") + input_dict = { + "r0": { + "static_routes": [ + { + "network": "0::0/0", + "no_of_ip": 1, + "next_hop": "Null0", + "delete": True, + } + ] + } + } + result = create_static_routes(tgen, input_dict) + 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_single_area.py b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_single_area.py index ed70c09fae..9ec06ec36b 100644 --- a/tests/topotests/ospfv3_basic_functionality/test_ospfv3_single_area.py +++ b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_single_area.py @@ -26,6 +26,8 @@ import os import sys import time import pytest +import ipaddress + from copy import deepcopy from lib.topotest import frr_unicode @@ -47,6 +49,8 @@ from lib.common_config import ( step, create_interfaces_cfg, topo_daemons, + create_debug_log_config, + apply_raw_config, ) from lib.topolog import logger from lib.topojson import build_config_from_json @@ -55,6 +59,9 @@ from lib.ospf import ( verify_ospf6_neighbor, clear_ospf, verify_ospf6_interface, + create_router_ospf, + config_ospf6_interface, + verify_ospf6_rib, ) from ipaddress import IPv6Address @@ -381,6 +388,956 @@ def test_ospfv3_p2p_tc3_p0(request): write_test_footer(tc_name) +def test_ospfv3_hello_tc10_p0(request): + """ + OSPF timers. + + Verify OSPF interface timer hello interval 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) + + step("modify hello timer from default value to some other value on r1") + + topo1 = { + "r1": { + "links": { + "r0": { + "interface": topo["routers"]["r1"]["links"]["r0"]["interface"], + "ospf6": {"hello_interval": 11, "dead_interval": 12}, + } + } + } + } + + result = create_interfaces_cfg(tgen, topo1) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step( + "verify that new timer value is configured and applied using " + "the show ip ospf interface command." + ) + dut = "r1" + input_dict = { + "r1": { + "links": { + "r0": { + "ospf6": { + "timerIntervalsConfigHello": 11, + "timerIntervalsConfigDead": 12, + } + } + } + } + } + result = verify_ospf6_interface(tgen, topo, dut=dut, input_dict=input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("modify hello timer from default value to r1 hello timer on r2") + + topo1 = { + "r0": { + "links": { + "r1": { + "interface": topo["routers"]["r0"]["links"]["r1"]["interface"], + "ospf6": {"hello_interval": 11, "dead_interval": 12}, + } + } + } + } + + result = create_interfaces_cfg(tgen, topo1) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("verify that new timer value is configured.") + input_dict = { + "r0": { + "links": { + "r1": { + "ospf6": { + "timerIntervalsConfigHello": 11, + "timerIntervalsConfigDead": 12, + } + } + } + } + } + dut = "r0" + result = verify_ospf6_interface(tgen, topo, dut=dut, input_dict=input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("verify that ospf neighbours are full") + ospf_covergence = verify_ospf6_neighbor(tgen, topo, dut=dut) + assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format( + ospf_covergence + ) + + step("reconfigure the default hello timer value to default on r1 and r2") + + topo1 = { + "r0": { + "links": { + "r1": { + "interface": topo["routers"]["r0"]["links"]["r1"]["interface"], + "ospf6": {"hello_interval": 10, "dead_interval": 40}, + } + } + } + } + + result = create_interfaces_cfg(tgen, topo1) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + topo1 = { + "r1": { + "links": { + "r0": { + "interface": topo["routers"]["r1"]["links"]["r0"]["interface"], + "ospf6": {"hello_interval": 10, "dead_interval": 40}, + } + } + } + } + + result = create_interfaces_cfg(tgen, topo1) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("verify that new timer value is configured.") + input_dict = { + "r0": { + "links": { + "r1": { + "ospf6": { + "timerIntervalsConfigHello": 10, + "timerIntervalsConfigDead": 40, + } + } + } + } + } + dut = "r0" + result = verify_ospf6_interface(tgen, topo, dut=dut, input_dict=input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("verify that ospf neighbours are full") + ospf_covergence = verify_ospf6_neighbor(tgen, topo, dut=dut) + assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format( + ospf_covergence + ) + + step("reconfigure the default hello timer value to default on r1 and r2") + + topo1 = { + "r0": { + "links": { + "r1": { + "interface": topo["routers"]["r0"]["links"]["r1"]["interface"], + "ospf6": {"hello_interval": 10, "dead_interval": 40}, + } + } + } + } + + result = create_interfaces_cfg(tgen, topo1) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + topo1 = { + "r1": { + "links": { + "r0": { + "interface": topo["routers"]["r1"]["links"]["r0"]["interface"], + "ospf6": {"hello_interval": 10, "dead_interval": 40}, + } + } + } + } + + result = create_interfaces_cfg(tgen, topo1) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("verify that new timer value is configured.") + input_dict = { + "r0": { + "links": { + "r1": { + "ospf6": { + "timerIntervalsConfigHello": 10, + "timerIntervalsConfigDead": 40, + } + } + } + } + } + dut = "r0" + result = verify_ospf6_interface(tgen, topo, dut=dut, input_dict=input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("verify that ospf neighbours are full") + ospf_covergence = verify_ospf6_neighbor(tgen, topo, dut=dut) + assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format( + ospf_covergence + ) + + step("configure hello timer = 1 on r1 and r2") + topo1 = { + "r0": { + "links": { + "r1": { + "interface": topo["routers"]["r0"]["links"]["r1"]["interface"], + "ospf6": {"hello_interval": 1, "dead_interval": 4}, + } + } + } + } + + result = create_interfaces_cfg(tgen, topo1) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + topo1 = { + "r1": { + "links": { + "r0": { + "interface": topo["routers"]["r1"]["links"]["r0"]["interface"], + "ospf6": {"hello_interval": 1, "dead_interval": 4}, + } + } + } + } + + result = create_interfaces_cfg(tgen, topo1) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("verify that new timer value is configured.") + input_dict = { + "r0": { + "links": { + "r1": { + "ospf6": { + "timerIntervalsConfigHello": 1, + "timerIntervalsConfigDead": 4, + } + } + } + } + } + dut = "r0" + result = verify_ospf6_interface(tgen, topo, dut=dut, input_dict=input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("verify that ospf neighbours are full") + ospf_covergence = verify_ospf6_neighbor(tgen, topo, dut=dut) + assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format( + ospf_covergence + ) + + step(" Configure hello timer = 65535") + topo1 = { + "r0": { + "links": { + "r1": { + "interface": topo["routers"]["r0"]["links"]["r1"]["interface"], + "ospf6": {"hello_interval": 65535, "dead_interval": 4}, + } + } + } + } + + result = create_interfaces_cfg(tgen, topo1) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + topo1 = { + "r1": { + "links": { + "r0": { + "interface": topo["routers"]["r1"]["links"]["r0"]["interface"], + "ospf6": {"hello_interval": 65535, "dead_interval": 4}, + } + } + } + } + + result = create_interfaces_cfg(tgen, topo1) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("verify that new timer value is configured.") + input_dict = { + "r0": { + "links": { + "r1": { + "ospf6": { + "timerIntervalsConfigHello": 65535, + "timerIntervalsConfigDead": 4, + } + } + } + } + } + dut = "r0" + result = verify_ospf6_interface(tgen, topo, dut=dut, input_dict=input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("verify that ospf neighbours are full") + ospf_covergence = verify_ospf6_neighbor(tgen, topo, dut=dut) + assert ospf_covergence is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, ospf_covergence + ) + step(" Try configuring timer values outside range for example 65536") + topo1 = { + "r0": { + "links": { + "r1": { + "interface": topo["routers"]["r0"]["links"]["r1"]["interface"], + "ospf6": {"hello_interval": 65536, "dead_interval": 4}, + } + } + } + } + + result = create_interfaces_cfg(tgen, topo1) + assert ( + result is not True + ), "Testcase {} : Failed \n Create interface failed. Error: {}".format( + tc_name, result + ) + + step("Unconfigure the hello timer from the interface from r1 and r2.") + + topo1 = { + "r1": { + "links": { + "r0": { + "interface": topo["routers"]["r1"]["links"]["r0"]["interface"], + "ospf6": {"hello_interval": 65535}, + "delete": True, + } + } + } + } + + result = create_interfaces_cfg(tgen, topo1) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step( + "Verify that timer value is deleted from intf & " "set to default value 40 sec." + ) + input_dict = {"r1": {"links": {"r0": {"ospf6": {"timerIntervalsConfigHello": 10}}}}} + dut = "r1" + result = verify_ospf6_interface(tgen, topo, dut=dut, input_dict=input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + write_test_footer(tc_name) + + +def test_ospfv3_dead_tc11_p0(request): + """ + OSPF timers. + + Verify OSPF interface timer dead interval 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) + + step("modify dead interval from default value to some other value on r1") + + topo1 = { + "r1": { + "links": { + "r0": { + "interface": topo["routers"]["r1"]["links"]["r0"]["interface"], + "ospf6": {"hello_interval": 12, "dead_interval": 48}, + } + } + } + } + + result = create_interfaces_cfg(tgen, topo1) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step( + "verify that new timer value is configured and applied using " + "the show ip ospf interface command." + ) + dut = "r1" + input_dict = {"r1": {"links": {"r0": {"ospf6": {"timerIntervalsConfigDead": 48}}}}} + result = verify_ospf6_interface(tgen, topo, dut=dut, input_dict=input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("modify dead interval from default value to r1" "dead interval timer on r2") + + topo1 = { + "r0": { + "links": { + "r1": { + "interface": topo["routers"]["r0"]["links"]["r1"]["interface"], + "ospf6": {"dead_interval": 48, "hello_interval": 12}, + } + } + } + } + + result = create_interfaces_cfg(tgen, topo1) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("verify that new timer value is configured.") + input_dict = {"r0": {"links": {"r1": {"ospf6": {"timerIntervalsConfigDead": 48}}}}} + dut = "r0" + result = verify_ospf6_interface(tgen, topo, dut=dut, input_dict=input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("verify that ospf neighbours are full") + ospf_covergence = verify_ospf6_neighbor(tgen, topo, dut=dut) + assert ospf_covergence is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, ospf_covergence + ) + + step("remove ospf on R0") + ospf_del = {"r0": {"ospf6": {"delete": True}}} + result = create_router_ospf(tgen, topo, ospf_del) + assert result is True, "Testcase : Failed \n Error: {}".format(result) + + # reconfiguring deleted ospf process by resetting the configs. + reset_config_on_routers(tgen) + + step("reconfigure the default dead interval timer value to " "default on r1 and r2") + topo1 = { + "r0": { + "links": { + "r1": { + "interface": topo["routers"]["r0"]["links"]["r1"]["interface"], + "ospf6": {"dead_interval": 40}, + } + } + } + } + + result = create_interfaces_cfg(tgen, topo1) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + topo1 = { + "r1": { + "links": { + "r0": { + "interface": topo["routers"]["r1"]["links"]["r0"]["interface"], + "ospf6": {"dead_interval": 40}, + } + } + } + } + + result = create_interfaces_cfg(tgen, topo1) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("verify that new timer value is configured.") + input_dict = {"r0": {"links": {"r1": {"ospf6": {"timerIntervalsConfigDead": 40}}}}} + dut = "r0" + result = verify_ospf6_interface(tgen, topo, dut=dut, input_dict=input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("verify that ospf neighbours are full") + ospf_covergence = verify_ospf6_neighbor(tgen, topo, dut=dut) + assert ospf_covergence is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, ospf_covergence + ) + + step(" Configure dead timer = 65535 on r1 and r2") + + topo1 = { + "r0": { + "links": { + "r1": { + "interface": topo["routers"]["r0"]["links"]["r1"]["interface"], + "ospf6": {"dead_interval": 65535}, + } + } + } + } + + result = create_interfaces_cfg(tgen, topo1) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + topo1 = { + "r1": { + "links": { + "r0": { + "interface": topo["routers"]["r1"]["links"]["r0"]["interface"], + "ospf6": {"dead_interval": 65535}, + } + } + } + } + + result = create_interfaces_cfg(tgen, topo1) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("verify that new timer value is configured.") + input_dict = { + "r0": {"links": {"r1": {"ospf6": {"timerIntervalsConfigDead": 65535}}}} + } + dut = "r0" + result = verify_ospf6_interface(tgen, topo, dut=dut, input_dict=input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("verify that ospf neighbours are full") + ospf_covergence = verify_ospf6_neighbor(tgen, topo, dut=dut) + assert ospf_covergence is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, ospf_covergence + ) + + step(" Try configuring timer values outside range for example 65536") + topo1 = { + "r0": { + "links": { + "r1": { + "interface": topo["routers"]["r0"]["links"]["r1"]["interface"], + "ospf6": {"dead_interval": 65536}, + } + } + } + } + + result = create_interfaces_cfg(tgen, topo1) + assert ( + result is not True + ), "Testcase {} : Failed \n Create interface config failed. Error: {}".format( + tc_name, result + ) + + step("Unconfigure the dead timer from the interface from r1 and r2.") + + topo1 = { + "r1": { + "links": { + "r0": { + "interface": topo["routers"]["r1"]["links"]["r0"]["interface"], + "ospf6": {"dead_interval": 65535}, + "delete": True, + } + } + } + } + + result = create_interfaces_cfg(tgen, topo1) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step( + "Verify that timer value is deleted from intf & " "set to default value 40 sec." + ) + input_dict = {"r1": {"links": {"r0": {"ospf6": {"timerIntervalsConfigDead": 40}}}}} + dut = "r1" + result = verify_ospf6_interface(tgen, topo, dut=dut, input_dict=input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + write_test_footer(tc_name) + + +def test_ospfv3_tc4_mtu_ignore_p0(request): + """ + OSPF NFSM - MTU change + + Verify NFSM events when ospf nbr changes with different MTU values + """ + 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.") + step("Verify that OSPF neighbors are FULL.") + reset_config_on_routers(tgen) + + step( + "Modify the MTU to non default Value on R0 to R1 interface. " + "Reset ospf neighbors on R0." + ) + + rtr0 = tgen.routers()["r0"] + rtr1 = tgen.routers()["r1"] + + r0_r1_intf = topo["routers"]["r0"]["links"]["r1"]["interface"] + r1_r0_intf = topo["routers"]["r1"]["links"]["r0"]["interface"] + + rtr0.run("ifconfig {} mtu 1400".format(r0_r1_intf)) + + clear_ospf(tgen, "r0", ospf="ospf6") + clear_ospf(tgen, "r1", ospf="ospf6") + + step( + "Verify that OSPF neighborship between R0 and R1 is stuck in Exstart" " State." + ) + result = verify_ospf6_neighbor(tgen, topo, expected=False) + assert result is not True, ( + "Testcase {} : Failed \n OSPF nbrs are Full " + "instead of Exstart. Error: {}".format(tc_name, result) + ) + + step( + "Verify that configured MTU value is updated in the show ip " "ospf interface." + ) + + dut = "r0" + input_dict = {"r0": {"links": {"r1": {"ospf6": {"interfaceMtu": 1400}}}}} + result = verify_ospf6_interface(tgen, topo, dut=dut, input_dict=input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step( + "Modify the MTU to non default Value on R0 to R1 interface. " + "Reset ospf neighbors on R0." + ) + rtr0.run("ifconfig {} mtu 1500".format(r0_r1_intf)) + + clear_ospf(tgen, "r0", ospf="ospf6") + + step("Verify that OSPF neighborship between R0 and R1 becomes full.") + result = verify_ospf6_neighbor(tgen, topo) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step( + "Configure mtu ignore and change the value of the mtu to non default" + " on R0 to R1 interface. Reset ospf neighbors on R0." + ) + r0_ospf_mtu = {"r0": {"links": {"r1": {"ospf6": {"mtu_ignore": True}}}}} + result = config_ospf6_interface(tgen, topo, r0_ospf_mtu) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + dut = "r0" + input_dict = {"r0": {"links": {"r1": {"ospf6": {"mtuMismatchDetection": True}}}}} + result = verify_ospf6_interface(tgen, topo, dut=dut, input_dict=input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + r1_ospf_mtu = {"r1": {"links": {"r0": {"ospf6": {"mtu_ignore": True}}}}} + result = config_ospf6_interface(tgen, topo, r1_ospf_mtu) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + rtr0.run("ifconfig {} mtu 1400".format(r0_r1_intf)) + + clear_ospf(tgen, "r0", ospf="ospf6") + + step("Verify that OSPF neighborship between R0 and R1 becomes full.") + result = verify_ospf6_neighbor(tgen, topo) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step( + "Unconfigure mtu-ignore command from the interface. " + "Reset ospf neighbors on R0." + ) + + r1_ospf_mtu = { + "r1": {"links": {"r0": {"ospf6": {"mtu_ignore": True, "delete": True}}}} + } + result = config_ospf6_interface(tgen, topo, r1_ospf_mtu) + assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result) + + clear_ospf(tgen, "r0", ospf="ospf6") + + step( + "Verify that OSPF neighborship between R0 and R1 is stuck in Exstart" " State." + ) + result = verify_ospf6_neighbor(tgen, topo, expected=False) + assert result is not True, ( + "Testcase {} : Failed \n OSPF nbrs are Full " + "instead of Exstart. Error: {}".format(tc_name, result) + ) + + step("Modify the MTU to again default valaue on R0 to R1 interface.") + + rtr0.run("ifconfig {} mtu 1500".format(r0_r1_intf)) + + clear_ospf(tgen, "r0", ospf="ospf6") + + step("Verify that OSPF neighborship between R0 and R1 becomes full.") + result = verify_ospf6_neighbor(tgen, topo) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step( + "Configure ospf interface with jumbo MTU (9216)." "Reset ospf neighbors on R0." + ) + + rtr0.run("ifconfig {} mtu 9216".format(r0_r1_intf)) + rtr1.run("ifconfig {} mtu 9216".format(r1_r0_intf)) + + clear_ospf(tgen, "r0", ospf="ospf6") + clear_ospf(tgen, "r1", ospf="ospf6") + + step("Verify that OSPF neighborship between R0 and R1 becomes full.") + result = verify_ospf6_neighbor(tgen, topo) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Verify that jumbo MTU is updated in the show ip ospf interface.") + dut = "r0" + input_dict = {"r0": {"links": {"r1": {"ospf6": {"interfaceMtu": 9216}}}}} + result = verify_ospf6_interface(tgen, topo, dut=dut, input_dict=input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + write_test_footer(tc_name) + + +def test_ospfv3_show_p1(request): + """Verify ospf show commands with json output.""" + 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) + + input_dict = {"r2": {"debug": {"log_file": "debug.log", "enable": ["ospf6"]}}} + + result = create_debug_log_config(tgen, input_dict) + + # Code coverage steps #Do Not upstream + input_dict_config = { + "r1": { + "raw_config": [ + "end", + "debug ospf6 event", + "debug ospf6 gr helper", + "debug ospf6 ism events", + "debug ospf6 ism status", + "debug ospf6 ism timers", + "debug ospf6 nsm events", + "debug ospf6 nsm status", + "debug ospf6 nsm timers ", + "debug ospf6 nssa", + "debug ospf6 lsa aggregate", + "debug ospf6 lsa flooding ", + "debug ospf6 lsa generate", + "debug ospf6 lsa install ", + "debug ospf6 lsa refresh", + "debug ospf6 packet all detail", + "debug ospf6 packet all recv", + "debug ospf6 packet all send", + "debug ospf6 packet dd detail", + "debug ospf6 packet dd recv", + "debug ospf6 packet dd send ", + "debug ospf6 packet hello detail", + "debug ospf6 packet hello recv", + "debug ospf6 packet hello send", + "debug ospf6 packet ls-ack detail", + "debug ospf6 packet ls-ack recv", + "debug ospf6 packet ls-ack send", + "debug ospf6 packet ls-request detail", + "debug ospf6 packet ls-request recv", + "debug ospf6 packet ls-request send", + "debug ospf6 packet ls-update detail", + "debug ospf6 packet ls-update recv", + "debug ospf6 packet ls-update send", + "debug ospf6 sr", + "debug ospf6 te ", + "debug ospf6 zebra interface", + "debug ospf6 zebra redistribute", + ] + } + } + + apply_raw_config(tgen, input_dict_config) + + for rtr in topo["routers"]: + clear_ospf(tgen, rtr, ospf="ospf6") + + step(" Bring up the base config as per the topology") + reset_config_on_routers(tgen) + + for rtr in topo["routers"]: + clear_ospf(tgen, rtr, ospf="ospf6") + + dut = "r1" + input_dict = { + "r1": { + "links": { + "r0": { + "ospf6": { + "status": "up", + "type": "BROADCAST", + "ospf6Enabled": True, + "attachedToArea": True, + "instanceId": 0, + "interfaceMtu": 1500, + "autoDetect": 1500, + "mtuMismatchDetection": "enabled", + "areaId": "0.0.0.0", + "cost": 10, + "transmitDelaySec": 1, + "priority": 1, + "timerIntervalsConfigHello": 1, + "timerIntervalsConfigDead": 4, + "timerIntervalsConfigRetransmit": 5, + "dr": "0.0.0.0", + "bdr": "0.0.0.0", + "numberOfInterfaceScopedLsa": 2, + "pendingLsaLsUpdateCount": 0, + "lsUpdateSendThread": "off", + "pendingLsaLsAckCount": 0, + "lsAckSendThread": "off", + } + } + } + } + } + result = verify_ospf6_interface(tgen, topo, dut=dut, input_dict=input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + ip = topo["routers"]["r0"]["links"]["r3"]["ipv6"] + ip_net = str(ipaddress.ip_interface(u"{}".format(ip)).network) + nh = topo["routers"]["r0"]["links"]["r1"]["ipv6"].split("/")[0] + input_dict = { + "r1": { + "static_routes": [ + {"network": ip_net, "no_of_ip": 1, "routeType": "Network"} + ] + } + } + + dut = "r1" + result = verify_ospf6_rib(tgen, dut, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + write_test_footer(tc_name) + + +def ospfv3_router_id_tc14_p2(request): + """OSPF Router ID - Verify OSPF router id changes.""" + 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 system router id as 1.1.1.1 on R1 , clear ospf router") + ospf_rid = {"r0": {"ospf6": {"router_id": "1.1.1.1"}}} + result = create_router_ospf(tgen, topo, ospf_rid) + assert result is True, "Testcase : Failed \n Error: {}".format(result) + + step("configure ospf router id as 1.1.1.2 on R1, clear ospf router") + ospf_rid = {"r1": {"ospf6": {"router_id": "1.1.1.2"}}} + result = create_router_ospf(tgen, topo, ospf_rid) + assert result is True, "Testcase : Failed \n Error: {}".format(result) + + topo1 = deepcopy(topo) + step("Verify that OSPF takes system router ID as ospf router id.") + + topo1["routers"]["r0"]["ospf6"]["router_id"] = "1.1.1.1" + topo1["routers"]["r1"]["ospf6"]["router_id"] = "1.1.1.2" + + for rtr in topo["routers"]: + clear_ospf(tgen, rtr, ospf="ospf6") + + ospf_covergence = verify_ospf6_neighbor(tgen, topo1) + assert ospf_covergence is True, "OSPF NBRs not up.Failed \n Error:" " {}".format( + ospf_covergence + ) + + step(" delete ospf router id and clear ospf process.") + ospf_rid = {"r0": {"ospf6": {"del_router_id": "1.1.1.1"}}} + result = create_router_ospf(tgen, topo, ospf_rid) + assert result is True, "Testcase : Failed \n Error: {}".format(result) + + ospf_rid = {"r1": {"ospf6": {"del_router_id": "1.1.1.2"}}} + result = create_router_ospf(tgen, topo, ospf_rid) + assert result is True, "Testcase : Failed \n Error: {}".format(result) + + reset_config_on_routers(tgen) + + step(" Configure R0 R1 R2 with same router ids") + ospf_rid = {"r0": {"ospf6": {"router_id": "1.1.1.1"}}} + result = create_router_ospf(tgen, topo, ospf_rid) + assert result is True, "Testcase : Failed \n Error: {}".format(result) + + step("configure ospf router id as 1.1.1.2 on R1, reboot router") + ospf_rid = {"r1": {"ospf6": {"router_id": "1.1.1.1"}}} + result = create_router_ospf(tgen, topo, ospf_rid) + assert result is True, "Testcase : Failed \n Error: {}".format(result) + + ospf_covergence = verify_ospf6_neighbor(tgen, topo, expected=False) + assert ( + ospf_covergence is not True + ), "OSPF NBRs are up.Failed \n Error:" " {}".format(ospf_covergence) + topo1 = {} + topo1 = deepcopy(topo) + + for rtr in ["r1", "r2", "r3", "r0"]: + topo1["routers"][rtr]["ospf6"].pop("router_id") + + build_config_from_json(tgen, topo1, save_bkup=False) + + ospf_covergence = verify_ospf6_neighbor(tgen, topo) + assert ospf_covergence is not True, ( + "Testcase {} :Failed \n Neighborship " + "should not up as no router id is configured. Error: {}".format(tc_name, result) + ) + + step("Clear ospf process and check nbrs should not be up.") + for rtr in topo["routers"]: + clear_ospf(tgen, rtr, ospf="ospf6") + + ospf_covergence = verify_ospf6_neighbor(tgen, topo) + assert ospf_covergence is not True, ( + "Testcase {} :Failed \n Neighborship " + "should not up as no router id is configured. Error: {}".format(tc_name, result) + ) + + topo1 = deepcopy(topo) + + step("Configure system router id on routers , clear ospf router") + ospf_rid = { + "r0": {"ospf6": {"router_id": "1.1.1.1"}}, + "r1": {"ospf6": {"router_id": "1.1.1.2"}}, + "r2": {"ospf6": {"router_id": "1.1.1.3"}}, + "r3": {"ospf6": {"router_id": "1.1.1.4"}}, + } + result = create_router_ospf(tgen, topo1, ospf_rid) + assert result is True, "Testcase : Failed \n Error: {}".format(result) + + topo1["routers"]["r0"]["ospf6"]["router_id"] = "1.1.1.1" + topo1["routers"]["r1"]["ospf6"]["router_id"] = "1.1.1.2" + topo1["routers"]["r2"]["ospf6"]["router_id"] = "1.1.1.3" + topo1["routers"]["r3"]["ospf6"]["router_id"] = "1.1.1.4" + + ospf_covergence = verify_ospf6_neighbor(tgen, topo1) + assert ospf_covergence is True, "OSPF NBRs not up.Failed \n Error:" " {}".format( + ospf_covergence + ) + + step(" Bring up the base config as per the topology") + reset_config_on_routers(tgen) + + ospf_covergence = verify_ospf6_neighbor(tgen, topo) + assert ospf_covergence is True, "OSPF NBRs not up.Failed \n Error:" " {}".format( + ospf_covergence + ) + + write_test_footer(tc_name) + + if __name__ == "__main__": args = ["-s"] + sys.argv[1:] sys.exit(pytest.main(args)) -- 2.39.5