diff options
| -rw-r--r-- | pimd/pim_mroute.c | 7 | ||||
| -rw-r--r-- | tests/topotests/lib/common_config.py | 100 | ||||
| -rw-r--r-- | tests/topotests/lib/ospf.py | 187 | ||||
| -rw-r--r-- | tests/topotests/lib/topojson.py | 3 | ||||
| -rw-r--r-- | tests/topotests/ospf-dual-stack/test_ospf_dual_stack.dot | 107 | ||||
| -rw-r--r-- | tests/topotests/ospf-dual-stack/test_ospf_dual_stack.jpg | bin | 0 -> 98314 bytes | |||
| -rw-r--r-- | tests/topotests/ospf-dual-stack/test_ospf_dual_stack.json | 255 | ||||
| -rw-r--r-- | tests/topotests/ospf-dual-stack/test_ospf_dual_stack.py | 152 |
8 files changed, 684 insertions, 127 deletions
diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 23259900b7..afd38face3 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -1221,10 +1221,9 @@ void pim_mroute_update_counters(struct channel_oil *c_oil) sg.src = c_oil->oil.mfcc_origin; sg.grp = c_oil->oil.mfcc_mcastgrp; - if (PIM_DEBUG_MROUTE) - zlog_debug( - "Channel%s is not installed no need to collect data from kernel", - pim_str_sg_dump(&sg)); + zlog_debug( + "Channel%s is not installed no need to collect data from kernel", + pim_str_sg_dump(&sg)); } return; } diff --git a/tests/topotests/lib/common_config.py b/tests/topotests/lib/common_config.py index 175d660d1e..3f360ef40a 100644 --- a/tests/topotests/lib/common_config.py +++ b/tests/topotests/lib/common_config.py @@ -257,6 +257,7 @@ def create_common_configuration( "bgp": "! BGP Config\n", "vrf": "! VRF Config\n", "ospf": "! OSPF Config\n", + "ospf6": "! OSPF Config\n", "pim": "! PIM Config\n", } ) @@ -752,6 +753,12 @@ def start_topology(tgen, daemon=None): TopoRouter.RD_OSPF, "{}/{}/ospfd.conf".format(TMPDIR, rname) ) + if daemon and "ospf6d" in daemon: + # Loading empty ospf.conf file to router, to start the bgp daemon + router.load_config( + TopoRouter.RD_OSPF6, "{}/{}/ospf6d.conf".format(TMPDIR, rname) + ) + if daemon and "pimd" in daemon: # Loading empty pimd.conf file to router, to start the pim deamon router.load_config( @@ -845,6 +852,9 @@ def topo_daemons(tgen, topo): if "ospf" in topo["routers"][rtr] and "ospfd" not in daemon_list: daemon_list.append("ospfd") + if "ospf6" in topo["routers"][rtr] and "ospf6d" not in daemon_list: + daemon_list.append("ospf6d") + for val in topo["routers"][rtr]["links"].values(): if "pim" in val and "pimd" not in daemon_list: daemon_list.append("pimd") @@ -1594,6 +1604,25 @@ def create_interfaces_cfg(tgen, topo, build=False): ------- True or False """ + + def _create_interfaces_ospf_cfg(ospf, c_data, data, ospf_keywords): + interface_data = [] + ip_ospf = "ipv6 ospf6" if ospf == "ospf6" else "ip ospf" + for keyword in ospf_keywords: + if keyword in data[ospf]: + intf_ospf_value = c_data["links"][destRouterLink][ospf][keyword] + if "delete" in data and data["delete"]: + interface_data.append( + "no {} {}".format(ip_ospf, keyword.replace("_", "-")) + ) + else: + interface_data.append( + "{} {} {}".format( + ip_ospf, keyword.replace("_", "-"), intf_ospf_value + ) + ) + return interface_data + result = False topo = deepcopy(topo) @@ -1640,66 +1669,26 @@ def create_interfaces_cfg(tgen, topo, build=False): else: interface_data.append("ipv6 address {}\n".format(intf_addr)) + ospf_keywords = [ + "hello_interval", + "dead_interval", + "network", + "priority", + "cost", + ] if "ospf" in data: - ospf_data = data["ospf"] - if "area" in ospf_data: - intf_ospf_area = c_data["links"][destRouterLink]["ospf"]["area"] - if "delete" in data and data["delete"]: - interface_data.append("no ip ospf area") - else: - interface_data.append( - "ip ospf area {}".format(intf_ospf_area) - ) - - if "hello_interval" in ospf_data: - intf_ospf_hello = c_data["links"][destRouterLink]["ospf"][ - "hello_interval" - ] - if "delete" in data and data["delete"]: - interface_data.append("no ip ospf " " hello-interval") - else: - interface_data.append( - "ip ospf" " hello-interval {}".format(intf_ospf_hello) - ) - - if "dead_interval" in ospf_data: - intf_ospf_dead = c_data["links"][destRouterLink]["ospf"][ - "dead_interval" - ] - if "delete" in data and data["delete"]: - interface_data.append("no ip ospf" " dead-interval") - else: - interface_data.append( - "ip ospf" " dead-interval {}".format(intf_ospf_dead) - ) - - if "network" in ospf_data: - intf_ospf_nw = c_data["links"][destRouterLink]["ospf"][ - "network" - ] - if "delete" in data and data["delete"]: - interface_data.append( - "no ip ospf" " network {}".format(intf_ospf_nw) - ) - else: - interface_data.append( - "ip ospf" " network {}".format(intf_ospf_nw) - ) - - if "priority" in ospf_data: - intf_ospf_nw = c_data["links"][destRouterLink]["ospf"][ - "priority" - ] + interface_data += _create_interfaces_ospf_cfg( + "ospf", c_data, data, ospf_keywords + ["area"] + ) + if "ospf6" in data: + interface_data += _create_interfaces_ospf_cfg( + "ospf6", c_data, data, ospf_keywords + ) - if "delete" in data and data["delete"]: - interface_data.append("no ip ospf" " priority") - else: - interface_data.append( - "ip ospf" " priority {}".format(intf_ospf_nw) - ) result = create_common_configuration( tgen, c_router, interface_data, "interface_config", build=build ) + except InvalidCLIError: # Traceback errormsg = traceback.format_exc() @@ -4395,4 +4384,3 @@ def verify_ip_nht(tgen, input_dict): logger.debug("Exiting lib API: verify_ip_nht()") return False - diff --git a/tests/topotests/lib/ospf.py b/tests/topotests/lib/ospf.py index 3e368cd7d3..5bc9f14fea 100644 --- a/tests/topotests/lib/ospf.py +++ b/tests/topotests/lib/ospf.py @@ -94,7 +94,7 @@ def create_router_ospf(tgen, topo, input_dict=None, build=False, load_config=Tru return result -def __create_ospf_global(tgen, input_dict, router, build=False, load_config=True): +def __create_ospf_global(tgen, input_dict, router, build=False, load_config=True, ospf="ospf"): """ Helper API to create ospf global configuration. @@ -105,6 +105,33 @@ def __create_ospf_global(tgen, input_dict, router, build=False, load_config=True * `router` : router to be configured. * `build` : Only for initial setup phase this is set as True. * `load_config` : Loading the config to router this is set as True. + * `ospf` : either 'ospf' or 'ospf6' + + Usage + ----- + input_dict = { + "routers": { + "r1": { + "links": { + "r3": { + "ipv6": "2013:13::1/64", + "ospf6": { + "hello_interval": 1, + "dead_interval": 4, + "network": "point-to-point" + } + } + }, + "ospf6": { + "router_id": "1.1.1.1", + "neighbors": { + "r3": { + "area": "1.1.1.1" + } + } + } + } + } Returns ------- @@ -115,17 +142,17 @@ def __create_ospf_global(tgen, input_dict, router, build=False, load_config=True logger.debug("Entering lib API: __create_ospf_global()") try: - ospf_data = input_dict[router]["ospf"] + ospf_data = input_dict[router][ospf] del_ospf_action = ospf_data.setdefault("delete", False) if del_ospf_action: - config_data = ["no router ospf"] + config_data = ["no router {}".format(ospf)] result = create_common_configuration( - tgen, router, config_data, "ospf", build, load_config + tgen, router, config_data, ospf, build, load_config ) return result config_data = [] - cmd = "router ospf" + cmd = "router {}".format(ospf) config_data.append(cmd) @@ -133,9 +160,9 @@ def __create_ospf_global(tgen, input_dict, router, build=False, load_config=True router_id = ospf_data.setdefault("router_id", None) del_router_id = ospf_data.setdefault("del_router_id", False) if del_router_id: - config_data.append("no ospf router-id") + config_data.append("no {} router-id".format(ospf)) if router_id: - config_data.append("ospf router-id {}".format(router_id)) + config_data.append("{} router-id {}".format(ospf, router_id)) # redistribute command redistribute_data = ospf_data.setdefault("redistribute", {}) @@ -154,6 +181,7 @@ def __create_ospf_global(tgen, input_dict, router, build=False, load_config=True if del_action: cmd = "no {}".format(cmd) config_data.append(cmd) + # area information area_data = ospf_data.setdefault("area", {}) if area_data: @@ -173,6 +201,20 @@ def __create_ospf_global(tgen, input_dict, router, build=False, load_config=True cmd = "no {}".format(cmd) config_data.append(cmd) + # area interface information for ospf6d only + if ospf == "ospf6": + area_iface = ospf_data.setdefault("neighbors", {}) + if area_iface: + for neighbor in area_iface: + if "area" in area_iface[neighbor]: + iface = input_dict[router]["links"][neighbor]["interface"] + cmd = "interface {} area {}".format( + iface, area_iface[neighbor]["area"] + ) + if area_iface[neighbor].setdefault("delete", False): + cmd = "no {}".format(cmd) + config_data.append(cmd) + # summary information summary_data = ospf_data.setdefault("summary-address", {}) if summary_data: @@ -197,8 +239,9 @@ def __create_ospf_global(tgen, input_dict, router, build=False, load_config=True if del_action: cmd = "no {}".format(cmd) config_data.append(cmd) + result = create_common_configuration( - tgen, router, config_data, "ospf", build, load_config + tgen, router, config_data, ospf, build, load_config ) except InvalidCLIError: @@ -235,7 +278,7 @@ def create_router_ospf6(tgen, topo, input_dict=None, build=False, load_config=Tr ------- True or False """ - logger.debug("Entering lib API: create_router_ospf()") + logger.debug("Entering lib API: create_router_ospf6()") result = False if not input_dict: @@ -244,67 +287,15 @@ def create_router_ospf6(tgen, topo, input_dict=None, build=False, load_config=Tr topo = topo["routers"] input_dict = deepcopy(input_dict) for router in input_dict.keys(): - if "ospf" not in input_dict[router]: - logger.debug("Router %s: 'ospf' not present in input_dict", router) + if "ospf6" not in input_dict[router]: + logger.debug("Router %s: 'ospf6' not present in input_dict", router) continue - result = __create_ospf_global(tgen, input_dict, router, build, load_config) - - logger.debug("Exiting lib API: create_router_ospf()") - return result - - -def __create_ospf6_global(tgen, input_dict, router, build=False, load_config=True): - """ - Helper API to create ospf global configuration. - - Parameters - ---------- - * `tgen` : Topogen object - * `input_dict` : Input dict data, required when configuring from testcase - * `router` : router id to be configured. - * `build` : Only for initial setup phase this is set as True. - - Returns - ------- - True or False - """ - - result = False - logger.debug("Entering lib API: __create_ospf_global()") - try: - - ospf_data = input_dict[router]["ospf6"] - del_ospf_action = ospf_data.setdefault("delete", False) - if del_ospf_action: - config_data = ["no ipv6 router ospf"] - result = create_common_configuration( - tgen, router, config_data, "ospf", build, load_config - ) - return result - - config_data = [] - cmd = "router ospf" - - config_data.append(cmd) - - router_id = ospf_data.setdefault("router_id", None) - del_router_id = ospf_data.setdefault("del_router_id", False) - if del_router_id: - config_data.append("no ospf router-id") - if router_id: - config_data.append("ospf router-id {}".format(router_id)) - - result = create_common_configuration( - tgen, router, config_data, "ospf", build, load_config + result = __create_ospf_global( + tgen, input_dict, router, build, load_config, "ospf6" ) - except InvalidCLIError: - # Traceback - errormsg = traceback.format_exc() - logger.error(errormsg) - return errormsg - logger.debug("Exiting lib API: create_ospf_global()") + logger.debug("Exiting lib API: create_router_ospf6()") return result @@ -682,6 +673,70 @@ def verify_ospf_neighbor(tgen, topo, dut=None, input_dict=None, lan=False): return result +################################ +# Verification procs +################################ +@retry(attempts=40, wait=2, return_is_str=True) +def verify_ospf6_neighbor(tgen, topo): + """ + This API is to verify ospf neighborship by running + show ip ospf neighbour command, + + Parameters + ---------- + * `tgen` : Topogen object + * `topo` : json file data + + Usage + ----- + Check FULL neighbors. + verify_ospf_neighbor(tgen, topo) + + result = verify_ospf_neighbor(tgen, topo) + + Returns + ------- + True or False (Error Message) + """ + + logger.debug("Entering lib API: verify_ospf6_neighbor()") + result = False + for router, rnode in tgen.routers().items(): + if "ospf6" not in topo["routers"][router]: + continue + + logger.info("Verifying OSPF6 neighborship on router %s:", router) + show_ospf_json = run_frr_cmd( + rnode, "show ipv6 ospf6 neighbor json", isjson=True + ) + + if not show_ospf_json: + return "OSPF6 is not running" + + ospf_nbr_list = topo["routers"][router]["ospf6"]["neighbors"] + no_of_peer = 0 + for ospf_nbr in ospf_nbr_list: + ospf_nbr_rid = topo["routers"][ospf_nbr]["ospf6"]["router_id"] + for neighbor in show_ospf_json["neighbors"]: + if neighbor["neighborId"] == ospf_nbr_rid: + nh_state = neighbor["state"] + break + else: + return "[DUT: {}] OSPF6 peer {} missing".format(router, data_rid) + + if nh_state == "Full": + no_of_peer += 1 + + if no_of_peer == len(ospf_nbr_list): + logger.info("[DUT: {}] OSPF6 is Converged".format(router)) + result = True + else: + return "[DUT: {}] OSPF6 is not Converged".format(router) + + logger.debug("Exiting API: verify_ospf6_neighbor()") + return result + + @retry(attempts=21, wait=2, return_is_str=True) def verify_ospf_rib( tgen, dut, input_dict, next_hop=None, tag=None, metric=None, fib=None diff --git a/tests/topotests/lib/topojson.py b/tests/topotests/lib/topojson.py index 88e6f78b92..fcc6c19868 100644 --- a/tests/topotests/lib/topojson.py +++ b/tests/topotests/lib/topojson.py @@ -45,7 +45,7 @@ from lib.common_config import ( from lib.pim import create_pim_config, create_igmp_config from lib.bgp import create_router_bgp -from lib.ospf import create_router_ospf +from lib.ospf import create_router_ospf, create_router_ospf6 ROUTER_LIST = [] @@ -314,6 +314,7 @@ def build_config_from_json(tgen, topo, save_bkup=True): ("igmp", create_igmp_config), ("bgp", create_router_bgp), ("ospf", create_router_ospf), + ("ospf6", create_router_ospf6), ] ) diff --git a/tests/topotests/ospf-dual-stack/test_ospf_dual_stack.dot b/tests/topotests/ospf-dual-stack/test_ospf_dual_stack.dot new file mode 100644 index 0000000000..2c6d0aab16 --- /dev/null +++ b/tests/topotests/ospf-dual-stack/test_ospf_dual_stack.dot @@ -0,0 +1,107 @@ +## Color coding: +######################### +## Main FRR: #f08080 red +## Switches: #d0e0d0 gray +## RIP: #19e3d9 Cyan +## RIPng: #fcb314 dark yellow +## OSPFv2: #32b835 Green +## OSPFv3: #19e3d9 Cyan +## ISIS IPv4 #fcb314 dark yellow +## ISIS IPv6 #9a81ec purple +## BGP IPv4 #eee3d3 beige +## BGP IPv6 #fdff00 yellow +##### Colors (see http://www.color-hex.com/) + +graph ospf_topo1 { + label="ospf dual stack"; + + # Routers + r1 [ + label="r1\nrtr-id 1.1.1.1/32", + shape=doubleoctagon, + fillcolor="#f08080", + style=filled, + ]; + r2 [ + label="r2\nrtr-id 2.2.2.2/32", + shape=doubleoctagon, + fillcolor="#f08080", + style=filled, + ]; + r3 [ + label="r3\nrtr-id 3.3.3.3/32", + shape=doubleoctagon, + fillcolor="#f08080", + style=filled, + ]; + r4 [ + label="r4\nrtr-id 4.4.4.4/32", + shape=doubleoctagon, + fillcolor="#f08080", + style=filled, + ]; + r5 [ + label="r5\nrtr-id 5.5.5.5/32", + shape=doubleoctagon, + fillcolor="#f08080", + style=filled, + ]; + + # Switches + s1 [ + label="s1\n10.0.13.0/24\n2013:13::/64", + shape=oval, + fillcolor="#d0e0d0", + style=filled, + ]; + s2 [ + label="s2\n10.0.23.0/24\n2023:23::/64", + shape=oval, + fillcolor="#d0e0d0", + style=filled, + ]; + s3 [ + label="s3\n10.0.34.0/24\n2034:34::/64", + shape=oval, + fillcolor="#d0e0d0", + style=filled, + ]; + s4 [ + label="s4\n10.0.24.0/24\n2024:24::/64", + shape=oval, + fillcolor="#d0e0d0", + style=filled, + ]; + s5 [ + label="s5\n10.0.45.0/24\n2045:45::/64", + shape=oval, + fillcolor="#d0e0d0", + style=filled, + ]; + + # Connections + subgraph cluster1 { + label="area 1.1.1.1" + + r1 -- s1 [label="eth0\n.1\n::1"]; + r3 -- s1 [label="eth0\n.3\n::3"]; + r3 -- s2 [label="eth1\n.3\n::3"]; + r2 -- s2 [label="eth0\n.2\n::2"]; + } + + subgraph cluster0 { + label="area 0.0.0.0" + + r3 -- s3 [label="eth2\n.3\n::3"]; + r4 -- s3 [label="eth0\n.4\n::4"]; + r2 -- s4 [label="eth1\n.2\n::2"]; + r4 -- s4 [label="eth1\n.4\n::4"]; + } + + subgraph cluster2 { + label="area 2.2.2.2" + + r4 -- s5 [label="eth2\n.4\n::4"]; + r5 -- s5 [label="eth0\n.5\n::5"]; + } +} diff --git a/tests/topotests/ospf-dual-stack/test_ospf_dual_stack.jpg b/tests/topotests/ospf-dual-stack/test_ospf_dual_stack.jpg Binary files differnew file mode 100644 index 0000000000..44efda8390 --- /dev/null +++ b/tests/topotests/ospf-dual-stack/test_ospf_dual_stack.jpg diff --git a/tests/topotests/ospf-dual-stack/test_ospf_dual_stack.json b/tests/topotests/ospf-dual-stack/test_ospf_dual_stack.json new file mode 100644 index 0000000000..c8a3ce783b --- /dev/null +++ b/tests/topotests/ospf-dual-stack/test_ospf_dual_stack.json @@ -0,0 +1,255 @@ +{ + "ipv4base": "10.0.0.0", + "ipv4mask": 24, + "link_ip_start": { + "ipv4": "10.0.0.0", + "v4mask": 24 + }, + "lo_prefix": { + "ipv4": "1.0.", + "v4mask": 32 + }, + "routers": { + "r1": { + "links": { + "r3": { + "ipv4": "10.0.13.1/24", + "ipv6": "2013:13::1/64", + "ospf": { + "area": "1.1.1.1", + "hello_interval": 1, + "dead_interval": 4, + "network": "point-to-point" + }, + "ospf6": { + "hello_interval": 1, + "dead_interval": 4 + } + } + }, + "ospf": { + "router_id": "1.1.1.1", + "neighbors": { + "r3": {} + } + }, + "ospf6": { + "router_id": "1.1.1.1", + "neighbors": { + "r3": { + "area": "1.1.1.1" + } + } + } + }, + "r2": { + "links": { + "r3": { + "ipv4": "10.0.23.2/24", + "ipv6": "2023:23::2/64", + "ospf": { + "area": "1.1.1.1", + "hello_interval": 1, + "dead_interval": 4, + "network": "point-to-point" + }, + "ospf6": { + "hello_interval": 1, + "dead_interval": 4, + "network": "point-to-point" + } + }, + "r4": { + "ipv4": "10.0.24.2/24", + "ipv6": "2034:34::2/64", + "ospf": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4, + "network": "point-to-point" + }, + "ospf6": { + "hello_interval": 1, + "dead_interval": 4, + "network": "point-to-point" + } + } + }, + "ospf": { + "router_id": "2.2.2.2", + "neighbors": { + "r3": {}, + "r4": {} + } + }, + "ospf6": { + "router_id": "2.2.2.2", + "neighbors": { + "r3": { "area": "1.1.1.1" }, + "r4": { "area": "0.0.0.0" } + } + } + }, + "r3": { + "links": { + "r1": { + "ipv4": "10.0.13.3/24", + "ipv6": "2013:13::3/64", + "ospf": { + "area": "1.1.1.1", + "hello_interval": 1, + "dead_interval": 4, + "network": "point-to-point" + }, + "ospf6": { + "hello_interval": 1, + "dead_interval": 4, + "network": "point-to-point" + } + }, + "r2": { + "ipv4": "10.0.23.3/24", + "ipv6": "2023:23::3/64", + "ospf": { + "area": "1.1.1.1", + "hello_interval": 1, + "dead_interval": 4, + "network": "point-to-point" + }, + "ospf6": { + "hello_interval": 1, + "dead_interval": 4, + "network": "point-to-point" + } + }, + "r4": { + "ipv4": "10.0.34.3/24", + "ipv6": "2034:34::3/64", + "ospf": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4, + "network": "point-to-point" + }, + "ospf6": { + "hello_interval": 1, + "dead_interval": 4, + "network": "point-to-point" + } + } + }, + "ospf": { + "router_id": "3.3.3.3", + "neighbors": { + "r1": {}, + "r2": {}, + "r4": {} + } + }, + "ospf6": { + "router_id": "3.3.3.3", + "neighbors": { + "r1": { "area": "1.1.1.1" }, + "r2": { "area": "1.1.1.1" }, + "r4": { "area": "0.0.0.0" } + } + } + }, + "r4": { + "links": { + "r2": { + "ipv4": "10.0.24.4/24", + "ipv6": "2024:24::4/64", + "ospf": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4, + "network": "point-to-point" + }, + "ospf6": { + "hello_interval": 1, + "dead_interval": 4, + "network": "point-to-point" + } + }, + "r3": { + "ipv4": "10.0.34.4/24", + "ipv6": "2034:34::4/64", + "ospf": { + "area": "0.0.0.0", + "hello_interval": 1, + "dead_interval": 4, + "network": "point-to-point" + }, + "ospf6": { + "hello_interval": 1, + "dead_interval": 4, + "network": "point-to-point" + } + }, + "r5": { + "ipv4": "10.0.45.4/24", + "ipv6": "2045:45::4/64", + "ospf": { + "area": "2.2.2.2", + "hello_interval": 1, + "dead_interval": 4, + "network": "point-to-point" + }, + "ospf6": { + "hello_interval": 1, + "dead_interval": 4, + "network": "point-to-point" + } + } + }, + "ospf": { + "router_id": "4.4.4.4", + "neighbors": { + "r2": {}, + "r3": {}, + "r5": {} + } + }, + "ospf6": { + "router_id": "4.4.4.4", + "neighbors": { + "r2": { "area": "0.0.0.0" }, + "r3": { "area": "0.0.0.0" }, + "r5": { "area": "2.2.2.2" } + } + } + }, + "r5": { + "links": { + "r4": { + "ipv4": "10.0.45.5/24", + "ipv6": "2045:45::5/64", + "ospf": { + "area": "2.2.2.2", + "hello_interval": 1, + "dead_interval": 4, + "network": "point-to-point" + }, + "ospf6": { + "hello_interval": 1, + "dead_interval": 4, + "network": "point-to-point" + } + } + }, + "ospf": { + "router_id": "5.5.5.5", + "neighbors": { + "r4": {} + } + }, + "ospf6": { + "router_id": "5.5.5.5", + "neighbors": { + "r4": { "area": "2.2.2.2" } + } + } + } + } +} diff --git a/tests/topotests/ospf-dual-stack/test_ospf_dual_stack.py b/tests/topotests/ospf-dual-stack/test_ospf_dual_stack.py new file mode 100644 index 0000000000..5e7802fa04 --- /dev/null +++ b/tests/topotests/ospf-dual-stack/test_ospf_dual_stack.py @@ -0,0 +1,152 @@ +#!/usr/bin/python + +import os +import sys +import time +import pytest +import json + +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) +sys.path.append(os.path.join(CWD, "../lib/")) + +from mininet.topo import Topo +from lib.topogen import Topogen, get_topogen + +from lib.common_config import ( + start_topology, + write_test_header, + write_test_footer, + reset_config_on_routers, + stop_router, + start_router, + verify_rib, + create_static_routes, + step, + start_router_daemons, + shutdown_bringup_interface, + topo_daemons, + create_prefix_lists, + create_interfaces_cfg, + run_frr_cmd, +) +from lib.topolog import logger +from lib.topojson import build_topo_from_json, build_config_from_json +from lib.ospf import ( + verify_ospf_neighbor, + verify_ospf6_neighbor, + create_router_ospf, + create_router_ospf6, + verify_ospf_summary, + redistribute_ospf, + verify_ospf_database, +) + +# Global variables +topo = None + +# Reading the data from JSON File for topology creation +jsonFile = "{}/test_ospf_dual_stack.json".format(CWD) +try: + with open(jsonFile, "r") as topoJson: + topo = json.load(topoJson) +except IOError: + assert False, "Could not read file {}".format(jsonFile) + + +class CreateTopo(Topo): + """Test topology builder.""" + + def build(self, *_args, **_opts): + """Build function.""" + tgen = get_topogen(self) + + # Building topology from json file + build_topo_from_json(tgen, topo) + + +def setup_module(mod): + """Sets up the pytest environment.""" + global topo + testsuite_run_time = time.asctime(time.localtime(time.time())) + logger.info("Testsuite start time: {}".format(testsuite_run_time)) + logger.info("=" * 40) + + logger.info("Running setup_module to create topology") + + # This function initiates the topology build with Topogen... + tgen = Topogen(CreateTopo, mod.__name__) + # ... and here it calls Mininet initialization functions. + + # get list of daemons needs to be started for this suite. + daemons = topo_daemons(tgen, topo) + + # Starting topology, create tmp files which are loaded to routers + # to start daemons 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 converged + ospf_covergence_ipv4 = verify_ospf_neighbor(tgen, topo) + assert ospf_covergence_ipv4 is True, "setup_module :Failed \n Error:" " {}".format( + ospf_covergence_ipv4 + ) + + # Api call verify whether OSPF6 converged + ospf_covergence_ipv6 = verify_ospf6_neighbor(tgen, topo) + assert ospf_covergence_ipv6 is True, "setup_module :Failed \n Error:" " {}".format( + ospf_covergence_ipv6 + ) + 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 topology and remove tmp files + tgen.stop_topology() + logger.info( + "Testsuite end time: {}".format(time.asctime(time.localtime(time.time()))) + ) + logger.info("=" * 40) + + +# +# ################################## +# Test cases start here. +# ################################## +# +# +def test_ospf_dual_stack(request): + """OSPF test dual stack.""" + + tc_name = request.node.name + write_test_header(tc_name) + + # Don't run this test if we have any failure. + tgen = get_topogen() + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + global topo + + step("Bring up the base configuration as per the JSON topology") + reset_config_on_routers(tgen) + write_test_footer(tc_name) + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) |
