]> git.puffer.fish Git - matthieu/frr.git/commitdiff
tests: Adding static routing topojson automation suites.
authornaveen <nguggarigoud@vmware.com>
Mon, 13 Apr 2020 15:54:45 +0000 (21:24 +0530)
committerVijay Kumar Gupta <vijayg@vmware.com>
Fri, 11 Dec 2020 00:44:48 +0000 (16:44 -0800)
1. Enhanced framework to
a. Verify fib active routes(lib/common_config.py).
b. Verify bgp multi path routes(lib/bgp.py).
c. Create mininet nodes with different names(lib/topojson.py).

4. 12 Test cases of static routing with ibgp.
Test suite execution time is ~30 minutes.

5. 12 Test cases of static routing with ebgp.
Test suite execution time is ~30 minutes.

Signed-off-by: naveen <nguggarigoud@vmware.com>
19 files changed:
tests/topotests/lib/bgp.py
tests/topotests/lib/common_config.py
tests/topotests/lib/topojson.py
tests/topotests/static_routing_with_ebgp/static_routes_topo1_ebgp.json [new file with mode: 0644]
tests/topotests/static_routing_with_ebgp/static_routes_topo2_ebgp.json [new file with mode: 0644]
tests/topotests/static_routing_with_ebgp/static_routes_topo3_ebgp.json [new file with mode: 0644]
tests/topotests/static_routing_with_ebgp/static_routes_topo4_ebgp.json [new file with mode: 0644]
tests/topotests/static_routing_with_ebgp/test_static_routes_topo1_ebgp.py [new file with mode: 0644]
tests/topotests/static_routing_with_ebgp/test_static_routes_topo2_ebgp.py [new file with mode: 0644]
tests/topotests/static_routing_with_ebgp/test_static_routes_topo3_ebgp.py [new file with mode: 0644]
tests/topotests/static_routing_with_ebgp/test_static_routes_topo4_ebgp.py [new file with mode: 0644]
tests/topotests/static_routing_with_ibgp/static_routes_topo1_ibgp.json [new file with mode: 0644]
tests/topotests/static_routing_with_ibgp/static_routes_topo2_ibgp.json [new file with mode: 0644]
tests/topotests/static_routing_with_ibgp/static_routes_topo3_ibgp.json [new file with mode: 0644]
tests/topotests/static_routing_with_ibgp/static_routes_topo4_ibgp.json [new file with mode: 0644]
tests/topotests/static_routing_with_ibgp/test_static_routes_topo1_ibgp.py [new file with mode: 0644]
tests/topotests/static_routing_with_ibgp/test_static_routes_topo2_ibgp.py [new file with mode: 0644]
tests/topotests/static_routing_with_ibgp/test_static_routes_topo3_ibgp.py [new file with mode: 0644]
tests/topotests/static_routing_with_ibgp/test_static_routes_topo4_ibgp.py [new file with mode: 0644]

index ddeaf55b330b15f402b9240436f9ff689ba2bb75..13c794f182d22e53a7a515306afaedf656f7a5bb 100644 (file)
@@ -21,6 +21,7 @@
 from copy import deepcopy
 from time import sleep
 import traceback
+import ipaddr
 import ipaddress
 import os
 import sys
@@ -2115,8 +2116,8 @@ def verify_bgp_attributes(
     errormsg(str) or True
     """
 
-    logger.debug("Entering lib API: verify_bgp_attributes()")
-    for router, rnode in tgen.routers().items():
+    logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
+    for router, rnode in tgen.routers().iteritems():
         if router != dut:
             continue
 
@@ -2194,7 +2195,7 @@ def verify_bgp_attributes(
                                             )
                                             return errormsg
 
-    logger.debug("Exiting lib API: verify_bgp_attributes()")
+    logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
     return True
 
 
@@ -2550,6 +2551,7 @@ def verify_bgp_rib(tgen, addr_type, dut, input_dict, next_hop=None, aspath=None)
     additional_nexthops_in_required_nhs = []
     list1 = []
     list2 = []
+    found_hops = []
     for routerInput in input_dict.keys():
         for router, rnode in router_list.items():
             if router != dut:
@@ -2616,20 +2618,29 @@ def verify_bgp_rib(tgen, addr_type, dut, input_dict, next_hop=None, aspath=None)
                             st_found = True
                             found_routes.append(st_rt)
 
-                            if next_hop:
+                            if next_hop and multi_nh and st_found:
                                 if not isinstance(next_hop, list):
                                     next_hop = [next_hop]
                                     list1 = next_hop
 
-                                found_hops = [
-                                    rib_r["ip"]
-                                    for rib_r in rib_routes_json["routes"][st_rt][0][
-                                        "nexthops"
-                                    ]
-                                ]
-                                list2 = found_hops
-
-                                missing_list_of_nexthops = set(list2).difference(list1)
+                                for mnh in range(
+                                    0, len(rib_routes_json["routes"][st_rt])
+                                ):
+                                    found_hops.append(
+                                        [
+                                            rib_r["ip"]
+                                            for rib_r in rib_routes_json["routes"][
+                                                st_rt
+                                            ][mnh]["nexthops"]
+                                        ]
+                                    )
+                                for mnh in found_hops:
+                                    for each_nh_in_multipath in mnh:
+                                        list2.append(each_nh_in_multipath)
+                                if found_hops[0]:
+                                    missing_list_of_nexthops = set(list2).difference(
+                                        list1
+                                    )
                                 additional_nexthops_in_required_nhs = set(
                                     list1
                                 ).difference(list2)
@@ -2643,17 +2654,37 @@ def verify_bgp_rib(tgen, addr_type, dut, input_dict, next_hop=None, aspath=None)
                                             st_rt,
                                             dut,
                                         )
-                                        errormsg = (
-                                            "Nexthop {} is Missing for "
-                                            "route {} in RIB of router {}\n".format(
-                                                additional_nexthops_in_required_nhs,
-                                                st_rt,
-                                                dut,
-                                            )
-                                        )
                                         return errormsg
                                     else:
                                         nh_found = True
+
+                            elif next_hop and multi_nh is None:
+                                if not isinstance(next_hop, list):
+                                    next_hop = [next_hop]
+                                    list1 = next_hop
+                                found_hops = [rib_r["ip"] for rib_r in
+                                              rib_routes_json["routes"][
+                                                  st_rt][0]["nexthops"]]
+                                list2 = found_hops
+                                missing_list_of_nexthops = \
+                                    set(list2).difference(list1)
+                                additional_nexthops_in_required_nhs = \
+                                    set(list1).difference(list2)
+
+                                if list2:
+                                    if additional_nexthops_in_required_nhs:
+                                        logger.info("Missing nexthop %s for route"\
+                                        " %s in RIB of router %s\n", \
+                                        additional_nexthops_in_required_nhs,  \
+                                        st_rt, dut)
+                                        errormsg=("Nexthop {} is Missing for "\
+                                        "route {} in RIB of router {}\n".format(
+                                            additional_nexthops_in_required_nhs,
+                                            st_rt, dut))
+                                        return errormsg
+                                    else:
+                                        nh_found = True
+
                             if aspath:
                                 found_paths = rib_routes_json["routes"][st_rt][0][
                                     "path"
index 6c24b6ddbb5a61f6a866aa0a9ae2875acecc1323..cc6e783f9b99fa27b6cfc9d44a2b4ec6fc568b1b 100644 (file)
@@ -1156,10 +1156,16 @@ def generate_ips(network, no_of_ips):
 
         addr_type = validate_ip_address(start_ip)
         if addr_type == "ipv4":
-            start_ip = ipaddress.IPv4Address(frr_unicode(start_ip))
+            if start_ip == "0.0.0.0" and mask == 0 and no_of_ips == 1:
+                ipaddress_list.append("{}/{}".format(start_ip, mask))
+                return ipaddress_list
+            start_ip = ipaddr.IPv4Address(unicode(start_ip))
             step = 2 ** (32 - mask)
         if addr_type == "ipv6":
-            start_ip = ipaddress.IPv6Address(frr_unicode(start_ip))
+            if start_ip == "0::0" and mask == 0 and no_of_ips == 1:
+                ipaddress_list.append("{}/{}".format(start_ip, mask))
+                return ipaddress_list
+            start_ip = ipaddr.IPv6Address(unicode(start_ip))
             step = 2 ** (128 - mask)
 
         next_ip = start_ip
@@ -2240,6 +2246,51 @@ def shutdown_bringup_interface(tgen, dut, intf_name, ifaceaction=False):
     interface_set_status(router_list[dut], intf_name, ifaceaction)
 
 
+def stop_router(tgen, router):
+    """
+    Router's current config would be saved to /tmp/topotest/<suite>/<router>
+    for each deamon and router and its deamons would be stopped.
+
+    * `tgen`  : topogen object
+    * `router`: Device under test
+    """
+
+    router_list = tgen.routers()
+
+    # Saving router config to /etc/frr, which will be loaded to router
+    # when it starts
+    router_list[router].vtysh_cmd("write memory")
+
+    # Stop router
+    router_list[router].stop()
+
+
+def start_router(tgen, router):
+    """
+    Router will be started and config would be loaded from
+    /tmp/topotest/<suite>/<router> for each deamon
+
+    * `tgen`  : topogen object
+    * `router`: Device under test
+    """
+
+    logger.debug("Entering lib API: start_router")
+
+    try:
+        router_list = tgen.routers()
+
+        # Router and its deamons would be started and config would
+        #  be loaded to router for each deamon from /etc/frr
+        router_list[router].start()
+
+    except Exception as e:
+        errormsg = traceback.format_exc()
+        logger.error(errormsg)
+        return errormsg
+
+    logger.debug("Exiting lib API: start_router()")
+
+
 def addKernelRoute(
     tgen, router, intf, group_addr_range, next_hop=None, src=None, del_action=None
 ):
@@ -3327,7 +3378,12 @@ def verify_prefix_lists(tgen, input_dict):
         for addr_type in prefix_lists_addr:
             if not check_address_types(addr_type):
                 continue
-
+            # show ip prefix list
+            if addr_type == "ipv4":
+                cmd = "show ip prefix-list"
+            else:
+                cmd = "show {} prefix-list".format(addr_type)
+            show_prefix_list = run_frr_cmd(rnode, cmd)
             for prefix_list in prefix_lists_addr[addr_type].keys():
                 if prefix_list in show_prefix_list:
                     errormsg = (
index f2fafa5e2a91a22fbf1e99e87cf122e174a4be73..0e59f90a20a3878212c2e628259074e6255cde5a 100644 (file)
@@ -96,6 +96,7 @@ def build_topo_from_json(tgen, topo):
     for router in listRouters:
         topo["routers"][router]["nextIfname"] = 0
 
+    router_count = 0
     while listRouters != []:
         curRouter = listRouters.pop(0)
         # Physical Interfaces
@@ -116,13 +117,14 @@ def build_topo_from_json(tgen, topo):
                 currRouter_lo_json = topo["routers"][curRouter]["links"][destRouterLink]
                 # Loopback interfaces
                 if "type" in data and data["type"] == "loopback":
+                    router_count += 1
                     if (
                         "ipv4" in currRouter_lo_json
                         and currRouter_lo_json["ipv4"] == "auto"
                     ):
                         currRouter_lo_json["ipv4"] = "{}{}.{}/{}".format(
                             topo["lo_prefix"]["ipv4"],
-                            number_to_row(curRouter),
+                            router_count,
                             number_to_column(curRouter),
                             topo["lo_prefix"]["v4mask"],
                         )
@@ -132,7 +134,7 @@ def build_topo_from_json(tgen, topo):
                     ):
                         currRouter_lo_json["ipv6"] = "{}{}:{}/{}".format(
                             topo["lo_prefix"]["ipv6"],
-                            number_to_row(curRouter),
+                            router_count,
                             number_to_column(curRouter),
                             topo["lo_prefix"]["v6mask"],
                         )
@@ -167,6 +169,14 @@ def build_topo_from_json(tgen, topo):
                         destRouter, curRouter, topo["routers"][destRouter]["nextIfname"]
                     )
 
+                    # add link interface
+                    destRouter_link_json["peer-interface"] = "{}-{}-eth{}".format(
+                        curRouter, destRouter, topo["routers"][curRouter]["nextIfname"]
+                    )
+                    currRouter_link_json["peer-interface"] = "{}-{}-eth{}".format(
+                        destRouter, curRouter, topo["routers"][destRouter]["nextIfname"]
+                    )
+
                     topo["routers"][curRouter]["nextIfname"] += 1
                     topo["routers"][destRouter]["nextIfname"] += 1
 
diff --git a/tests/topotests/static_routing_with_ebgp/static_routes_topo1_ebgp.json b/tests/topotests/static_routing_with_ebgp/static_routes_topo1_ebgp.json
new file mode 100644 (file)
index 0000000..9d337f6
--- /dev/null
@@ -0,0 +1,145 @@
+{
+    "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": {
+        "r1": {
+            "links": {
+                "lo": {
+                    "ipv4": "auto",
+                    "ipv6": "auto",
+                    "type": "loopback"
+                },
+                "r2-link0": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link1": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r3-link0": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r3-link1": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                }
+            }
+        },
+        "r2": {
+            "links": {
+                "lo": {
+                    "ipv4": "auto",
+                    "ipv6": "auto",
+                    "type": "loopback"
+                },
+                "r1-link0": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r1-link1": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r3": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                }
+            },
+            "bgp": {
+                "local_as": "100",
+                "address_family": {
+                    "ipv4": {
+                        "unicast": {
+                            "neighbor": {
+                                "r3": {
+                                    "dest_link": {
+                                        "r2": {}
+                                    }
+                                }
+                            }
+                        }
+                    },
+                    "ipv6": {
+                        "unicast": {
+                            "neighbor": {
+                                "r3": {
+                                    "dest_link": {
+                                        "r2": {}
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        },
+        "r3": {
+            "links": {
+                "lo": {
+                    "ipv4": "auto",
+                    "ipv6": "auto",
+                    "type": "loopback"
+                },
+                "r2": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r1-link0": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r1-link1": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                }
+            },
+            "bgp": {
+                "local_as": "200",
+                "address_family": {
+                    "ipv4": {
+                        "unicast": {
+                            "neighbor": {
+                                "r2": {
+                                    "dest_link": {
+                                        "r3": {}
+                                    }
+                                }
+                            }
+                        }
+                    },
+                    "ipv6": {
+                        "unicast": {
+                            "neighbor": {
+                                "r2": {
+                                    "dest_link": {
+                                        "r3": {}
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/topotests/static_routing_with_ebgp/static_routes_topo2_ebgp.json b/tests/topotests/static_routing_with_ebgp/static_routes_topo2_ebgp.json
new file mode 100644 (file)
index 0000000..fc849d8
--- /dev/null
@@ -0,0 +1,267 @@
+{
+    "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": {
+        "r1": {
+            "links": {
+                "lo": {
+                    "ipv4": "auto",
+                    "ipv6": "auto",
+                    "type": "loopback"
+                },
+                "r2-link0": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link1": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link2": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link3": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link4": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link5": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link6": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link7": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                }
+            }
+        },
+        "r2": {
+            "links": {
+                "lo": {
+                    "ipv4": "auto",
+                    "ipv6": "auto",
+                    "type": "loopback"
+                },
+                "r1-link0": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r1-link1": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r1-link2": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r1-link3": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r1-link4": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r1-link5": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r1-link6": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r1-link7": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r3-link0": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r3-link1": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r3-link2": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r3-link3": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r3-link4": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r3-link5": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r3-link6": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r3-link7": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                }
+            },
+            "bgp": {
+                "local_as": "200",
+                "address_family": {
+                    "ipv4": {
+                        "unicast": {
+                            "neighbor": {
+                                "r3": {
+                                    "dest_link": {
+                                        "r2-link0": {},
+                                        "r2-link1": {},
+                                        "r2-link2": {},
+                                        "r2-link3": {},
+                                        "r2-link4": {},
+                                        "r2-link5": {},
+                                        "r2-link6": {},
+                                        "r2-link7": {}
+                                    }
+                                }
+                            },
+                            "redistribute": [{
+                                "redist_type": "static"
+                            }]
+                        }
+                    },
+                    "ipv6": {
+                        "unicast": {
+                            "neighbor": {
+                                "r3": {
+                                    "dest_link": {
+                                        "r2-link0": {},
+                                        "r2-link1": {},
+                                        "r2-link2": {},
+                                        "r2-link3": {},
+                                        "r2-link4": {},
+                                        "r2-link5": {},
+                                        "r2-link6": {},
+                                        "r2-link7": {}
+                                    }
+                                }
+                            },
+                            "redistribute": [{
+                                "redist_type": "static"
+                            }]
+                        }
+                    }
+                }
+            }
+        },
+        "r3": {
+            "links": {
+                "lo": {
+                    "ipv4": "auto",
+                    "ipv6": "auto",
+                    "type": "loopback"
+                },
+                "r2-link0": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link1": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link2": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link3": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link4": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link5": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link6": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link7": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                }
+            },
+            "bgp": {
+                "local_as": "300",
+                "address_family": {
+                    "ipv4": {
+                        "unicast": {
+                            "neighbor": {
+                                "r2": {
+                                    "dest_link": {
+                                        "r3-link0": {},
+                                        "r3-link1": {},
+                                        "r3-link2": {},
+                                        "r3-link3": {},
+                                        "r3-link4": {},
+                                        "r3-link5": {},
+                                        "r3-link6": {},
+                                        "r3-link7": {}
+                                    }
+                                }
+                            }
+                        }
+                    },
+                    "ipv6": {
+                        "unicast": {
+                            "neighbor": {
+                                "r2": {
+                                    "dest_link": {
+                                        "r3-link0": {},
+                                        "r3-link1": {},
+                                        "r3-link2": {},
+                                        "r3-link3": {},
+                                        "r3-link4": {},
+                                        "r3-link5": {},
+                                        "r3-link6": {},
+                                        "r3-link7": {}
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/topotests/static_routing_with_ebgp/static_routes_topo3_ebgp.json b/tests/topotests/static_routing_with_ebgp/static_routes_topo3_ebgp.json
new file mode 100644 (file)
index 0000000..7c1d7f8
--- /dev/null
@@ -0,0 +1,177 @@
+{
+    "address_types": [
+        "ipv4",
+        "ipv6"
+    ],
+    "ipv4base": "10.0.0.0",
+    "ipv4mask": 30,
+    "ipv6base": "fd00::",
+    "ipv6mask": 64,
+    "link_ip_start": {
+        "ipv4": "10.0.0.0",
+        "v4mask": 29,
+        "ipv6": "fd00::",
+        "v6mask": 64
+    },
+    "lo_prefix": {
+        "ipv4": "1.0.",
+        "v4mask": 32,
+        "ipv6": "2001:db8:f::",
+        "v6mask": 128
+    },
+    "routers": {
+        "r1": {
+            "links": {
+                "lo": {
+                    "ipv4": "auto",
+                    "ipv6": "auto",
+                    "type": "loopback"
+                },
+                "r2-link0": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link1": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link2": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link3": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link4": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link5": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link6": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link7": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                }
+            }
+        },
+        "r2": {
+            "links": {
+                "lo": {
+                    "ipv4": "auto",
+                    "ipv6": "auto",
+                    "type": "loopback"
+                },
+                "r1-link0": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r1-link1": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r1-link2": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r1-link3": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r1-link4": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r1-link5": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r1-link6": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r1-link7": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r3-link0": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                }
+            },
+            "bgp": {
+                "local_as": "100",
+                "address_family": {
+                    "ipv4": {
+                        "unicast": {
+                            "neighbor": {
+                                "r3": {
+                                    "dest_link": {
+                                        "r2-link0": {}
+                                    }
+                                }
+                            }
+                        }
+                    },
+                    "ipv6": {
+                        "unicast": {
+                            "neighbor": {
+                                "r3": {
+                                    "dest_link": {
+                                        "r2-link0": {}
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        },
+        "r3": {
+            "links": {
+                "lo": {
+                    "ipv4": "auto",
+                    "ipv6": "auto",
+                    "type": "loopback"
+                },
+                "r2-link0": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                }
+            },
+            "bgp": {
+                "local_as": "200",
+                "address_family": {
+                    "ipv4": {
+                        "unicast": {
+                            "neighbor": {
+                                "r2": {
+                                    "dest_link": {
+                                        "r3-link0": {}
+                                    }
+                                }
+                            }
+                        }
+                    },
+                    "ipv6": {
+                        "unicast": {
+                            "neighbor": {
+                                "r2": {
+                                    "dest_link": {
+                                        "r3-link0": {}
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/topotests/static_routing_with_ebgp/static_routes_topo4_ebgp.json b/tests/topotests/static_routing_with_ebgp/static_routes_topo4_ebgp.json
new file mode 100644 (file)
index 0000000..bb72578
--- /dev/null
@@ -0,0 +1,428 @@
+{
+    "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": {
+        "r1": {
+            "links": {
+                "lo": {
+                    "ipv4": "auto",
+                    "ipv6": "auto",
+                    "type": "loopback"
+                },
+                "r2-link0": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link1": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link2": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link3": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "vm4": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                }
+            },
+            "bgp": {
+                "local_as": "100",
+                "address_family": {
+                    "ipv4": {
+                        "unicast": {
+                            "neighbor": {
+                                "r2": {
+                                    "dest_link": {
+                                        "r1-link0": {
+                                            "password": "r1",
+                                            "holddowntimer": 3,
+                                            "keepalivetimer": 1
+                                        },
+                                        "r1-link1": {
+                                            "password": "r1",
+                                            "holddowntimer": 3,
+                                            "keepalivetimer": 1
+                                        },
+                                        "r1-link2": {
+                                            "password": "r1",
+                                            "holddowntimer": 3,
+                                            "keepalivetimer": 1
+                                        },
+                                        "r1-link3": {
+                                            "password": "r1",
+                                            "holddowntimer": 3,
+                                            "keepalivetimer": 1
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    },
+                    "ipv6": {
+                        "unicast": {
+                            "neighbor": {
+                                "r2": {
+                                    "dest_link": {
+                                        "r1-link0": {
+                                            "password": "r1",
+                                            "holddowntimer": 3,
+                                            "keepalivetimer": 1
+                                        },
+                                        "r1-link1": {
+                                            "password": "r1",
+                                            "holddowntimer": 3,
+                                            "keepalivetimer": 1
+                                        },
+                                        "r1-link2": {
+                                            "password": "r1",
+                                            "holddowntimer": 3,
+                                            "keepalivetimer": 1
+                                        },
+                                        "r1-link3": {
+                                            "password": "r1",
+                                            "holddowntimer": 3,
+                                            "keepalivetimer": 1
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        },
+        "r2": {
+            "links": {
+                "lo": {
+                    "ipv4": "auto",
+                    "ipv6": "auto",
+                    "type": "loopback"
+                },
+                "r1-link0": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r1-link1": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r1-link2": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r1-link3": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r3-link0": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r3-link1": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r3-link2": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "vm1": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "vm2": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "vm3": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "vm6": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r3-link3": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                }
+            },
+            "bgp": {
+                "local_as": "200",
+                "address_family": {
+                    "ipv4": {
+                        "unicast": {
+                            "neighbor": {
+                                "r1": {
+                                    "dest_link": {
+                                        "r2-link0": {
+                                            "password": "r1"
+                                        },
+                                        "r2-link1": {
+                                            "password": "r1"
+                                        },
+                                        "r2-link2": {
+                                            "password": "r1"
+                                        },
+                                        "r2-link3": {
+                                            "password": "r1"
+                                        }
+                                    }
+                                },
+                                "r3": {
+                                    "dest_link": {
+                                        "r2-link0": {
+                                            "password": "r1"
+                                        },
+                                        "r2-link1": {
+                                            "password": "r1"
+                                        },
+                                        "r2-link2": {
+                                            "password": "r1"
+                                        },
+                                        "r2-link3": {
+                                            "password": "r1"
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    },
+                    "ipv6": {
+                        "unicast": {
+                            "neighbor": {
+                                "r1": {
+                                    "dest_link": {
+                                        "r2-link0": {
+                                            "password": "r1"
+                                        },
+                                        "r2-link1": {
+                                            "password": "r1"
+                                        },
+                                        "r2-link2": {
+                                            "password": "r1"
+                                        },
+                                        "r2-link3": {
+                                            "password": "r1"
+                                        }
+                                    }
+                                },
+                                "r3": {
+                                    "dest_link": {
+                                        "r2-link0": {
+                                            "password": "r1"
+                                        },
+                                        "r2-link1": {
+                                            "password": "r1"
+                                        },
+                                        "r2-link2": {
+                                            "password": "r1"
+                                        },
+                                        "r2-link3": {
+                                            "password": "r1"
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        },
+        "r3": {
+            "links": {
+                "lo": {
+                    "ipv4": "auto",
+                    "ipv6": "auto",
+                    "type": "loopback"
+                },
+                "r2-link0": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link1": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link2": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link3": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "vm5": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                }
+            },
+            "bgp": {
+                "local_as": "300",
+                "address_family": {
+                    "ipv4": {
+                        "unicast": {
+                            "neighbor": {
+                                "r2": {
+                                    "dest_link": {
+                                        "r3-link0": {
+                                            "password": "r1",
+                                            "holddowntimer": 3,
+                                            "keepalivetimer": 1
+                                        },
+                                        "r3-link1": {
+                                            "password": "r1",
+                                            "holddowntimer": 3,
+                                            "keepalivetimer": 1
+                                        },
+                                        "r3-link2": {
+                                            "password": "r1",
+                                            "holddowntimer": 3,
+                                            "keepalivetimer": 1
+                                        },
+                                        "r3-link3": {
+                                            "password": "r1",
+                                            "holddowntimer": 3,
+                                            "keepalivetimer": 1
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    },
+                    "ipv6": {
+                        "unicast": {
+                            "neighbor": {
+                                "r2": {
+                                    "dest_link": {
+                                        "r3-link0": {
+                                            "password": "r1",
+                                            "holddowntimer": 3,
+                                            "keepalivetimer": 1
+                                        },
+                                        "r3-link1": {
+                                            "password": "r1",
+                                            "holddowntimer": 3,
+                                            "keepalivetimer": 1
+                                        },
+                                        "r3-link2": {
+                                            "password": "r1",
+                                            "holddowntimer": 3,
+                                            "keepalivetimer": 1
+                                        },
+                                        "r3-link3": {
+                                            "password": "r1",
+                                            "holddowntimer": 3,
+                                            "keepalivetimer": 1
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        },
+        "vm1": {
+            "links": {
+                "lo": {
+                    "ipv4": "auto",
+                    "ipv6": "auto",
+                    "type": "loopback"
+                },
+                "r2": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                }
+            }
+        },
+        "vm2": {
+            "links": {
+                "lo": {
+                    "ipv4": "auto",
+                    "ipv6": "auto",
+                    "type": "loopback"
+                },
+                "r2": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                }
+            }
+        },
+        "vm3": {
+            "links": {
+                "lo": {
+                    "ipv4": "auto",
+                    "ipv6": "auto",
+                    "type": "loopback"
+                },
+                "r2": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                }
+            }
+        },
+        "vm4": {
+            "links": {
+                "lo": {
+                    "ipv4": "auto",
+                    "ipv6": "auto",
+                    "type": "loopback"
+                },
+                "r1": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                }
+            }
+        },
+        "vm5": {
+            "links": {
+                "lo": {
+                    "ipv4": "auto",
+                    "ipv6": "auto",
+                    "type": "loopback"
+                },
+                "r3": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                }
+            }
+        },
+        "vm6": {
+            "links": {
+                "lo": {
+                    "ipv4": "auto",
+                    "ipv6": "auto",
+                    "type": "loopback"
+                },
+                "r2": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/topotests/static_routing_with_ebgp/test_static_routes_topo1_ebgp.py b/tests/topotests/static_routing_with_ebgp/test_static_routes_topo1_ebgp.py
new file mode 100644 (file)
index 0000000..7a31ec5
--- /dev/null
@@ -0,0 +1,1343 @@
+#!/usr/bin/python
+
+#
+# Copyright (c) 2020 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.
+#
+"""
+
+    -Verify static route ECMP functionality with 2 next hop.
+
+    -Verify static route functionality with 2 next hop and different AD
+    value.
+
+    -Verify RIB status when same route advertise via BGP and static route.
+
+"""
+import sys
+import json
+import time
+import os
+import pytest
+import ipaddr
+from time import sleep
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+sys.path.append(os.path.join(CWD, "../lib/"))
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from mininet.topo import Topo
+from lib.topogen import Topogen, get_topogen
+
+# Import 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,
+    check_address_types,
+    step,
+    create_interfaces_cfg,
+    shutdown_bringup_interface,
+    stop_router,
+    start_router,
+)
+from lib.topolog import logger
+from lib.bgp import verify_bgp_convergence, create_router_bgp, verify_bgp_rib
+from lib.topojson import build_topo_from_json, build_config_from_json
+
+# Reading the data from JSON File for topology creation
+jsonFile = "{}/static_routes_topo1_ebgp.json".format(CWD)
+try:
+    with open(jsonFile, "r") as topoJson:
+        topo = json.load(topoJson)
+except IOError:
+    assert False, "Could not read file {}".format(jsonFile)
+
+# Global variables
+BGP_CONVERGENCE = False
+ADDR_TYPES = check_address_types()
+NETWORK = {"ipv4": ["11.0.20.1/32", "11.0.20.2/32"], "ipv6": ["2::1/128", "2::2/128"]}
+NETWORK2 = {"ipv4": "11.0.20.1/32", "ipv6": "2::1/128"}
+
+PREFIX1 = {"ipv4": "110.0.20.1/32", "ipv6": "20::1/128"}
+
+
+class CreateTopo(Topo):
+    """
+    Test CreateTopo - topology 1.
+
+    * `Topo`: Topology object
+    """
+
+    def build(self, *_args, **_opts):
+        """Build function."""
+        tgen = get_topogen(self)
+
+        # Building topology from json file
+        build_topo_from_json(tgen, topo)
+
+
+def setup_module(mod):
+    """
+    Sets up the pytest environment.
+
+    * `mod`: module name
+    """
+    global topo
+    testsuite_run_time = time.asctime(time.localtime(time.time()))
+    logger.info("Testsuite start time: {}".format(testsuite_run_time))
+    logger.info("=" * 40)
+
+    logger.info("Running setup_module to create topology")
+
+    # This function initiates the topology build with Topogen...
+    tgen = Topogen(CreateTopo, mod.__name__)
+    # ... and here it calls Mininet initialization functions.
+
+    # Starting topology, create tmp files which are loaded to routers
+    #  to start deamons and then start routers
+    start_topology(tgen)
+
+    # Creating configuration from JSON
+    build_config_from_json(tgen, topo)
+
+    # Checking BGP convergence
+    global BGP_CONVERGENCE
+    global ADDR_TYPES
+    # Don't run this test if we have any failure.
+    if tgen.routers_have_failure():
+        pytest.skip(tgen.errors)
+    # Api call verify whether BGP is converged
+    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo)
+    assert BGP_CONVERGENCE is True, "setup_module :Failed \n Error: {}".format(
+        BGP_CONVERGENCE
+    )
+
+    logger.info("Running setup_module() done")
+
+
+def teardown_module(mod):
+    """
+    Teardown the pytest environment.
+
+    * `mod`: module name
+    """
+
+    logger.info("Running teardown_module to delete topology")
+
+    tgen = get_topogen()
+
+    # Stop toplogy and Remove tmp files
+    tgen.stop_topology()
+
+    logger.info(
+        "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
+    )
+    logger.info("=" * 40)
+
+
+def populate_nh():
+    NEXT_HOP_IP = {
+        "nh1": {
+            "ipv4": topo["routers"]["r1"]["links"]["r2-link0"]["ipv4"].split("/")[0],
+            "ipv6": topo["routers"]["r1"]["links"]["r2-link0"]["ipv6"].split("/")[0],
+        },
+        "nh2": {
+            "ipv4": topo["routers"]["r1"]["links"]["r2-link1"]["ipv4"].split("/")[0],
+            "ipv6": topo["routers"]["r1"]["links"]["r2-link1"]["ipv6"].split("/")[0],
+        },
+    }
+    return NEXT_HOP_IP
+
+
+#####################################################
+#
+#   Testcases
+#
+#####################################################
+
+
+def test_static_route_2nh_p0_tc_1_ebgp(request):
+    """
+    Verify static route ECMP functionality with 2 next hop.
+
+    """
+    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)
+
+    reset_config_on_routers(tgen)
+    NEXT_HOP_IP = populate_nh()
+
+    step(
+        "Configure IPv4 static route (10.1.1.1) in R2 with next hop N1"
+        "(28.1.1.2 ) and N2 (29.1.1.2) , Static route next-hop present on"
+        "R1"
+    )
+    step("ex :- ip route 10.1.1.1/24 28.1.1.2 & ip route 10.1.1.1/24 29.1.1.1")
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": NETWORK[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                    },
+                    {
+                        "network": NETWORK[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh2"][addr_type],
+                    },
+                ]
+            }
+        }
+
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step(
+            "On R2, static route installed in RIB using show ip route"
+            " with 2 ECMP next hop "
+        )
+        nh = [NEXT_HOP_IP["nh1"][addr_type], NEXT_HOP_IP["nh2"][addr_type]]
+        dut = "r2"
+        protocol = "static"
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol
+        )
+        assert (
+            result is True
+        ), "Testcase {} : Failed" "Error: Routes is missing in RIB".format(tc_name)
+
+        step("Configure IBGP IPv4 peering between R2 and R3 router.")
+        step("Configure redistribute static in BGP on R2 router")
+
+        input_dict_2 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {"redistribute": [{"redist_type": "static"}]}
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step("Remove the static route configured with nexthop N1 from" "running config")
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": NETWORK[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "delete": True,
+                    }
+                ]
+            }
+        }
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step(
+            "On R2, after removing the static route with N1 , "
+            "route become active with nexthop N2 and vice versa."
+        )
+        nh = NEXT_HOP_IP["nh1"][addr_type]
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            expected=False,
+        )
+        assert (
+            result is not True
+        ), "Testcase {} : Failed" "Error: Routes is still present in RIB".format(
+            tc_name
+        )
+
+        nh = [NEXT_HOP_IP["nh2"][addr_type]]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes is"
+        " missing in RIB".format(tc_name)
+
+        step("Configure the static route with nexthop N1")
+
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": NETWORK[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                    }
+                ]
+            }
+        }
+
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step("Remove the static route configured with nexthop N2 from" "running config")
+
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": NETWORK[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh2"][addr_type],
+                        "delete": True,
+                    }
+                ]
+            }
+        }
+
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step(
+            "On R2, after removing the static route with N2 , "
+            "route become active with nexthop N1 and vice versa."
+        )
+        nh = NEXT_HOP_IP["nh2"][addr_type]
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes is"
+        " still present in RIB".format(tc_name)
+
+        nh = [NEXT_HOP_IP["nh1"][addr_type]]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes is"
+        " missing in RIB".format(tc_name)
+
+        step("Configure the static route with nexthop N2")
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": NETWORK[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh2"][addr_type],
+                    }
+                ]
+            }
+        }
+
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step("Shut nexthop interface N1")
+        intf = topo["routers"]["r2"]["links"]["r1-link0"]["interface"]
+
+        shutdown_bringup_interface(tgen, dut, intf, False)
+
+        step("Only one the nexthops should be active in RIB.")
+
+        nh = NEXT_HOP_IP["nh2"][addr_type]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes is"
+        " missing in RIB".format(tc_name)
+
+        nh = NEXT_HOP_IP["nh1"][addr_type]
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes is"
+        " still present in RIB".format(tc_name)
+
+        dut = "r3"
+        result = verify_bgp_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, expected=False
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Route is"
+        " still present in RIB".format(tc_name)
+
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            protocol=protocol,
+            next_hop=nh,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Route is"
+        " still present in RIB".format(tc_name)
+
+        dut = "r2"
+        nh = [NEXT_HOP_IP["nh2"][addr_type]]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes is"
+        " missing in RIB".format(tc_name)
+
+        dut = "r3"
+        result = verify_bgp_rib(tgen, addr_type, dut, input_dict_4)
+        assert result is True, "Testcase {} : Failed \nError: Route is"
+        " missing in RIB".format(tc_name)
+
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, protocol=protocol, expected=False
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Route is"
+        " still present in RIB".format(tc_name)
+
+        dut = "r2"
+        step("No shut the nexthop interface N1")
+        shutdown_bringup_interface(tgen, dut, intf, True)
+
+        step(
+            "after shut of nexthop N1 , route become active "
+            "with nexthop N2 and vice versa."
+        )
+        nh = [NEXT_HOP_IP["nh1"][addr_type], NEXT_HOP_IP["nh2"][addr_type]]
+
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes is"
+        " missing in RIB".format(tc_name)
+
+        step("Shut nexthop interface N2")
+        intf = topo["routers"]["r2"]["links"]["r1-link1"]["interface"]
+        dut = "r2"
+        shutdown_bringup_interface(tgen, dut, intf, False)
+
+        step(
+            " after shut of nexthop N1 , route become active with "
+            "nexthop N2 and vice versa."
+        )
+        nh = NEXT_HOP_IP["nh2"][addr_type]
+
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes is"
+        " still present in RIB".format(tc_name)
+
+        nh = [NEXT_HOP_IP["nh1"][addr_type]]
+        dut = "r2"
+        protocol = "static"
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes is"
+        " missing in RIB".format(tc_name)
+
+        dut = "r3"
+        result = verify_bgp_rib(tgen, addr_type, dut, input_dict_4)
+        assert result is True, "Testcase {} : Failed \nError: Route is"
+        " missing in RIB".format(tc_name)
+
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, protocol=protocol, expected=False
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Route is"
+        " still present in RIB".format(tc_name)
+
+        step("No shut nexthop interface N2")
+        dut = "r2"
+        shutdown_bringup_interface(tgen, dut, intf, True)
+
+        step(
+            "after shut of nexthop N1 , route become active "
+            "with nexthop N2 and vice versa."
+        )
+        nh = [NEXT_HOP_IP["nh1"][addr_type], NEXT_HOP_IP["nh2"][addr_type]]
+
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes is"
+        " missing in RIB".format(tc_name)
+
+        dut = "r3"
+        result = verify_bgp_rib(tgen, addr_type, dut, input_dict_4)
+        assert result is True, "Testcase {} : Failed \nError: Route is"
+        " missing in RIB".format(tc_name)
+
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, protocol=protocol, expected=False
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Route is"
+        " still present in RIB".format(tc_name)
+
+        step("Reload the FRR router")
+        # stop/start -> restart FRR router and verify
+        stop_router(tgen, "r2")
+        sleep(5)
+        start_router(tgen, "r2")
+
+        dut = "r2"
+        step(
+            "After reload of FRR router , static route installed"
+            " in RIB and FIB properly ."
+        )
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes is"
+        " missing in RIB".format(tc_name)
+
+        dut = "r3"
+        result = verify_bgp_rib(tgen, addr_type, dut, input_dict_4)
+        assert result is True, "Testcase {} : Failed \nError: Route is"
+        " still present in RIB".format(tc_name)
+
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, protocol=protocol, expected=False
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Route is"
+        " still present in RIB".format(tc_name)
+
+    write_test_footer(tc_name)
+
+
+def test_static_route_2nh_admin_dist_p0_tc_2_ebgp(request):
+    """
+    Verify static route functionality with 2 next hop & different AD value.
+
+    """
+    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)
+
+    reset_config_on_routers(tgen)
+    NEXT_HOP_IP = populate_nh()
+    step(
+        "Configure IPv4 static route (10.1.1.1) in R2 with next hop N1"
+        "(28.1.1.2 ) AD 10 and N2 (29.1.1.2) AD 20 , Static route next-hop"
+        "present on R1 \n ex :- ip route 10.1.1.1/24 28.1.1.2 10 & "
+        "ip route 10.1.1.1/24 29.1.1.2 20"
+    )
+
+    reset_config_on_routers(tgen)
+    NEXT_HOP_IP = populate_nh()
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": NETWORK2[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "admin_distance": 10,
+                    },
+                    {
+                        "network": NETWORK2[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh2"][addr_type],
+                        "admin_distance": 20,
+                    },
+                ]
+            }
+        }
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step(
+            "On R2, static route installed in RIB using "
+            "show ip route with 2 next hop , lowest AD nexthop is active "
+        )
+        rte1_nh1 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": NETWORK2[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "admin_distance": 10,
+                    }
+                ]
+            }
+        }
+        nh = [NEXT_HOP_IP["nh1"][addr_type]]
+        dut = "r2"
+        protocol = "static"
+        result = verify_rib(
+            tgen, addr_type, dut, rte1_nh1, next_hop=nh, protocol=protocol, fib=True
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes is"
+        "missing in RIB".format(tc_name)
+
+        rte2_nh2 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": NETWORK2[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh2"][addr_type],
+                        "admin_distance": 20,
+                    }
+                ]
+            }
+        }
+        nh = [NEXT_HOP_IP["nh2"][addr_type]]
+        dut = "r2"
+        protocol = "static"
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            rte2_nh2,
+            next_hop=nh,
+            protocol=protocol,
+            fib=True,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes is"
+        "not active in RIB".format(tc_name)
+
+        step("Configure IBGP IPv4 peering between R2 and R3 router.")
+        step("Explicit route is added in R3 for R2 nexthop rechability")
+        rt3_rtes = {
+            "r3": {
+                "static_routes": [
+                    {
+                        "network": NEXT_HOP_IP["nh1"][addr_type] + "/32",
+                        "next_hop": topo["routers"]["r2"]["links"]["r3"][addr_type],
+                    },
+                    {
+                        "network": NEXT_HOP_IP["nh2"][addr_type] + "/32",
+                        "next_hop": topo["routers"]["r2"]["links"]["r3"][addr_type],
+                    },
+                ]
+            }
+        }
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, rt3_rtes)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+        step("Configure redistribute static in BGP on R2 router")
+
+        input_dict_2 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {"redistribute": [{"redist_type": "static"}]}
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step("Remove the static route configured with nexthop N1 from" "running config")
+        rt1_nh1 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": NETWORK[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "delete": True,
+                    }
+                ]
+            }
+        }
+
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, rt1_nh1)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step(
+            "On R2, after removing the static route with N1 , "
+            "route become active with nexthop N2 and vice versa."
+        )
+        rte1_nh1 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": NETWORK2[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "admin_distance": 10,
+                    }
+                ]
+            }
+        }
+        nh = [NEXT_HOP_IP["nh1"][addr_type]]
+        dut = "r2"
+        protocol = "static"
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            rte1_nh1,
+            next_hop=nh,
+            protocol=protocol,
+            fib=True,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes is"
+        "missing in RIB".format(tc_name)
+
+        rte2_nh2 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": NETWORK2[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh2"][addr_type],
+                        "admin_distance": 20,
+                    }
+                ]
+            }
+        }
+        nh = [NEXT_HOP_IP["nh2"][addr_type]]
+        result = verify_rib(
+            tgen, addr_type, dut, rte2_nh2, next_hop=nh, protocol=protocol, fib=True
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes is"
+        "not active in RIB".format(tc_name)
+
+        step("Configure the static route with nexthop N1")
+        rte1_nh1 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": NETWORK[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "admin_distance": 10,
+                    }
+                ]
+            }
+        }
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, rte1_nh1)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step("Remove the static route configured with nexthop N2 from" "running config")
+        rte2_nh2 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": NETWORK[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh2"][addr_type],
+                        "delete": True,
+                    }
+                ]
+            }
+        }
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, rte2_nh2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step(
+            "On R2, after removing the static route with N2 , "
+            "route become active with nexthop N1 and vice versa."
+        )
+        nh = NEXT_HOP_IP["nh2"][addr_type]
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            rte2_nh2,
+            next_hop=nh,
+            protocol=protocol,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes is"
+        " still present in RIB".format(tc_name)
+
+        nh = [NEXT_HOP_IP["nh1"][addr_type]]
+        result = verify_rib(
+            tgen, addr_type, dut, rte1_nh1, next_hop=nh, protocol=protocol
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes is"
+        " missing in RIB".format(tc_name)
+
+        step("Configure the static route with nexthop N2")
+        rte2_nh2 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": NETWORK[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh2"][addr_type],
+                        "admin_distance": 20,
+                    }
+                ]
+            }
+        }
+
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, rte2_nh2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step("Shut nexthop interface N1")
+        intf = topo["routers"]["r2"]["links"]["r1-link0"]["interface"]
+
+        shutdown_bringup_interface(tgen, dut, intf, False)
+
+        step("after shut of nexthop N1 , route become active with nexthop N2")
+
+        nh = NEXT_HOP_IP["nh1"][addr_type]
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            rte1_nh1,
+            next_hop=nh,
+            protocol=protocol,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes is"
+        " still present in RIB".format(tc_name)
+
+        nh = [NEXT_HOP_IP["nh2"][addr_type]]
+        result = verify_rib(
+            tgen, addr_type, dut, rte2_nh2, next_hop=nh, protocol=protocol, fib=True
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes is"
+        " missing in RIB".format(tc_name)
+
+        step("No shut the nexthop interface N1")
+        shutdown_bringup_interface(tgen, dut, intf, True)
+
+        step(
+            "after shut of nexthop N1 , route become active "
+            "with nexthop N2 and vice versa."
+        )
+        nh = [NEXT_HOP_IP["nh1"][addr_type]]
+
+        result = verify_rib(
+            tgen, addr_type, dut, rte1_nh1, next_hop=nh, protocol=protocol, fib=True
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes is"
+        " missing in RIB".format(tc_name)
+
+        step("Shut nexthop interface N2")
+        intf = topo["routers"]["r2"]["links"]["r1-link1"]["interface"]
+
+        shutdown_bringup_interface(tgen, dut, intf, False)
+
+        step(
+            " after shut of nexthop N1 , route become active with "
+            "nexthop N2 and vice versa."
+        )
+        nh = NEXT_HOP_IP["nh2"][addr_type]
+
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            rte2_nh2,
+            next_hop=nh,
+            protocol=protocol,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes is"
+        " still present in RIB".format(tc_name)
+
+        nh = [NEXT_HOP_IP["nh1"][addr_type]]
+        result = verify_rib(
+            tgen, addr_type, dut, rte1_nh1, next_hop=nh, protocol=protocol
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes is"
+        " missing in RIB".format(tc_name)
+
+        step("No shut nexthop interface N2")
+        shutdown_bringup_interface(tgen, dut, intf, True)
+
+        step(
+            "after shut of nexthop N1 , route become active "
+            "with nexthop N2 and vice versa."
+        )
+        rte1_nh1 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": NETWORK2[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "admin_distance": 10,
+                    }
+                ]
+            }
+        }
+        nh = [NEXT_HOP_IP["nh1"][addr_type]]
+        dut = "r2"
+        protocol = "static"
+        result = verify_rib(
+            tgen, addr_type, dut, rte1_nh1, next_hop=nh, protocol=protocol, fib=True
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes is"
+        "missing in RIB".format(tc_name)
+
+        rte2_nh2 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": NETWORK2[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh2"][addr_type],
+                        "admin_distance": 20,
+                    }
+                ]
+            }
+        }
+        nh = [NEXT_HOP_IP["nh2"][addr_type]]
+        dut = "r2"
+        protocol = "static"
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            rte2_nh2,
+            next_hop=nh,
+            protocol=protocol,
+            fib=True,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes is"
+        "not active in RIB".format(tc_name)
+
+        dut = "r3"
+        protocol = "bgp"
+
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            rte2_nh2,
+            next_hop=nh,
+            protocol=protocol,
+            fib=True,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes is"
+        "not active in RIB".format(tc_name)
+
+        dut = "r2"
+        step("Reload the FRR router")
+        # stop/start -> restart FRR router and verify
+        stop_router(tgen, "r2")
+        sleep(5)
+        start_router(tgen, "r2")
+
+        step(
+            "After reload of FRR router , static route installed"
+            " in RIB and FIB properly ."
+        )
+        rte1_nh1 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": NETWORK2[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "admin_distance": 10,
+                    }
+                ]
+            }
+        }
+        nh = [NEXT_HOP_IP["nh1"][addr_type]]
+        dut = "r2"
+        protocol = "static"
+        result = verify_rib(
+            tgen, addr_type, dut, rte1_nh1, next_hop=nh, protocol=protocol, fib=True
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes is"
+        "missing in RIB".format(tc_name)
+
+        dut = "r3"
+        protocol = "bgp"
+        result = verify_bgp_rib(tgen, addr_type, dut, rte1_nh1, next_hop=nh)
+        assert result is True, "Testcase {} : Failed \nError: Routes is"
+        "missing in RIB".format(tc_name)
+
+        rte2_nh2 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": NETWORK2[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh2"][addr_type],
+                        "admin_distance": 20,
+                    }
+                ]
+            }
+        }
+        nh = [NEXT_HOP_IP["nh2"][addr_type]]
+        dut = "r2"
+        protocol = "static"
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            rte2_nh2,
+            next_hop=nh,
+            protocol=protocol,
+            fib=True,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes is"
+        "not active in RIB".format(tc_name)
+
+        dut = "r3"
+        protocol = "bgp"
+        result = verify_bgp_rib(tgen, addr_type, dut, rte2_nh2, next_hop=nh)
+        assert result is True, "Testcase {} : Failed \nError: Routes is"
+        "not active in RIB".format(tc_name)
+
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            rte2_nh2,
+            next_hop=nh,
+            protocol=protocol,
+            fib=True,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes is"
+        "not active in RIB".format(tc_name)
+
+    write_test_footer(tc_name)
+
+
+def test_same_rte_from_bgp_static_p0_tc5_ebgp(request):
+    """
+    Verify RIB status when same route advertise via BGP and static
+    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():
+        pytest.skip(tgen.errors)
+
+    reset_config_on_routers(tgen)
+
+    NEXT_HOP_IP = populate_nh()
+    step("Configure EBGP IPv4 peering between R2 and R3 router.")
+
+    step(
+        "Configure IPv4 static route (10.1.1.1/24) in R2 with next hop"
+        "N1 (28.1.1.2 ) and N2 (29.1.1.2) , Static route next-hop present"
+        "on R1"
+    )
+
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": NETWORK[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                    },
+                    {
+                        "network": NETWORK[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh2"][addr_type],
+                    },
+                ]
+            }
+        }
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step("Configure redistribute static in BGP.")
+    for addr_type in ADDR_TYPES:
+        input_dict_2 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {"redistribute": [{"redist_type": "static"}]}
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+        step("Verify on R3 , route receive on R3 BGP table ")
+        dut = "r3"
+        result = verify_bgp_rib(tgen, addr_type, dut, input_dict_4)
+        assert result is True, "Testcase {} : Failed \nError: Route is"
+        " still present in RIB".format(tc_name)
+
+        step("Verify route installed in the RIB and FIB of R3")
+        protocol = "bgp"
+        result = verify_rib(tgen, addr_type, dut, input_dict_4, protocol=protocol)
+        assert result is True, "Testcase {} : Failed \nError: Route is"
+        " still present in RIB".format(tc_name)
+
+    step(
+        "Configure 2 links/interfaces between R1 and R3 , keep one"
+        "interface in shut (active) state and other interface in no shut"
+        "(inactive) state"
+    )
+    dut = "r3"
+    intf = topo["routers"]["r3"]["links"]["r1-link0"]["interface"]
+    shutdown_bringup_interface(tgen, dut, intf, False)
+
+    step(
+        "Configure same static route (10.1.1.1/24) in R3 with inactive"
+        "nexthop interface"
+    )
+
+    step(
+        "Configure same static route 10.1.1.1/24) again in R3 with"
+        "active nexthop interface"
+    )
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {
+            "r3": {
+                "static_routes": [
+                    {
+                        "network": NETWORK[addr_type],
+                        "next_hop": topo["routers"]["r1"]["links"]["r3-link0"][
+                            addr_type
+                        ],
+                    },
+                    {
+                        "network": NETWORK[addr_type],
+                        "next_hop": topo["routers"]["r1"]["links"]["r3-link1"][
+                            addr_type
+                        ],
+                    },
+                ]
+            }
+        }
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step(
+            "Verify when static route configure with inactive nexthop , "
+            "verify BGP received route is active in the RIB and FIB"
+        )
+        dut = "r3"
+        result = verify_bgp_rib(tgen, addr_type, dut, input_dict_4)
+        assert result is True, "Testcase {} : Failed \nError: Route is"
+        " missing in BGP RIB".format(tc_name)
+
+        protocol = "bgp"
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, protocol=protocol, fib=True
+        )
+        assert result is True, "Testcase {} : Failed \nError: Route is"
+        " missing in RIB".format(tc_name)
+
+    step("Remove the redistribute static knob from R2 router")
+    for addr_type in ADDR_TYPES:
+        input_dict_2 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {
+                                "redistribute": [
+                                    {"redist_type": "static", "delete": True}
+                                ]
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step(
+            "After removing /adding the redistribute static knob , "
+            "BGP received route is deleted and added in RIB of R3 "
+        )
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": NETWORK[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                    },
+                    {
+                        "network": NETWORK[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh2"][addr_type],
+                    },
+                ]
+            }
+        }
+        dut = "r3"
+        result = verify_bgp_rib(tgen, addr_type, dut, input_dict_4)
+        assert result is not True, "Testcase {} : Failed \nError: Route is"
+        " still present in RIB".format(tc_name)
+
+        protocol = "bgp"
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            protocol=protocol,
+            fib=True,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Route is"
+        " still present in RIB".format(tc_name)
+
+    step("Configure the redistribute static knob again on R2 router")
+    for addr_type in ADDR_TYPES:
+        input_dict_2 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {"redistribute": [{"redist_type": "static",}]}
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+        dut = "r3"
+        result = verify_bgp_rib(tgen, addr_type, dut, input_dict_4)
+        assert result is True, "Testcase {} : Failed \nError: Route is"
+        " missing in BGP RIB".format(tc_name)
+
+        protocol = "bgp"
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, protocol=protocol, fib=True
+        )
+        assert result is True, "Testcase {} : Failed \nError: Route is"
+        " missing in RIB".format(tc_name)
+
+    step("Remove the static route on R3 configured with active" "interface")
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {
+            "r3": {
+                "static_routes": [
+                    {
+                        "network": NETWORK[addr_type],
+                        "next_hop": topo["routers"]["r1"]["links"]["r3-link0"][
+                            addr_type
+                        ],
+                        "delete": True,
+                    },
+                    {
+                        "network": NETWORK[addr_type],
+                        "next_hop": topo["routers"]["r1"]["links"]["r3-link1"][
+                            addr_type
+                        ],
+                        "delete": True,
+                    },
+                ]
+            }
+        }
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+        step(
+            "After removing the static route with active nexthop verify "
+            "BGP received route is became active in RIB and FIB"
+        )
+        dut = "r3"
+        result = verify_bgp_rib(tgen, addr_type, dut, input_dict_4)
+        assert result is True, "Testcase {} : Failed \nError: Route is"
+        " missing in BGP RIB".format(tc_name)
+
+        protocol = "bgp"
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, protocol=protocol, fib=True
+        )
+        assert result is True, "Testcase {} : Failed \nError: Route is"
+        " missing in RIB".format(tc_name)
+
+    write_test_footer(tc_name)
+
+
+if __name__ == "__main__":
+    args = ["-s"] + sys.argv[1:]
+    sys.exit(pytest.main(args))
diff --git a/tests/topotests/static_routing_with_ebgp/test_static_routes_topo2_ebgp.py b/tests/topotests/static_routing_with_ebgp/test_static_routes_topo2_ebgp.py
new file mode 100644 (file)
index 0000000..e9ca4d7
--- /dev/null
@@ -0,0 +1,2338 @@
+#!/usr/bin/python
+
+#
+# Copyright (c) 2020 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.
+#
+
+
+"""
+    -Verify static route functionality with 8 next hop different AD value
+    and BGP ECMP
+
+    -Verify 8 static route functionality with 8 next hop different AD
+
+    -Verify static route with 8 next hop with different AD value and 8
+    EBGP neighbors
+
+    -Verify static route with 8 next hop with different AD value and 8
+    IBGP neighbors
+
+    -Delete the static route and verify the RIB and FIB state
+
+    -Verify 8 static route functionality with 8 ECMP next hop
+"""
+import sys
+import json
+import time
+import os
+import pytest
+import ipaddr
+from time import sleep
+from copy import deepcopy
+import random
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+sys.path.append(os.path.join(CWD, "../lib/"))
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from mininet.topo import Topo
+from lib.topogen import Topogen, get_topogen
+
+# Import 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,
+    check_address_types,
+    step,
+    create_interfaces_cfg,
+    shutdown_bringup_interface,
+    stop_router,
+    start_router,
+)
+from lib.topolog import logger
+from lib.bgp import verify_bgp_convergence, create_router_bgp, verify_bgp_rib
+from lib.topojson import build_topo_from_json, build_config_from_json
+
+# Reading the data from JSON File for topology creation
+jsonFile = "{}/static_routes_topo2_ebgp.json".format(CWD)
+try:
+    with open(jsonFile, "r") as topoJson:
+        topo = json.load(topoJson)
+except IOError:
+    assert False, "Could not read file {}".format(jsonFile)
+# Global variables
+BGP_CONVERGENCE = False
+ADDR_TYPES = check_address_types()
+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",
+        "11.0.20.6/32",
+        "11.0.20.7/32",
+        "11.0.20.8/32",
+    ],
+    "ipv6": [
+        "2::1/128",
+        "2::2/128",
+        "2::3/128",
+        "2::4/128",
+        "2::5/128",
+        "2::6/128",
+        "2::7/128",
+        "2::8/128",
+    ],
+}
+PREFIX1 = {"ipv4": "110.0.20.1/32", "ipv6": "20::1/128"}
+PREFIX2 = {"ipv4": "110.0.20.2/32", "ipv6": "20::2/128"}
+NEXT_HOP_IP = []
+topo_diag = """
+          Please view in a fixed-width font such as Courier.
+    +------+              +------+              +------+
+    |      +--------------+      +--------------+      |
+    |      |              |      |              |      |
+    |  R1  +---8 links----+ R2   +---8 links----+ R3   |
+    |      |              |      |              |      |
+    |      +--------------+      +--------------+      |
+    +------+              +------+              +------+
+
+"""
+
+
+class CreateTopo(Topo):
+    """
+    Test CreateTopo - topology 1.
+
+    * `Topo`: Topology object
+    """
+
+    def build(self, *_args, **_opts):
+        """Build function."""
+        tgen = get_topogen(self)
+
+        # Building topology from json file
+        build_topo_from_json(tgen, topo)
+
+
+def setup_module(mod):
+    """
+
+    Set up the pytest environment.
+
+    * `mod`: module name
+    """
+    global topo
+    testsuite_run_time = time.asctime(time.localtime(time.time()))
+    logger.info("Testsuite start time: {}".format(testsuite_run_time))
+    logger.info("=" * 40)
+
+    logger.info("Running setup_module to create topology")
+
+    # This function initiates the topology build with Topogen...
+    tgen = Topogen(CreateTopo, mod.__name__)
+    # ... and here it calls Mininet initialization functions.
+
+    # Starting topology, create tmp files which are loaded to routers
+    #  to start deamons and then start routers
+    start_topology(tgen)
+
+    # Creating configuration from JSON
+    build_config_from_json(tgen, topo)
+
+    # Checking BGP convergence
+    global BGP_CONVERGENCE
+    global ADDR_TYPES
+    # Don't run this test if we have any failure.
+    if tgen.routers_have_failure():
+        pytest.skip(tgen.errors)
+    # Api call verify whether BGP is converged
+    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo)
+    assert BGP_CONVERGENCE is True, "setup_module :Failed \n Error: {}".format(
+        BGP_CONVERGENCE
+    )
+
+    logger.info("Running setup_module() done")
+
+
+def teardown_module(mod):
+    """
+    Teardown the pytest environment
+
+    * `mod`: module name
+    """
+
+    logger.info("Running teardown_module to delete topology")
+
+    tgen = get_topogen()
+
+    # Stop toplogy and Remove tmp files
+    tgen.stop_topology()
+
+    logger.info(
+        "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
+    )
+    logger.info("=" * 40)
+
+
+def populate_nh():
+    NEXT_HOP_IP = {
+        "nh1": {
+            "ipv4": topo["routers"]["r1"]["links"]["r2-link0"]["ipv4"].split("/")[0],
+            "ipv6": topo["routers"]["r1"]["links"]["r2-link0"]["ipv6"].split("/")[0],
+        },
+        "nh2": {
+            "ipv4": topo["routers"]["r1"]["links"]["r2-link1"]["ipv4"].split("/")[0],
+            "ipv6": topo["routers"]["r1"]["links"]["r2-link1"]["ipv6"].split("/")[0],
+        },
+        "nh3": {
+            "ipv4": topo["routers"]["r1"]["links"]["r2-link2"]["ipv4"].split("/")[0],
+            "ipv6": topo["routers"]["r1"]["links"]["r2-link2"]["ipv6"].split("/")[0],
+        },
+        "nh4": {
+            "ipv4": topo["routers"]["r1"]["links"]["r2-link3"]["ipv4"].split("/")[0],
+            "ipv6": topo["routers"]["r1"]["links"]["r2-link3"]["ipv6"].split("/")[0],
+        },
+        "nh5": {
+            "ipv4": topo["routers"]["r1"]["links"]["r2-link4"]["ipv4"].split("/")[0],
+            "ipv6": topo["routers"]["r1"]["links"]["r2-link4"]["ipv6"].split("/")[0],
+        },
+        "nh6": {
+            "ipv4": topo["routers"]["r1"]["links"]["r2-link5"]["ipv4"].split("/")[0],
+            "ipv6": topo["routers"]["r1"]["links"]["r2-link5"]["ipv6"].split("/")[0],
+        },
+        "nh7": {
+            "ipv4": topo["routers"]["r1"]["links"]["r2-link6"]["ipv4"].split("/")[0],
+            "ipv6": topo["routers"]["r1"]["links"]["r2-link6"]["ipv6"].split("/")[0],
+        },
+        "nh8": {
+            "ipv4": topo["routers"]["r1"]["links"]["r2-link7"]["ipv4"].split("/")[0],
+            "ipv6": topo["routers"]["r1"]["links"]["r2-link7"]["ipv6"].split("/")[0],
+        },
+    }
+    return NEXT_HOP_IP
+
+
+#####################################################
+#
+#   Testcases
+#
+#####################################################
+
+
+def test_static_rte_with_8ecmp_nh_p1_tc9_ebgp(request):
+    """
+    Verify 8 static route functionality with 8 ECMP next hop
+
+    """
+    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)
+    NEXT_HOP_IP = populate_nh()
+    step("Configure 8 interfaces / links between R1 and R2")
+    step("Configure 8 interfaces / links between R2 and R3")
+    step("Configure 8 IBGP IPv4 peering between R2 and R3 router.")
+    reset_config_on_routers(tgen)
+
+    step(
+        "Configure 8 IPv4 static route in R2 with 8 next hop"
+        "N1(21.1.1.2) , N2(22.1.1.2) , N3(23.1.1.2) , N4(24.1.1.2) ,"
+        "N5(25.1.1.2) , N6(26.1.1.2) , N7(27.1.1.2) , N8(28.1.1.2) ,"
+        "Static route next-hop present on R1"
+    )
+    nh_all = {}
+    for addr_type in ADDR_TYPES:
+        # Enable static routes
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                        }
+                    ]
+                }
+            }
+            logger.info("Configure static routes")
+            result = create_static_routes(tgen, input_dict_4)
+            assert result is True, "Testcase {} : Failed \n Error: {}".format(
+                tc_name, result
+            )
+        logger.info("Verifying %s routes on r2", addr_type)
+        nh_all[addr_type] = [
+            NEXT_HOP_IP["nh1"][addr_type],
+            NEXT_HOP_IP["nh2"][addr_type],
+            NEXT_HOP_IP["nh3"][addr_type],
+            NEXT_HOP_IP["nh4"][addr_type],
+            NEXT_HOP_IP["nh5"][addr_type],
+            NEXT_HOP_IP["nh6"][addr_type],
+            NEXT_HOP_IP["nh7"][addr_type],
+            NEXT_HOP_IP["nh8"][addr_type],
+        ]
+
+        dut = "r2"
+        protocol = "static"
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh_all[addr_type],
+            protocol=protocol,
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes are"
+        " missing in RIB".format(tc_name)
+
+    step("Configure redistribute static in BGP on R2 router")
+    for addr_type in ADDR_TYPES:
+        input_dict_2 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {"redistribute": [{"redist_type": "static"}]}
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        dut = "r3"
+        protocol = "bgp"
+        result = verify_bgp_rib(tgen, addr_type, dut, input_dict_4)
+        assert result is True, "Testcase {} : Failed \nError: Routes are"
+        " missing in RIB".format(tc_name)
+
+    step(
+        "Remove the static route configured with nexthop N1 to N8, one"
+        "by one from running config"
+    )
+    dut = "r2"
+    protocol = "static"
+    step(
+        "After removing the static route with N1 to N8 one by one , "
+        "verify that entry is removed from RIB and FIB of R3 "
+    )
+    for addr_type in ADDR_TYPES:
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                            "delete": True,
+                        }
+                    ]
+                }
+            }
+            logger.info("Configure static routes")
+            result = create_static_routes(tgen, input_dict_4)
+            assert result is True, "Testcase {} : Failed \n Error: {}".format(
+                tc_name, result
+            )
+
+            step(
+                "After removing the static route with N1 to N8 one by one , "
+                "verify that entry is removed from RIB and FIB of R3 "
+            )
+            nh = NEXT_HOP_IP["nh" + str(nhp)][addr_type]
+            result = verify_rib(
+                tgen,
+                addr_type,
+                dut,
+                input_dict_4,
+                next_hop=nh,
+                protocol=protocol,
+                expected=False,
+            )
+            assert result is not True, "Testcase {} : Failed\nError: Routes is"
+            " still present in RIB".format(tc_name)
+
+    step("Configure the static route with nexthop N1 to N8, one by one")
+    for addr_type in ADDR_TYPES:
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                        }
+                    ]
+                }
+            }
+            logger.info("Configure static routes")
+            result = create_static_routes(tgen, input_dict_4)
+            assert result is True, "Testcase {} : Failed \n Error: {}".format(
+                tc_name, result
+            )
+
+            nh = NEXT_HOP_IP["nh" + str(nhp)][addr_type]
+            result = verify_rib(
+                tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol
+            )
+            assert result is True, "Testcase {} : Failed\nError: Routes are"
+            " missing in RIB".format(tc_name)
+
+    dut = "r2"
+    protocol = "static"
+    step("Shut nexthop interfaces N1 to N3 one by one")
+    for intfr in range(0, 3):
+        intf = topo["routers"]["r2"]["links"]["r1-link{}".format(intfr)]["interface"]
+        shutdown_bringup_interface(tgen, dut, intf, False)
+        for addr_type in ADDR_TYPES:
+            nhp = intfr + 1
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                        }
+                    ]
+                }
+            }
+        nh = NEXT_HOP_IP["nh" + str(nhp)][addr_type]
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            expected=False,
+        )
+        assert result is not True, "Testcase {}: Failed\nError: Routes are"
+        " still present in RIB".format(tc_name)
+
+    step("No shut the nexthop interfaces N1 to N3 one by one .")
+    for intfr in range(0, 3):
+        intf = topo["routers"]["r2"]["links"]["r1-link{}".format(intfr)]["interface"]
+        shutdown_bringup_interface(tgen, dut, intf, True)
+        for addr_type in ADDR_TYPES:
+            nhp = intfr + 1
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                        }
+                    ]
+                }
+            }
+        nh = NEXT_HOP_IP["nh" + str(nhp)][addr_type]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes are"
+        " missing in RIB".format(tc_name)
+
+    step("Random shut of the nexthop interfaces")
+    randnum = random.randint(0, 7)
+    # Shutdown interface
+    dut = "r2"
+    step(
+        " interface which is about to be shut no shut between r1 and r2 is " "%s",
+        topo["routers"]["r2"]["links"]["r1-link{}".format(randnum)]["interface"],
+    )
+    intf = topo["routers"]["r2"]["links"]["r1-link{}".format(randnum)]["interface"]
+    shutdown_bringup_interface(tgen, dut, intf, False)
+
+    sleep(5)
+
+    step("Random no shut of the nexthop interfaces")
+    # Bringup interface
+    shutdown_bringup_interface(tgen, dut, intf, True)
+
+    step(
+        "After random shut/no shut of nexthop , only that "
+        "nexthop deleted/added from all the routes , other nexthop remain "
+        "unchanged"
+    )
+    dut = "r2"
+    protocol = "static"
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                    }
+                ]
+            }
+        }
+    result = verify_rib(
+        tgen,
+        addr_type,
+        dut,
+        input_dict_4,
+        next_hop=nh_all[addr_type],
+        protocol=protocol,
+    )
+    assert result is True, "Testcase {} : Failed \nError: Routes are"
+    " missing in RIB".format(tc_name)
+
+    step("Remove random static route with all the nexthop")
+    dut = "r2"
+    randnum = random.randint(1, 7)
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh" + str(randnum)][addr_type],
+                        "delete": True,
+                    }
+                ]
+            }
+        }
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step(
+            "After delete of random route , that route only got deleted from"
+            " RIB/FIB other route are showing properly"
+        )
+        nh = NEXT_HOP_IP["nh{}".format(randnum)][addr_type]
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes are"
+        " missing in RIB".format(tc_name)
+
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh" + str(randnum)][addr_type],
+                    }
+                ]
+            }
+        }
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step("Reload the FRR router")
+    # stop/start -> restart FRR router and verify
+    stop_router(tgen, "r2")
+    sleep(5)
+    start_router(tgen, "r2")
+
+    step(
+        "After reload of FRR router , static route "
+        "installed in RIB and FIB properly ."
+    )
+    for addr_type in ADDR_TYPES:
+        # Enable static routes
+        nhp = 1
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                    }
+                ]
+            }
+        }
+        logger.info("Verifying %s routes on r2", addr_type)
+        dut = "r2"
+        protocol = "static"
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh_all[addr_type],
+            protocol=protocol,
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes are"
+        " missing in RIB".format(tc_name)
+
+    step(
+        "Remove and add the IBGP nbrs using interface shut and"
+        "deactivate/activate from address family"
+    )
+
+    for intfr in range(0, 8):
+        intf = topo["routers"]["r2"]["links"]["r3-link{}".format(intfr)]["interface"]
+        shutdown_bringup_interface(tgen, dut, intf, False)
+
+    sleep(200)
+
+    step("verify bgp convergence as all interface are shut")
+
+    bgp_convergence = verify_bgp_convergence(tgen, topo)
+    assert bgp_convergence is not True, "Testcase {} : Failed"
+    " \n Error: {}".format(tc_name, bgp_convergence)
+
+    dut = "r3"
+    protocol = "static"
+    for addr_type in ADDR_TYPES:
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                        }
+                    ]
+                }
+            }
+        nh = NEXT_HOP_IP["nh" + str(nhp)][addr_type]
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes are"
+        " still present in RIB".format(tc_name)
+    dut = "r2"
+    for intfr in range(0, 8):
+        intf = topo["routers"]["r2"]["links"]["r3-link{}".format(intfr)]["interface"]
+        shutdown_bringup_interface(tgen, dut, intf, True)
+
+    step("verify bgp convergence as all interface are un shut")
+    bgp_convergence = verify_bgp_convergence(tgen, topo)
+    assert bgp_convergence is True, "Testcase {} :"
+    " Failed \n Error:  {}".format(tc_name, bgp_convergence)
+
+    step("Remove the redistribute static knob")
+    for addr_type in ADDR_TYPES:
+        input_dict_2 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {
+                                "redistribute": [
+                                    {"redist_type": "static", "delete": True}
+                                ]
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step(
+            "After removing the BGP neighbor or redistribute static knob , "
+            "verify route got clear from RIB and FIB of R3 routes "
+        )
+        dut = "r3"
+        protocol = "bgp"
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, protocol=protocol, expected=False
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes are"
+        " still present in RIB".format(tc_name)
+
+    write_test_footer(tc_name)
+
+
+def test_static_route_8nh_diff_AD_bgp_ecmp_p1_tc6_ebgp(request):
+    """
+    Verify static route functionality with 8 next hop different AD
+    value and BGP ECMP
+
+    """
+    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)
+
+    step("Configure 8 interfaces / links between R1 and R2 ,")
+    step("Configure 8 interlaces/links between R2 and R3")
+    step(
+        "Configure IBGP IPv4 peering over loopback interface between"
+        "R2 and R3 router."
+    )
+    step("Configure redistribute static in BGP on R2 router")
+    reset_config_on_routers(tgen)
+    NEXT_HOP_IP = populate_nh()
+    nh_all = {}
+    for addr_type in ADDR_TYPES:
+        nh_all[addr_type] = []
+        for nhp in range(1, 9):
+            nh_all[addr_type].append(NEXT_HOP_IP["nh" + str(nhp)][addr_type])
+    step(
+        "Configure IPv4 static route in R2 with 8 next hop"
+        "N1(21.1.1.2) AD 10, N2(22.1.1.2) AD 20, N3(23.1.1.2) AD 30,"
+        "N4(24.1.1.2) AD 40, N5(25.1.1.2) AD 50, N6(26.1.1.2) AD 60,"
+        "N7(27.1.1.2) AD 70, N8(28.1.1.2) AD 80, Static route next-hop"
+        "present on R1"
+    )
+    for addr_type in ADDR_TYPES:
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                            "admin_distance": 10 * nhp,
+                        }
+                    ]
+                }
+            }
+            logger.info("Configure static routes")
+            result = create_static_routes(tgen, input_dict_4)
+            assert result is True, "Testcase {} : Failed \n Error: {}".format(
+                tc_name, result
+            )
+        logger.info("Verifying %s routes on r2", addr_type)
+
+        step(
+            "On R2, static route installed in RIB using "
+            "show ip route with 8 next hop , lowest AD nexthop is active"
+        )
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "admin_distance": 10,
+                    }
+                ]
+            }
+        }
+        dut = "r2"
+        protocol = "static"
+        nh = NEXT_HOP_IP["nh1"][addr_type]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol, fib=True
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes are"
+        " missing in RIB".format(tc_name)
+
+        nh = []
+        for nhp in range(2, 9):
+            nh.append(NEXT_HOP_IP["nh" + str(nhp)][addr_type])
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            fib=True,
+            expected=False,
+            wait=2,
+            attempts=3,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes "
+        " are missing in RIB".format(tc_name)
+
+    step(
+        "Remove the static route configured with nexthop N1 to N8, one"
+        "by one from running config"
+    )
+
+    for addr_type in ADDR_TYPES:
+        # delete static routes
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                            "admin_distance": 10 * nhp,
+                            "delete": True,
+                        }
+                    ]
+                }
+            }
+
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step(
+        "After removing the static route with N1 to N8 one by one , "
+        "route become active with next preferred nexthop and nexthop which "
+        "got removed is not shown in RIB and FIB"
+    )
+    result = verify_rib(
+        tgen,
+        addr_type,
+        dut,
+        input_dict_4,
+        next_hop=nh_all[addr_type],
+        protocol=protocol,
+        expected=False,
+    )
+    assert result is not True, "Testcase {} : Failed \nError: Routes are"
+    " still present in RIB".format(tc_name)
+
+    step("Configure the static route with nexthop N1 to N8, one by one")
+
+    for addr_type in ADDR_TYPES:
+        # add static routes
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                            "admin_distance": 10 * nhp,
+                        }
+                    ]
+                }
+            }
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step(
+        " After configuring them, route is always active with lowest AD"
+        " value and all the nexthop populated in RIB and FIB again"
+    )
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "admin_distance": 10,
+                    }
+                ]
+            }
+        }
+        dut = "r2"
+        protocol = "static"
+        nh = NEXT_HOP_IP["nh1"][addr_type]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol, fib=True
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes are"
+        " missing in RIB".format(tc_name)
+        nh = []
+        for nhp in range(2, 9):
+            nh.append(NEXT_HOP_IP["nh" + str(nhp)][addr_type])
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            fib=True,
+            expected=False,
+            wait=2,
+            attempts=3,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes "
+        " are missing in RIB".format(tc_name)
+
+    step("Shut nexthop interfaces N1 to N8 one by one")
+    for addr_type in ADDR_TYPES:
+        for nhp in range(0, 8):
+            intf = topo["routers"]["r2"]["links"]["r1-link" + str(nhp)]["interface"]
+            shutdown_bringup_interface(tgen, dut, intf, False)
+
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh_all[addr_type],
+            protocol=protocol,
+            fib=True,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes "
+        " are still present in RIB".format(tc_name)
+
+    step("No shut the nexthop interfaces N1 to N3 one by one .")
+    for addr_type in ADDR_TYPES:
+        for nhp in range(0, 3):
+            intf = topo["routers"]["r2"]["links"]["r1-link" + str(nhp)]["interface"]
+            shutdown_bringup_interface(tgen, dut, intf, True)
+
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "admin_distance": 10,
+                    }
+                ]
+            }
+        }
+        dut = "r2"
+        protocol = "static"
+        nh = NEXT_HOP_IP["nh1"][addr_type]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol, fib=True
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes are"
+        " missing in RIB".format(tc_name)
+
+        nh = []
+        for nhp in range(2, 9):
+            nh.append(NEXT_HOP_IP["nh" + str(nhp)][addr_type])
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            fib=True,
+            expected=False,
+            wait=2,
+            attempts=3,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes "
+        " are missing in RIB".format(tc_name)
+
+    step("Random shut of the nexthop interfaces")
+    randnum = random.randint(0, 7)
+    for addr_type in ADDR_TYPES:
+        intf = topo["routers"]["r2"]["links"]["r1-link" + str(randnum)]["interface"]
+        shutdown_bringup_interface(tgen, dut, intf, False)
+        nhip = NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type]
+        input_dict_5 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type],
+                    }
+                ]
+            }
+        }
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_5,
+            next_hop=nhip,
+            protocol=protocol,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \n"
+        "Error: Routes are still present in RIB".format(tc_name)
+
+    step("Random no shut of the nexthop interfaces")
+    for addr_type in ADDR_TYPES:
+        intf = topo["routers"]["r2"]["links"]["r1-link" + str(randnum)]["interface"]
+        shutdown_bringup_interface(tgen, dut, intf, True)
+        nhip = NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_5, next_hop=nhip, protocol=protocol
+        )
+        assert result is True, "Testcase {} : Failed \n"
+        "Error: Routes are missing in RIB".format(tc_name)
+
+    dut = "r2"
+    step("Shut the interfaces connected between R2 and R3 one by one")
+    for nhp in range(0, 3):
+        intf = topo["routers"]["r2"]["links"]["r3-link" + str(nhp)]["interface"]
+        shutdown_bringup_interface(tgen, dut, intf, False)
+
+    protocol = "bgp"
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type]}]}}
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, protocol=protocol, expected=False
+        )
+        assert result is not True, "Testcase {} : Failed \n"
+        "Error: Routes are still present in RIB".format(tc_name)
+
+    step("No shut the interfaces between R2 and R3 one by one")
+    dut = "r2"
+    for nhp in range(0, 3):
+        intf = topo["routers"]["r2"]["links"]["r3-link" + str(nhp)]["interface"]
+        shutdown_bringup_interface(tgen, dut, intf, True)
+    step(
+        "After each interface shut and no shut between R2 -R3 ,verify static"
+        "route is present in the RIB & FIB of R3 & R2 RIB/FIB is remain"
+        " unchanged"
+    )
+    protocol = "static"
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type]}]}}
+        result = verify_rib(tgen, addr_type, dut, input_dict_4, protocol=protocol)
+        assert result is True, "Testcase {} : Failed \n"
+        "Error: Routes are missing in RIB".format(tc_name)
+
+    protocol = "static"
+    dut = "r2"
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type]}]}}
+        result = verify_rib(tgen, addr_type, dut, input_dict_4, protocol=protocol)
+        assert (
+            result is True
+        ), "Testcase {}: Failed \n " "Error: Routes are missing in RIB".format(tc_name)
+
+    protocol = "bgp"
+    dut = "r3"
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type]}]}}
+        result = verify_rib(tgen, addr_type, dut, input_dict_4, protocol=protocol)
+        assert (
+            result is True
+        ), "Testcase {}: Failed \n " "Error: Routes are missing in RIB".format(tc_name)
+
+    step("Reload the FRR router")
+    # stop/start -> restart FRR router and verify
+    stop_router(tgen, "r2")
+    sleep(5)
+    start_router(tgen, "r2")
+
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type]}]}}
+        result = verify_rib(tgen, addr_type, dut, input_dict_4, protocol=protocol)
+        assert result is True, (
+            "Testcase {} : Failed \n"
+            "Error: Routes are still present in RIB".format(tc_name)
+        )
+
+    step("BGP neighbor remove and add")
+    for rtr in ["r2", "r3"]:
+        if "bgp" in topo["routers"][rtr].keys():
+            delete_bgp = {rtr: {"bgp": {"delete": True}}}
+            result = create_router_bgp(tgen, topo, delete_bgp)
+            assert result is True, "Testcase {} : Failed \n Error: {}".format(
+                tc_name, result
+            )
+
+    create_router_bgp(tgen, topo["routers"])
+
+    NEXT_HOP_IP = populate_nh()
+    step("Verify routes are still present after delete and add bgp")
+    dut = "r2"
+    protocol = "static"
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type]}]}}
+        result = verify_rib(tgen, addr_type, dut, input_dict_4, protocol=protocol)
+        assert result is True, (
+            "Testcase {} : Failed \n"
+            "Error: Routes are still present in RIB".format(tc_name)
+        )
+
+    dut = "r3"
+    protocol = "bgp"
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type]}]}}
+        result = verify_rib(tgen, addr_type, dut, input_dict_4, protocol=protocol)
+        assert result is True, (
+            "Testcase {} : Failed \n"
+            "Error: Routes are still present in RIB".format(tc_name)
+        )
+
+    step("Remove the redistribute static knob")
+    for addr_type in ADDR_TYPES:
+        input_dict_2 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {
+                                "redistribute": [
+                                    {"redist_type": "static", "delete": True}
+                                ]
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        logger.info("Remove redistribute static")
+        result = create_router_bgp(tgen, topo, input_dict_2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+        step("verify that routes are deleted from R3 routing table")
+
+        dut = "r3"
+        protocol = "bgp"
+        input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type]}]}}
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes are"
+        " strill present in RIB of R3".format(tc_name)
+
+    write_test_footer(tc_name)
+
+
+def test_static_route_8nh_diff_AD_ebgp_ecmp_p1_tc8_ebgp(request):
+    """
+    Verify static route with 8 next hop with different AD value and 8
+    EBGP neighbors
+    """
+    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)
+
+    step("Configure 8 interfaces / links between R1 and R2")
+    step("Configure 8 interlaces/links between R2 and R3")
+    step("Configure 8 EBGP IPv4 peering between R2 and R3")
+
+    reset_config_on_routers(tgen)
+    NEXT_HOP_IP = populate_nh()
+
+    step("Configure redistribute static in BGP on R2 router")
+    for addr_type in ADDR_TYPES:
+        input_dict_2 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {"redistribute": [{"redist_type": "static"}]}
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step(
+        "Configure IPv4 static route in R2 with 8 next hop"
+        "N1(21.1.1.2) AD 10, N2(22.1.1.2) AD 20, N3(23.1.1.2) AD 30,"
+        "N4(24.1.1.2) AD 40, N5(25.1.1.2) AD 50, N6(26.1.1.2) AD 60,"
+        "N7(27.1.1.2) AD 70, N8(28.1.1.2) AD 80, Static route next-hop"
+        "present on R1"
+    )
+    nh_all = {}
+    for addr_type in ADDR_TYPES:
+        nh_all[addr_type] = []
+        for nhp in range(1, 9):
+            nh_all[addr_type].append(NEXT_HOP_IP["nh" + str(nhp)][addr_type])
+    for addr_type in ADDR_TYPES:
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                            "admin_distance": 10 * nhp,
+                        }
+                    ]
+                }
+            }
+            logger.info("Configure static routes")
+            result = create_static_routes(tgen, input_dict_4)
+            assert result is True, "Testcase {} : Failed \n Error: {}".format(
+                tc_name, result
+            )
+        logger.info("Verifying %s routes on r2", addr_type)
+
+        step(
+            "On R2, static route installed in RIB using "
+            "show ip route with 8 next hop , lowest AD nexthop is active"
+        )
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "admin_distance": 10,
+                    }
+                ]
+            }
+        }
+        dut = "r2"
+        protocol = "static"
+        nh = NEXT_HOP_IP["nh1"][addr_type]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol, fib=True
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes are"
+        " missing in RIB".format(tc_name)
+
+        nh = []
+        for nhp in range(2, 9):
+            nh.append(NEXT_HOP_IP["nh" + str(nhp)][addr_type])
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            fib=True,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes "
+        " are missing in RIB".format(tc_name)
+
+    step(
+        "Remove the static route configured with nexthop N1 to N8, one"
+        "by one from running config"
+    )
+
+    for addr_type in ADDR_TYPES:
+        # delete static routes
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                            "admin_distance": 10 * nhp,
+                            "delete": True,
+                        }
+                    ]
+                }
+            }
+
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step(
+        "After removing the static route with N1 to N8 one by one , "
+        "route become active with next preferred nexthop and nexthop which "
+        "got removed is not shown in RIB and FIB"
+    )
+    result = verify_rib(
+        tgen,
+        addr_type,
+        dut,
+        input_dict_4,
+        next_hop=nh_all[addr_type],
+        protocol=protocol,
+        expected=False,
+    )
+    assert result is not True, "Testcase {} : Failed \nError: Routes are"
+    " still present in RIB".format(tc_name)
+
+    step("Configure the static route with nexthop N1 to N8, one by one")
+
+    for addr_type in ADDR_TYPES:
+        # add static routes
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                            "admin_distance": 10 * nhp,
+                        }
+                    ]
+                }
+            }
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step(
+        " After configuring them, route is always active with lowest AD"
+        " value and all the nexthop populated in RIB and FIB again"
+    )
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "admin_distance": 10,
+                    }
+                ]
+            }
+        }
+        dut = "r2"
+        protocol = "static"
+        nh = NEXT_HOP_IP["nh1"][addr_type]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol, fib=True
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes are"
+        " missing in RIB".format(tc_name)
+        nh = []
+        for nhp in range(2, 9):
+            nh.append(NEXT_HOP_IP["nh" + str(nhp)][addr_type])
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            fib=True,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes "
+        " are missing in RIB".format(tc_name)
+
+    step("Shut nexthop interfaces N1 to N8 one by one")
+    for addr_type in ADDR_TYPES:
+        for nhp in range(0, 8):
+            intf = topo["routers"]["r2"]["links"]["r1-link" + str(nhp)]["interface"]
+            shutdown_bringup_interface(tgen, dut, intf, False)
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "admin_distance": 10,
+                    }
+                ]
+            }
+        }
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh_all[addr_type],
+            protocol=protocol,
+            fib=True,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes "
+        " are still present in RIB".format(tc_name)
+
+    step("No shut the nexthop interfaces N1 to N8 one by one .")
+    for addr_type in ADDR_TYPES:
+        for nhp in range(0, 8):
+            intf = topo["routers"]["r2"]["links"]["r1-link" + str(nhp)]["interface"]
+            shutdown_bringup_interface(tgen, dut, intf, True)
+
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "admin_distance": 10,
+                    }
+                ]
+            }
+        }
+        dut = "r2"
+        protocol = "static"
+        nh = NEXT_HOP_IP["nh1"][addr_type]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol, fib=True
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes are"
+        " missing in RIB".format(tc_name)
+
+        nh = []
+        for nhp in range(2, 9):
+            nh.append(NEXT_HOP_IP["nh" + str(nhp)][addr_type])
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            fib=True,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes "
+        " are missing in RIB".format(tc_name)
+
+    step("Random shut of the nexthop interfaces")
+    randnum = random.randint(0, 7)
+    for addr_type in ADDR_TYPES:
+        intf = topo["routers"]["r2"]["links"]["r1-link" + str(randnum)]["interface"]
+        shutdown_bringup_interface(tgen, dut, intf, False)
+        nhip = NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type]
+        input_dict_5 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type],
+                    }
+                ]
+            }
+        }
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_5,
+            next_hop=nhip,
+            protocol=protocol,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \n"
+        "Error: Routes are still present in RIB".format(tc_name)
+
+    step("Random no shut of the nexthop interfaces")
+    for addr_type in ADDR_TYPES:
+        intf = topo["routers"]["r2"]["links"]["r1-link" + str(randnum)]["interface"]
+        shutdown_bringup_interface(tgen, dut, intf, True)
+        nhip = NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_5, next_hop=nhip, protocol=protocol
+        )
+        assert result is True, "Testcase {} : Failed \n"
+        "Error: Routes are missing in RIB".format(tc_name)
+
+    dut = "r2"
+    step("Shut the interfaces connected between R2 and R3 one by one")
+    for nhp in range(0, 3):
+        intf = topo["routers"]["r2"]["links"]["r3-link" + str(nhp)]["interface"]
+        shutdown_bringup_interface(tgen, dut, intf, False)
+
+    protocol = "bgp"
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type]}]}}
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, protocol=protocol, expected=False
+        )
+        assert result is not True, "Testcase {} : Failed \n"
+        "Error: Routes are still present in RIB".format(tc_name)
+
+    step("No shut the interfaces between R2 and R3 one by one")
+    dut = "r2"
+    for nhp in range(0, 3):
+        intf = topo["routers"]["r2"]["links"]["r3-link" + str(nhp)]["interface"]
+        shutdown_bringup_interface(tgen, dut, intf, True)
+
+    step(
+        "After each interface shut and no shut between R2 -R3 ,verify static"
+        "route is present in the RIB & FIB of R3 & R2 RIB/FIB is remain"
+        " unchanged"
+    )
+    protocol = "static"
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type]}]}}
+        result = verify_rib(tgen, addr_type, dut, input_dict_4, protocol=protocol)
+        assert result is True, "Testcase {} : Failed \n"
+        "Error: Routes are missing in RIB".format(tc_name)
+
+    protocol = "static"
+    dut = "r2"
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type]}]}}
+        result = verify_rib(tgen, addr_type, dut, input_dict_4, protocol=protocol)
+        assert (
+            result is True
+        ), "Testcase {}: Failed \n " "Error: Routes are missing in RIB".format(tc_name)
+
+    protocol = "bgp"
+    dut = "r3"
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type]}]}}
+        result = verify_rib(tgen, addr_type, dut, input_dict_4, protocol=protocol)
+        assert (
+            result is True
+        ), "Testcase {}: Failed \n " "Error: Routes are missing in RIB".format(tc_name)
+
+    step("Reload the FRR router")
+    # stop/start -> restart FRR router and verify
+    stop_router(tgen, "r2")
+    sleep(5)
+    start_router(tgen, "r2")
+
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type]}]}}
+        result = verify_rib(tgen, addr_type, dut, input_dict_4, protocol=protocol)
+        assert result is True, (
+            "Testcase {} : Failed \n"
+            "Error: Routes are still present in RIB".format(tc_name)
+        )
+
+    step("BGP neighbor remove and add")
+    for rtr in ["r2", "r3"]:
+        if "bgp" in topo["routers"][rtr].keys():
+            delete_bgp = {rtr: {"bgp": {"delete": True}}}
+            result = create_router_bgp(tgen, topo, delete_bgp)
+            assert result is True, "Testcase {} : Failed \n Error: {}".format(
+                tc_name, result
+            )
+
+    create_router_bgp(tgen, topo["routers"])
+
+    NEXT_HOP_IP = populate_nh()
+    step("Verify routes are still present after delete and add bgp")
+    dut = "r2"
+    protocol = "static"
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type]}]}}
+        result = verify_rib(tgen, addr_type, dut, input_dict_4, protocol=protocol)
+        assert result is True, (
+            "Testcase {} : Failed \n"
+            "Error: Routes are still present in RIB".format(tc_name)
+        )
+
+    dut = "r3"
+    protocol = "bgp"
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type]}]}}
+        result = verify_rib(tgen, addr_type, dut, input_dict_4, protocol=protocol)
+        assert result is True, (
+            "Testcase {} : Failed \n"
+            "Error: Routes are still present in RIB".format(tc_name)
+        )
+
+    step("Remove the redistribute static knob")
+    for addr_type in ADDR_TYPES:
+        input_dict_2 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {
+                                "redistribute": [
+                                    {"redist_type": "static", "delete": True}
+                                ]
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        logger.info("Remove redistribute static")
+        result = create_router_bgp(tgen, topo, input_dict_2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+        step("verify that routes are deleted from R3 routing table")
+
+        dut = "r3"
+        protocol = "bgp"
+        input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type]}]}}
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes are"
+        " still present in RIB of R3".format(tc_name)
+
+    write_test_footer(tc_name)
+
+
+def test_static_route_8nh_diff_AD_bgp_ecmp_p1_tc10_ebgp(request):
+    """
+    Verify 8 static route functionality with 8 next hop different AD'
+
+    """
+    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)
+    NEXT_HOP_IP = populate_nh()
+
+    step("Configure 8 interfaces / links between R1 and R2 ")
+    step("Configure 8 IBGP IPv4 peering between R2 and R3 router.")
+    reset_config_on_routers(tgen)
+
+    step(
+        "Configure IPv4 static route in R2 with 8 next hop"
+        "N1(21.1.1.2) AD 10, N2(22.1.1.2) AD 20, N3(23.1.1.2) AD 30,"
+        "N4(24.1.1.2) AD 40, N5(25.1.1.2) AD 50, N6(26.1.1.2) AD 60,"
+        "N7(27.1.1.2) AD 70, N8(28.1.1.2) AD 80"
+    )
+    step(
+        "Configure nexthop AD in such way for static route S1 , N1 is"
+        "preferred and for S2 , N2 is preferred and so on .."
+    )
+    nh_all = {}
+    for addr_type in ADDR_TYPES:
+        nh_all[addr_type] = []
+        for nhp in range(1, 9):
+            nh_all[addr_type].append(NEXT_HOP_IP["nh" + str(nhp)][addr_type])
+
+    for addr_type in ADDR_TYPES:
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                            "admin_distance": 10 * nhp,
+                        }
+                    ]
+                }
+            }
+            logger.info("Configure static routes")
+            result = create_static_routes(tgen, input_dict_4)
+            assert result is True, "Testcase {} : Failed \n Error: {}".format(
+                tc_name, result
+            )
+            second_rte = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX2[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                            "admin_distance": 10 * nhp,
+                        }
+                    ]
+                }
+            }
+            logger.info("Configure static routes")
+            result = create_static_routes(tgen, second_rte)
+            assert result is True, "Testcase {} : Failed \n Error: {}".format(
+                tc_name, result
+            )
+        logger.info("Verifying %s routes on r2", addr_type)
+
+        step(
+            "On R2, static route installed in RIB using "
+            "show ip route with 8 next hop , lowest AD nexthop is active"
+        )
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "admin_distance": 10,
+                    }
+                ]
+            }
+        }
+        dut = "r2"
+        protocol = "static"
+        nh = NEXT_HOP_IP["nh1"][addr_type]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol, fib=True
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes are"
+        " missing in RIB".format(tc_name)
+
+        step("Verify that highest AD nexthop are inactive")
+        nh = []
+        for nhp in range(2, 9):
+            nh.append(NEXT_HOP_IP["nh" + str(nhp)][addr_type])
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            fib=True,
+            expected=False,
+            wait=2,
+            attempts=3,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes "
+        " are missing in RIB".format(tc_name)
+
+    step("Configure redistribute static in BGP on R2 router")
+    for addr_type in ADDR_TYPES:
+        input_dict_2 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {"redistribute": [{"redist_type": "static"}]}
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step(
+        "Remove the static route configured with nexthop N1 to N8, one"
+        "by one from running config"
+    )
+
+    for addr_type in ADDR_TYPES:
+        # delete static routes
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                            "admin_distance": 10 * nhp,
+                            "delete": True,
+                        }
+                    ]
+                }
+            }
+
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step(
+            "After removing the static route with N1 to N8 one by one , "
+            "route become active with next preferred nexthop and nexthop which"
+            "got removed is not shown in RIB and FIB"
+        )
+
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes are"
+        " still present in RIB".format(tc_name)
+
+    step("Configure the static route with nexthop N1 to N8, one by one")
+    for addr_type in ADDR_TYPES:
+        # add static routes
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                            "admin_distance": 10 * nhp,
+                        }
+                    ]
+                }
+            }
+
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step(
+        " After configuring them, route is always active with lowest AD"
+        " value and all the nexthop populated in RIB and FIB again"
+    )
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type],}]}}
+        nh = NEXT_HOP_IP["nh1"][addr_type]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol, fib=True
+        )
+        assert result is True, "Testcase {} : Failed \nError: Route with "
+        "lowest AD  is missing in RIB".format(tc_name)
+
+    step("Shut nexthop interfaces N1 to N3 one by one")
+    for addr_type in ADDR_TYPES:
+        for nhp in range(0, 3):
+            intf = topo["routers"]["r2"]["links"]["r1-link" + str(nhp)]["interface"]
+            shutdown_bringup_interface(tgen, dut, intf, False)
+        input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type],}]}}
+        nh = NEXT_HOP_IP["nh1"][addr_type]
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            fib=True,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \n"
+        "Error: Routes are still present in RIB".format(tc_name)
+
+    step("No shut the nexthop interfaces N1 to N3 one by one .")
+
+    for addr_type in ADDR_TYPES:
+        for nhp in range(0, 3):
+            intf = topo["routers"]["r2"]["links"]["r1-link" + str(nhp)]["interface"]
+            shutdown_bringup_interface(tgen, dut, intf, True)
+        input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type],}]}}
+        nh = NEXT_HOP_IP["nh1"][addr_type]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol, fib=True
+        )
+        assert result is True, "Testcase {} : Failed \n"
+        "Error: Routes are missing in RIB".format(tc_name)
+
+    step("Random shut of the nexthop interfaces")
+    randnum = random.randint(0, 7)
+    for addr_type in ADDR_TYPES:
+        intf = topo["routers"]["r2"]["links"]["r1-link" + str(randnum)]["interface"]
+        shutdown_bringup_interface(tgen, dut, intf, False)
+        nhip = NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type]
+        input_dict_5 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type],
+                    }
+                ]
+            }
+        }
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_5,
+            next_hop=nhip,
+            protocol=protocol,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \n"
+        "Error: Routes are still present in RIB".format(tc_name)
+
+    step("Random no shut of the nexthop interfaces")
+    for addr_type in ADDR_TYPES:
+        intf = topo["routers"]["r2"]["links"]["r1-link" + str(randnum)]["interface"]
+        shutdown_bringup_interface(tgen, dut, intf, True)
+        nhip = NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_5, next_hop=nhip, protocol=protocol
+        )
+        assert result is True, "Testcase {} : Failed \n"
+        "Error: Routes are missing in RIB".format(tc_name)
+
+    step("Remove random static route with all the nexthop")
+    for addr_type in ADDR_TYPES:
+        # delete static routes
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                            "admin_distance": 10 * nhp,
+                            "delete": True,
+                        }
+                    ]
+                }
+            }
+            logger.info("Configure static routes")
+            result = create_static_routes(tgen, input_dict_4)
+            assert result is True, "Testcase {} : Failed \n Error: {}".format(
+                tc_name, result
+            )
+
+            step(
+                "After removing the static route with N1 to N8 one by one , "
+                "route become active with next preferred nexthop and nexthop "
+                "which got removed is not shown in RIB and FIB"
+            )
+            nh = NEXT_HOP_IP["nh" + str(nhp)][addr_type]
+            result = verify_rib(
+                tgen,
+                addr_type,
+                dut,
+                input_dict_4,
+                next_hop=nh,
+                protocol=protocol,
+                expected=False,
+            )
+            assert result is not True, "Testcase {} : Failed \nError: Route "
+            " is still present in RIB".format(tc_name)
+
+        step("Reconfigure the deleted routes and verify they are installed")
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                            "admin_distance": 10 * nhp,
+                        }
+                    ]
+                }
+            }
+            logger.info("Configure static routes")
+            result = create_static_routes(tgen, input_dict_4)
+            assert result is True, "Testcase {} : Failed \n Error: {}".format(
+                tc_name, result
+            )
+
+            dut = "r2"
+            protocol = "static"
+            nh = NEXT_HOP_IP["nh1"][addr_type]
+            result = verify_rib(tgen, addr_type, dut, input_dict_4, protocol=protocol)
+            assert result is True, "Testcase {} : Failed \nError: Route "
+            " is still present in RIB".format(tc_name)
+
+            step("Reload the FRR router")
+            # stop/start -> restart FRR router and verify
+            stop_router(tgen, "r2")
+            sleep(5)
+            start_router(tgen, "r2")
+
+            step("After reloading, verify that routes are still present in R2.")
+            result = verify_rib(
+                tgen,
+                addr_type,
+                dut,
+                second_rte,
+                next_hop=nh,
+                protocol=protocol,
+                fib=True,
+            )
+            assert result is True, (
+                "Testcase {} : Failed \nError: Route "
+                " is missing in RIB".format(tc_name)
+            )
+
+        dut = "r2"
+        for intfr in range(0, 8):
+            intf = topo["routers"]["r2"]["links"]["r3-link{}".format(intfr)][
+                "interface"
+            ]
+            shutdown_bringup_interface(tgen, dut, intf, False)
+
+        dut = "r3"
+        for intfr in range(0, 8):
+            intf = topo["routers"]["r3"]["links"]["r2-link{}".format(intfr)][
+                "interface"
+            ]
+            shutdown_bringup_interface(tgen, dut, intf, False)
+        sleep(180)
+        step("verify bgp convergence as all interface are shut")
+
+        bgp_convergence = verify_bgp_convergence(tgen, topo)
+        assert bgp_convergence is not True, "Testcase {} : Failed \n"
+        "Error: {}".format(tc_name, bgp_convergence)
+
+        dut = "r2"
+        protocol = "static"
+        for addr_type in ADDR_TYPES:
+            for nhp in range(1, 9):
+                input_dict_4 = {
+                    "r2": {
+                        "static_routes": [
+                            {
+                                "network": PREFIX1[addr_type],
+                                "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                            }
+                        ]
+                    }
+                }
+            nh = NEXT_HOP_IP["nh1"][addr_type]
+            result = verify_rib(
+                tgen,
+                addr_type,
+                dut,
+                input_dict_4,
+                next_hop=nh,
+                protocol=protocol,
+                fib=True,
+            )
+            assert result is True, "Testcase {} : Failed \nError: Routes are"
+            " missing present in RIB".format(tc_name)
+
+        dut = "r3"
+        protocol = "bgp"
+        for addr_type in ADDR_TYPES:
+            input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type],}]}}
+            nh = NEXT_HOP_IP["nh1"][addr_type]
+            result = verify_rib(
+                tgen,
+                addr_type,
+                dut,
+                input_dict_4,
+                next_hop=nh,
+                protocol=protocol,
+                expected=False,
+            )
+            assert result is not True, "Testcase {} : Failed \nError: Routes "
+            " are still present in RIB after BGP nbr is down".format(tc_name)
+
+        sleep(5)
+        dut = "r2"
+        for intfr in range(0, 8):
+            intf = topo["routers"]["r2"]["links"]["r3-link{}".format(intfr)][
+                "interface"
+            ]
+            shutdown_bringup_interface(tgen, dut, intf, True)
+
+        sleep(5)
+        dut = "r3"
+        for intfr in range(0, 8):
+            intf = topo["routers"]["r3"]["links"]["r2-link{}".format(intfr)][
+                "interface"
+            ]
+            shutdown_bringup_interface(tgen, dut, intf, True)
+
+        step("verify bgp convergence as all interface are un shut")
+        bgp_convergence = verify_bgp_convergence(tgen, topo)
+        assert bgp_convergence is True, "Testcase {} : Failed \n"
+        "Error: {}".format(tc_name, bgp_convergence)
+
+    step("Remove the redistribute static knob")
+    for addr_type in ADDR_TYPES:
+        input_dict_2 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {
+                                "redistribute": [
+                                    {"redist_type": "static", "delete": True}
+                                ]
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step(
+        "After removing the BGP neighbor or redistribute static knob , "
+        "verify route got clear from RIB and FIB of R3 routes "
+    )
+    dut = "r3"
+    protocol = "bgp"
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                    }
+                ]
+            }
+        }
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, protocol=protocol, expected=False
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes are"
+        " still present in RIB".format(tc_name)
+
+    write_test_footer(tc_name)
+
+
+def test_static_route_delete_p0_tc11_ebgp(request):
+    """
+    Delete the static route and verify the RIB and FIB state
+    """
+    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)
+    NEXT_HOP_IP = populate_nh()
+
+    step("Configure 8 interfaces / links between R1 and R2 ")
+    step("Configure 8 IBGP IPv4 peering between R2 and R3 router.")
+    reset_config_on_routers(tgen)
+
+    step(
+        "Configure IPv4 static route in R2 with 8 next hop"
+        "N1(21.1.1.2) AD 10, N2(22.1.1.2) AD 20, N3(23.1.1.2) AD 30,"
+        "N4(24.1.1.2) AD 40, N5(25.1.1.2) AD 50, N6(26.1.1.2) AD 60,"
+        "N7(27.1.1.2) AD 70, N8(28.1.1.2) AD 80"
+    )
+    step(
+        "Configure nexthop AD in such way for static route S1 , N1 is"
+        "preferred and for S2 , N2 is preferred and so on .."
+    )
+    nh_all = {}
+    for addr_type in ADDR_TYPES:
+        nh_all[addr_type] = []
+        for nhp in range(1, 9):
+            nh_all[addr_type].append(NEXT_HOP_IP["nh" + str(nhp)][addr_type])
+
+    for addr_type in ADDR_TYPES:
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                            "admin_distance": 10 * nhp,
+                        }
+                    ]
+                }
+            }
+            logger.info("Configure static routes")
+            result = create_static_routes(tgen, input_dict_4)
+            assert result is True, "Testcase {} : Failed \n Error: {}".format(
+                tc_name, result
+            )
+            second_rte = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX2[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                            "admin_distance": 10 * nhp,
+                        }
+                    ]
+                }
+            }
+            logger.info("Configure static routes")
+            result = create_static_routes(tgen, second_rte)
+            assert result is True, "Testcase {} : Failed \n Error: {}".format(
+                tc_name, result
+            )
+        logger.info("Verifying %s routes on r2", addr_type)
+
+        step(
+            "On R2, static route installed in RIB using "
+            "show ip route with 8 next hop , lowest AD nexthop is active"
+        )
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "admin_distance": 10,
+                    }
+                ]
+            }
+        }
+        dut = "r2"
+        protocol = "static"
+        nh = NEXT_HOP_IP["nh1"][addr_type]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol, fib=True
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes are"
+        " missing in RIB".format(tc_name)
+
+        step("Verify that highest AD nexthop are inactive")
+        nh = []
+        for nhp in range(2, 9):
+            nh.append(NEXT_HOP_IP["nh" + str(nhp)][addr_type])
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            fib=True,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes "
+        " are missing in RIB".format(tc_name)
+
+    step("Configure redistribute static in BGP on R2 router")
+    for addr_type in ADDR_TYPES:
+        input_dict_2 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {"redistribute": [{"redist_type": "static"}]}
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step("Remove the redistribute static knob")
+    for addr_type in ADDR_TYPES:
+        input_dict_2 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {
+                                "redistribute": [
+                                    {"redist_type": "static", "delete": True}
+                                ]
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step(
+            "Verify after removing the redistribute static from BGP all the"
+            "routes got delete from RIB and FIB of R3 "
+        )
+
+        dut = "r3"
+        protocol = "bgp"
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, protocol=protocol, expected=False
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes are"
+        " still present in RIB".format(tc_name)
+
+    for addr_type in ADDR_TYPES:
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                            "admin_distance": 10 * nhp,
+                            "delete": True,
+                        }
+                    ]
+                }
+            }
+            logger.info("Configure static routes")
+            result = create_static_routes(tgen, input_dict_4)
+            assert result is True, "Testcase {} : Failed \n Error: {}".format(
+                tc_name, result
+            )
+            second_rte = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX2[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                            "admin_distance": 10 * nhp,
+                        }
+                    ]
+                }
+            }
+            logger.info("Configure static routes")
+            result = create_static_routes(tgen, second_rte)
+            assert result is True, "Testcase {} : Failed \n Error: {}".format(
+                tc_name, result
+            )
+        logger.info("Verifying %s routes on r2", addr_type)
+
+        step(
+            " After removing all the routes and nexthop from R2 , "
+            " verify R2 RIB and FIB is cleared"
+        )
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "admin_distance": 10,
+                    }
+                ]
+            }
+        }
+        dut = "r2"
+        protocol = "static"
+        nh = NEXT_HOP_IP["nh1"][addr_type]
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            fib=True,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes are"
+        " still active in RIB".format(tc_name)
+    write_test_footer(tc_name)
+
+
+if __name__ == "__main__":
+    args = ["-s"] + sys.argv[1:]
+    sys.exit(pytest.main(args))
diff --git a/tests/topotests/static_routing_with_ebgp/test_static_routes_topo3_ebgp.py b/tests/topotests/static_routing_with_ebgp/test_static_routes_topo3_ebgp.py
new file mode 100644 (file)
index 0000000..e055a16
--- /dev/null
@@ -0,0 +1,990 @@
+#!/usr/bin/python
+
+#
+# Copyright (c) 2020 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.
+#
+"""
+    -Verify static route ECMP functionality with 8 next hop
+
+    -Verify static route functionality with 8 next hop different AD value
+
+    -Verify static route with tag option
+
+    -Verify BGP did not install the static route when it receive route
+    with local next hop
+
+"""
+import sys
+import json
+import time
+import os
+import pytest
+import ipaddr
+from time import sleep
+from copy import deepcopy
+import random
+from re import search as re_search
+
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+sys.path.append(os.path.join(CWD, "../lib/"))
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from mininet.topo import Topo
+from lib.topogen import Topogen, get_topogen
+
+from lib.common_config import (
+    start_topology,
+    write_test_header,
+    write_test_footer,
+    reset_config_on_routers,
+    verify_rib,
+    create_static_routes,
+    check_address_types,
+    step,
+    create_interfaces_cfg,
+    shutdown_bringup_interface,
+    stop_router,
+    start_router,
+)
+from lib.topolog import logger
+from lib.bgp import verify_bgp_convergence, create_router_bgp, verify_bgp_rib
+from lib.topojson import build_topo_from_json, build_config_from_json
+
+# Reading the data from JSON File for topology creation
+jsonFile = "{}/static_routes_topo3_ebgp.json".format(CWD)
+try:
+    with open(jsonFile, "r") as topoJson:
+        topo = json.load(topoJson)
+except IOError:
+    assert False, "Could not read file {}".format(jsonFile)
+
+# Global variables
+BGP_CONVERGENCE = False
+ADDR_TYPES = check_address_types()
+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",
+        "11.0.20.6/32",
+        "11.0.20.7/32",
+        "11.0.20.8/32",
+    ],
+    "ipv6": [
+        "2::1/128",
+        "2::2/128",
+        "2::3/128",
+        "2::4/128",
+        "2::5/128",
+        "2::6/128",
+        "2::7/128",
+        "2::8/128",
+    ],
+}
+PREFIX1 = {"ipv4": "110.0.20.1/32", "ipv6": "20::1/128"}
+NETWORK2 = {"ipv4": ["11.0.20.1/32"], "ipv6": ["2::1/128"]}
+NEXT_HOP_IP = []
+
+
+class CreateTopo(Topo):
+    """
+    Test CreateTopo - topology 1.
+
+    * `Topo`: Topology object
+    """
+
+    def build(self, *_args, **_opts):
+        """Build function."""
+        tgen = get_topogen(self)
+
+        # Building topology from json file
+        build_topo_from_json(tgen, topo)
+
+
+def setup_module(mod):
+    """
+
+    Set up the pytest environment.
+
+    * `mod`: module name
+    """
+    global topo
+    testsuite_run_time = time.asctime(time.localtime(time.time()))
+    logger.info("Testsuite start time: {}".format(testsuite_run_time))
+    logger.info("=" * 40)
+
+    logger.info("Running setup_module to create topology")
+
+    # This function initiates the topology build with Topogen...
+    tgen = Topogen(CreateTopo, mod.__name__)
+    # ... and here it calls Mininet initialization functions.
+
+    # Starting topology, create tmp files which are loaded to routers
+    #  to start deamons and then start routers
+    start_topology(tgen)
+
+    # Creating configuration from JSON
+    build_config_from_json(tgen, topo)
+
+    # Checking BGP convergence
+    global BGP_CONVERGENCE
+    global ADDR_TYPES
+
+    # Don't run this test if we have any failure.
+    if tgen.routers_have_failure():
+        pytest.skip(tgen.errors)
+    # Api call verify whether BGP is converged
+    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo)
+    assert BGP_CONVERGENCE is True, "setup_module :Failed \n Error: {}".format(
+        BGP_CONVERGENCE
+    )
+
+    logger.info("Running setup_module() done")
+
+
+def teardown_module(mod):
+    """
+    Teardown the pytest environment
+
+    * `mod`: module name
+    """
+
+    logger.info("Running teardown_module to delete topology")
+
+    tgen = get_topogen()
+
+    # Stop toplogy and Remove tmp files
+    tgen.stop_topology()
+
+    logger.info(
+        "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
+    )
+    logger.info("=" * 40)
+
+
+def populate_nh():
+    NEXT_HOP_IP = {
+        "nh1": {
+            "ipv4": topo["routers"]["r1"]["links"]["r2-link0"]["ipv4"].split("/")[0],
+            "ipv6": topo["routers"]["r1"]["links"]["r2-link0"]["ipv6"].split("/")[0],
+        },
+        "nh2": {
+            "ipv4": topo["routers"]["r1"]["links"]["r2-link1"]["ipv4"].split("/")[0],
+            "ipv6": topo["routers"]["r1"]["links"]["r2-link1"]["ipv6"].split("/")[0],
+        },
+        "nh3": {
+            "ipv4": topo["routers"]["r1"]["links"]["r2-link2"]["ipv4"].split("/")[0],
+            "ipv6": topo["routers"]["r1"]["links"]["r2-link2"]["ipv6"].split("/")[0],
+        },
+        "nh4": {
+            "ipv4": topo["routers"]["r1"]["links"]["r2-link3"]["ipv4"].split("/")[0],
+            "ipv6": topo["routers"]["r1"]["links"]["r2-link3"]["ipv6"].split("/")[0],
+        },
+        "nh5": {
+            "ipv4": topo["routers"]["r1"]["links"]["r2-link4"]["ipv4"].split("/")[0],
+            "ipv6": topo["routers"]["r1"]["links"]["r2-link4"]["ipv6"].split("/")[0],
+        },
+        "nh6": {
+            "ipv4": topo["routers"]["r1"]["links"]["r2-link5"]["ipv4"].split("/")[0],
+            "ipv6": topo["routers"]["r1"]["links"]["r2-link5"]["ipv6"].split("/")[0],
+        },
+        "nh7": {
+            "ipv4": topo["routers"]["r1"]["links"]["r2-link6"]["ipv4"].split("/")[0],
+            "ipv6": topo["routers"]["r1"]["links"]["r2-link6"]["ipv6"].split("/")[0],
+        },
+        "nh8": {
+            "ipv4": topo["routers"]["r1"]["links"]["r2-link7"]["ipv4"].split("/")[0],
+            "ipv6": topo["routers"]["r1"]["links"]["r2-link7"]["ipv6"].split("/")[0],
+        },
+    }
+    return NEXT_HOP_IP
+
+
+#####################################################
+#
+#   Tests starting
+#
+#####################################################
+
+
+def test_staticroute_with_ecmp_p0_tc3_ebgp(request):
+    """
+    Verify static route ECMP functionality with 8 next hop'
+
+    """
+    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)
+
+    reset_config_on_routers(tgen)
+    NEXT_HOP_IP = populate_nh()
+
+    step("Configure 8 interfaces / links between R1 and R2,")
+    step(
+        "Configure IPv4 static route in R2 with 8 next hop"
+        "N1(21.1.1.2), N2(22.1.1.2), N3(23.1.1.2), N4(24.1.1.2),"
+        "N5(25.1.1.2), N6(26.1.1.2), N7(27.1.1.2),N8(28.1.1.2), Static"
+        "route next-hop present on R1"
+    )
+
+    step("Configure IBGP IPv4 peering between R2 and R3 router.")
+
+    for addr_type in ADDR_TYPES:
+        # Enable static routes
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                        }
+                    ]
+                }
+            }
+            logger.info("Configure static routes")
+            result = create_static_routes(tgen, input_dict_4)
+            assert result is True, "Testcase {} : Failed \n Error: {}".format(
+                tc_name, result
+            )
+        logger.info("Verifying %s routes on r2", addr_type)
+        nh = [
+            NEXT_HOP_IP["nh1"][addr_type],
+            NEXT_HOP_IP["nh2"][addr_type],
+            NEXT_HOP_IP["nh3"][addr_type],
+            NEXT_HOP_IP["nh4"][addr_type],
+            NEXT_HOP_IP["nh5"][addr_type],
+            NEXT_HOP_IP["nh6"][addr_type],
+            NEXT_HOP_IP["nh7"][addr_type],
+            NEXT_HOP_IP["nh8"][addr_type],
+        ]
+
+        dut = "r2"
+        protocol = "static"
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes are"
+        " missing in RIB".format(tc_name)
+    step("Configure redistribute static in BGP on R2 router")
+    for addr_type in ADDR_TYPES:
+        input_dict_2 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {"redistribute": [{"redist_type": "static"}]}
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step(
+        "Remove the static route configured with nexthop N1 to N8, one"
+        "by one from running config"
+    )
+    for addr_type in ADDR_TYPES:
+        # delete static routes
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                            "delete": True,
+                        }
+                    ]
+                }
+            }
+
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes are"
+        " still present in RIB".format(tc_name)
+
+    step("Configure the static route with nexthop N1 to N8, one by" "one")
+
+    for addr_type in ADDR_TYPES:
+        # add static routes
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                        }
+                    ]
+                }
+            }
+
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    result = verify_rib(
+        tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol
+    )
+    assert result is True, "Testcase {} : Failed \nError: Routes are"
+    " missing in RIB".format(tc_name)
+
+    step("Shut nexthop interfaces N1 to N8 one by one")
+    for addr_type in ADDR_TYPES:
+        for nhp in range(0, 8):
+            intf = topo["routers"]["r2"]["links"]["r1-link" + str(nhp)]["interface"]
+            shutdown_bringup_interface(tgen, dut, intf, False)
+
+    result = verify_rib(
+        tgen,
+        addr_type,
+        dut,
+        input_dict_4,
+        next_hop=nh,
+        protocol=protocol,
+        expected=False,
+    )
+    assert result is not True, "Testcase {} : Failed \n"
+    "Error: Routes are still present in RIB".format(tc_name)
+
+    step("No shut the nexthop interfaces N1 to N8 one by one .")
+
+    for addr_type in ADDR_TYPES:
+        for nhp in range(0, 8):
+            intf = topo["routers"]["r2"]["links"]["r1-link" + str(nhp)]["interface"]
+            shutdown_bringup_interface(tgen, dut, intf, True)
+
+    result = verify_rib(
+        tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol
+    )
+    assert result is True, "Testcase {} : Failed \n"
+    "Error: Routes are missing in RIB".format(tc_name)
+
+    step("Random shut of the nexthop interfaces")
+    randnum = random.randint(0, 7)
+    for addr_type in ADDR_TYPES:
+        intf = topo["routers"]["r2"]["links"]["r1-link" + str(randnum)]["interface"]
+        shutdown_bringup_interface(tgen, dut, intf, False)
+        nhip = NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type]
+        input_dict_5 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type],
+                    }
+                ]
+            }
+        }
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_5,
+            next_hop=nhip,
+            protocol=protocol,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \n"
+        "Error: Routes are still present in RIB".format(tc_name)
+
+    step("Random no shut of the nexthop interfaces")
+    for addr_type in ADDR_TYPES:
+        intf = topo["routers"]["r2"]["links"]["r1-link" + str(randnum)]["interface"]
+        shutdown_bringup_interface(tgen, dut, intf, True)
+        nhip = NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_5, next_hop=nhip, protocol=protocol
+        )
+        assert result is True, "Testcase {} : Failed \n"
+        "Error: Routes are missing in RIB".format(tc_name)
+
+    step("Reload the FRR router")
+    # stop/start -> restart FRR router and verify
+    stop_router(tgen, "r2")
+    sleep(5)
+    start_router(tgen, "r2")
+
+    result = verify_rib(
+        tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol
+    )
+    assert result is True, "Testcase {} : Failed \nError: Routes are"
+    " missing in RIB".format(tc_name)
+
+    write_test_footer(tc_name)
+
+
+def test_staticroute_with_ecmp_with_diff_AD_p0_tc4_ebgp(request):
+    """
+    Verify static route ECMP functionality with 8 next hop
+
+    """
+    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)
+
+    reset_config_on_routers(tgen)
+    NEXT_HOP_IP = populate_nh()
+
+    step("Configure 8 interfaces / links between R1 and R2,")
+    step("Configure IBGP IPv4 peering between R2 and R3 router.")
+    reset_config_on_routers(tgen)
+    NEXT_HOP_IP = populate_nh()
+    nh_all = {}
+    for addr_type in ADDR_TYPES:
+        nh_all[addr_type] = []
+        for nhp in range(1, 9):
+            nh_all[addr_type].append(NEXT_HOP_IP["nh" + str(nhp)][addr_type])
+    step(
+        "Configure IPv4 static route in R2 with 8 next hop"
+        "N1(21.1.1.2) AD 10, N2(22.1.1.2) AD 20, N3(23.1.1.2) AD 30,"
+        "N4(24.1.1.2) AD 40, N5(25.1.1.2) AD 50, N6(26.1.1.2) AD 60,"
+        "N7(27.1.1.2) AD 70, N8(28.1.1.2) AD 80, Static route next-hop"
+        "present on R1"
+    )
+    for addr_type in ADDR_TYPES:
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                            "admin_distance": 10 * nhp,
+                        }
+                    ]
+                }
+            }
+            logger.info("Configure static routes")
+            result = create_static_routes(tgen, input_dict_4)
+            assert result is True, "Testcase {} : Failed \n Error: {}".format(
+                tc_name, result
+            )
+        logger.info("Verifying %s routes on r2", addr_type)
+
+        step(
+            "On R2, static route installed in RIB using "
+            "show ip route with 8 next hop, lowest AD nexthop is active"
+        )
+        step("On R2, static route with lowest AD nexthop installed in FIB")
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "admin_distance": 10,
+                    }
+                ]
+            }
+        }
+        dut = "r2"
+        protocol = "static"
+        nh = NEXT_HOP_IP["nh1"][addr_type]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol, fib=True
+        )
+        assert result is True, "Testcase {} : Failed \nError: Route with "
+        " lowest AD is missing in RIB".format(tc_name)
+
+        nh = []
+        for nhp in range(2, 9):
+            nh.append(NEXT_HOP_IP["nh" + str(nhp)][addr_type])
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            fib=True,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes "
+        " with high AD are active in RIB".format(tc_name)
+
+    step("Configure redistribute static in BGP on R2 router")
+    for addr_type in ADDR_TYPES:
+        input_dict_2 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {"redistribute": [{"redist_type": "static"}]}
+                        }
+                    }
+                }
+            }
+        }
+
+        logger.info("Configuring redistribute static")
+        result = create_router_bgp(tgen, topo, input_dict_2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step(
+            "After configuring them, route is always active with lowest AD"
+            "value and all the nexthop populated in RIB and FIB again "
+        )
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "admin_distance": 10,
+                    }
+                ]
+            }
+        }
+        dut = "r2"
+        protocol = "static"
+        nh = NEXT_HOP_IP["nh1"][addr_type]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol, fib=True
+        )
+        assert result is True, "Testcase {} : Failed \nError: Route with "
+        " lowest AD is missing in RIB".format(tc_name)
+
+    step(
+        "Remove the static route configured with nexthop N1 to N8, one"
+        "by one from running config"
+    )
+
+    for addr_type in ADDR_TYPES:
+        # delete static routes
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                            "admin_distance": 10 * nhp,
+                            "delete": True,
+                        }
+                    ]
+                }
+            }
+
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step(
+        "After removing the static route with N1 to N8 one by one, "
+        "route become active with next preferred nexthop and nexthop which "
+        "got removed is not shown in RIB and FIB"
+    )
+    result = verify_rib(
+        tgen,
+        addr_type,
+        dut,
+        input_dict_4,
+        next_hop=nh_all[addr_type],
+        protocol=protocol,
+        expected=False,
+    )
+    assert result is not True, "Testcase {} : Failed \nError: Routes are"
+    " still present in RIB".format(tc_name)
+
+    step("Configure the static route with nexthop N1 to N8, one by" "one")
+    for addr_type in ADDR_TYPES:
+        # add static routes
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                            "admin_distance": 10 * nhp,
+                        }
+                    ]
+                }
+            }
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step("On R2, static route with lowest AD nexthop installed in FIB")
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "admin_distance": 10,
+                    }
+                ]
+            }
+        }
+        dut = "r2"
+        protocol = "static"
+        nh = NEXT_HOP_IP["nh1"][addr_type]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol, fib=True
+        )
+        assert result is True, "Testcase {} : Failed \nError: Route with "
+        " lowest AD is missing in RIB".format(tc_name)
+
+        nh = []
+        for nhp in range(2, 9):
+            nh.append(NEXT_HOP_IP["nh" + str(nhp)][addr_type])
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            fib=True,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes "
+        " with high AD are active in RIB".format(tc_name)
+
+    step("Shut nexthop interfaces N1 to N8 one by one")
+    for addr_type in ADDR_TYPES:
+        for nhp in range(0, 8):
+            intf = topo["routers"]["r2"]["links"]["r1-link" + str(nhp)]["interface"]
+            shutdown_bringup_interface(tgen, dut, intf, False)
+
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh_all[addr_type],
+            protocol=protocol,
+            fib=True,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes "
+        " are still present in RIB".format(tc_name)
+
+    step("No shut the nexthop interfaces N1 to N8 one by one .")
+    for addr_type in ADDR_TYPES:
+        for nhp in range(0, 8):
+            intf = topo["routers"]["r2"]["links"]["r1-link" + str(nhp)]["interface"]
+            shutdown_bringup_interface(tgen, dut, intf, True)
+
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "admin_distance": 10,
+                    }
+                ]
+            }
+        }
+        dut = "r2"
+        protocol = "static"
+        nh = NEXT_HOP_IP["nh1"][addr_type]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol, fib=True
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes are"
+        " missing in RIB".format(tc_name)
+
+        nh = []
+        for nhp in range(2, 9):
+            nh.append(NEXT_HOP_IP["nh" + str(nhp)][addr_type])
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            fib=True,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes "
+        " are missing in RIB".format(tc_name)
+
+    step("Random shut of the nexthop interfaces")
+    randnum = random.randint(0, 7)
+    for addr_type in ADDR_TYPES:
+        intf = topo["routers"]["r2"]["links"]["r1-link" + str(randnum)]["interface"]
+        shutdown_bringup_interface(tgen, dut, intf, False)
+        nhip = NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type]
+        input_dict_5 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type],
+                    }
+                ]
+            }
+        }
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_5,
+            next_hop=nhip,
+            protocol=protocol,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \n"
+        "Error: Routes are still present in RIB".format(tc_name)
+
+    step("Random no shut of the nexthop interfaces")
+    for addr_type in ADDR_TYPES:
+        intf = topo["routers"]["r2"]["links"]["r1-link" + str(randnum)]["interface"]
+        shutdown_bringup_interface(tgen, dut, intf, True)
+        nhip = NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_5, next_hop=nhip, protocol=protocol
+        )
+        assert result is True, "Testcase {} : Failed \n"
+        "Error: Routes are missing in RIB".format(tc_name)
+
+    step("Reload the FRR router")
+    # stop/start -> restart FRR router and verify
+    stop_router(tgen, "r2")
+    sleep(5)
+    start_router(tgen, "r2")
+
+    step(
+        "After reload of FRR router, static route installed "
+        "in RIB and FIB properly ."
+    )
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "admin_distance": 10,
+                    }
+                ]
+            }
+        }
+        dut = "r2"
+        protocol = "static"
+        nh = NEXT_HOP_IP["nh1"][addr_type]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol, fib=True
+        )
+        assert result is True, "Testcase {} : Failed \nError: Route with "
+        " lowest AD is missing in RIB".format(tc_name)
+
+        nh = []
+        for nhp in range(2, 9):
+            nh.append(NEXT_HOP_IP["nh" + str(nhp)][addr_type])
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            fib=True,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes "
+        " with high AD are active in RIB".format(tc_name)
+
+    step("BGP neighbor remove and add")
+    for rtr in ["r2", "r3"]:
+        if "bgp" in topo["routers"][rtr].keys():
+            delete_bgp = {rtr: {"bgp": {"delete": True}}}
+            result = create_router_bgp(tgen, topo, delete_bgp)
+            assert result is True, "Testcase {} : Failed \n Error: {}".format(
+                tc_name, result
+            )
+
+    reset_config_on_routers(tgen)
+    NEXT_HOP_IP = populate_nh()
+    step("Verify routes are still present after delete and add bgp")
+    dut = "r3"
+    protocol = "bgp"
+    result = verify_rib(
+        tgen,
+        addr_type,
+        dut,
+        input_dict_4,
+        next_hop=nh,
+        protocol=protocol,
+        expected=False,
+    )
+    assert result is not True, "Testcase {} : Failed \n"
+    "Error: Routes still present in RIB".format(tc_name)
+
+    step("Remove the redistribute static knob")
+
+    for addr_type in ADDR_TYPES:
+        input_dict_2 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {
+                                "redistribute": [
+                                    {"redist_type": "static", "delete": True}
+                                ]
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        logger.info("Remove redistribute static")
+        result = create_router_bgp(tgen, topo, input_dict_2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+        step("verify that routes are deleted from R3 routing table")
+        dut = "r3"
+        protocol = "bgp"
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes are"
+        " strill present in RIB of R3".format(tc_name)
+
+    write_test_footer(tc_name)
+
+
+def test_bgp_local_nexthop_p1_tc14_ebgp(request):
+    """
+    Verify BGP did not install the static route when it receive route
+    with local next hop
+
+    """
+    tc_name = request.node.name
+    write_test_header(tc_name)
+    tgen = get_topogen()
+
+    step("Configure BGP IPv4 session between R2 and R3")
+    step("Configure IPv4 static route on R2")
+    reset_config_on_routers(tgen)
+
+    for addr_type in ADDR_TYPES:
+        # Enable static routes
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": NETWORK[addr_type],
+                        "next_hop": topo["routers"]["r3"]["links"]["r2-link0"][
+                            addr_type
+                        ].split("/")[0],
+                    }
+                ]
+            }
+        }
+
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step("Configure redistribute static in the BGP")
+
+        input_dict_2 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {"redistribute": [{"redist_type": "static"}]}
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step("Verify R2 BGP table has IPv4 route")
+        dut = "r2"
+        result = verify_rib(tgen, addr_type, dut, input_dict_4)
+        assert result is True, "Testcase {} : Failed \nError: Routes is"
+        " missing in RIB of R2".format(tc_name)
+
+        step(" Verify route did not install in the R3 BGP table, RIB/FIB")
+        dut = "r3"
+        result = verify_bgp_rib(tgen, addr_type, dut, input_dict_4, expected=False)
+        assert result is not True, "Testcase {} : Failed \nError: Routes is"
+        " still present in BGP RIB of R2".format(tc_name)
+
+        result = verify_rib(tgen, addr_type, dut, input_dict_4, expected=False)
+        assert result is not True, "Testcase {} : Failed \nError: Routes is"
+        " still present in RIB of R2".format(tc_name)
+
+    write_test_footer(tc_name)
+
+
+if __name__ == "__main__":
+    args = ["-s"] + sys.argv[1:]
+    sys.exit(pytest.main(args))
diff --git a/tests/topotests/static_routing_with_ebgp/test_static_routes_topo4_ebgp.py b/tests/topotests/static_routing_with_ebgp/test_static_routes_topo4_ebgp.py
new file mode 100644 (file)
index 0000000..a089407
--- /dev/null
@@ -0,0 +1,989 @@
+#!/usr/bin/python
+
+#
+# Copyright (c) 2020 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.
+#
+
+"""
+
+Following tests are covered in the script.
+
+- Verify static route are blocked from route-map and prefix-list
+    applied in BGP nbrs
+- Verify Static route when FRR connected to 2 TOR
+"""
+
+import sys
+import json
+import time
+import os
+import pytest
+import ipaddr
+import ipaddress
+from time import sleep
+from copy import deepcopy
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+sys.path.append(os.path.join(CWD, "../lib/"))
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from mininet.topo import Topo
+from lib.topogen import Topogen, get_topogen
+
+# Import 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,
+    check_address_types,
+    step,
+    create_prefix_lists,
+    create_route_maps,
+    create_interfaces_cfg,
+    verify_prefix_lists,
+    verify_route_maps,
+)
+from lib.topolog import logger
+from lib.bgp import (
+    verify_bgp_convergence,
+    create_router_bgp,
+    clear_bgp_and_verify,
+    clear_bgp,
+)
+from lib.topojson import build_topo_from_json, build_config_from_json
+
+# Reading the data from JSON File for topology creation
+jsonFile = "{}/static_routes_topo4_ebgp.json".format(CWD)
+try:
+    with open(jsonFile, "r") as topoJson:
+        topo = json.load(topoJson)
+except IOError:
+    assert False, "Could not read file {}".format(jsonFile)
+
+# Global variables
+BGP_CONVERGENCE = False
+ADDR_TYPES = check_address_types()
+NETWORK = {"ipv4": "2.2.2.2/32", "ipv6": "22:22::2/128"}
+NEXT_HOP_IP = {}
+
+
+class CreateTopo(Topo):
+    """
+    Test CreateTopo - topology 1.
+
+    * `Topo`: Topology object
+    """
+
+    def build(self, *_args, **_opts):
+        """Build function."""
+        tgen = get_topogen(self)
+
+        # Building topology from json file
+        build_topo_from_json(tgen, topo)
+
+
+def setup_module(mod):
+    """
+    Set up the pytest environment.
+    * `mod`: module name
+    """
+    global topo
+    testsuite_run_time = time.asctime(time.localtime(time.time()))
+    logger.info("Testsuite start time: {}".format(testsuite_run_time))
+    logger.info("=" * 40)
+
+    logger.info("Running setup_module to create topology")
+
+    # This function initiates the topology build with Topogen...
+    tgen = Topogen(CreateTopo, mod.__name__)
+    # ... and here it calls Mininet initialization functions.
+
+    # Starting topology, create tmp files which are loaded to routers
+    #  to start deamons and then start routers
+    start_topology(tgen)
+
+    # Creating configuration from JSON
+    build_config_from_json(tgen, topo)
+
+    # Checking BGP convergence
+    global BGP_CONVERGENCE
+    global ADDR_TYPES
+    # Don't run this test if we have any failure.
+    if tgen.routers_have_failure():
+        pytest.skip(tgen.errors)
+    # Api call verify whether BGP is converged
+    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo)
+    assert BGP_CONVERGENCE is True, "setup_module :Failed \n Error: {}".format(
+        BGP_CONVERGENCE
+    )
+
+    logger.info("Running setup_module() done")
+
+
+def teardown_module(mod):
+    """
+    Teardown the pytest environment.
+
+    * `mod`: module name
+    """
+    logger.info("Running teardown_module to delete topology")
+
+    tgen = get_topogen()
+
+    # Stop toplogy and Remove tmp files
+    tgen.stop_topology()
+
+    logger.info(
+        "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
+    )
+    logger.info("=" * 40)
+
+
+#####################################################
+#
+#   Tests starting
+#
+#####################################################
+def test_static_routes_rmap_pfxlist_p0_tc7_ebgp(request):
+    """
+    Verify static route are blocked from route-map & prefix-list applied in BGP
+    nbrs
+
+    """
+    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)
+    reset_config_on_routers(tgen)
+    step("Configure holddown timer = 1 keep alive = 3 in all the neighbors")
+    step("verify bgp convergence before starting test case")
+
+    bgp_convergence = verify_bgp_convergence(tgen, topo)
+    assert bgp_convergence is True, "Testcase {} : Failed \n Error: {}".format(
+        tc_name, bgp_convergence
+    )
+
+    step(
+        "Configure 4 IPv4 and 4 IPv6 nbrs with password with mismatch "
+        " authentication between FRR routers "
+    )
+
+    for addr_type in ADDR_TYPES:
+        # Api call to modfiy BGP timerse
+        input_dict = {
+            "r2": {
+                "bgp": {
+                    "local_as": "200",
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {
+                                "neighbor": {
+                                    "r1": {
+                                        "dest_link": {
+                                            "r2-link0": {"password": "r2"},
+                                            "r2-link1": {"password": "r2"},
+                                            "r2-link2": {"password": "r2"},
+                                            "r2-link3": {"password": "r2"},
+                                        }
+                                    },
+                                    "r3": {
+                                        "dest_link": {
+                                            "r2-link0": {"password": "r2"},
+                                            "r2-link1": {"password": "r2"},
+                                            "r2-link2": {"password": "r2"},
+                                            "r2-link3": {"password": "r2"},
+                                        }
+                                    },
+                                }
+                            }
+                        }
+                    },
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict)
+        assert result is True, "Testcase {} :Failed \n Error: {}".format(
+            tc_name, result
+        )
+        clear_bgp(tgen, addr_type, "r2")
+
+    step(" All BGP nbrs are down as authentication is mismatch on both" " the sides")
+
+    bgp_convergence = verify_bgp_convergence(tgen, topo)
+    assert bgp_convergence is not True, "Testcase {} : "
+    "Failed \n BGP nbrs must be down. Error: {}".format(tc_name, bgp_convergence)
+
+    step(
+        "Configure 4 IPv4 and 4 IPv6 nbrs with macthing password  "
+        " authentication between FRR routers "
+    )
+    for addr_type in ADDR_TYPES:
+        input_dict = {
+            "r2": {
+                "bgp": {
+                    "local_as": "200",
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {
+                                "neighbor": {
+                                    "r1": {
+                                        "dest_link": {
+                                            "r2-link0": {"password": "r1"},
+                                            "r2-link1": {"password": "r1"},
+                                            "r2-link2": {"password": "r1"},
+                                            "r2-link3": {"password": "r1"},
+                                        }
+                                    },
+                                    "r3": {
+                                        "dest_link": {
+                                            "r2-link0": {"password": "r1"},
+                                            "r2-link1": {"password": "r1"},
+                                            "r2-link2": {"password": "r1"},
+                                            "r2-link3": {"password": "r1"},
+                                        }
+                                    },
+                                }
+                            }
+                        }
+                    },
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, deepcopy(input_dict))
+        assert result is True, "Testcase {} :Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step("All BGP nbrs are up as authentication is matched now")
+    bgp_convergence = verify_bgp_convergence(tgen, topo)
+    assert bgp_convergence is True, "Testcase {} : Failed \n " "Error: {}".format(
+        tc_name, bgp_convergence
+    )
+
+    step("Create prefix list P1 to permit VM3 & deny VM1 v4 & v6 routes")
+    step("Create prefix list P2 to permit VM6 IPv4 and IPv6 routes")
+    for addr_type in ADDR_TYPES:
+        input_dict_2 = {
+            "r2": {
+                "prefix_lists": {
+                    addr_type: {
+                        "pf_list_1_{}".format(addr_type): [
+                            {
+                                "seqid": 10,
+                                "network": topo["routers"]["r2"]["links"]["vm3"][
+                                    addr_type
+                                ],
+                                "action": "permit",
+                            },
+                            {
+                                "seqid": 20,
+                                "network": topo["routers"]["r2"]["links"]["vm1"][
+                                    addr_type
+                                ],
+                                "action": "deny",
+                            },
+                        ],
+                        "pf_list_2_{}".format(addr_type): [
+                            {
+                                "seqid": 10,
+                                "network": topo["routers"]["r2"]["links"]["vm6"][
+                                    addr_type
+                                ],
+                                "action": "permit",
+                            }
+                        ],
+                    }
+                }
+            }
+        }
+        result = create_prefix_lists(tgen, input_dict_2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step(
+            "Prefix list created with matching networks deny or permit "
+            "show ip prefix list"
+        )
+        result = verify_prefix_lists(tgen, input_dict_2)
+        assert result is not True, "Testcase {} : Failed \n"
+        " Error: {}".format(tc_name, result)
+
+        step("Redistribute all the routes (connected, static)")
+        input_dict_2_r1 = {
+            "r1": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {"redistribute": [{"redist_type": "static"}]}
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_2_r1)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        input_dict_2_r2 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {"redistribute": [{"redist_type": "static"}]}
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_2_r2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        input_dict_2_r3 = {
+            "r3": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {"redistribute": [{"redist_type": "static"}]}
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_2_r3)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step("configure redistribute connected in Router BGP")
+
+        input_dict_2_r1 = {
+            "r1": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {"redistribute": [{"redist_type": "connected"}]}
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_2_r1)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        input_dict_2_r3 = {
+            "r3": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {"redistribute": [{"redist_type": "connected"}]}
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_2_r3)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        input_dict_2 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {"redistribute": [{"redist_type": "connected"}]}
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step("Apply prefix list P1 on BGP neighbors 1 2 3 4 connected from " "frr r1")
+        # Configure prefix list to bgp neighbor
+        input_dict_4 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {
+                                "neighbor": {
+                                    "r1": {
+                                        "dest_link": {
+                                            "r2-link0": {
+                                                "prefix_lists": [
+                                                    {
+                                                        "name": "pf_list_1_{}".format(
+                                                            addr_type
+                                                        ),
+                                                        "direction": "out",
+                                                    }
+                                                ]
+                                            },
+                                            "r2-link1": {
+                                                "prefix_lists": [
+                                                    {
+                                                        "name": "pf_list_1_{}".format(
+                                                            addr_type
+                                                        ),
+                                                        "direction": "out",
+                                                    }
+                                                ]
+                                            },
+                                            "r2-link2": {
+                                                "prefix_lists": [
+                                                    {
+                                                        "name": "pf_list_1_{}".format(
+                                                            addr_type
+                                                        ),
+                                                        "direction": "out",
+                                                    }
+                                                ]
+                                            },
+                                            "r2-link3": {
+                                                "prefix_lists": [
+                                                    {
+                                                        "name": "pf_list_1_{}".format(
+                                                            addr_type
+                                                        ),
+                                                        "direction": "out",
+                                                    }
+                                                ]
+                                            },
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step("Apply prefix list P2 on BGP nbrs 5 & 6 connected from FRR-2")
+        # Configure prefix list to bgp neighbor
+        input_dict_4 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {
+                                "neighbor": {
+                                    "r3": {
+                                        "dest_link": {
+                                            "r2-link0": {
+                                                "prefix_lists": [
+                                                    {
+                                                        "name": "pf_list_2_{}".format(
+                                                            addr_type
+                                                        ),
+                                                        "direction": "out",
+                                                    }
+                                                ]
+                                            },
+                                            "r2-link1": {
+                                                "prefix_lists": [
+                                                    {
+                                                        "name": "pf_list_2_{}".format(
+                                                            addr_type
+                                                        ),
+                                                        "direction": "out",
+                                                    }
+                                                ]
+                                            },
+                                            "r2-link2": {
+                                                "prefix_lists": [
+                                                    {
+                                                        "name": "pf_list_2_{}".format(
+                                                            addr_type
+                                                        ),
+                                                        "direction": "out",
+                                                    }
+                                                ]
+                                            },
+                                            "r2-link3": {
+                                                "prefix_lists": [
+                                                    {
+                                                        "name": "pf_list_2_{}".format(
+                                                            addr_type
+                                                        ),
+                                                        "direction": "out",
+                                                    }
+                                                ]
+                                            },
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        clear_bgp_and_verify(tgen, topo, "r2")
+
+        step(
+            "VM1 IPv4 and IPv6 Route which is denied using prefix list is "
+            "not present on FRR1 side routing table , also not able to "
+            "ping the routes show ip route"
+        )
+
+        dut = "r1"
+        protocol = "bgp"
+        ntwk_r2_vm1 = str(
+            ipaddress.ip_interface(
+                u"{}".format(topo["routers"]["r2"]["links"]["vm1"][addr_type])
+            ).network
+        )
+        input_dict = {"r1": {"static_routes": [{"network": ntwk_r2_vm1}]}}
+        result4 = verify_rib(
+            tgen, addr_type, dut, input_dict, protocol=protocol, expected=False
+        )
+        assert result4 is not True, "Testcase {} : Failed , VM1 route is "
+        "not filtered out via prefix list. \n Error: {}".format(tc_name, result4)
+
+        step(
+            "VM4 and VM6 IPV4 and IPv6 address are present in local and "
+            "FRR2 routing table show ip bgp show ip route"
+        )
+
+        dut = "r2"
+        ntwk_r2_vm6 = str(
+            ipaddress.ip_interface(
+                u"{}".format(topo["routers"]["r2"]["links"]["vm6"][addr_type])
+            ).network
+        )
+        input_dict = {"r3": {"static_routes": [{"network": ntwk_r2_vm6}]}}
+        result4 = verify_rib(tgen, addr_type, dut, input_dict)
+        assert result4 is True, "Testcase {} : Failed.\n Error: {}".format(
+            tc_name, result4
+        )
+
+        step("Remove prefix list from all the neighbors")
+        input_dict_4 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {
+                                "neighbor": {
+                                    "r1": {
+                                        "dest_link": {
+                                            "r2-link0": {
+                                                "prefix_lists": [
+                                                    {
+                                                        "name": "pf_list_1_{}".format(
+                                                            addr_type
+                                                        ),
+                                                        "direction": "out",
+                                                        "delete": True,
+                                                    }
+                                                ]
+                                            },
+                                            "r2-link1": {
+                                                "prefix_lists": [
+                                                    {
+                                                        "name": "pf_list_1_{}".format(
+                                                            addr_type
+                                                        ),
+                                                        "direction": "out",
+                                                        "delete": True,
+                                                    }
+                                                ]
+                                            },
+                                            "r2-link2": {
+                                                "prefix_lists": [
+                                                    {
+                                                        "name": "pf_list_1_{}".format(
+                                                            addr_type
+                                                        ),
+                                                        "direction": "out",
+                                                        "delete": True,
+                                                    }
+                                                ]
+                                            },
+                                            "r2-link3": {
+                                                "prefix_lists": [
+                                                    {
+                                                        "name": "pf_list_1_{}".format(
+                                                            addr_type
+                                                        ),
+                                                        "direction": "out",
+                                                        "delete": True,
+                                                    }
+                                                ]
+                                            },
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        input_dict_4 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {
+                                "neighbor": {
+                                    "r3": {
+                                        "dest_link": {
+                                            "r2-link0": {
+                                                "prefix_lists": [
+                                                    {
+                                                        "name": "pf_list_2_{}".format(
+                                                            addr_type
+                                                        ),
+                                                        "direction": "out",
+                                                        "delete": True,
+                                                    }
+                                                ]
+                                            },
+                                            "r2-link1": {
+                                                "prefix_lists": [
+                                                    {
+                                                        "name": "pf_list_2_{}".format(
+                                                            addr_type
+                                                        ),
+                                                        "direction": "out",
+                                                        "delete": True,
+                                                    }
+                                                ]
+                                            },
+                                            "r2-link2": {
+                                                "prefix_lists": [
+                                                    {
+                                                        "name": "pf_list_2_{}".format(
+                                                            addr_type
+                                                        ),
+                                                        "direction": "out",
+                                                        "delete": True,
+                                                    }
+                                                ]
+                                            },
+                                            "r2-link3": {
+                                                "prefix_lists": [
+                                                    {
+                                                        "name": "pf_list_2_{}".format(
+                                                            addr_type
+                                                        ),
+                                                        "direction": "out",
+                                                        "delete": True,
+                                                    }
+                                                ]
+                                            },
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        clear_bgp_and_verify(tgen, topo, "r2")
+
+        step("Create RouteMap_1 with prefix list P1 and weight 50")
+        # Create route map
+        rmap_dict = {
+            "r2": {
+                "route_maps": {
+                    "rmap_pf_list_1_{}".format(addr_type): [
+                        {
+                            "action": "permit",
+                            "set": {"weight": 50},
+                            "match": {
+                                addr_type: {
+                                    "prefix_lists": "pf_list_1_{}".format(addr_type)
+                                }
+                            },
+                        }
+                    ]
+                }
+            }
+        }
+        result = create_route_maps(tgen, rmap_dict)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step("Create RouteMap_2 with prefix list P2 and weight 50")
+        # Create route map
+        rmap_dict = {
+            "r2": {
+                "route_maps": {
+                    "rmap_pf_list_2_{}".format(addr_type): [
+                        {
+                            "action": "permit",
+                            "set": {"weight": 50},
+                            "match": {
+                                addr_type: {
+                                    "prefix_lists": "pf_list_2_{}".format(addr_type)
+                                }
+                            },
+                        }
+                    ]
+                }
+            }
+        }
+        result = create_route_maps(tgen, rmap_dict)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step("Verify Route-map created verify using show route-map")
+        # verify rmap_pf_list_1 and rmap_pf_list_2 are present in router r2
+        input_dict = {
+            "r2": {
+                "route_maps": [
+                    "rmap_pf_list_1_{}".format(addr_type),
+                    "rmap_pf_list_2_{}".format(addr_type),
+                ]
+            }
+        }
+        result = verify_route_maps(tgen, input_dict)
+        assert result is not True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step("Apply policy RouteMap_1 nbrs 1 2 3 4 to FRR 1")
+        # Configure prefix list to bgp neighbor
+        input_dict_4 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {
+                                "neighbor": {
+                                    "r1": {
+                                        "dest_link": {
+                                            "r2-link0": {
+                                                "route_maps": [
+                                                    {
+                                                        "name": "rmap_pf_list_1_"
+                                                        "{}".format(addr_type),
+                                                        "direction": "out",
+                                                    }
+                                                ]
+                                            },
+                                            "r2-link1": {
+                                                "route_maps": [
+                                                    {
+                                                        "name": "rmap_pf_list_1_"
+                                                        "{}".format(addr_type),
+                                                        "direction": "out",
+                                                    }
+                                                ]
+                                            },
+                                            "r2-link2": {
+                                                "route_maps": [
+                                                    {
+                                                        "name": "rmap_pf_list_1_"
+                                                        "{}".format(addr_type),
+                                                        "direction": "out",
+                                                    }
+                                                ]
+                                            },
+                                            "r2-link3": {
+                                                "route_maps": [
+                                                    {
+                                                        "name": "rmap_pf_list_1_"
+                                                        "{}".format(addr_type),
+                                                        "direction": "out",
+                                                    }
+                                                ]
+                                            },
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step("Apply policy RouteMap_2 nbrs 5 and 6 to FRR2")
+        # Configure prefix list to bgp neighbor
+        input_dict_4 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {
+                                "neighbor": {
+                                    "r3": {
+                                        "dest_link": {
+                                            "r2-link0": {
+                                                "route_maps": [
+                                                    {
+                                                        "name": "rmap_pf_list_2_"
+                                                        "{}".format(addr_type),
+                                                        "direction": "out",
+                                                    }
+                                                ]
+                                            },
+                                            "r2-link1": {
+                                                "route_maps": [
+                                                    {
+                                                        "name": "rmap_pf_list_2_"
+                                                        "{}".format(addr_type),
+                                                        "direction": "out",
+                                                    }
+                                                ]
+                                            },
+                                            "r2-link2": {
+                                                "route_maps": [
+                                                    {
+                                                        "name": "rmap_pf_list_2_"
+                                                        "{}".format(addr_type),
+                                                        "direction": "out",
+                                                    }
+                                                ]
+                                            },
+                                            "r2-link3": {
+                                                "route_maps": [
+                                                    {
+                                                        "name": "rmap_pf_list_2_"
+                                                        "{}".format(addr_type),
+                                                        "direction": "out",
+                                                    }
+                                                ]
+                                            },
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step(
+            "After applying to BGP neighbors verify VM1 IPv4 and IPv6 Route"
+            " which is denied using prefix list is not present on FRR side"
+            " routing table , also not able to ping the routes show ip route"
+            " and VM4 and VM6 IPV4 and IPv6 address are present in local and"
+            " FRR routing table show ip bgp show ip route"
+        )
+
+        dut = "r1"
+        protocol = "bgp"
+        ntwk_r2_vm1 = str(
+            ipaddress.ip_interface(
+                u"{}".format(topo["routers"]["r2"]["links"]["vm1"][addr_type])
+            ).network
+        )
+        input_dict = {"r1": {"static_routes": [{"network": ntwk_r2_vm1}]}}
+        result4 = verify_rib(
+            tgen, addr_type, dut, input_dict, protocol=protocol, expected=False
+        )
+        assert result4 is not True, "Testcase {} : Failed \n" "Error: {}".format(
+            tc_name, result4
+        )
+
+        step("vm4 should be present in FRR1")
+        dut = "r1"
+        ntwk_r2_vm1 = str(
+            ipaddress.ip_interface(
+                u"{}".format(topo["routers"]["r1"]["links"]["vm4"][addr_type])
+            ).network
+        )
+        input_dict = {"r1": {"static_routes": [{"network": ntwk_r2_vm1}]}}
+        result4 = verify_rib(tgen, addr_type, dut, input_dict)
+        assert result4 is True, "Testcase {} : Failed , VM1 route is "
+        "not filtered out via prefix list. \n Error: {}".format(tc_name, result4)
+
+        step("vm4 should be present in FRR2")
+        dut = "r2"
+        ntwk_r2_vm1 = str(
+            ipaddress.ip_interface(
+                u"{}".format(topo["routers"]["r1"]["links"]["vm4"][addr_type])
+            ).network
+        )
+        input_dict = {"r1": {"static_routes": [{"network": ntwk_r2_vm1}]}}
+        result4 = verify_rib(tgen, addr_type, dut, input_dict)
+        assert result4 is True, "Testcase {} : Failed , VM1 route is "
+        "not filtered out via prefix list. \n Error: {}".format(tc_name, result4)
+
+        dut = "r3"
+        protocol = "bgp"
+        ntwk_r2_vm6 = str(
+            ipaddress.ip_interface(
+                u"{}".format(topo["routers"]["r2"]["links"]["vm6"][addr_type])
+            ).network
+        )
+        input_dict = {"r3": {"static_routes": [{"network": ntwk_r2_vm6}]}}
+        result4 = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
+        assert result4 is True, "Testcase {} : Failed.\n Error: {}".format(
+            tc_name, result4
+        )
+
+    write_test_footer(tc_name)
+
+
+if __name__ == "__main__":
+    args = ["-s"] + sys.argv[1:]
+    sys.exit(pytest.main(args))
diff --git a/tests/topotests/static_routing_with_ibgp/static_routes_topo1_ibgp.json b/tests/topotests/static_routing_with_ibgp/static_routes_topo1_ibgp.json
new file mode 100644 (file)
index 0000000..5f26307
--- /dev/null
@@ -0,0 +1,145 @@
+{
+    "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": {
+        "r1": {
+            "links": {
+                "lo": {
+                    "ipv4": "auto",
+                    "ipv6": "auto",
+                    "type": "loopback"
+                },
+                "r2-link0": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link1": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r3-link0": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r3-link1": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                }
+            }
+        },
+        "r2": {
+            "links": {
+                "lo": {
+                    "ipv4": "auto",
+                    "ipv6": "auto",
+                    "type": "loopback"
+                },
+                "r1-link0": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r1-link1": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r3": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                }
+            },
+            "bgp": {
+                "local_as": "100",
+                "address_family": {
+                    "ipv4": {
+                        "unicast": {
+                            "neighbor": {
+                                "r3": {
+                                    "dest_link": {
+                                        "r2": {}
+                                    }
+                                }
+                            }
+                        }
+                    },
+                    "ipv6": {
+                        "unicast": {
+                            "neighbor": {
+                                "r3": {
+                                    "dest_link": {
+                                        "r2": {}
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        },
+        "r3": {
+            "links": {
+                "lo": {
+                    "ipv4": "auto",
+                    "ipv6": "auto",
+                    "type": "loopback"
+                },
+                "r2": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r1-link0": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r1-link1": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                }
+            },
+            "bgp": {
+                "local_as": "100",
+                "address_family": {
+                    "ipv4": {
+                        "unicast": {
+                            "neighbor": {
+                                "r2": {
+                                    "dest_link": {
+                                        "r3": {}
+                                    }
+                                }
+                            }
+                        }
+                    },
+                    "ipv6": {
+                        "unicast": {
+                            "neighbor": {
+                                "r2": {
+                                    "dest_link": {
+                                        "r3": {}
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/topotests/static_routing_with_ibgp/static_routes_topo2_ibgp.json b/tests/topotests/static_routing_with_ibgp/static_routes_topo2_ibgp.json
new file mode 100644 (file)
index 0000000..7537e5c
--- /dev/null
@@ -0,0 +1,267 @@
+{
+    "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": {
+        "r1": {
+            "links": {
+                "lo": {
+                    "ipv4": "auto",
+                    "ipv6": "auto",
+                    "type": "loopback"
+                },
+                "r2-link0": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link1": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link2": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link3": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link4": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link5": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link6": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link7": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                }
+            }
+        },
+        "r2": {
+            "links": {
+                "lo": {
+                    "ipv4": "auto",
+                    "ipv6": "auto",
+                    "type": "loopback"
+                },
+                "r1-link0": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r1-link1": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r1-link2": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r1-link3": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r1-link4": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r1-link5": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r1-link6": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r1-link7": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r3-link0": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r3-link1": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r3-link2": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r3-link3": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r3-link4": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r3-link5": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r3-link6": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r3-link7": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                }
+            },
+            "bgp": {
+                "local_as": "100",
+                "address_family": {
+                    "ipv4": {
+                        "unicast": {
+                            "neighbor": {
+                                "r3": {
+                                    "dest_link": {
+                                        "r2-link0": {},
+                                        "r2-link1": {},
+                                        "r2-link2": {},
+                                        "r2-link3": {},
+                                        "r2-link4": {},
+                                        "r2-link5": {},
+                                        "r2-link6": {},
+                                        "r2-link7": {}
+                                    }
+                                }
+                            },
+                            "redistribute": [{
+                                "redist_type": "static"
+                            }]
+                        }
+                    },
+                    "ipv6": {
+                        "unicast": {
+                            "neighbor": {
+                                "r3": {
+                                    "dest_link": {
+                                        "r2-link0": {},
+                                        "r2-link1": {},
+                                        "r2-link2": {},
+                                        "r2-link3": {},
+                                        "r2-link4": {},
+                                        "r2-link5": {},
+                                        "r2-link6": {},
+                                        "r2-link7": {}
+                                    }
+                                }
+                            },
+                            "redistribute": [{
+                                "redist_type": "static"
+                            }]
+                        }
+                    }
+                }
+            }
+        },
+        "r3": {
+            "links": {
+                "lo": {
+                    "ipv4": "auto",
+                    "ipv6": "auto",
+                    "type": "loopback"
+                },
+                "r2-link0": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link1": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link2": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link3": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link4": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link5": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link6": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link7": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                }
+            },
+            "bgp": {
+                "local_as": "100",
+                "address_family": {
+                    "ipv4": {
+                        "unicast": {
+                            "neighbor": {
+                                "r2": {
+                                    "dest_link": {
+                                        "r3-link0": {},
+                                        "r3-link1": {},
+                                        "r3-link2": {},
+                                        "r3-link3": {},
+                                        "r3-link4": {},
+                                        "r3-link5": {},
+                                        "r3-link6": {},
+                                        "r3-link7": {}
+                                    }
+                                }
+                            }
+                        }
+                    },
+                    "ipv6": {
+                        "unicast": {
+                            "neighbor": {
+                                "r2": {
+                                    "dest_link": {
+                                        "r3-link0": {},
+                                        "r3-link1": {},
+                                        "r3-link2": {},
+                                        "r3-link3": {},
+                                        "r3-link4": {},
+                                        "r3-link5": {},
+                                        "r3-link6": {},
+                                        "r3-link7": {}
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/topotests/static_routing_with_ibgp/static_routes_topo3_ibgp.json b/tests/topotests/static_routing_with_ibgp/static_routes_topo3_ibgp.json
new file mode 100644 (file)
index 0000000..3346609
--- /dev/null
@@ -0,0 +1,177 @@
+{
+    "address_types": [
+        "ipv4",
+        "ipv6"
+    ],
+    "ipv4base": "10.0.0.0",
+    "ipv4mask": 30,
+    "ipv6base": "fd00::",
+    "ipv6mask": 64,
+    "link_ip_start": {
+        "ipv4": "10.0.0.0",
+        "v4mask": 29,
+        "ipv6": "fd00::",
+        "v6mask": 64
+    },
+    "lo_prefix": {
+        "ipv4": "1.0.",
+        "v4mask": 32,
+        "ipv6": "2001:db8:f::",
+        "v6mask": 128
+    },
+    "routers": {
+        "r1": {
+            "links": {
+                "lo": {
+                    "ipv4": "auto",
+                    "ipv6": "auto",
+                    "type": "loopback"
+                },
+                "r2-link0": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link1": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link2": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link3": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link4": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link5": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link6": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link7": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                }
+            }
+        },
+        "r2": {
+            "links": {
+                "lo": {
+                    "ipv4": "auto",
+                    "ipv6": "auto",
+                    "type": "loopback"
+                },
+                "r1-link0": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r1-link1": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r1-link2": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r1-link3": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r1-link4": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r1-link5": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r1-link6": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r1-link7": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r3-link0": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                }
+            },
+            "bgp": {
+                "local_as": "100",
+                "address_family": {
+                    "ipv4": {
+                        "unicast": {
+                            "neighbor": {
+                                "r3": {
+                                    "dest_link": {
+                                        "r2-link0": {}
+                                    }
+                                }
+                            }
+                        }
+                    },
+                    "ipv6": {
+                        "unicast": {
+                            "neighbor": {
+                                "r3": {
+                                    "dest_link": {
+                                        "r2-link0": {}
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        },
+        "r3": {
+            "links": {
+                "lo": {
+                    "ipv4": "auto",
+                    "ipv6": "auto",
+                    "type": "loopback"
+                },
+                "r2-link0": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                }
+            },
+            "bgp": {
+                "local_as": "100",
+                "address_family": {
+                    "ipv4": {
+                        "unicast": {
+                            "neighbor": {
+                                "r2": {
+                                    "dest_link": {
+                                        "r3-link0": {}
+                                    }
+                                }
+                            }
+                        }
+                    },
+                    "ipv6": {
+                        "unicast": {
+                            "neighbor": {
+                                "r2": {
+                                    "dest_link": {
+                                        "r3-link0": {}
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/topotests/static_routing_with_ibgp/static_routes_topo4_ibgp.json b/tests/topotests/static_routing_with_ibgp/static_routes_topo4_ibgp.json
new file mode 100644 (file)
index 0000000..bb72578
--- /dev/null
@@ -0,0 +1,428 @@
+{
+    "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": {
+        "r1": {
+            "links": {
+                "lo": {
+                    "ipv4": "auto",
+                    "ipv6": "auto",
+                    "type": "loopback"
+                },
+                "r2-link0": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link1": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link2": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link3": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "vm4": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                }
+            },
+            "bgp": {
+                "local_as": "100",
+                "address_family": {
+                    "ipv4": {
+                        "unicast": {
+                            "neighbor": {
+                                "r2": {
+                                    "dest_link": {
+                                        "r1-link0": {
+                                            "password": "r1",
+                                            "holddowntimer": 3,
+                                            "keepalivetimer": 1
+                                        },
+                                        "r1-link1": {
+                                            "password": "r1",
+                                            "holddowntimer": 3,
+                                            "keepalivetimer": 1
+                                        },
+                                        "r1-link2": {
+                                            "password": "r1",
+                                            "holddowntimer": 3,
+                                            "keepalivetimer": 1
+                                        },
+                                        "r1-link3": {
+                                            "password": "r1",
+                                            "holddowntimer": 3,
+                                            "keepalivetimer": 1
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    },
+                    "ipv6": {
+                        "unicast": {
+                            "neighbor": {
+                                "r2": {
+                                    "dest_link": {
+                                        "r1-link0": {
+                                            "password": "r1",
+                                            "holddowntimer": 3,
+                                            "keepalivetimer": 1
+                                        },
+                                        "r1-link1": {
+                                            "password": "r1",
+                                            "holddowntimer": 3,
+                                            "keepalivetimer": 1
+                                        },
+                                        "r1-link2": {
+                                            "password": "r1",
+                                            "holddowntimer": 3,
+                                            "keepalivetimer": 1
+                                        },
+                                        "r1-link3": {
+                                            "password": "r1",
+                                            "holddowntimer": 3,
+                                            "keepalivetimer": 1
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        },
+        "r2": {
+            "links": {
+                "lo": {
+                    "ipv4": "auto",
+                    "ipv6": "auto",
+                    "type": "loopback"
+                },
+                "r1-link0": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r1-link1": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r1-link2": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r1-link3": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r3-link0": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r3-link1": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r3-link2": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "vm1": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "vm2": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "vm3": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "vm6": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r3-link3": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                }
+            },
+            "bgp": {
+                "local_as": "200",
+                "address_family": {
+                    "ipv4": {
+                        "unicast": {
+                            "neighbor": {
+                                "r1": {
+                                    "dest_link": {
+                                        "r2-link0": {
+                                            "password": "r1"
+                                        },
+                                        "r2-link1": {
+                                            "password": "r1"
+                                        },
+                                        "r2-link2": {
+                                            "password": "r1"
+                                        },
+                                        "r2-link3": {
+                                            "password": "r1"
+                                        }
+                                    }
+                                },
+                                "r3": {
+                                    "dest_link": {
+                                        "r2-link0": {
+                                            "password": "r1"
+                                        },
+                                        "r2-link1": {
+                                            "password": "r1"
+                                        },
+                                        "r2-link2": {
+                                            "password": "r1"
+                                        },
+                                        "r2-link3": {
+                                            "password": "r1"
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    },
+                    "ipv6": {
+                        "unicast": {
+                            "neighbor": {
+                                "r1": {
+                                    "dest_link": {
+                                        "r2-link0": {
+                                            "password": "r1"
+                                        },
+                                        "r2-link1": {
+                                            "password": "r1"
+                                        },
+                                        "r2-link2": {
+                                            "password": "r1"
+                                        },
+                                        "r2-link3": {
+                                            "password": "r1"
+                                        }
+                                    }
+                                },
+                                "r3": {
+                                    "dest_link": {
+                                        "r2-link0": {
+                                            "password": "r1"
+                                        },
+                                        "r2-link1": {
+                                            "password": "r1"
+                                        },
+                                        "r2-link2": {
+                                            "password": "r1"
+                                        },
+                                        "r2-link3": {
+                                            "password": "r1"
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        },
+        "r3": {
+            "links": {
+                "lo": {
+                    "ipv4": "auto",
+                    "ipv6": "auto",
+                    "type": "loopback"
+                },
+                "r2-link0": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link1": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link2": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "r2-link3": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                },
+                "vm5": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                }
+            },
+            "bgp": {
+                "local_as": "300",
+                "address_family": {
+                    "ipv4": {
+                        "unicast": {
+                            "neighbor": {
+                                "r2": {
+                                    "dest_link": {
+                                        "r3-link0": {
+                                            "password": "r1",
+                                            "holddowntimer": 3,
+                                            "keepalivetimer": 1
+                                        },
+                                        "r3-link1": {
+                                            "password": "r1",
+                                            "holddowntimer": 3,
+                                            "keepalivetimer": 1
+                                        },
+                                        "r3-link2": {
+                                            "password": "r1",
+                                            "holddowntimer": 3,
+                                            "keepalivetimer": 1
+                                        },
+                                        "r3-link3": {
+                                            "password": "r1",
+                                            "holddowntimer": 3,
+                                            "keepalivetimer": 1
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    },
+                    "ipv6": {
+                        "unicast": {
+                            "neighbor": {
+                                "r2": {
+                                    "dest_link": {
+                                        "r3-link0": {
+                                            "password": "r1",
+                                            "holddowntimer": 3,
+                                            "keepalivetimer": 1
+                                        },
+                                        "r3-link1": {
+                                            "password": "r1",
+                                            "holddowntimer": 3,
+                                            "keepalivetimer": 1
+                                        },
+                                        "r3-link2": {
+                                            "password": "r1",
+                                            "holddowntimer": 3,
+                                            "keepalivetimer": 1
+                                        },
+                                        "r3-link3": {
+                                            "password": "r1",
+                                            "holddowntimer": 3,
+                                            "keepalivetimer": 1
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        },
+        "vm1": {
+            "links": {
+                "lo": {
+                    "ipv4": "auto",
+                    "ipv6": "auto",
+                    "type": "loopback"
+                },
+                "r2": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                }
+            }
+        },
+        "vm2": {
+            "links": {
+                "lo": {
+                    "ipv4": "auto",
+                    "ipv6": "auto",
+                    "type": "loopback"
+                },
+                "r2": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                }
+            }
+        },
+        "vm3": {
+            "links": {
+                "lo": {
+                    "ipv4": "auto",
+                    "ipv6": "auto",
+                    "type": "loopback"
+                },
+                "r2": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                }
+            }
+        },
+        "vm4": {
+            "links": {
+                "lo": {
+                    "ipv4": "auto",
+                    "ipv6": "auto",
+                    "type": "loopback"
+                },
+                "r1": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                }
+            }
+        },
+        "vm5": {
+            "links": {
+                "lo": {
+                    "ipv4": "auto",
+                    "ipv6": "auto",
+                    "type": "loopback"
+                },
+                "r3": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                }
+            }
+        },
+        "vm6": {
+            "links": {
+                "lo": {
+                    "ipv4": "auto",
+                    "ipv6": "auto",
+                    "type": "loopback"
+                },
+                "r2": {
+                    "ipv4": "auto",
+                    "ipv6": "auto"
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/topotests/static_routing_with_ibgp/test_static_routes_topo1_ibgp.py b/tests/topotests/static_routing_with_ibgp/test_static_routes_topo1_ibgp.py
new file mode 100644 (file)
index 0000000..dc68f16
--- /dev/null
@@ -0,0 +1,1313 @@
+#!/usr/bin/python
+
+#
+# Copyright (c) 2020 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.
+#
+"""
+
+    -Verify static route ECMP functionality with 2 next hop
+
+    -Verify static route functionality with 2 next hop and different AD
+    value
+
+    -Verify RIB status when same route advertise via BGP and static route
+
+"""
+import sys
+import json
+import time
+import os
+import pytest
+import ipaddr
+from time import sleep
+from copy import deepcopy
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+sys.path.append(os.path.join(CWD, "../lib/"))
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from mininet.topo import Topo
+from lib.topogen import Topogen, get_topogen
+
+# Import 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,
+    check_address_types,
+    step,
+    create_interfaces_cfg,
+    shutdown_bringup_interface,
+    stop_router,
+    start_router,
+)
+from lib.topolog import logger
+from lib.bgp import verify_bgp_convergence, create_router_bgp, verify_bgp_rib
+from lib.topojson import build_topo_from_json, build_config_from_json
+
+# Reading the data from JSON File for topology creation
+jsonFile = "{}/static_routes_topo1_ibgp.json".format(CWD)
+try:
+    with open(jsonFile, "r") as topoJson:
+        topo = json.load(topoJson)
+except IOError:
+    assert False, "Could not read file {}".format(jsonFile)
+
+# Global variables
+BGP_CONVERGENCE = False
+ADDR_TYPES = check_address_types()
+NETWORK = {"ipv4": ["11.0.20.1/32", "11.0.20.2/32"], "ipv6": ["2::1/128", "2::2/128"]}
+NETWORK2 = {"ipv4": "11.0.20.1/32", "ipv6": "2::1/128"}
+
+PREFIX1 = {"ipv4": "110.0.20.1/32", "ipv6": "20::1/128"}
+
+
+class CreateTopo(Topo):
+    """
+    Test CreateTopo - topology 1.
+
+    * `Topo`: Topology object
+    """
+
+    def build(self, *_args, **_opts):
+        """Build function."""
+        tgen = get_topogen(self)
+
+        # Building topology from json file
+        build_topo_from_json(tgen, topo)
+
+
+def setup_module(mod):
+    """
+
+    Set up the pytest environment.
+
+    * `mod`: module name
+    """
+    global topo
+    testsuite_run_time = time.asctime(time.localtime(time.time()))
+    logger.info("Testsuite start time: {}".format(testsuite_run_time))
+    logger.info("=" * 40)
+
+    logger.info("Running setup_module to create topology")
+
+    # This function initiates the topology build with Topogen...
+    tgen = Topogen(CreateTopo, mod.__name__)
+    # ... and here it calls Mininet initialization functions.
+
+    # Starting topology, create tmp files which are loaded to routers
+    #  to start deamons and then start routers
+    start_topology(tgen)
+
+    # Creating configuration from JSON
+    build_config_from_json(tgen, topo)
+
+    # Checking BGP convergence
+    global BGP_CONVERGENCE
+    global ADDR_TYPES
+
+    # Don't run this test if we have any failure.
+    if tgen.routers_have_failure():
+        pytest.skip(tgen.errors)
+    # Api call verify whether BGP is converged
+    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo)
+    assert BGP_CONVERGENCE is True, "setup_module :Failed \n Error: {}".format(
+        BGP_CONVERGENCE
+    )
+
+    logger.info("Running setup_module() done")
+
+
+def teardown_module(mod):
+    """
+    Teardown the pytest environment
+
+    * `mod`: module name
+    """
+
+    logger.info("Running teardown_module to delete topology")
+
+    tgen = get_topogen()
+
+    # Stop toplogy and Remove tmp files
+    tgen.stop_topology()
+
+    logger.info(
+        "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
+    )
+    logger.info("=" * 40)
+
+
+def populate_nh():
+    NEXT_HOP_IP = {
+        "nh1": {
+            "ipv4": topo["routers"]["r1"]["links"]["r2-link0"]["ipv4"].split("/")[0],
+            "ipv6": topo["routers"]["r1"]["links"]["r2-link0"]["ipv6"].split("/")[0],
+        },
+        "nh2": {
+            "ipv4": topo["routers"]["r1"]["links"]["r2-link1"]["ipv4"].split("/")[0],
+            "ipv6": topo["routers"]["r1"]["links"]["r2-link1"]["ipv6"].split("/")[0],
+        },
+    }
+    return NEXT_HOP_IP
+
+
+#####################################################
+#
+#   Tests starting
+#
+#####################################################
+
+
+def test_static_route_2nh_p0_tc_1_ibgp(request):
+    """
+    Verify static route ECMP functionality with 2 next hop
+
+    """
+    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)
+
+    reset_config_on_routers(tgen)
+    NEXT_HOP_IP = populate_nh()
+
+    step(
+        "Configure IPv4 static route (10.1.1.1) in R2 with next hop N1"
+        "(28.1.1.2 ) and N2 (29.1.1.2) , Static route next-hop present on"
+        "R1"
+    )
+    step("ex :- ip route 10.1.1.1/24 28.1.1.2 & ip route 10.1.1.1/24 29.1.1.1")
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": NETWORK[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                    },
+                    {
+                        "network": NETWORK[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh2"][addr_type],
+                    },
+                ]
+            }
+        }
+
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step(
+            "On R2, static route installed in RIB using show ip route"
+            " with 2 ECMP next hop "
+        )
+        nh = [NEXT_HOP_IP["nh1"][addr_type], NEXT_HOP_IP["nh2"][addr_type]]
+        dut = "r2"
+        protocol = "static"
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes is"
+        " missing in RIB".format(tc_name)
+
+        step("Configure IBGP IPv4 peering between R2 and R3 router.")
+        step("Configure redistribute static in BGP on R2 router")
+
+        input_dict_2 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {"redistribute": [{"redist_type": "static"}]}
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step("Remove the static route configured with nexthop N1 from" "running config")
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": NETWORK[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "delete": True,
+                    }
+                ]
+            }
+        }
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step(
+            "On R2, after removing the static route with N1 , "
+            "route become active with nexthop N2 and vice versa."
+        )
+        nh = NEXT_HOP_IP["nh1"][addr_type]
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes is"
+        " still present in RIB".format(tc_name)
+
+        nh = [NEXT_HOP_IP["nh2"][addr_type]]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes is"
+        " missing in RIB".format(tc_name)
+
+        step("Configure the static route with nexthop N1")
+
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": NETWORK[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                    }
+                ]
+            }
+        }
+
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step("Remove the static route configured with nexthop N2 from" "running config")
+
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": NETWORK[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh2"][addr_type],
+                        "delete": True,
+                    }
+                ]
+            }
+        }
+
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step(
+            "On R2, after removing the static route with N2 , "
+            "route become active with nexthop N1 and vice versa."
+        )
+        nh = NEXT_HOP_IP["nh2"][addr_type]
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes is"
+        " still present in RIB".format(tc_name)
+
+        nh = [NEXT_HOP_IP["nh1"][addr_type]]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes is"
+        " missing in RIB".format(tc_name)
+
+        step("Configure the static route with nexthop N2")
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": NETWORK[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh2"][addr_type],
+                    }
+                ]
+            }
+        }
+
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step("Shut nexthop interface N1")
+        intf = topo["routers"]["r2"]["links"]["r1-link0"]["interface"]
+
+        shutdown_bringup_interface(tgen, dut, intf, False)
+
+        step("Only one the nexthops should be active in RIB.")
+
+        nh = NEXT_HOP_IP["nh2"][addr_type]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes is"
+        " missing in RIB".format(tc_name)
+
+        nh = NEXT_HOP_IP["nh1"][addr_type]
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes is"
+        " still present in RIB".format(tc_name)
+
+        dut = "r3"
+        result = verify_bgp_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, expected=False
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Route is"
+        " still present in RIB".format(tc_name)
+
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            protocol=protocol,
+            next_hop=nh,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Route is"
+        " still present in RIB".format(tc_name)
+
+        dut = "r2"
+        nh = [NEXT_HOP_IP["nh2"][addr_type]]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes is"
+        " missing in RIB".format(tc_name)
+
+        dut = "r3"
+        result = verify_bgp_rib(tgen, addr_type, dut, input_dict_4)
+        assert result is True, "Testcase {} : Failed \nError: Route is"
+        " missing in RIB".format(tc_name)
+
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, protocol=protocol, expected=False
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Route is"
+        " still present in RIB".format(tc_name)
+
+        dut = "r2"
+        step("No shut the nexthop interface N1")
+        shutdown_bringup_interface(tgen, dut, intf, True)
+
+        step(
+            "after shut of nexthop N1 , route become active "
+            "with nexthop N2 and vice versa."
+        )
+        nh = [NEXT_HOP_IP["nh1"][addr_type], NEXT_HOP_IP["nh2"][addr_type]]
+
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes is"
+        " missing in RIB".format(tc_name)
+
+        step("Shut nexthop interface N2")
+        intf = topo["routers"]["r2"]["links"]["r1-link1"]["interface"]
+        dut = "r2"
+        shutdown_bringup_interface(tgen, dut, intf, False)
+
+        step(
+            " after shut of nexthop N1 , route become active with "
+            "nexthop N2 and vice versa."
+        )
+        nh = NEXT_HOP_IP["nh2"][addr_type]
+
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes is"
+        " still present in RIB".format(tc_name)
+
+        nh = [NEXT_HOP_IP["nh1"][addr_type]]
+        dut = "r2"
+        protocol = "static"
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes is"
+        " missing in RIB".format(tc_name)
+
+        dut = "r3"
+        result = verify_bgp_rib(tgen, addr_type, dut, input_dict_4)
+        assert result is True, "Testcase {} : Failed \nError: Route is"
+        " missing in RIB".format(tc_name)
+
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, protocol=protocol, expected=False
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Route is"
+        " still present in RIB".format(tc_name)
+
+        step("No shut nexthop interface N2")
+        dut = "r2"
+        shutdown_bringup_interface(tgen, dut, intf, True)
+
+        step(
+            "after shut of nexthop N1 , route become active "
+            "with nexthop N2 and vice versa."
+        )
+        nh = [NEXT_HOP_IP["nh1"][addr_type], NEXT_HOP_IP["nh2"][addr_type]]
+
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes is"
+        " missing in RIB".format(tc_name)
+
+        dut = "r3"
+        result = verify_bgp_rib(tgen, addr_type, dut, input_dict_4)
+        assert result is True, "Testcase {} : Failed \nError: Route is"
+        " missing in RIB".format(tc_name)
+
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, protocol=protocol, expected=False
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Route is"
+        " still present in RIB".format(tc_name)
+
+        step("Reload the FRR router")
+        # stop/start -> restart FRR router and verify
+        stop_router(tgen, "r2")
+        sleep(5)
+        start_router(tgen, "r2")
+
+        dut = "r2"
+        step(
+            "After reload of FRR router , static route installed"
+            " in RIB and FIB properly ."
+        )
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes is"
+        " missing in RIB".format(tc_name)
+
+        dut = "r3"
+        result = verify_bgp_rib(tgen, addr_type, dut, input_dict_4)
+        assert result is True, "Testcase {} : Failed \nError: Route is"
+        " still present in RIB".format(tc_name)
+
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, protocol=protocol, expected=False
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Route is"
+        " still present in RIB".format(tc_name)
+
+    write_test_footer(tc_name)
+
+
+def test_static_route_2nh_admin_dist_p0_tc_2_ibgp(request):
+    """
+    Verify static route functionality with 2 next hop & different AD value
+
+    """
+    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)
+
+    reset_config_on_routers(tgen)
+    NEXT_HOP_IP = populate_nh()
+    step(
+        "Configure IPv4 static route (10.1.1.1) in R2 with next hop N1"
+        "(28.1.1.2 ) AD 10 and N2 (29.1.1.2) AD 20 , Static route next-hop"
+        "present on R1 \n ex :- ip route 10.1.1.1/24 28.1.1.2 10 & "
+        "ip route 10.1.1.1/24 29.1.1.2 20"
+    )
+
+    reset_config_on_routers(tgen)
+    NEXT_HOP_IP = populate_nh()
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": NETWORK2[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "admin_distance": 10,
+                    },
+                    {
+                        "network": NETWORK2[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh2"][addr_type],
+                        "admin_distance": 20,
+                    },
+                ]
+            }
+        }
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step(
+            "On R2, static route installed in RIB using "
+            "show ip route with 2 next hop , lowest AD nexthop is active "
+        )
+        rte1_nh1 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": NETWORK2[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "admin_distance": 10,
+                    }
+                ]
+            }
+        }
+        nh = [NEXT_HOP_IP["nh1"][addr_type]]
+        dut = "r2"
+        protocol = "static"
+        result = verify_rib(
+            tgen, addr_type, dut, rte1_nh1, next_hop=nh, protocol=protocol, fib=True
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes is"
+        "missing in RIB".format(tc_name)
+
+        rte2_nh2 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": NETWORK2[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh2"][addr_type],
+                        "admin_distance": 20,
+                    }
+                ]
+            }
+        }
+        nh = [NEXT_HOP_IP["nh2"][addr_type]]
+        dut = "r2"
+        protocol = "static"
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            rte2_nh2,
+            next_hop=nh,
+            protocol=protocol,
+            fib=True,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes is"
+        "not active in RIB".format(tc_name)
+
+        step("Configure IBGP IPv4 peering between R2 and R3 router.")
+        step("Explicit route is added in R3 for R2 nexthop rechability")
+        rt3_rtes = {
+            "r3": {
+                "static_routes": [
+                    {
+                        "network": NEXT_HOP_IP["nh1"][addr_type] + "/32",
+                        "next_hop": topo["routers"]["r2"]["links"]["r3"][addr_type],
+                    },
+                    {
+                        "network": NEXT_HOP_IP["nh2"][addr_type] + "/32",
+                        "next_hop": topo["routers"]["r2"]["links"]["r3"][addr_type],
+                    },
+                ]
+            }
+        }
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, rt3_rtes)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+        step("Configure redistribute static in BGP on R2 router")
+
+        input_dict_2 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {"redistribute": [{"redist_type": "static"}]}
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step("Remove the static route configured with nexthop N1 from" "running config")
+        rt1_nh1 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": NETWORK[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "delete": True,
+                    }
+                ]
+            }
+        }
+
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, rt1_nh1)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step(
+            "On R2, after removing the static route with N1 , "
+            "route become active with nexthop N2 and vice versa."
+        )
+        rte1_nh1 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": NETWORK2[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "admin_distance": 10,
+                    }
+                ]
+            }
+        }
+        nh = [NEXT_HOP_IP["nh1"][addr_type]]
+        dut = "r2"
+        protocol = "static"
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            rte1_nh1,
+            next_hop=nh,
+            protocol=protocol,
+            fib=True,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes is"
+        "missing in RIB".format(tc_name)
+
+        rte2_nh2 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": NETWORK2[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh2"][addr_type],
+                        "admin_distance": 20,
+                    }
+                ]
+            }
+        }
+        nh = [NEXT_HOP_IP["nh2"][addr_type]]
+        result = verify_rib(
+            tgen, addr_type, dut, rte2_nh2, next_hop=nh, protocol=protocol, fib=True
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes is"
+        "not active in RIB".format(tc_name)
+
+        step("Configure the static route with nexthop N1")
+        rte1_nh1 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": NETWORK[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "admin_distance": 10,
+                    }
+                ]
+            }
+        }
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, rte1_nh1)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step("Remove the static route configured with nexthop N2 from" "running config")
+        rte2_nh2 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": NETWORK[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh2"][addr_type],
+                        "delete": True,
+                    }
+                ]
+            }
+        }
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, rte2_nh2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step(
+            "On R2, after removing the static route with N2 , "
+            "route become active with nexthop N1 and vice versa."
+        )
+        nh = NEXT_HOP_IP["nh2"][addr_type]
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            rte2_nh2,
+            next_hop=nh,
+            protocol=protocol,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes is"
+        " still present in RIB".format(tc_name)
+
+        nh = [NEXT_HOP_IP["nh1"][addr_type]]
+        result = verify_rib(
+            tgen, addr_type, dut, rte1_nh1, next_hop=nh, protocol=protocol
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes is"
+        " missing in RIB".format(tc_name)
+
+        step("Configure the static route with nexthop N2")
+        rte2_nh2 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": NETWORK[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh2"][addr_type],
+                        "admin_distance": 20,
+                    }
+                ]
+            }
+        }
+
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, rte2_nh2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step("Shut nexthop interface N1")
+        intf = topo["routers"]["r2"]["links"]["r1-link0"]["interface"]
+
+        shutdown_bringup_interface(tgen, dut, intf, False)
+
+        step("after shut of nexthop N1 , route become active with nexthop N2")
+
+        nh = NEXT_HOP_IP["nh1"][addr_type]
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            rte1_nh1,
+            next_hop=nh,
+            protocol=protocol,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes is"
+        " still present in RIB".format(tc_name)
+
+        nh = [NEXT_HOP_IP["nh2"][addr_type]]
+        result = verify_rib(
+            tgen, addr_type, dut, rte2_nh2, next_hop=nh, protocol=protocol, fib=True
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes is"
+        " missing in RIB".format(tc_name)
+
+        step("No shut the nexthop interface N1")
+        shutdown_bringup_interface(tgen, dut, intf, True)
+
+        step(
+            "after shut of nexthop N1 , route become active "
+            "with nexthop N2 and vice versa."
+        )
+        nh = [NEXT_HOP_IP["nh1"][addr_type]]
+
+        result = verify_rib(
+            tgen, addr_type, dut, rte1_nh1, next_hop=nh, protocol=protocol, fib=True
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes is"
+        " missing in RIB".format(tc_name)
+
+        step("Shut nexthop interface N2")
+        intf = topo["routers"]["r2"]["links"]["r1-link1"]["interface"]
+
+        shutdown_bringup_interface(tgen, dut, intf, False)
+
+        step(
+            " after shut of nexthop N1 , route become active with "
+            "nexthop N2 and vice versa."
+        )
+        nh = NEXT_HOP_IP["nh2"][addr_type]
+
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            rte2_nh2,
+            next_hop=nh,
+            protocol=protocol,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes is"
+        " still present in RIB".format(tc_name)
+
+        nh = [NEXT_HOP_IP["nh1"][addr_type]]
+        result = verify_rib(
+            tgen, addr_type, dut, rte1_nh1, next_hop=nh, protocol=protocol
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes is"
+        " missing in RIB".format(tc_name)
+
+        step("No shut nexthop interface N2")
+        shutdown_bringup_interface(tgen, dut, intf, True)
+
+        step(
+            "after shut of nexthop N1 , route become active "
+            "with nexthop N2 and vice versa."
+        )
+        rte1_nh1 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": NETWORK2[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "admin_distance": 10,
+                    }
+                ]
+            }
+        }
+        nh = [NEXT_HOP_IP["nh1"][addr_type]]
+        dut = "r2"
+        protocol = "static"
+        result = verify_rib(
+            tgen, addr_type, dut, rte1_nh1, next_hop=nh, protocol=protocol, fib=True
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes is"
+        "missing in RIB".format(tc_name)
+
+        rte2_nh2 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": NETWORK2[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh2"][addr_type],
+                        "admin_distance": 20,
+                    }
+                ]
+            }
+        }
+        nh = [NEXT_HOP_IP["nh2"][addr_type]]
+        dut = "r2"
+        protocol = "static"
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            rte2_nh2,
+            next_hop=nh,
+            protocol=protocol,
+            fib=True,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes is"
+        "not active in RIB".format(tc_name)
+
+        dut = "r3"
+        protocol = "bgp"
+
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            rte2_nh2,
+            next_hop=nh,
+            protocol=protocol,
+            fib=True,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes is"
+        "not active in RIB".format(tc_name)
+
+        dut = "r2"
+        step("Reload the FRR router")
+        # stop/start -> restart FRR router and verify
+        stop_router(tgen, "r2")
+        sleep(5)
+        start_router(tgen, "r2")
+
+        step(
+            "After reload of FRR router , static route installed"
+            " in RIB and FIB properly ."
+        )
+        rte1_nh1 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": NETWORK2[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "admin_distance": 10,
+                    }
+                ]
+            }
+        }
+        nh = [NEXT_HOP_IP["nh1"][addr_type]]
+        dut = "r2"
+        protocol = "static"
+        result = verify_rib(
+            tgen, addr_type, dut, rte1_nh1, next_hop=nh, protocol=protocol, fib=True
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes is"
+        "missing in RIB".format(tc_name)
+
+        dut = "r3"
+        protocol = "bgp"
+        result = verify_bgp_rib(tgen, addr_type, dut, rte1_nh1, next_hop=nh)
+        assert result is True, "Testcase {} : Failed \nError: Routes is"
+        "missing in RIB".format(tc_name)
+
+        rte2_nh2 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": NETWORK2[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh2"][addr_type],
+                        "admin_distance": 20,
+                    }
+                ]
+            }
+        }
+        nh = [NEXT_HOP_IP["nh2"][addr_type]]
+        dut = "r2"
+        protocol = "static"
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            rte2_nh2,
+            next_hop=nh,
+            protocol=protocol,
+            fib=True,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes is"
+        "not active in RIB".format(tc_name)
+
+        dut = "r3"
+        protocol = "bgp"
+        result = verify_bgp_rib(tgen, addr_type, dut, rte2_nh2, next_hop=nh)
+        assert result is True, "Testcase {} : Failed \nError: Routes is"
+        "not active in RIB".format(tc_name)
+
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            rte2_nh2,
+            next_hop=nh,
+            protocol=protocol,
+            fib=True,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes is"
+        "not active in RIB".format(tc_name)
+
+    write_test_footer(tc_name)
+
+
+"""
+def test_same_rte_from_bgp_static_P0_tc5(request):
+
+    #Verify RIB status when same route advertise via BGP and static
+    #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():
+        pytest.skip(tgen.errors)
+
+    NEXT_HOP_IP = populate_nh()
+    step('Configure iBGP IPv4 peering between R2 and R3 router.')
+    reset_config_on_routers(tgen)
+    step(
+        'Configure IPv4 static route (10.1.1.1/24) in R2 with next hop'
+        'N1 (28.1.1.2 ) and N2 (29.1.1.2) , Static route next-hop present'
+        'on R1')
+
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": NETWORK[addr_type],
+                        "next_hop": NEXT_HOP_IP['nh1'][addr_type]
+                    },
+                    {
+                        "network": NETWORK[addr_type],
+                        "next_hop": NEXT_HOP_IP['nh2'][addr_type]
+                    }
+                ]
+            }
+        }
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result)
+
+    step('Configure redistribute static in BGP.')
+    for addr_type in ADDR_TYPES:
+        input_dict_2 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {
+                                "redistribute": [{
+                                    "redist_type": "static"
+                                }]
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result)
+        step("Verify on R3 , route receive on R3 BGP table ")
+        dut = 'r3'
+        result = verify_bgp_rib(tgen, addr_type, dut, input_dict_4)
+        assert result is True, "Testcase {} : Failed \nError: Route is"
+        " still present in RIB".format(tc_name)
+
+        step("Verify route installed in the RIB and FIB of R3")
+        protocol = 'bgp'
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, protocol=protocol)
+        assert result is True, "Testcase {} : Failed \nError: Route is"
+        " still present in RIB".format(tc_name)
+
+    step(
+        'Configure 2 links/interfaces between R1 and R3 , keep one'
+        'interface in shut (active) state and other interface in no shut'
+        '(inactive) state')
+    dut = 'r3'
+    intf = topo['routers']['r3']['links']['r1-link0']['interface']
+    shutdown_bringup_interface(tgen, dut, intf, False)
+
+    step(
+        'Configure same static route (10.1.1.1/24) in R3 with inactive'
+        'nexthop interface')
+
+    step(
+        'Configure same static route 10.1.1.1/24) again in R3 with'
+        'active nexthop interface')
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {
+            "r3": {
+                "static_routes": [
+                    {
+                        "network": NETWORK[addr_type],
+                        "next_hop": topo['routers']['r1']['links']['r3-link0'][
+                            addr_type]
+                    },
+                    {
+                        "network": NETWORK[addr_type],
+                        "next_hop": topo['routers']['r1']['links']['r3-link1'][
+                            addr_type]
+                    }
+                ]
+            }
+        }
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result)
+
+        step(
+            "Verify when static route configure with inactive nexthop , "
+            "verify BGP received route is active in the RIB and FIB")
+        dut = 'r3'
+        result = verify_bgp_rib(tgen, addr_type, dut, input_dict_4)
+        assert result is True, "Testcase {} : Failed \nError: Route is"
+        " missing in BGP RIB".format(tc_name)
+
+        protocol = 'bgp'
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, protocol=protocol, fib=True)
+        assert result is True, "Testcase {} : Failed \nError: Route is"
+        " missing in RIB".format(tc_name)
+
+    step('Remove the redistribute static knob from R2 router')
+    for addr_type in ADDR_TYPES:
+        input_dict_2 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {
+                                "redistribute": [{
+                                    "redist_type": "static",
+                                    "delete": True
+                                }]
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result)
+
+        step(
+            "After removing /adding the redistribute static knob , "
+            "BGP received route is deleted and added in RIB of R3 ")
+        dut = 'r3'
+        result = verify_bgp_rib(tgen, addr_type, dut, input_dict_4)
+        assert result is not True, "Testcase {} : Failed \nError: Route is"
+        " still present in RIB".format(tc_name)
+
+        protocol = 'bgp'
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, protocol=protocol, fib=True)
+        assert result is not True, "Testcase {} : Failed \nError: Route is"
+        " still present in RIB".format(tc_name)
+
+    step('Configure the redistribute static knob again on R2 router')
+    for addr_type in ADDR_TYPES:
+        input_dict_2 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {
+                                "redistribute": [{
+                                    "redist_type": "static",
+                                }]
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result)
+        dut = 'r3'
+        result = verify_bgp_rib(tgen, addr_type, dut, input_dict_4)
+        assert result is True, "Testcase {} : Failed \nError: Route is"
+        " missing in BGP RIB".format(tc_name)
+
+        protocol = 'bgp'
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, protocol=protocol, fib=True)
+        assert result is True, "Testcase {} : Failed \nError: Route is"
+        " missing in RIB".format(tc_name)
+
+    step(
+        'Remove the static route on R3 configured with active'
+        'interface')
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {
+            "r3": {
+                "static_routes": [
+                    {
+                        "network": NETWORK[addr_type],
+                        "next_hop": topo['routers']['r1']['links']['r3-link0'][
+                            addr_type],
+                        "delete": True
+                    },
+                    {
+                        "network": NETWORK[addr_type],
+                        "next_hop": topo['routers']['r1']['links']['r3-link1'][
+                            addr_type],
+                        "delete": True
+                    }
+                ]
+            }
+        }
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result)
+        step(
+            "After removing the static route with active nexthop verify "
+            "BGP received route is became active in RIB and FIB")
+        dut = 'r3'
+        result = verify_bgp_rib(tgen, addr_type, dut, input_dict_4)
+        assert result is True, "Testcase {} : Failed \nError: Route is"
+        " missing in BGP RIB".format(tc_name)
+
+        protocol = 'bgp'
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, protocol=protocol, fib=True)
+        assert result is True, "Testcase {} : Failed \nError: Route is"
+        " missing in RIB".format(tc_name)
+
+    write_test_footer(tc_name)
+"""
+
+
+if __name__ == "__main__":
+    args = ["-s"] + sys.argv[1:]
+    sys.exit(pytest.main(args))
diff --git a/tests/topotests/static_routing_with_ibgp/test_static_routes_topo2_ibgp.py b/tests/topotests/static_routing_with_ibgp/test_static_routes_topo2_ibgp.py
new file mode 100644 (file)
index 0000000..0e051d6
--- /dev/null
@@ -0,0 +1,2357 @@
+#!/usr/bin/python
+
+#
+# Copyright (c) 2020 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.
+#
+
+
+"""
+    -Verify static route functionality with 8 next hop different AD value
+    and BGP ECMP
+
+    -Verify 8 static route functionality with 8 next hop different AD
+
+    -Verify static route with 8 next hop with different AD value and 8
+    EBGP neighbors
+
+    -Verify static route with 8 next hop with different AD value and 8
+    IBGP neighbors
+
+    -Delete the static route and verify the RIB and FIB state
+
+    -Verify 8 static route functionality with 8 ECMP next hop
+"""
+import sys
+import json
+import time
+import os
+import pytest
+import ipaddr
+from time import sleep
+from copy import deepcopy
+import random
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+sys.path.append(os.path.join(CWD, "../lib/"))
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from mininet.topo import Topo
+from lib.topogen import Topogen, get_topogen
+
+# Import 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,
+    check_address_types,
+    step,
+    create_interfaces_cfg,
+    shutdown_bringup_interface,
+    stop_router,
+    start_router,
+)
+from lib.topolog import logger
+from lib.bgp import verify_bgp_convergence, create_router_bgp, verify_bgp_rib
+from lib.topojson import build_topo_from_json, build_config_from_json
+
+# Reading the data from JSON File for topology creation
+jsonFile = "{}/static_routes_topo2_ibgp.json".format(CWD)
+try:
+    with open(jsonFile, "r") as topoJson:
+        topo = json.load(topoJson)
+except IOError:
+    assert False, "Could not read file {}".format(jsonFile)
+# Global variables
+BGP_CONVERGENCE = False
+ADDR_TYPES = check_address_types()
+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",
+        "11.0.20.6/32",
+        "11.0.20.7/32",
+        "11.0.20.8/32",
+    ],
+    "ipv6": [
+        "2::1/128",
+        "2::2/128",
+        "2::3/128",
+        "2::4/128",
+        "2::5/128",
+        "2::6/128",
+        "2::7/128",
+        "2::8/128",
+    ],
+}
+PREFIX1 = {"ipv4": "110.0.20.1/32", "ipv6": "20::1/128"}
+PREFIX2 = {"ipv4": "110.0.20.2/32", "ipv6": "20::2/128"}
+NEXT_HOP_IP = []
+topo_diag = """
+          Please view in a fixed-width font such as Courier.
+    +------+              +------+              +------+
+    |      +--------------+      +--------------+      |
+    |      |              |      |              |      |
+    |  R1  +---8 links----+ R2   +---8 links----+ R3   |
+    |      |              |      |              |      |
+    |      +--------------+      +--------------+      |
+    +------+              +------+              +------+
+
+"""
+
+
+class CreateTopo(Topo):
+    """
+    Test CreateTopo - topology 1.
+
+    * `Topo`: Topology object
+    """
+
+    def build(self, *_args, **_opts):
+        """Build function."""
+        tgen = get_topogen(self)
+
+        # Building topology from json file
+        build_topo_from_json(tgen, topo)
+
+
+def setup_module(mod):
+    """
+
+    Set up the pytest environment.
+
+    * `mod`: module name
+    """
+    global topo
+    testsuite_run_time = time.asctime(time.localtime(time.time()))
+    logger.info("Testsuite start time: {}".format(testsuite_run_time))
+    logger.info("=" * 40)
+
+    logger.info("Running setup_module to create topology")
+
+    # This function initiates the topology build with Topogen...
+    tgen = Topogen(CreateTopo, mod.__name__)
+    # ... and here it calls Mininet initialization functions.
+
+    # Starting topology, create tmp files which are loaded to routers
+    #  to start deamons and then start routers
+    start_topology(tgen)
+
+    # Creating configuration from JSON
+    build_config_from_json(tgen, topo)
+
+    # Checking BGP convergence
+    global BGP_CONVERGENCE
+    global ADDR_TYPES
+
+    # Don't run this test if we have any failure.
+    if tgen.routers_have_failure():
+        pytest.skip(tgen.errors)
+
+    # Api call verify whether BGP is converged
+    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo)
+    assert BGP_CONVERGENCE is True, "setup_module :Failed \n Error: {}".format(
+        BGP_CONVERGENCE
+    )
+
+    logger.info("Running setup_module() done")
+
+
+def teardown_module(mod):
+    """
+    Teardown the pytest environment
+
+    * `mod`: module name
+    """
+
+    logger.info("Running teardown_module to delete topology")
+
+    tgen = get_topogen()
+
+    # Stop toplogy and Remove tmp files
+    tgen.stop_topology()
+
+    logger.info(
+        "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
+    )
+    logger.info("=" * 40)
+
+
+def populate_nh():
+    NEXT_HOP_IP = {
+        "nh1": {
+            "ipv4": topo["routers"]["r1"]["links"]["r2-link0"]["ipv4"].split("/")[0],
+            "ipv6": topo["routers"]["r1"]["links"]["r2-link0"]["ipv6"].split("/")[0],
+        },
+        "nh2": {
+            "ipv4": topo["routers"]["r1"]["links"]["r2-link1"]["ipv4"].split("/")[0],
+            "ipv6": topo["routers"]["r1"]["links"]["r2-link1"]["ipv6"].split("/")[0],
+        },
+        "nh3": {
+            "ipv4": topo["routers"]["r1"]["links"]["r2-link2"]["ipv4"].split("/")[0],
+            "ipv6": topo["routers"]["r1"]["links"]["r2-link2"]["ipv6"].split("/")[0],
+        },
+        "nh4": {
+            "ipv4": topo["routers"]["r1"]["links"]["r2-link3"]["ipv4"].split("/")[0],
+            "ipv6": topo["routers"]["r1"]["links"]["r2-link3"]["ipv6"].split("/")[0],
+        },
+        "nh5": {
+            "ipv4": topo["routers"]["r1"]["links"]["r2-link4"]["ipv4"].split("/")[0],
+            "ipv6": topo["routers"]["r1"]["links"]["r2-link4"]["ipv6"].split("/")[0],
+        },
+        "nh6": {
+            "ipv4": topo["routers"]["r1"]["links"]["r2-link5"]["ipv4"].split("/")[0],
+            "ipv6": topo["routers"]["r1"]["links"]["r2-link5"]["ipv6"].split("/")[0],
+        },
+        "nh7": {
+            "ipv4": topo["routers"]["r1"]["links"]["r2-link6"]["ipv4"].split("/")[0],
+            "ipv6": topo["routers"]["r1"]["links"]["r2-link6"]["ipv6"].split("/")[0],
+        },
+        "nh8": {
+            "ipv4": topo["routers"]["r1"]["links"]["r2-link7"]["ipv4"].split("/")[0],
+            "ipv6": topo["routers"]["r1"]["links"]["r2-link7"]["ipv6"].split("/")[0],
+        },
+    }
+    return NEXT_HOP_IP
+
+
+#####################################################
+#
+#   Tests starting
+#
+#####################################################
+
+
+def test_static_rte_with_8ecmp_nh_p1_tc9_ibgp(request):
+    """
+    Verify 8 static route functionality with 8 ECMP next hop
+
+    """
+    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)
+    NEXT_HOP_IP = populate_nh()
+    step("Configure 8 interfaces / links between R1 and R2")
+    step("Configure 8 interfaces / links between R2 and R3")
+    step("Configure 8 IBGP IPv4 peering between R2 and R3 router.")
+    reset_config_on_routers(tgen)
+
+    step(
+        "Configure 8 IPv4 static route in R2 with 8 next hop"
+        "N1(21.1.1.2) , N2(22.1.1.2) , N3(23.1.1.2) , N4(24.1.1.2) ,"
+        "N5(25.1.1.2) , N6(26.1.1.2) , N7(27.1.1.2) , N8(28.1.1.2) ,"
+        "Static route next-hop present on R1"
+    )
+    nh_all = {}
+    for addr_type in ADDR_TYPES:
+        # Enable static routes
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                        }
+                    ]
+                }
+            }
+            logger.info("Configure static routes")
+            result = create_static_routes(tgen, input_dict_4)
+            assert result is True, "Testcase {} : Failed \n Error: {}".format(
+                tc_name, result
+            )
+        logger.info("Verifying %s routes on r2", addr_type)
+        nh_all[addr_type] = [
+            NEXT_HOP_IP["nh1"][addr_type],
+            NEXT_HOP_IP["nh2"][addr_type],
+            NEXT_HOP_IP["nh3"][addr_type],
+            NEXT_HOP_IP["nh4"][addr_type],
+            NEXT_HOP_IP["nh5"][addr_type],
+            NEXT_HOP_IP["nh6"][addr_type],
+            NEXT_HOP_IP["nh7"][addr_type],
+            NEXT_HOP_IP["nh8"][addr_type],
+        ]
+
+        dut = "r2"
+        protocol = "static"
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh_all[addr_type],
+            protocol=protocol,
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes are"
+        " missing in RIB".format(tc_name)
+
+    step("Configure redistribute static in BGP on R2 router")
+    for addr_type in ADDR_TYPES:
+        input_dict_2 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {"redistribute": [{"redist_type": "static"}]}
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        dut = "r3"
+        protocol = "bgp"
+        result = verify_bgp_rib(tgen, addr_type, dut, input_dict_4)
+        assert result is True, "Testcase {} : Failed \nError: Routes are"
+        " missing in RIB".format(tc_name)
+
+    step(
+        "Remove the static route configured with nexthop N1 to N8, one"
+        "by one from running config"
+    )
+    dut = "r2"
+    protocol = "static"
+    step(
+        "After removing the static route with N1 to N8 one by one , "
+        "verify that entry is removed from RIB and FIB of R3 "
+    )
+    for addr_type in ADDR_TYPES:
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                            "delete": True,
+                        }
+                    ]
+                }
+            }
+            logger.info("Configure static routes")
+            result = create_static_routes(tgen, input_dict_4)
+            assert result is True, "Testcase {} : Failed \n Error: {}".format(
+                tc_name, result
+            )
+
+            step(
+                "After removing the static route with N1 to N8 one by one , "
+                "verify that entry is removed from RIB and FIB of R3 "
+            )
+            nh = NEXT_HOP_IP["nh" + str(nhp)][addr_type]
+            result = verify_rib(
+                tgen,
+                addr_type,
+                dut,
+                input_dict_4,
+                next_hop=nh,
+                protocol=protocol,
+                expected=False,
+            )
+            assert result is not True, "Testcase {} : Failed\nError: Routes is"
+            " still present in RIB".format(tc_name)
+
+    step("Configure the static route with nexthop N1 to N8, one by one")
+    for addr_type in ADDR_TYPES:
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                        }
+                    ]
+                }
+            }
+            logger.info("Configure static routes")
+            result = create_static_routes(tgen, input_dict_4)
+            assert result is True, "Testcase {} : Failed \n Error: {}".format(
+                tc_name, result
+            )
+
+            nh = NEXT_HOP_IP["nh" + str(nhp)][addr_type]
+            result = verify_rib(
+                tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol
+            )
+            assert result is True, "Testcase {} : Failed\nError: Routes are"
+            " missing in RIB".format(tc_name)
+
+    dut = "r2"
+    protocol = "static"
+    step("Shut nexthop interfaces N1 to N8 one by one")
+    for intfr in range(0, 3):
+        intf = topo["routers"]["r2"]["links"]["r1-link{}".format(intfr)]["interface"]
+        shutdown_bringup_interface(tgen, dut, intf, False)
+        for addr_type in ADDR_TYPES:
+            nhp = intfr + 1
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                        }
+                    ]
+                }
+            }
+            nh = NEXT_HOP_IP["nh" + str(nhp)][addr_type]
+            result = verify_rib(
+                tgen,
+                addr_type,
+                dut,
+                input_dict_4,
+                next_hop=nh,
+                protocol=protocol,
+                expected=False,
+            )
+            assert result is not True, "Testcase {}: Failed\nError: Routes are"
+            " still present in RIB".format(tc_name)
+
+    step("No shut the nexthop interfaces N1 to N8 one by one .")
+    for intfr in range(0, 3):
+        intf = topo["routers"]["r2"]["links"]["r1-link{}".format(intfr)]["interface"]
+        shutdown_bringup_interface(tgen, dut, intf, True)
+        for addr_type in ADDR_TYPES:
+            nhp = intfr + 1
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                        }
+                    ]
+                }
+            }
+            nh = NEXT_HOP_IP["nh" + str(nhp)][addr_type]
+            result = verify_rib(
+                tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol
+            )
+            assert result is True, "Testcase {} : Failed \nError: Routes are"
+            " missing in RIB".format(tc_name)
+
+    step("Random shut of the nexthop interfaces")
+    randnum = random.randint(0, 7)
+    # Shutdown interface
+    dut = "r2"
+    step(
+        " interface which is about to be shut no shut between r1 and r2 is " "%s",
+        topo["routers"]["r2"]["links"]["r1-link{}".format(randnum)]["interface"],
+    )
+    intf = topo["routers"]["r2"]["links"]["r1-link{}".format(randnum)]["interface"]
+    shutdown_bringup_interface(tgen, dut, intf, False)
+
+    sleep(5)
+
+    step("Random no shut of the nexthop interfaces")
+    # Bringup interface
+    shutdown_bringup_interface(tgen, dut, intf, True)
+
+    step(
+        "After random shut/no shut of nexthop , only that "
+        "nexthop deleted/added from all the routes , other nexthop remain "
+        "unchanged"
+    )
+    dut = "r2"
+    protocol = "static"
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                    }
+                ]
+            }
+        }
+    result = verify_rib(
+        tgen,
+        addr_type,
+        dut,
+        input_dict_4,
+        next_hop=nh_all[addr_type],
+        protocol=protocol,
+    )
+    assert result is True, "Testcase {} : Failed \nError: Routes are"
+    " missing in RIB".format(tc_name)
+
+    step("Remove random static route with all the nexthop")
+    dut = "r2"
+    randnum = random.randint(1, 7)
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh" + str(randnum)][addr_type],
+                        "delete": True,
+                    }
+                ]
+            }
+        }
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step(
+            "After delete of random route , that route only got deleted from"
+            " RIB/FIB other route are showing properly"
+        )
+        nh = NEXT_HOP_IP["nh{}".format(randnum)][addr_type]
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes are"
+        " missing in RIB".format(tc_name)
+
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh" + str(randnum)][addr_type],
+                    }
+                ]
+            }
+        }
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step("Reload the FRR router")
+    # stop/start -> restart FRR router and verify
+    stop_router(tgen, "r2")
+    sleep(5)
+    start_router(tgen, "r2")
+
+    step(
+        "After reload of FRR router , static route "
+        "installed in RIB and FIB properly ."
+    )
+    for addr_type in ADDR_TYPES:
+        # Enable static routes
+        nhp = 1
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                    }
+                ]
+            }
+        }
+        logger.info("Verifying %s routes on r2", addr_type)
+        dut = "r2"
+        protocol = "static"
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh_all[addr_type],
+            protocol=protocol,
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes are"
+        " missing in RIB".format(tc_name)
+
+    step(
+        "Remove and add the IBGP nbrs using interface shut and"
+        "deactivate/activate from address family"
+    )
+
+    for intfr in range(0, 8):
+        intf = topo["routers"]["r2"]["links"]["r3-link{}".format(intfr)]["interface"]
+        shutdown_bringup_interface(tgen, dut, intf, False)
+
+    sleep(200)
+
+    step("verify bgp convergence as all interface are shut")
+
+    bgp_convergence = verify_bgp_convergence(tgen, topo)
+    assert bgp_convergence is not True, "Testcase {} : Failed"
+    " \n Error: {}".format(tc_name, bgp_convergence)
+
+    dut = "r3"
+    protocol = "static"
+    for addr_type in ADDR_TYPES:
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                        }
+                    ]
+                }
+            }
+        nh = NEXT_HOP_IP["nh" + str(nhp)][addr_type]
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes are"
+        " still present in RIB".format(tc_name)
+    dut = "r2"
+    for intfr in range(0, 8):
+        intf = topo["routers"]["r2"]["links"]["r3-link{}".format(intfr)]["interface"]
+        shutdown_bringup_interface(tgen, dut, intf, True)
+
+    step("verify bgp convergence as all interface are un shut")
+    bgp_convergence = verify_bgp_convergence(tgen, topo)
+    assert bgp_convergence is True, "Testcase {} :"
+    " Failed \n Error:  {}".format(tc_name, bgp_convergence)
+
+    step("Remove the redistribute static knob")
+    for addr_type in ADDR_TYPES:
+        input_dict_2 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {
+                                "redistribute": [
+                                    {"redist_type": "static", "delete": True}
+                                ]
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step(
+            "After removing the BGP neighbor or redistribute static knob , "
+            "verify route got clear from RIB and FIB of R3 routes "
+        )
+        dut = "r3"
+        protocol = "bgp"
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, protocol=protocol, expected=False
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes are"
+        " still present in RIB".format(tc_name)
+
+    write_test_footer(tc_name)
+
+
+def test_static_route_8nh_diff_AD_bgp_ecmp_p1_tc6_ibgp(request):
+    """
+    Verify static route functionality with 8 next hop different AD
+    value and BGP ECMP
+
+    """
+    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)
+
+    step("Configure 8 interfaces / links between R1 and R2 ,")
+    step("Configure 8 interlaces/links between R2 and R3")
+    step(
+        "Configure IBGP IPv4 peering over loopback interface between"
+        "R2 and R3 router."
+    )
+    step("Configure redistribute static in BGP on R2 router")
+    reset_config_on_routers(tgen)
+    NEXT_HOP_IP = populate_nh()
+    nh_all = {}
+    for addr_type in ADDR_TYPES:
+        nh_all[addr_type] = []
+        for nhp in range(1, 9):
+            nh_all[addr_type].append(NEXT_HOP_IP["nh" + str(nhp)][addr_type])
+    step(
+        "Configure IPv4 static route in R2 with 8 next hop"
+        "N1(21.1.1.2) AD 10, N2(22.1.1.2) AD 20, N3(23.1.1.2) AD 30,"
+        "N4(24.1.1.2) AD 40, N5(25.1.1.2) AD 50, N6(26.1.1.2) AD 60,"
+        "N7(27.1.1.2) AD 70, N8(28.1.1.2) AD 80, Static route next-hop"
+        "present on R1"
+    )
+    for addr_type in ADDR_TYPES:
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                            "admin_distance": 10 * nhp,
+                        }
+                    ]
+                }
+            }
+            logger.info("Configure static routes")
+            result = create_static_routes(tgen, input_dict_4)
+            assert result is True, "Testcase {} : Failed \n Error: {}".format(
+                tc_name, result
+            )
+        logger.info("Verifying %s routes on r2", addr_type)
+
+        step(
+            "On R2, static route installed in RIB using "
+            "show ip route with 8 next hop , lowest AD nexthop is active"
+        )
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "admin_distance": 10,
+                    }
+                ]
+            }
+        }
+        dut = "r2"
+        protocol = "static"
+        nh = NEXT_HOP_IP["nh1"][addr_type]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol, fib=True
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes are"
+        " missing in RIB".format(tc_name)
+
+        nh = []
+        for nhp in range(2, 9):
+            nh.append(NEXT_HOP_IP["nh" + str(nhp)][addr_type])
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            fib=True,
+            expected=False,
+            wait=2,
+            attempts=3,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes "
+        " are missing in RIB".format(tc_name)
+
+    step(
+        "Remove the static route configured with nexthop N1 to N8, one"
+        "by one from running config"
+    )
+
+    for addr_type in ADDR_TYPES:
+        # delete static routes
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                            "admin_distance": 10 * nhp,
+                            "delete": True,
+                        }
+                    ]
+                }
+            }
+
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step(
+        "After removing the static route with N1 to N8 one by one , "
+        "route become active with next preferred nexthop and nexthop which "
+        "got removed is not shown in RIB and FIB"
+    )
+    result = verify_rib(
+        tgen,
+        addr_type,
+        dut,
+        input_dict_4,
+        next_hop=nh_all[addr_type],
+        protocol=protocol,
+        expected=False,
+    )
+    assert result is not True, "Testcase {} : Failed \nError: Routes are"
+    " still present in RIB".format(tc_name)
+
+    step("Configure the static route with nexthop N1 to N8, one by one")
+
+    for addr_type in ADDR_TYPES:
+        # add static routes
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                            "admin_distance": 10 * nhp,
+                        }
+                    ]
+                }
+            }
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step(
+        " After configuring them, route is always active with lowest AD"
+        " value and all the nexthop populated in RIB and FIB again"
+    )
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "admin_distance": 10,
+                    }
+                ]
+            }
+        }
+        dut = "r2"
+        protocol = "static"
+        nh = NEXT_HOP_IP["nh1"][addr_type]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol, fib=True
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes are"
+        " missing in RIB".format(tc_name)
+        nh = []
+        for nhp in range(2, 9):
+            nh.append(NEXT_HOP_IP["nh" + str(nhp)][addr_type])
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            fib=True,
+            expected=False,
+            wait=2,
+            attempts=3,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes "
+        " are missing in RIB".format(tc_name)
+
+    step("Shut nexthop interfaces N1 to N8 one by one")
+    for addr_type in ADDR_TYPES:
+        for nhp in range(0, 8):
+            intf = topo["routers"]["r2"]["links"]["r1-link" + str(nhp)]["interface"]
+            shutdown_bringup_interface(tgen, dut, intf, False)
+
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh_all[addr_type],
+            protocol=protocol,
+            fib=True,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes "
+        " are still present in RIB".format(tc_name)
+
+    step("No shut the nexthop interfaces N1 to N3 one by one .")
+    for addr_type in ADDR_TYPES:
+        for nhp in range(0, 3):
+            intf = topo["routers"]["r2"]["links"]["r1-link" + str(nhp)]["interface"]
+            shutdown_bringup_interface(tgen, dut, intf, True)
+
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "admin_distance": 10,
+                    }
+                ]
+            }
+        }
+        dut = "r2"
+        protocol = "static"
+        nh = NEXT_HOP_IP["nh1"][addr_type]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol, fib=True
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes are"
+        " missing in RIB".format(tc_name)
+
+        nh = []
+        for nhp in range(2, 9):
+            nh.append(NEXT_HOP_IP["nh" + str(nhp)][addr_type])
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            fib=True,
+            expected=False,
+            wait=2,
+            attempts=3,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes "
+        " are missing in RIB".format(tc_name)
+
+    step("Random shut of the nexthop interfaces")
+    randnum = random.randint(0, 7)
+    for addr_type in ADDR_TYPES:
+        intf = topo["routers"]["r2"]["links"]["r1-link" + str(randnum)]["interface"]
+        shutdown_bringup_interface(tgen, dut, intf, False)
+        nhip = NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type]
+        input_dict_5 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type],
+                    }
+                ]
+            }
+        }
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_5,
+            next_hop=nhip,
+            protocol=protocol,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \n"
+        "Error: Routes are still present in RIB".format(tc_name)
+
+    step("Random no shut of the nexthop interfaces")
+    for addr_type in ADDR_TYPES:
+        intf = topo["routers"]["r2"]["links"]["r1-link" + str(randnum)]["interface"]
+        shutdown_bringup_interface(tgen, dut, intf, True)
+        nhip = NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_5, next_hop=nhip, protocol=protocol
+        )
+        assert result is True, "Testcase {} : Failed \n"
+        "Error: Routes are missing in RIB".format(tc_name)
+
+    dut = "r2"
+    step("Shut the interfaces connected between R2 and R3 one by one")
+    for nhp in range(0, 3):
+        intf = topo["routers"]["r2"]["links"]["r3-link" + str(nhp)]["interface"]
+        shutdown_bringup_interface(tgen, dut, intf, False)
+
+    protocol = "bgp"
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type]}]}}
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, protocol=protocol, expected=False
+        )
+        assert result is not True, "Testcase {} : Failed \n"
+        "Error: Routes are still present in RIB".format(tc_name)
+
+    step("No shut the interfaces between R2 and R3 one by one")
+    dut = "r2"
+    for nhp in range(0, 3):
+        intf = topo["routers"]["r2"]["links"]["r3-link" + str(nhp)]["interface"]
+        shutdown_bringup_interface(tgen, dut, intf, True)
+
+    # this is next hop reachability route  in r3 as we are using ibgp
+    dut = "r3"
+    for addr_type in ADDR_TYPES:
+        nh_as_rte = NEXT_HOP_IP["nh1"][addr_type] + "/32"
+        # add static routes
+        nh_static_rte = {
+            "r3": {"static_routes": [{"network": nh_as_rte, "next_hop": "Null0"}]}
+        }
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, nh_static_rte)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step(
+        "After each interface shut and no shut between R2 -R3 ,verify static"
+        "route is present in the RIB & FIB of R3 & R2 RIB/FIB is remain"
+        " unchanged"
+    )
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type]}]}}
+        result = verify_rib(tgen, addr_type, dut, input_dict_4, protocol=protocol)
+        assert result is True, "Testcase {} : Failed \n"
+        "Error: Routes are missing in RIB".format(tc_name)
+
+    protocol = "static"
+    dut = "r2"
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type]}]}}
+        result = verify_rib(tgen, addr_type, dut, input_dict_4, protocol=protocol)
+        assert (
+            result is True
+        ), "Testcase {}: Failed \n " "Error: Routes are missing in RIB".format(tc_name)
+
+    protocol = "bgp"
+    dut = "r3"
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type]}]}}
+        result = verify_rib(tgen, addr_type, dut, input_dict_4, protocol=protocol)
+        assert (
+            result is True
+        ), "Testcase {}: Failed \n " "Error: Routes are missing in RIB".format(tc_name)
+
+    step("Reload the FRR router")
+    # stop/start -> restart FRR router and verify
+    stop_router(tgen, "r2")
+    sleep(5)
+    start_router(tgen, "r2")
+
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type]}]}}
+        result = verify_rib(tgen, addr_type, dut, input_dict_4, protocol=protocol)
+        assert result is True, (
+            "Testcase {} : Failed \n"
+            "Error: Routes are still present in RIB".format(tc_name)
+        )
+
+    step("BGP neighbor remove and add")
+    for rtr in ["r2", "r3"]:
+        if "bgp" in topo["routers"][rtr].keys():
+            delete_bgp = {rtr: {"bgp": {"delete": True}}}
+            result = create_router_bgp(tgen, topo, delete_bgp)
+            assert result is True, "Testcase {} : Failed \n Error: {}".format(
+                tc_name, result
+            )
+
+    create_router_bgp(tgen, topo["routers"])
+
+    NEXT_HOP_IP = populate_nh()
+    step("Verify routes are still present after delete and add bgp")
+    dut = "r2"
+    protocol = "static"
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type]}]}}
+        result = verify_rib(tgen, addr_type, dut, input_dict_4, protocol=protocol)
+        assert result is True, (
+            "Testcase {} : Failed \n"
+            "Error: Routes are still present in RIB".format(tc_name)
+        )
+
+    dut = "r3"
+    protocol = "bgp"
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type]}]}}
+        result = verify_rib(tgen, addr_type, dut, input_dict_4, protocol=protocol)
+        assert result is True, (
+            "Testcase {} : Failed \n"
+            "Error: Routes are still present in RIB".format(tc_name)
+        )
+
+    step("Remove the redistribute static knob")
+    for addr_type in ADDR_TYPES:
+        input_dict_2 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {
+                                "redistribute": [
+                                    {"redist_type": "static", "delete": True}
+                                ]
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        logger.info("Remove redistribute static")
+        result = create_router_bgp(tgen, topo, input_dict_2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+        step("verify that routes are deleted from R3 routing table")
+
+        dut = "r3"
+        protocol = "bgp"
+        input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type]}]}}
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes are"
+        " strill present in RIB of R3".format(tc_name)
+
+    write_test_footer(tc_name)
+
+
+def test_static_route_8nh_diff_AD_ibgp_ecmp_p1_tc7_ibgp(request):
+    """
+    Verify static route with 8 next hop with different AD value and 8
+    IBGP neighbors
+    """
+    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)
+
+    step("Configure 8 interfaces / links between R1 and R2")
+    step("Configure 8 interlaces/links between R2 and R3")
+    step("Configure 8 IBGP IPv4 peering between R2 and R3")
+
+    reset_config_on_routers(tgen)
+    NEXT_HOP_IP = populate_nh()
+
+    step("Configure redistribute static in BGP on R2 router")
+    for addr_type in ADDR_TYPES:
+        input_dict_2 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {"redistribute": [{"redist_type": "static"}]}
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step(
+        "Configure IPv4 static route in R2 with 8 next hop"
+        "N1(21.1.1.2) AD 10, N2(22.1.1.2) AD 20, N3(23.1.1.2) AD 30,"
+        "N4(24.1.1.2) AD 40, N5(25.1.1.2) AD 50, N6(26.1.1.2) AD 60,"
+        "N7(27.1.1.2) AD 70, N8(28.1.1.2) AD 80, Static route next-hop"
+        "present on R1"
+    )
+    nh_all = {}
+    for addr_type in ADDR_TYPES:
+        nh_all[addr_type] = []
+        for nhp in range(1, 9):
+            nh_all[addr_type].append(NEXT_HOP_IP["nh" + str(nhp)][addr_type])
+    for addr_type in ADDR_TYPES:
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                            "admin_distance": 10 * nhp,
+                        }
+                    ]
+                }
+            }
+            logger.info("Configure static routes")
+            result = create_static_routes(tgen, input_dict_4)
+            assert result is True, "Testcase {} : Failed \n Error: {}".format(
+                tc_name, result
+            )
+        logger.info("Verifying %s routes on r2", addr_type)
+
+        step(
+            "On R2, static route installed in RIB using "
+            "show ip route with 8 next hop , lowest AD nexthop is active"
+        )
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "admin_distance": 10,
+                    }
+                ]
+            }
+        }
+        dut = "r2"
+        protocol = "static"
+        nh = NEXT_HOP_IP["nh1"][addr_type]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol, fib=True
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes are"
+        " missing in RIB".format(tc_name)
+
+        nh = []
+        for nhp in range(2, 9):
+            nh.append(NEXT_HOP_IP["nh" + str(nhp)][addr_type])
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            fib=True,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes "
+        " are missing in RIB".format(tc_name)
+
+    step(
+        "Remove the static route configured with nexthop N1 to N8, one"
+        "by one from running config"
+    )
+
+    for addr_type in ADDR_TYPES:
+        # delete static routes
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                            "admin_distance": 10 * nhp,
+                            "delete": True,
+                        }
+                    ]
+                }
+            }
+
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step(
+        "After removing the static route with N1 to N8 one by one , "
+        "route become active with next preferred nexthop and nexthop which "
+        "got removed is not shown in RIB and FIB"
+    )
+    result = verify_rib(
+        tgen,
+        addr_type,
+        dut,
+        input_dict_4,
+        next_hop=nh_all[addr_type],
+        protocol=protocol,
+        expected=False,
+    )
+    assert result is not True, "Testcase {} : Failed \nError: Routes are"
+    " still present in RIB".format(tc_name)
+
+    step("Configure the static route with nexthop N1 to N8, one by one")
+
+    for addr_type in ADDR_TYPES:
+        # add static routes
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                            "admin_distance": 10 * nhp,
+                        }
+                    ]
+                }
+            }
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step(
+        " After configuring them, route is always active with lowest AD"
+        " value and all the nexthop populated in RIB and FIB again"
+    )
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "admin_distance": 10,
+                    }
+                ]
+            }
+        }
+        dut = "r2"
+        protocol = "static"
+        nh = NEXT_HOP_IP["nh1"][addr_type]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol, fib=True
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes are"
+        " missing in RIB".format(tc_name)
+        nh = []
+        for nhp in range(2, 9):
+            nh.append(NEXT_HOP_IP["nh" + str(nhp)][addr_type])
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            fib=True,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes "
+        " are missing in RIB".format(tc_name)
+
+    step("Shut nexthop interfaces N1 to N8 one by one")
+    for addr_type in ADDR_TYPES:
+        for nhp in range(0, 8):
+            intf = topo["routers"]["r2"]["links"]["r1-link" + str(nhp)]["interface"]
+            shutdown_bringup_interface(tgen, dut, intf, False)
+
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh_all[addr_type],
+            protocol=protocol,
+            fib=True,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes "
+        " are still present in RIB".format(tc_name)
+
+    step("No shut the nexthop interfaces N1 to N8 one by one .")
+    for addr_type in ADDR_TYPES:
+        for nhp in range(0, 8):
+            intf = topo["routers"]["r2"]["links"]["r1-link" + str(nhp)]["interface"]
+            shutdown_bringup_interface(tgen, dut, intf, True)
+
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "admin_distance": 10,
+                    }
+                ]
+            }
+        }
+        dut = "r2"
+        protocol = "static"
+        nh = NEXT_HOP_IP["nh1"][addr_type]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol, fib=True
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes are"
+        " missing in RIB".format(tc_name)
+
+        nh = []
+        for nhp in range(2, 9):
+            nh.append(NEXT_HOP_IP["nh" + str(nhp)][addr_type])
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            fib=True,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes "
+        " are missing in RIB".format(tc_name)
+
+    step("Random shut of the nexthop interfaces")
+    randnum = random.randint(0, 7)
+    for addr_type in ADDR_TYPES:
+        intf = topo["routers"]["r2"]["links"]["r1-link" + str(randnum)]["interface"]
+        shutdown_bringup_interface(tgen, dut, intf, False)
+        nhip = NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type]
+        input_dict_5 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type],
+                    }
+                ]
+            }
+        }
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_5,
+            next_hop=nhip,
+            protocol=protocol,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \n"
+        "Error: Routes are still present in RIB".format(tc_name)
+
+    step("Random no shut of the nexthop interfaces")
+    for addr_type in ADDR_TYPES:
+        intf = topo["routers"]["r2"]["links"]["r1-link" + str(randnum)]["interface"]
+        shutdown_bringup_interface(tgen, dut, intf, True)
+        nhip = NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_5, next_hop=nhip, protocol=protocol
+        )
+        assert result is True, "Testcase {} : Failed \n"
+        "Error: Routes are missing in RIB".format(tc_name)
+
+    dut = "r2"
+    step("Shut the interfaces connected between R2 and R3 one by one")
+    for nhp in range(0, 3):
+        intf = topo["routers"]["r2"]["links"]["r3-link" + str(nhp)]["interface"]
+        shutdown_bringup_interface(tgen, dut, intf, False)
+
+    protocol = "bgp"
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type]}]}}
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, protocol=protocol, expected=False
+        )
+        assert result is not True, "Testcase {} : Failed \n"
+        "Error: Routes are still present in RIB".format(tc_name)
+
+    step("No shut the interfaces between R2 and R3 one by one")
+    dut = "r2"
+    for nhp in range(0, 3):
+        intf = topo["routers"]["r2"]["links"]["r3-link" + str(nhp)]["interface"]
+        shutdown_bringup_interface(tgen, dut, intf, True)
+
+    # this is next hop reachability route  in r3 as we are using ibgp
+    dut = "r3"
+    for addr_type in ADDR_TYPES:
+        nh_as_rte = NEXT_HOP_IP["nh1"][addr_type] + "/32"
+        # add static routes
+        nh_static_rte = {
+            "r3": {"static_routes": [{"network": nh_as_rte, "next_hop": "Null0"}]}
+        }
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, nh_static_rte)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step(
+        "After each interface shut and no shut between R2 -R3 ,verify static"
+        "route is present in the RIB & FIB of R3 & R2 RIB/FIB is remain"
+        " unchanged"
+    )
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type]}]}}
+        result = verify_rib(tgen, addr_type, dut, input_dict_4, protocol=protocol)
+        assert result is True, "Testcase {} : Failed \n"
+        "Error: Routes are missing in RIB".format(tc_name)
+
+    protocol = "static"
+    dut = "r2"
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type]}]}}
+        result = verify_rib(tgen, addr_type, dut, input_dict_4, protocol=protocol)
+        assert (
+            result is True
+        ), "Testcase {}: Failed \n " "Error: Routes are missing in RIB".format(tc_name)
+
+    protocol = "bgp"
+    dut = "r3"
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type]}]}}
+        result = verify_rib(tgen, addr_type, dut, input_dict_4, protocol=protocol)
+        assert (
+            result is True
+        ), "Testcase {}: Failed \n " "Error: Routes are missing in RIB".format(tc_name)
+
+    step("Reload the FRR router")
+    # stop/start -> restart FRR router and verify
+    stop_router(tgen, "r2")
+    sleep(5)
+    start_router(tgen, "r2")
+
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type]}]}}
+        result = verify_rib(tgen, addr_type, dut, input_dict_4, protocol=protocol)
+        assert result is True, (
+            "Testcase {} : Failed \n"
+            "Error: Routes are still present in RIB".format(tc_name)
+        )
+
+    step("BGP neighbor remove and add")
+    for rtr in ["r2", "r3"]:
+        if "bgp" in topo["routers"][rtr].keys():
+            delete_bgp = {rtr: {"bgp": {"delete": True}}}
+            result = create_router_bgp(tgen, topo, delete_bgp)
+            assert result is True, "Testcase {} : Failed \n Error: {}".format(
+                tc_name, result
+            )
+
+    create_router_bgp(tgen, topo["routers"])
+
+    NEXT_HOP_IP = populate_nh()
+    step("Verify routes are still present after delete and add bgp")
+    dut = "r2"
+    protocol = "static"
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type]}]}}
+        result = verify_rib(tgen, addr_type, dut, input_dict_4, protocol=protocol)
+        assert result is True, (
+            "Testcase {} : Failed \n"
+            "Error: Routes are still present in RIB".format(tc_name)
+        )
+
+    dut = "r3"
+    protocol = "bgp"
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type]}]}}
+        result = verify_rib(tgen, addr_type, dut, input_dict_4, protocol=protocol)
+        assert result is True, (
+            "Testcase {} : Failed \n"
+            "Error: Routes are still present in RIB".format(tc_name)
+        )
+
+    step("Remove the redistribute static knob")
+    for addr_type in ADDR_TYPES:
+        input_dict_2 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {
+                                "redistribute": [
+                                    {"redist_type": "static", "delete": True}
+                                ]
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        logger.info("Remove redistribute static")
+        result = create_router_bgp(tgen, topo, input_dict_2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+        step("verify that routes are deleted from R3 routing table")
+
+        dut = "r3"
+        protocol = "bgp"
+        input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type]}]}}
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes are"
+        " still present in RIB of R3".format(tc_name)
+
+    write_test_footer(tc_name)
+
+
+def test_static_route_8nh_diff_AD_bgp_ecmp_p1_tc10_ibgp(request):
+    """
+    Verify 8 static route functionality with 8 next hop different AD'
+
+    """
+    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)
+    NEXT_HOP_IP = populate_nh()
+
+    step("Configure 8 interfaces / links between R1 and R2 ")
+    step("Configure 8 IBGP IPv4 peering between R2 and R3 router.")
+    reset_config_on_routers(tgen)
+
+    step(
+        "Configure IPv4 static route in R2 with 8 next hop"
+        "N1(21.1.1.2) AD 10, N2(22.1.1.2) AD 20, N3(23.1.1.2) AD 30,"
+        "N4(24.1.1.2) AD 40, N5(25.1.1.2) AD 50, N6(26.1.1.2) AD 60,"
+        "N7(27.1.1.2) AD 70, N8(28.1.1.2) AD 80"
+    )
+    step(
+        "Configure nexthop AD in such way for static route S1 , N1 is"
+        "preferred and for S2 , N2 is preferred and so on .."
+    )
+    nh_all = {}
+    for addr_type in ADDR_TYPES:
+        nh_all[addr_type] = []
+        for nhp in range(1, 9):
+            nh_all[addr_type].append(NEXT_HOP_IP["nh" + str(nhp)][addr_type])
+
+    for addr_type in ADDR_TYPES:
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                            "admin_distance": 10 * nhp,
+                        }
+                    ]
+                }
+            }
+            logger.info("Configure static routes")
+            result = create_static_routes(tgen, input_dict_4)
+            assert result is True, "Testcase {} : Failed \n Error: {}".format(
+                tc_name, result
+            )
+            second_rte = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX2[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                            "admin_distance": 10 * nhp,
+                        }
+                    ]
+                }
+            }
+            logger.info("Configure static routes")
+            result = create_static_routes(tgen, second_rte)
+            assert result is True, "Testcase {} : Failed \n Error: {}".format(
+                tc_name, result
+            )
+        logger.info("Verifying %s routes on r2", addr_type)
+
+        step(
+            "On R2, static route installed in RIB using "
+            "show ip route with 8 next hop , lowest AD nexthop is active"
+        )
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "admin_distance": 10,
+                    }
+                ]
+            }
+        }
+        dut = "r2"
+        protocol = "static"
+        nh = NEXT_HOP_IP["nh1"][addr_type]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol, fib=True
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes are"
+        " missing in RIB".format(tc_name)
+
+        step("Verify that highest AD nexthop are inactive")
+        nh = []
+        for nhp in range(2, 9):
+            nh.append(NEXT_HOP_IP["nh" + str(nhp)][addr_type])
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            fib=True,
+            expected=False,
+            wait=2,
+            attempts=3,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes "
+        " are missing in RIB".format(tc_name)
+
+    step("Configure redistribute static in BGP on R2 router")
+    for addr_type in ADDR_TYPES:
+        input_dict_2 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {"redistribute": [{"redist_type": "static"}]}
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step(
+        "Remove the static route configured with nexthop N1 to N8, one"
+        "by one from running config"
+    )
+
+    for addr_type in ADDR_TYPES:
+        # delete static routes
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                            "admin_distance": 10 * nhp,
+                            "delete": True,
+                        }
+                    ]
+                }
+            }
+
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step(
+            "After removing the static route with N1 to N8 one by one , "
+            "route become active with next preferred nexthop and nexthop which"
+            "got removed is not shown in RIB and FIB"
+        )
+
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes are"
+        " still present in RIB".format(tc_name)
+
+    step("Configure the static route with nexthop N1 to N8, one by one")
+    for addr_type in ADDR_TYPES:
+        # add static routes
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                            "admin_distance": 10 * nhp,
+                        }
+                    ]
+                }
+            }
+
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step(
+        " After configuring them, route is always active with lowest AD"
+        " value and all the nexthop populated in RIB and FIB again"
+    )
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type],}]}}
+        nh = NEXT_HOP_IP["nh1"][addr_type]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol, fib=True
+        )
+        assert result is True, "Testcase {} : Failed \nError: Route with "
+        "lowest AD  is missing in RIB".format(tc_name)
+
+    step("Shut nexthop interfaces N1 to N3 one by one")
+    for addr_type in ADDR_TYPES:
+        for nhp in range(0, 3):
+            intf = topo["routers"]["r2"]["links"]["r1-link" + str(nhp)]["interface"]
+            shutdown_bringup_interface(tgen, dut, intf, False)
+        input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type],}]}}
+        nh = NEXT_HOP_IP["nh1"][addr_type]
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            fib=True,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \n"
+        "Error: Routes are still present in RIB".format(tc_name)
+
+    step("No shut the nexthop interfaces N1 to N3 one by one .")
+
+    for addr_type in ADDR_TYPES:
+        for nhp in range(0, 3):
+            intf = topo["routers"]["r2"]["links"]["r1-link" + str(nhp)]["interface"]
+            shutdown_bringup_interface(tgen, dut, intf, True)
+        input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type],}]}}
+        nh = NEXT_HOP_IP["nh1"][addr_type]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol, fib=True
+        )
+    assert result is True, "Testcase {} : Failed \n"
+    "Error: Routes are missing in RIB".format(tc_name)
+
+    step("Random shut of the nexthop interfaces")
+    randnum = random.randint(0, 7)
+    for addr_type in ADDR_TYPES:
+        intf = topo["routers"]["r2"]["links"]["r1-link" + str(randnum)]["interface"]
+        shutdown_bringup_interface(tgen, dut, intf, False)
+        nhip = NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type]
+        input_dict_5 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type],
+                    }
+                ]
+            }
+        }
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_5,
+            next_hop=nhip,
+            protocol=protocol,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \n"
+        "Error: Routes are still present in RIB".format(tc_name)
+
+    step("Random no shut of the nexthop interfaces")
+    for addr_type in ADDR_TYPES:
+        intf = topo["routers"]["r2"]["links"]["r1-link" + str(randnum)]["interface"]
+        shutdown_bringup_interface(tgen, dut, intf, True)
+        nhip = NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_5, next_hop=nhip, protocol=protocol
+        )
+        assert result is True, "Testcase {} : Failed \n"
+        "Error: Routes are missing in RIB".format(tc_name)
+
+    step("Remove random static route with all the nexthop")
+    for addr_type in ADDR_TYPES:
+        # delete static routes
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                            "admin_distance": 10 * nhp,
+                            "delete": True,
+                        }
+                    ]
+                }
+            }
+            logger.info("Configure static routes")
+            result = create_static_routes(tgen, input_dict_4)
+            assert result is True, "Testcase {} : Failed \n Error: {}".format(
+                tc_name, result
+            )
+
+            step(
+                "After removing the static route with N1 to N8 one by one , "
+                "route become active with next preferred nexthop and nexthop "
+                "which got removed is not shown in RIB and FIB"
+            )
+            nh = NEXT_HOP_IP["nh" + str(nhp)][addr_type]
+            result = verify_rib(
+                tgen,
+                addr_type,
+                dut,
+                input_dict_4,
+                next_hop=nh,
+                protocol=protocol,
+                expected=False,
+            )
+            assert result is not True, "Testcase {} : Failed \nError: Route "
+            " is still present in RIB".format(tc_name)
+
+        step("Reconfigure the deleted routes and verify they are installed")
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                            "admin_distance": 10 * nhp,
+                        }
+                    ]
+                }
+            }
+            logger.info("Configure static routes")
+            result = create_static_routes(tgen, input_dict_4)
+            assert result is True, "Testcase {} : Failed \n Error: {}".format(
+                tc_name, result
+            )
+
+            dut = "r2"
+            protocol = "static"
+            nh = NEXT_HOP_IP["nh1"][addr_type]
+            result = verify_rib(tgen, addr_type, dut, input_dict_4, protocol=protocol)
+            assert result is True, "Testcase {} : Failed \nError: Route "
+            " is still present in RIB".format(tc_name)
+
+            step("Reload the FRR router")
+            # stop/start -> restart FRR router and verify
+            stop_router(tgen, "r2")
+            sleep(5)
+            start_router(tgen, "r2")
+
+            step("After reloading, verify that routes are still present in R2.")
+            result = verify_rib(
+                tgen,
+                addr_type,
+                dut,
+                second_rte,
+                next_hop=nh,
+                protocol=protocol,
+                fib=True,
+            )
+            assert result is True, (
+                "Testcase {} : Failed \nError: Route "
+                " is missing in RIB".format(tc_name)
+            )
+
+        dut = "r2"
+        for intfr in range(0, 8):
+            intf = topo["routers"]["r2"]["links"]["r3-link{}".format(intfr)][
+                "interface"
+            ]
+            shutdown_bringup_interface(tgen, dut, intf, False)
+
+        dut = "r3"
+        for intfr in range(0, 8):
+            intf = topo["routers"]["r3"]["links"]["r2-link{}".format(intfr)][
+                "interface"
+            ]
+            shutdown_bringup_interface(tgen, dut, intf, False)
+        sleep(180)
+        step("verify bgp convergence as all interface are shut")
+
+        bgp_convergence = verify_bgp_convergence(tgen, topo)
+        assert bgp_convergence is not True, "Testcase {} : Failed \n"
+        "Error: {}".format(tc_name, bgp_convergence)
+
+        dut = "r2"
+        protocol = "static"
+        for addr_type in ADDR_TYPES:
+            for nhp in range(1, 9):
+                input_dict_4 = {
+                    "r2": {
+                        "static_routes": [
+                            {
+                                "network": PREFIX1[addr_type],
+                                "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                            }
+                        ]
+                    }
+                }
+            nh = NEXT_HOP_IP["nh1"][addr_type]
+            result = verify_rib(
+                tgen,
+                addr_type,
+                dut,
+                input_dict_4,
+                next_hop=nh,
+                protocol=protocol,
+                fib=True,
+            )
+            assert result is True, "Testcase {} : Failed \nError: Routes are"
+            " missing present in RIB".format(tc_name)
+
+        dut = "r3"
+        protocol = "bgp"
+        for addr_type in ADDR_TYPES:
+            input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type],}]}}
+            nh = NEXT_HOP_IP["nh1"][addr_type]
+            result = verify_rib(
+                tgen,
+                addr_type,
+                dut,
+                input_dict_4,
+                next_hop=nh,
+                protocol=protocol,
+                expected=False,
+            )
+            assert result is not True, "Testcase {} : Failed \nError: Routes "
+            " are still present in RIB after BGP nbr is down".format(tc_name)
+
+        sleep(5)
+        dut = "r2"
+        for intfr in range(0, 8):
+            intf = topo["routers"]["r2"]["links"]["r3-link{}".format(intfr)][
+                "interface"
+            ]
+            shutdown_bringup_interface(tgen, dut, intf, True)
+
+        sleep(5)
+        dut = "r3"
+        for intfr in range(0, 8):
+            intf = topo["routers"]["r3"]["links"]["r2-link{}".format(intfr)][
+                "interface"
+            ]
+            shutdown_bringup_interface(tgen, dut, intf, True)
+
+        step("verify bgp convergence as all interface are un shut")
+        bgp_convergence = verify_bgp_convergence(tgen, topo)
+        assert bgp_convergence is True, "Testcase {} : Failed \n"
+        "Error: {}".format(tc_name, bgp_convergence)
+
+    step("Remove the redistribute static knob")
+    for addr_type in ADDR_TYPES:
+        input_dict_2 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {
+                                "redistribute": [
+                                    {"redist_type": "static", "delete": True}
+                                ]
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step(
+        "After removing the BGP neighbor or redistribute static knob , "
+        "verify route got clear from RIB and FIB of R3 routes "
+    )
+    dut = "r3"
+    protocol = "bgp"
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                    }
+                ]
+            }
+        }
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, protocol=protocol, expected=False
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes are"
+        " still present in RIB".format(tc_name)
+
+    write_test_footer(tc_name)
+
+
+def test_static_route_delete_p0_tc11_ibgp(request):
+    """
+    Delete the static route and verify the RIB and FIB state
+    """
+    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)
+    NEXT_HOP_IP = populate_nh()
+
+    step("Configure 8 interfaces / links between R1 and R2 ")
+    step("Configure 8 IBGP IPv4 peering between R2 and R3 router.")
+    reset_config_on_routers(tgen)
+
+    step(
+        "Configure IPv4 static route in R2 with 8 next hop"
+        "N1(21.1.1.2) AD 10, N2(22.1.1.2) AD 20, N3(23.1.1.2) AD 30,"
+        "N4(24.1.1.2) AD 40, N5(25.1.1.2) AD 50, N6(26.1.1.2) AD 60,"
+        "N7(27.1.1.2) AD 70, N8(28.1.1.2) AD 80"
+    )
+    step(
+        "Configure nexthop AD in such way for static route S1 , N1 is"
+        "preferred and for S2 , N2 is preferred and so on .."
+    )
+    nh_all = {}
+    for addr_type in ADDR_TYPES:
+        nh_all[addr_type] = []
+        for nhp in range(1, 9):
+            nh_all[addr_type].append(NEXT_HOP_IP["nh" + str(nhp)][addr_type])
+
+    for addr_type in ADDR_TYPES:
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                            "admin_distance": 10 * nhp,
+                        }
+                    ]
+                }
+            }
+            logger.info("Configure static routes")
+            result = create_static_routes(tgen, input_dict_4)
+            assert result is True, "Testcase {} : Failed \n Error: {}".format(
+                tc_name, result
+            )
+            second_rte = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX2[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                            "admin_distance": 10 * nhp,
+                        }
+                    ]
+                }
+            }
+            logger.info("Configure static routes")
+            result = create_static_routes(tgen, second_rte)
+            assert result is True, "Testcase {} : Failed \n Error: {}".format(
+                tc_name, result
+            )
+        logger.info("Verifying %s routes on r2", addr_type)
+
+        step(
+            "On R2, static route installed in RIB using "
+            "show ip route with 8 next hop , lowest AD nexthop is active"
+        )
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "admin_distance": 10,
+                    }
+                ]
+            }
+        }
+        dut = "r2"
+        protocol = "static"
+        nh = NEXT_HOP_IP["nh1"][addr_type]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol, fib=True
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes are"
+        " missing in RIB".format(tc_name)
+
+        step("Verify that highest AD nexthop are inactive")
+        nh = []
+        for nhp in range(2, 9):
+            nh.append(NEXT_HOP_IP["nh" + str(nhp)][addr_type])
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            fib=True,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes "
+        " are missing in RIB".format(tc_name)
+
+    step("Configure redistribute static in BGP on R2 router")
+    for addr_type in ADDR_TYPES:
+        input_dict_2 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {"redistribute": [{"redist_type": "static"}]}
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step("Remove the redistribute static knob")
+    for addr_type in ADDR_TYPES:
+        input_dict_2 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {
+                                "redistribute": [
+                                    {"redist_type": "static", "delete": True}
+                                ]
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step(
+            "Verify after removing the redistribute static from BGP all the"
+            "routes got delete from RIB and FIB of R3 "
+        )
+
+        dut = "r3"
+        protocol = "bgp"
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, protocol=protocol, expected=False
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes are"
+        " still present in RIB".format(tc_name)
+
+    for addr_type in ADDR_TYPES:
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                            "admin_distance": 10 * nhp,
+                            "delete": True,
+                        }
+                    ]
+                }
+            }
+            logger.info("Configure static routes")
+            result = create_static_routes(tgen, input_dict_4)
+            assert result is True, "Testcase {} : Failed \n Error: {}".format(
+                tc_name, result
+            )
+            second_rte = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX2[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                            "admin_distance": 10 * nhp,
+                        }
+                    ]
+                }
+            }
+            logger.info("Configure static routes")
+            result = create_static_routes(tgen, second_rte)
+            assert result is True, "Testcase {} : Failed \n Error: {}".format(
+                tc_name, result
+            )
+        logger.info("Verifying %s routes on r2", addr_type)
+
+        step(
+            " After removing all the routes and nexthop from R2 , "
+            " verify R2 RIB and FIB is cleared"
+        )
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "admin_distance": 10,
+                    }
+                ]
+            }
+        }
+        dut = "r2"
+        protocol = "static"
+        nh = NEXT_HOP_IP["nh1"][addr_type]
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            fib=True,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes are"
+        " still active in RIB".format(tc_name)
+    write_test_footer(tc_name)
+
+
+if __name__ == "__main__":
+    args = ["-s"] + sys.argv[1:]
+    sys.exit(pytest.main(args))
diff --git a/tests/topotests/static_routing_with_ibgp/test_static_routes_topo3_ibgp.py b/tests/topotests/static_routing_with_ibgp/test_static_routes_topo3_ibgp.py
new file mode 100644 (file)
index 0000000..3458893
--- /dev/null
@@ -0,0 +1,992 @@
+#!/usr/bin/python
+
+#
+# Copyright (c) 2020 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.
+#
+"""
+    -Verify static route ECMP functionality with 8 next hop
+
+    -Verify static route functionality with 8 next hop different AD value
+
+    -Verify static route with tag option
+
+    -Verify BGP did not install the static route when it receive route
+    with local next hop
+
+"""
+import sys
+import json
+import time
+import os
+import pytest
+import ipaddr
+from time import sleep
+from copy import deepcopy
+import random
+from re import search as re_search
+
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+sys.path.append(os.path.join(CWD, "../lib/"))
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from mininet.topo import Topo
+from lib.topogen import Topogen, get_topogen
+
+from lib.common_config import (
+    start_topology,
+    write_test_header,
+    write_test_footer,
+    reset_config_on_routers,
+    verify_rib,
+    create_static_routes,
+    check_address_types,
+    step,
+    create_interfaces_cfg,
+    shutdown_bringup_interface,
+    stop_router,
+    start_router,
+)
+from lib.topolog import logger
+from lib.bgp import verify_bgp_convergence, create_router_bgp, verify_bgp_rib
+from lib.topojson import build_topo_from_json, build_config_from_json
+
+# Reading the data from JSON File for topology creation
+jsonFile = "{}/static_routes_topo3_ibgp.json".format(CWD)
+try:
+    with open(jsonFile, "r") as topoJson:
+        topo = json.load(topoJson)
+except IOError:
+    assert False, "Could not read file {}".format(jsonFile)
+
+# Global variables
+BGP_CONVERGENCE = False
+ADDR_TYPES = check_address_types()
+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",
+        "11.0.20.6/32",
+        "11.0.20.7/32",
+        "11.0.20.8/32",
+    ],
+    "ipv6": [
+        "2::1/128",
+        "2::2/128",
+        "2::3/128",
+        "2::4/128",
+        "2::5/128",
+        "2::6/128",
+        "2::7/128",
+        "2::8/128",
+    ],
+}
+PREFIX1 = {"ipv4": "110.0.20.1/32", "ipv6": "20::1/128"}
+NETWORK2 = {"ipv4": ["11.0.20.1/32"], "ipv6": ["2::1/128"]}
+NEXT_HOP_IP = []
+
+
+class CreateTopo(Topo):
+    """
+    Test CreateTopo - topology 1.
+
+    * `Topo`: Topology object
+    """
+
+    def build(self, *_args, **_opts):
+        """Build function."""
+        tgen = get_topogen(self)
+
+        # Building topology from json file
+        build_topo_from_json(tgen, topo)
+
+
+def setup_module(mod):
+    """
+
+    Set up the pytest environment.
+
+    * `mod`: module name
+    """
+    global topo
+    testsuite_run_time = time.asctime(time.localtime(time.time()))
+    logger.info("Testsuite start time: {}".format(testsuite_run_time))
+    logger.info("=" * 40)
+
+    logger.info("Running setup_module to create topology")
+
+    # This function initiates the topology build with Topogen...
+    tgen = Topogen(CreateTopo, mod.__name__)
+    # ... and here it calls Mininet initialization functions.
+
+    # Starting topology, create tmp files which are loaded to routers
+    #  to start deamons and then start routers
+    start_topology(tgen)
+
+    # Creating configuration from JSON
+    build_config_from_json(tgen, topo)
+
+    # Checking BGP convergence
+    global BGP_CONVERGENCE
+    global ADDR_TYPES
+
+    # Don't run this test if we have any failure.
+    if tgen.routers_have_failure():
+        pytest.skip(tgen.errors)
+    # Api call verify whether BGP is converged
+    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo)
+    assert BGP_CONVERGENCE is True, "setup_module :Failed \n Error: {}".format(
+        BGP_CONVERGENCE
+    )
+
+    logger.info("Running setup_module() done")
+
+
+def teardown_module(mod):
+    """
+    Teardown the pytest environment
+
+    * `mod`: module name
+    """
+
+    logger.info("Running teardown_module to delete topology")
+
+    tgen = get_topogen()
+
+    # Stop toplogy and Remove tmp files
+    tgen.stop_topology()
+
+    logger.info(
+        "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
+    )
+    logger.info("=" * 40)
+
+
+def populate_nh():
+    NEXT_HOP_IP = {
+        "nh1": {
+            "ipv4": topo["routers"]["r1"]["links"]["r2-link0"]["ipv4"].split("/")[0],
+            "ipv6": topo["routers"]["r1"]["links"]["r2-link0"]["ipv6"].split("/")[0],
+        },
+        "nh2": {
+            "ipv4": topo["routers"]["r1"]["links"]["r2-link1"]["ipv4"].split("/")[0],
+            "ipv6": topo["routers"]["r1"]["links"]["r2-link1"]["ipv6"].split("/")[0],
+        },
+        "nh3": {
+            "ipv4": topo["routers"]["r1"]["links"]["r2-link2"]["ipv4"].split("/")[0],
+            "ipv6": topo["routers"]["r1"]["links"]["r2-link2"]["ipv6"].split("/")[0],
+        },
+        "nh4": {
+            "ipv4": topo["routers"]["r1"]["links"]["r2-link3"]["ipv4"].split("/")[0],
+            "ipv6": topo["routers"]["r1"]["links"]["r2-link3"]["ipv6"].split("/")[0],
+        },
+        "nh5": {
+            "ipv4": topo["routers"]["r1"]["links"]["r2-link4"]["ipv4"].split("/")[0],
+            "ipv6": topo["routers"]["r1"]["links"]["r2-link4"]["ipv6"].split("/")[0],
+        },
+        "nh6": {
+            "ipv4": topo["routers"]["r1"]["links"]["r2-link5"]["ipv4"].split("/")[0],
+            "ipv6": topo["routers"]["r1"]["links"]["r2-link5"]["ipv6"].split("/")[0],
+        },
+        "nh7": {
+            "ipv4": topo["routers"]["r1"]["links"]["r2-link6"]["ipv4"].split("/")[0],
+            "ipv6": topo["routers"]["r1"]["links"]["r2-link6"]["ipv6"].split("/")[0],
+        },
+        "nh8": {
+            "ipv4": topo["routers"]["r1"]["links"]["r2-link7"]["ipv4"].split("/")[0],
+            "ipv6": topo["routers"]["r1"]["links"]["r2-link7"]["ipv6"].split("/")[0],
+        },
+    }
+    return NEXT_HOP_IP
+
+
+#####################################################
+#
+#   Tests starting
+#
+#####################################################
+
+
+def test_staticroute_with_ecmp_p0_tc3_ibgp(request):
+    """
+    Verify static route ECMP functionality with 8 next hop'
+
+    """
+    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)
+
+    reset_config_on_routers(tgen)
+    NEXT_HOP_IP = populate_nh()
+
+    step("Configure 8 interfaces / links between R1 and R2,")
+    step(
+        "Configure IPv4 static route in R2 with 8 next hop"
+        "N1(21.1.1.2), N2(22.1.1.2), N3(23.1.1.2), N4(24.1.1.2),"
+        "N5(25.1.1.2), N6(26.1.1.2), N7(27.1.1.2),N8(28.1.1.2), Static"
+        "route next-hop present on R1"
+    )
+
+    step("Configure IBGP IPv4 peering between R2 and R3 router.")
+
+    for addr_type in ADDR_TYPES:
+        # Enable static routes
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                        }
+                    ]
+                }
+            }
+            logger.info("Configure static routes")
+            result = create_static_routes(tgen, input_dict_4)
+            assert result is True, "Testcase {} : Failed \n Error: {}".format(
+                tc_name, result
+            )
+        logger.info("Verifying %s routes on r2", addr_type)
+        nh = [
+            NEXT_HOP_IP["nh1"][addr_type],
+            NEXT_HOP_IP["nh2"][addr_type],
+            NEXT_HOP_IP["nh3"][addr_type],
+            NEXT_HOP_IP["nh4"][addr_type],
+            NEXT_HOP_IP["nh5"][addr_type],
+            NEXT_HOP_IP["nh6"][addr_type],
+            NEXT_HOP_IP["nh7"][addr_type],
+            NEXT_HOP_IP["nh8"][addr_type],
+        ]
+
+        dut = "r2"
+        protocol = "static"
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes are"
+        " missing in RIB".format(tc_name)
+    step("Configure redistribute static in BGP on R2 router")
+    for addr_type in ADDR_TYPES:
+        input_dict_2 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {"redistribute": [{"redist_type": "static"}]}
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step(
+        "Remove the static route configured with nexthop N1 to N8, one"
+        "by one from running config"
+    )
+    for addr_type in ADDR_TYPES:
+        # delete static routes
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                            "delete": True,
+                        }
+                    ]
+                }
+            }
+
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes are"
+        " still present in RIB".format(tc_name)
+
+    step("Configure the static route with nexthop N1 to N8, one by" "one")
+
+    for addr_type in ADDR_TYPES:
+        # add static routes
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                        }
+                    ]
+                }
+            }
+
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    result = verify_rib(
+        tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol
+    )
+    assert result is True, "Testcase {} : Failed \nError: Routes are"
+    " missing in RIB".format(tc_name)
+
+    step("Shut nexthop interfaces N1 to N8 one by one")
+    for addr_type in ADDR_TYPES:
+        for nhp in range(0, 8):
+            intf = topo["routers"]["r2"]["links"]["r1-link" + str(nhp)]["interface"]
+            shutdown_bringup_interface(tgen, dut, intf, False)
+
+    result = verify_rib(
+        tgen,
+        addr_type,
+        dut,
+        input_dict_4,
+        next_hop=nh,
+        protocol=protocol,
+        expected=False,
+    )
+    assert result is not True, "Testcase {} : Failed \n"
+    "Error: Routes are still present in RIB".format(tc_name)
+
+    step("No shut the nexthop interfaces N1 to N8 one by one .")
+
+    for addr_type in ADDR_TYPES:
+        for nhp in range(0, 8):
+            intf = topo["routers"]["r2"]["links"]["r1-link" + str(nhp)]["interface"]
+            shutdown_bringup_interface(tgen, dut, intf, True)
+
+    result = verify_rib(
+        tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol
+    )
+    assert result is True, "Testcase {} : Failed \n"
+    "Error: Routes are missing in RIB".format(tc_name)
+
+    step("Random shut of the nexthop interfaces")
+    randnum = random.randint(0, 7)
+    for addr_type in ADDR_TYPES:
+        intf = topo["routers"]["r2"]["links"]["r1-link" + str(randnum)]["interface"]
+        shutdown_bringup_interface(tgen, dut, intf, False)
+        nhip = NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type]
+        input_dict_5 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type],
+                    }
+                ]
+            }
+        }
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_5,
+            next_hop=nhip,
+            protocol=protocol,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \n"
+        "Error: Routes are still present in RIB".format(tc_name)
+
+    step("Random no shut of the nexthop interfaces")
+    for addr_type in ADDR_TYPES:
+        intf = topo["routers"]["r2"]["links"]["r1-link" + str(randnum)]["interface"]
+        shutdown_bringup_interface(tgen, dut, intf, True)
+        nhip = NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_5, next_hop=nhip, protocol=protocol
+        )
+        assert result is True, "Testcase {} : Failed \n"
+        "Error: Routes are missing in RIB".format(tc_name)
+
+    step("Reload the FRR router")
+    # stop/start -> restart FRR router and verify
+    stop_router(tgen, "r2")
+    sleep(5)
+    start_router(tgen, "r2")
+
+    result = verify_rib(
+        tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol
+    )
+    assert result is True, "Testcase {} : Failed \nError: Routes are"
+    " missing in RIB".format(tc_name)
+
+    write_test_footer(tc_name)
+
+
+def test_staticroute_with_ecmp_with_diff_AD_p0_tc4_ibgp(request):
+    """
+    Verify static route ECMP functionality with 8 next hop
+
+    """
+    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)
+
+    reset_config_on_routers(tgen)
+    NEXT_HOP_IP = populate_nh()
+
+    step("Configure 8 interfaces / links between R1 and R2,")
+    step("Configure IBGP IPv4 peering between R2 and R3 router.")
+    reset_config_on_routers(tgen)
+    NEXT_HOP_IP = populate_nh()
+    nh_all = {}
+    for addr_type in ADDR_TYPES:
+        nh_all[addr_type] = []
+        for nhp in range(1, 9):
+            nh_all[addr_type].append(NEXT_HOP_IP["nh" + str(nhp)][addr_type])
+    step(
+        "Configure IPv4 static route in R2 with 8 next hop"
+        "N1(21.1.1.2) AD 10, N2(22.1.1.2) AD 20, N3(23.1.1.2) AD 30,"
+        "N4(24.1.1.2) AD 40, N5(25.1.1.2) AD 50, N6(26.1.1.2) AD 60,"
+        "N7(27.1.1.2) AD 70, N8(28.1.1.2) AD 80, Static route next-hop"
+        "present on R1"
+    )
+    for addr_type in ADDR_TYPES:
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                            "admin_distance": 10 * nhp,
+                        }
+                    ]
+                }
+            }
+            logger.info("Configure static routes")
+            result = create_static_routes(tgen, input_dict_4)
+            assert result is True, "Testcase {} : Failed \n Error: {}".format(
+                tc_name, result
+            )
+        logger.info("Verifying %s routes on r2", addr_type)
+
+        step(
+            "On R2, static route installed in RIB using "
+            "show ip route with 8 next hop, lowest AD nexthop is active"
+        )
+        step("On R2, static route with lowest AD nexthop installed in FIB")
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "admin_distance": 10,
+                    }
+                ]
+            }
+        }
+        dut = "r2"
+        protocol = "static"
+        nh = NEXT_HOP_IP["nh1"][addr_type]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol, fib=True
+        )
+        assert result is True, "Testcase {} : Failed \nError: Route with "
+        " lowest AD is missing in RIB".format(tc_name)
+
+        nh = []
+        for nhp in range(2, 9):
+            nh.append(NEXT_HOP_IP["nh" + str(nhp)][addr_type])
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            fib=True,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes "
+        " with high AD are active in RIB".format(tc_name)
+
+    step("Configure redistribute static in BGP on R2 router")
+    for addr_type in ADDR_TYPES:
+        input_dict_2 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {"redistribute": [{"redist_type": "static"}]}
+                        }
+                    }
+                }
+            }
+        }
+
+        logger.info("Configuring redistribute static")
+        result = create_router_bgp(tgen, topo, input_dict_2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step(
+            "After configuring them, route is always active with lowest AD"
+            "value and all the nexthop populated in RIB and FIB again "
+        )
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "admin_distance": 10,
+                    }
+                ]
+            }
+        }
+        dut = "r2"
+        protocol = "static"
+        nh = NEXT_HOP_IP["nh1"][addr_type]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol, fib=True
+        )
+        assert result is True, "Testcase {} : Failed \nError: Route with "
+        " lowest AD is missing in RIB".format(tc_name)
+
+    step(
+        "Remove the static route configured with nexthop N1 to N8, one"
+        "by one from running config"
+    )
+
+    for addr_type in ADDR_TYPES:
+        # delete static routes
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                            "admin_distance": 10 * nhp,
+                            "delete": True,
+                        }
+                    ]
+                }
+            }
+
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step(
+        "After removing the static route with N1 to N8 one by one, "
+        "route become active with next preferred nexthop and nexthop which "
+        "got removed is not shown in RIB and FIB"
+    )
+    result = verify_rib(
+        tgen,
+        addr_type,
+        dut,
+        input_dict_4,
+        next_hop=nh_all[addr_type],
+        protocol=protocol,
+        expected=False,
+    )
+    assert result is not True, "Testcase {} : Failed \nError: Routes are"
+    " still present in RIB".format(tc_name)
+
+    step("Configure the static route with nexthop N1 to N8, one by" "one")
+    for addr_type in ADDR_TYPES:
+        # add static routes
+        for nhp in range(1, 9):
+            input_dict_4 = {
+                "r2": {
+                    "static_routes": [
+                        {
+                            "network": PREFIX1[addr_type],
+                            "next_hop": NEXT_HOP_IP["nh" + str(nhp)][addr_type],
+                            "admin_distance": 10 * nhp,
+                        }
+                    ]
+                }
+            }
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step("On R2, static route with lowest AD nexthop installed in FIB")
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "admin_distance": 10,
+                    }
+                ]
+            }
+        }
+        dut = "r2"
+        protocol = "static"
+        nh = NEXT_HOP_IP["nh1"][addr_type]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol, fib=True
+        )
+        assert result is True, "Testcase {} : Failed \nError: Route with "
+        " lowest AD is missing in RIB".format(tc_name)
+
+        nh = []
+        for nhp in range(2, 9):
+            nh.append(NEXT_HOP_IP["nh" + str(nhp)][addr_type])
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            fib=True,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes "
+        " with high AD are active in RIB".format(tc_name)
+
+    step("Shut nexthop interfaces N1 to N8 one by one")
+    for addr_type in ADDR_TYPES:
+        for nhp in range(0, 8):
+            intf = topo["routers"]["r2"]["links"]["r1-link" + str(nhp)]["interface"]
+            shutdown_bringup_interface(tgen, dut, intf, False)
+
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh_all[addr_type],
+            protocol=protocol,
+            fib=True,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes "
+        " are still present in RIB".format(tc_name)
+
+    step("No shut the nexthop interfaces N1 to N8 one by one .")
+    for addr_type in ADDR_TYPES:
+        for nhp in range(0, 8):
+            intf = topo["routers"]["r2"]["links"]["r1-link" + str(nhp)]["interface"]
+            shutdown_bringup_interface(tgen, dut, intf, True)
+
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "admin_distance": 10,
+                    }
+                ]
+            }
+        }
+        dut = "r2"
+        protocol = "static"
+        nh = NEXT_HOP_IP["nh1"][addr_type]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol, fib=True
+        )
+        assert result is True, "Testcase {} : Failed \nError: Routes are"
+        " missing in RIB".format(tc_name)
+
+        nh = []
+        for nhp in range(2, 9):
+            nh.append(NEXT_HOP_IP["nh" + str(nhp)][addr_type])
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            fib=True,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes "
+        " are missing in RIB".format(tc_name)
+
+    step("Random shut of the nexthop interfaces")
+    randnum = random.randint(0, 7)
+    for addr_type in ADDR_TYPES:
+        intf = topo["routers"]["r2"]["links"]["r1-link" + str(randnum)]["interface"]
+        shutdown_bringup_interface(tgen, dut, intf, False)
+        nhip = NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type]
+        input_dict_5 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type],
+                    }
+                ]
+            }
+        }
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_5,
+            next_hop=nhip,
+            protocol=protocol,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \n"
+        "Error: Routes are still present in RIB".format(tc_name)
+
+    step("Random no shut of the nexthop interfaces")
+    for addr_type in ADDR_TYPES:
+        intf = topo["routers"]["r2"]["links"]["r1-link" + str(randnum)]["interface"]
+        shutdown_bringup_interface(tgen, dut, intf, True)
+        nhip = NEXT_HOP_IP["nh" + str(randnum + 1)][addr_type]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_5, next_hop=nhip, protocol=protocol
+        )
+        assert result is True, "Testcase {} : Failed \n"
+        "Error: Routes are missing in RIB".format(tc_name)
+
+    step("Reload the FRR router")
+    # stop/start -> restart FRR router and verify
+    stop_router(tgen, "r2")
+    sleep(5)
+    start_router(tgen, "r2")
+
+    step(
+        "After reload of FRR router, static route installed "
+        "in RIB and FIB properly ."
+    )
+    for addr_type in ADDR_TYPES:
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": PREFIX1[addr_type],
+                        "next_hop": NEXT_HOP_IP["nh1"][addr_type],
+                        "admin_distance": 10,
+                    }
+                ]
+            }
+        }
+        dut = "r2"
+        protocol = "static"
+        nh = NEXT_HOP_IP["nh1"][addr_type]
+        result = verify_rib(
+            tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol, fib=True
+        )
+        assert result is True, "Testcase {} : Failed \nError: Route with "
+        " lowest AD is missing in RIB".format(tc_name)
+
+        nh = []
+        for nhp in range(2, 9):
+            nh.append(NEXT_HOP_IP["nh" + str(nhp)][addr_type])
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            fib=True,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes "
+        " with high AD are active in RIB".format(tc_name)
+
+    step("BGP neighbor remove and add")
+    for rtr in ["r2", "r3"]:
+        if "bgp" in topo["routers"][rtr].keys():
+            delete_bgp = {rtr: {"bgp": {"delete": True}}}
+            result = create_router_bgp(tgen, topo, delete_bgp)
+            assert result is True, "Testcase {} : Failed \n Error: {}".format(
+                tc_name, result
+            )
+
+    reset_config_on_routers(tgen)
+    NEXT_HOP_IP = populate_nh()
+    step("Verify routes are still present after delete and add bgp")
+    dut = "r3"
+    protocol = "bgp"
+    result = verify_rib(
+        tgen,
+        addr_type,
+        dut,
+        input_dict_4,
+        next_hop=nh,
+        protocol=protocol,
+        expected=False,
+    )
+    assert result is not True, "Testcase {} : Failed \n"
+    "Error: Routes still present in RIB".format(tc_name)
+
+    step("Remove the redistribute static knob")
+
+    for addr_type in ADDR_TYPES:
+        input_dict_2 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {
+                                "redistribute": [
+                                    {"redist_type": "static", "delete": True}
+                                ]
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        logger.info("Remove redistribute static")
+        result = create_router_bgp(tgen, topo, input_dict_2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+        step("verify that routes are deleted from R3 routing table")
+        dut = "r3"
+        protocol = "bgp"
+        result = verify_rib(
+            tgen,
+            addr_type,
+            dut,
+            input_dict_4,
+            next_hop=nh,
+            protocol=protocol,
+            expected=False,
+        )
+        assert result is not True, "Testcase {} : Failed \nError: Routes are"
+        " strill present in RIB of R3".format(tc_name)
+
+    step("Repeat above steps  when EBGP IPv4 session is configure" "between R2 and R3")
+
+    write_test_footer(tc_name)
+
+
+def test_bgp_local_nexthop_p1_tc14_ibgp(request):
+    """
+    Verify BGP did not install the static route when it receive route
+    with local next hop
+
+    """
+    tc_name = request.node.name
+    write_test_header(tc_name)
+    tgen = get_topogen()
+
+    step("Configure BGP IPv4 session between R2 and R3")
+    step("Configure IPv4 static route on R2")
+    reset_config_on_routers(tgen)
+
+    for addr_type in ADDR_TYPES:
+        # Enable static routes
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": NETWORK[addr_type],
+                        "next_hop": topo["routers"]["r3"]["links"]["r2-link0"][
+                            addr_type
+                        ].split("/")[0],
+                    }
+                ]
+            }
+        }
+
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step("Configure redistribute static in the BGP")
+
+        input_dict_2 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {"redistribute": [{"redist_type": "static"}]}
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step("Verify R2 BGP table has IPv4 route")
+        dut = "r2"
+        result = verify_rib(tgen, addr_type, dut, input_dict_4)
+        assert result is True, "Testcase {} : Failed \nError: Routes is"
+        " missing in RIB of R2".format(tc_name)
+
+        step(" Verify route did not install in the R3 BGP table, RIB/FIB")
+        dut = "r3"
+        result = verify_bgp_rib(tgen, addr_type, dut, input_dict_4, expected=False)
+        assert result is not True, "Testcase {} : Failed \nError: Routes is"
+        " still present in BGP RIB of R2".format(tc_name)
+
+        result = verify_rib(tgen, addr_type, dut, input_dict_4, expected=False)
+        assert result is not True, "Testcase {} : Failed \nError: Routes is"
+        " still present in RIB of R2".format(tc_name)
+
+    write_test_footer(tc_name)
+
+
+if __name__ == "__main__":
+    args = ["-s"] + sys.argv[1:]
+    sys.exit(pytest.main(args))
diff --git a/tests/topotests/static_routing_with_ibgp/test_static_routes_topo4_ibgp.py b/tests/topotests/static_routing_with_ibgp/test_static_routes_topo4_ibgp.py
new file mode 100644 (file)
index 0000000..abc89b9
--- /dev/null
@@ -0,0 +1,1213 @@
+#!/usr/bin/python
+
+#
+# Copyright (c) 2020 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.
+#
+
+"""
+
+Following tests are covered in the script.
+
+- Verify static route are blocked from route-map and prefix-list
+    applied in BGP nbrs
+- Verify Static route when FRR connected to 2 TOR
+"""
+
+import sys
+import json
+import time
+import os
+import pytest
+import ipaddr
+import ipaddress
+from time import sleep
+from copy import deepcopy
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+sys.path.append(os.path.join(CWD, "../lib/"))
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from mininet.topo import Topo
+from lib.topogen import Topogen, get_topogen
+from time import sleep
+
+from lib.common_config import (
+    start_topology,
+    write_test_header,
+    write_test_footer,
+    reset_config_on_routers,
+    verify_kernel_ping,
+    verify_rib,
+    create_static_routes,
+    check_address_types,
+    step,
+    create_prefix_lists,
+    create_route_maps,
+    create_interfaces_cfg,
+    verify_prefix_lists,
+    verify_route_maps,
+)
+from lib.topolog import logger
+from lib.bgp import (
+    verify_bgp_convergence,
+    create_router_bgp,
+    clear_bgp_and_verify,
+    clear_bgp,
+)
+from lib.topojson import build_topo_from_json, build_config_from_json
+
+# Reading the data from JSON File for topology creation
+jsonFile = "{}/static_routes_topo4_ibgp.json".format(CWD)
+try:
+    with open(jsonFile, "r") as topoJson:
+        topo = json.load(topoJson)
+except IOError:
+    assert False, "Could not read file {}".format(jsonFile)
+# Global variables
+BGP_CONVERGENCE = False
+ADDR_TYPES = check_address_types()
+NETWORK = {"ipv4": "2.2.2.2/32", "ipv6": "22:22::2/128"}
+NEXT_HOP_IP = {}
+
+
+class CreateTopo(Topo):
+    """
+    Test CreateTopo - topology 1.
+
+    * `Topo`: Topology object
+    """
+
+    def build(self, *_args, **_opts):
+        """Build function."""
+        tgen = get_topogen(self)
+
+        # Building topology from json file
+        build_topo_from_json(tgen, topo)
+
+
+def setup_module(mod):
+    """
+
+    Set up the pytest environment.
+
+    * `mod`: module name
+    """
+    global topo
+    testsuite_run_time = time.asctime(time.localtime(time.time()))
+    logger.info("Testsuite start time: {}".format(testsuite_run_time))
+    logger.info("=" * 40)
+
+    logger.info("Running setup_module to create topology")
+
+    # This function initiates the topology build with Topogen...
+    tgen = Topogen(CreateTopo, mod.__name__)
+    # ... and here it calls Mininet initialization functions.
+
+    # Starting topology, create tmp files which are loaded to routers
+    #  to start deamons and then start routers
+    start_topology(tgen)
+
+    # Creating configuration from JSON
+    build_config_from_json(tgen, topo)
+
+    # Checking BGP convergence
+    global BGP_CONVERGENCE
+    global ADDR_TYPES
+    # Don't run this test if we have any failure.
+    if tgen.routers_have_failure():
+        pytest.skip(tgen.errors)
+    # Api call verify whether BGP is converged
+    BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo)
+    assert BGP_CONVERGENCE is True, "setup_module :Failed \n Error: {}".format(
+        BGP_CONVERGENCE
+    )
+
+    logger.info("Running setup_module() done")
+
+
+def teardown_module(mod):
+    """
+    Teardown the pytest environment.
+
+    * `mod`: module name
+    """
+    logger.info("Running teardown_module to delete topology")
+
+    tgen = get_topogen()
+
+    # Stop toplogy and Remove tmp files
+    tgen.stop_topology()
+
+    logger.info(
+        "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
+    )
+    logger.info("=" * 40)
+
+
+#####################################################
+#
+#   Tests starting
+#
+#####################################################
+def test_static_routes_rmap_pfxlist_p0_tc7_ibgp(request):
+    """
+    Verify static route are blocked from route-map & prefix-list applied in BGP
+    nbrs
+
+    """
+    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)
+    reset_config_on_routers(tgen)
+    step("Configure holddown timer = 1 keep alive = 3 in all the neighbors")
+    step("verify bgp convergence before starting test case")
+
+    bgp_convergence = verify_bgp_convergence(tgen, topo)
+    assert bgp_convergence is True, "Testcase {} : Failed \n Error: {}".format(
+        tc_name, bgp_convergence
+    )
+
+    step(
+        "Configure 4 IPv4 and 4 IPv6 nbrs with password with mismatch "
+        " authentication between FRR routers "
+    )
+
+    for addr_type in ADDR_TYPES:
+        # Api call to modfiy BGP timerse
+        input_dict = {
+            "r2": {
+                "bgp": {
+                    "local_as": "200",
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {
+                                "neighbor": {
+                                    "r1": {
+                                        "dest_link": {
+                                            "r2-link0": {"password": "r2"},
+                                            "r2-link1": {"password": "r2"},
+                                            "r2-link2": {"password": "r2"},
+                                            "r2-link3": {"password": "r2"},
+                                        }
+                                    },
+                                    "r3": {
+                                        "dest_link": {
+                                            "r2-link0": {"password": "r2"},
+                                            "r2-link1": {"password": "r2"},
+                                            "r2-link2": {"password": "r2"},
+                                            "r2-link3": {"password": "r2"},
+                                        }
+                                    },
+                                }
+                            }
+                        }
+                    },
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, deepcopy(input_dict))
+        assert result is True, "Testcase {} :Failed \n Error: {}".format(
+            tc_name, result
+        )
+        clear_bgp(tgen, addr_type, "r2")
+
+    step(" All BGP nbrs are down as authentication is mismatch on both" " the sides")
+
+    bgp_convergence = verify_bgp_convergence(tgen, topo)
+    assert bgp_convergence is not True, "Testcase {} : "
+    "Failed \n BGP nbrs must be down. Error: {}".format(tc_name, bgp_convergence)
+
+    step(
+        "Configure 4 IPv4 and 4 IPv6 nbrs with macthing password  "
+        " authentication between FRR routers "
+    )
+    for addr_type in ADDR_TYPES:
+        input_dict = {
+            "r2": {
+                "bgp": {
+                    "local_as": "200",
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {
+                                "neighbor": {
+                                    "r1": {
+                                        "dest_link": {
+                                            "r2-link0": {"password": "r1"},
+                                            "r2-link1": {"password": "r1"},
+                                            "r2-link2": {"password": "r1"},
+                                            "r2-link3": {"password": "r1"},
+                                        }
+                                    },
+                                    "r3": {
+                                        "dest_link": {
+                                            "r2-link0": {"password": "r1"},
+                                            "r2-link1": {"password": "r1"},
+                                            "r2-link2": {"password": "r1"},
+                                            "r2-link3": {"password": "r1"},
+                                        }
+                                    },
+                                }
+                            }
+                        }
+                    },
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, deepcopy(input_dict))
+        assert result is True, "Testcase {} :Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+    step("All BGP nbrs are up as authentication is matched now")
+    bgp_convergence = verify_bgp_convergence(tgen, topo)
+    assert bgp_convergence is True, "Testcase {} : Failed \n " "Error: {}".format(
+        tc_name, bgp_convergence
+    )
+
+    step("Create prefix list P1 to permit VM3 & deny VM1 v4 & v6 routes")
+    step("Create prefix list P2 to permit VM6 IPv4 and IPv6 routes")
+    for addr_type in ADDR_TYPES:
+        input_dict_2 = {
+            "r2": {
+                "prefix_lists": {
+                    addr_type: {
+                        "pf_list_1_{}".format(addr_type): [
+                            {
+                                "seqid": 10,
+                                "network": topo["routers"]["r2"]["links"]["vm3"][
+                                    addr_type
+                                ],
+                                "action": "permit",
+                            },
+                            {
+                                "seqid": 20,
+                                "network": topo["routers"]["r2"]["links"]["vm1"][
+                                    addr_type
+                                ],
+                                "action": "deny",
+                            },
+                        ],
+                        "pf_list_2_{}".format(addr_type): [
+                            {
+                                "seqid": 10,
+                                "network": topo["routers"]["r2"]["links"]["vm6"][
+                                    addr_type
+                                ],
+                                "action": "permit",
+                            }
+                        ],
+                    }
+                }
+            }
+        }
+        result = create_prefix_lists(tgen, input_dict_2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step(
+            "Prefix list created with matching networks deny or permit "
+            "show ip prefix list"
+        )
+        result = verify_prefix_lists(tgen, input_dict_2)
+        assert result is not True, "Testcase {} : Failed \n"
+        " Error: {}".format(tc_name, result)
+
+        step("Redistribute all the routes (connected, static)")
+        input_dict_2_r1 = {
+            "r1": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {"redistribute": [{"redist_type": "static"}]}
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_2_r1)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        input_dict_2_r2 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {"redistribute": [{"redist_type": "static"}]}
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_2_r2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        input_dict_2_r3 = {
+            "r3": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {"redistribute": [{"redist_type": "static"}]}
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_2_r3)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step("configure redistribute connected in Router BGP")
+
+        input_dict_2_r1 = {
+            "r1": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {"redistribute": [{"redist_type": "connected"}]}
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_2_r1)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        input_dict_2_r3 = {
+            "r3": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {"redistribute": [{"redist_type": "connected"}]}
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_2_r3)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        input_dict_2 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {"redistribute": [{"redist_type": "connected"}]}
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_2)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step("Apply prefix list P1 on BGP neighbors 1 2 3 4 connected from " "frr r1")
+        # Configure prefix list to bgp neighbor
+        input_dict_4 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {
+                                "neighbor": {
+                                    "r1": {
+                                        "dest_link": {
+                                            "r2-link0": {
+                                                "prefix_lists": [
+                                                    {
+                                                        "name": "pf_list_1_{}".format(
+                                                            addr_type
+                                                        ),
+                                                        "direction": "out",
+                                                    }
+                                                ]
+                                            },
+                                            "r2-link1": {
+                                                "prefix_lists": [
+                                                    {
+                                                        "name": "pf_list_1_{}".format(
+                                                            addr_type
+                                                        ),
+                                                        "direction": "out",
+                                                    }
+                                                ]
+                                            },
+                                            "r2-link2": {
+                                                "prefix_lists": [
+                                                    {
+                                                        "name": "pf_list_1_{}".format(
+                                                            addr_type
+                                                        ),
+                                                        "direction": "out",
+                                                    }
+                                                ]
+                                            },
+                                            "r2-link3": {
+                                                "prefix_lists": [
+                                                    {
+                                                        "name": "pf_list_1_{}".format(
+                                                            addr_type
+                                                        ),
+                                                        "direction": "out",
+                                                    }
+                                                ]
+                                            },
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step("Apply prefix list P2 on BGP nbrs 5 & 6 connected from FRR-2")
+        # Configure prefix list to bgp neighbor
+        input_dict_4 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {
+                                "neighbor": {
+                                    "r3": {
+                                        "dest_link": {
+                                            "r2-link0": {
+                                                "prefix_lists": [
+                                                    {
+                                                        "name": "pf_list_2_{}".format(
+                                                            addr_type
+                                                        ),
+                                                        "direction": "out",
+                                                    }
+                                                ]
+                                            },
+                                            "r2-link1": {
+                                                "prefix_lists": [
+                                                    {
+                                                        "name": "pf_list_2_{}".format(
+                                                            addr_type
+                                                        ),
+                                                        "direction": "out",
+                                                    }
+                                                ]
+                                            },
+                                            "r2-link2": {
+                                                "prefix_lists": [
+                                                    {
+                                                        "name": "pf_list_2_{}".format(
+                                                            addr_type
+                                                        ),
+                                                        "direction": "out",
+                                                    }
+                                                ]
+                                            },
+                                            "r2-link3": {
+                                                "prefix_lists": [
+                                                    {
+                                                        "name": "pf_list_2_{}".format(
+                                                            addr_type
+                                                        ),
+                                                        "direction": "out",
+                                                    }
+                                                ]
+                                            },
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        clear_bgp_and_verify(tgen, topo, "r2")
+
+        step(
+            "VM1 IPv4 and IPv6 Route which is denied using prefix list is "
+            "not present on FRR1 side routing table , also not able to "
+            "ping the routes show ip route"
+        )
+
+        dut = "r1"
+        protocol = "bgp"
+        ntwk_r2_vm1 = str(
+            ipaddress.ip_interface(
+                u"{}".format(topo["routers"]["r2"]["links"]["vm1"][addr_type])
+            ).network
+        )
+        input_dict = {"r1": {"static_routes": [{"network": ntwk_r2_vm1}]}}
+        result4 = verify_rib(
+            tgen, addr_type, dut, input_dict, protocol=protocol, expected=False
+        )
+        assert result4 is not True, "Testcase {} : Failed , VM1 route is "
+        "not filtered out via prefix list. \n Error: {}".format(tc_name, result4)
+
+        step(
+            "VM4 and VM6 IPV4 and IPv6 address are present in local and "
+            "FRR2 routing table show ip bgp show ip route"
+        )
+
+        dut = "r2"
+        ntwk_r2_vm6 = str(
+            ipaddress.ip_interface(
+                u"{}".format(topo["routers"]["r2"]["links"]["vm6"][addr_type])
+            ).network
+        )
+        input_dict = {"r3": {"static_routes": [{"network": ntwk_r2_vm6}]}}
+        result4 = verify_rib(tgen, addr_type, dut, input_dict)
+        assert result4 is True, "Testcase {} : Failed.\n Error: {}".format(
+            tc_name, result4
+        )
+
+        step("Remove prefix list from all the neighbors")
+        input_dict_4 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {
+                                "neighbor": {
+                                    "r1": {
+                                        "dest_link": {
+                                            "r2-link0": {
+                                                "prefix_lists": [
+                                                    {
+                                                        "name": "pf_list_1_{}".format(
+                                                            addr_type
+                                                        ),
+                                                        "direction": "out",
+                                                        "delete": True,
+                                                    }
+                                                ]
+                                            },
+                                            "r2-link1": {
+                                                "prefix_lists": [
+                                                    {
+                                                        "name": "pf_list_1_{}".format(
+                                                            addr_type
+                                                        ),
+                                                        "direction": "out",
+                                                        "delete": True,
+                                                    }
+                                                ]
+                                            },
+                                            "r2-link2": {
+                                                "prefix_lists": [
+                                                    {
+                                                        "name": "pf_list_1_{}".format(
+                                                            addr_type
+                                                        ),
+                                                        "direction": "out",
+                                                        "delete": True,
+                                                    }
+                                                ]
+                                            },
+                                            "r2-link3": {
+                                                "prefix_lists": [
+                                                    {
+                                                        "name": "pf_list_1_{}".format(
+                                                            addr_type
+                                                        ),
+                                                        "direction": "out",
+                                                        "delete": True,
+                                                    }
+                                                ]
+                                            },
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        input_dict_4 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {
+                                "neighbor": {
+                                    "r3": {
+                                        "dest_link": {
+                                            "r2-link0": {
+                                                "prefix_lists": [
+                                                    {
+                                                        "name": "pf_list_2_{}".format(
+                                                            addr_type
+                                                        ),
+                                                        "direction": "out",
+                                                        "delete": True,
+                                                    }
+                                                ]
+                                            },
+                                            "r2-link1": {
+                                                "prefix_lists": [
+                                                    {
+                                                        "name": "pf_list_2_{}".format(
+                                                            addr_type
+                                                        ),
+                                                        "direction": "out",
+                                                        "delete": True,
+                                                    }
+                                                ]
+                                            },
+                                            "r2-link2": {
+                                                "prefix_lists": [
+                                                    {
+                                                        "name": "pf_list_2_{}".format(
+                                                            addr_type
+                                                        ),
+                                                        "direction": "out",
+                                                        "delete": True,
+                                                    }
+                                                ]
+                                            },
+                                            "r2-link3": {
+                                                "prefix_lists": [
+                                                    {
+                                                        "name": "pf_list_2_{}".format(
+                                                            addr_type
+                                                        ),
+                                                        "direction": "out",
+                                                        "delete": True,
+                                                    }
+                                                ]
+                                            },
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        clear_bgp_and_verify(tgen, topo, "r2")
+
+        step("Create RouteMap_1 with prefix list P1 and weight 50")
+        # Create route map
+        rmap_dict = {
+            "r2": {
+                "route_maps": {
+                    "rmap_pf_list_1_{}".format(addr_type): [
+                        {
+                            "action": "permit",
+                            "set": {"weight": 50},
+                            "match": {
+                                addr_type: {
+                                    "prefix_lists": "pf_list_1_{}".format(addr_type)
+                                }
+                            },
+                        }
+                    ]
+                }
+            }
+        }
+        result = create_route_maps(tgen, rmap_dict)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step("Create RouteMap_2 with prefix list P2 and weight 50")
+        # Create route map
+        rmap_dict = {
+            "r2": {
+                "route_maps": {
+                    "rmap_pf_list_2_{}".format(addr_type): [
+                        {
+                            "action": "permit",
+                            "set": {"weight": 50},
+                            "match": {
+                                addr_type: {
+                                    "prefix_lists": "pf_list_2_{}".format(addr_type)
+                                }
+                            },
+                        }
+                    ]
+                }
+            }
+        }
+        result = create_route_maps(tgen, rmap_dict)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step("Verify Route-map created verify using show route-map")
+        # verify rmap_pf_list_1 and rmap_pf_list_2 are present in router r2
+        input_dict = {
+            "r2": {
+                "route_maps": [
+                    "rmap_pf_list_1_{}".format(addr_type),
+                    "rmap_pf_list_2_{}".format(addr_type),
+                ]
+            }
+        }
+        result = verify_route_maps(tgen, input_dict)
+        assert result is not True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step("Apply policy RouteMap_1 nbrs 1 2 3 4 to FRR 1")
+        # Configure prefix list to bgp neighbor
+        input_dict_4 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {
+                                "neighbor": {
+                                    "r1": {
+                                        "dest_link": {
+                                            "r2-link0": {
+                                                "route_maps": [
+                                                    {
+                                                        "name": "rmap_pf_list_1_"
+                                                        "{}".format(addr_type),
+                                                        "direction": "out",
+                                                    }
+                                                ]
+                                            },
+                                            "r2-link1": {
+                                                "route_maps": [
+                                                    {
+                                                        "name": "rmap_pf_list_1_"
+                                                        "{}".format(addr_type),
+                                                        "direction": "out",
+                                                    }
+                                                ]
+                                            },
+                                            "r2-link2": {
+                                                "route_maps": [
+                                                    {
+                                                        "name": "rmap_pf_list_1_"
+                                                        "{}".format(addr_type),
+                                                        "direction": "out",
+                                                    }
+                                                ]
+                                            },
+                                            "r2-link3": {
+                                                "route_maps": [
+                                                    {
+                                                        "name": "rmap_pf_list_1_"
+                                                        "{}".format(addr_type),
+                                                        "direction": "out",
+                                                    }
+                                                ]
+                                            },
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step("Apply policy RouteMap_2 nbrs 5 and 6 to FRR2")
+        # Configure prefix list to bgp neighbor
+        input_dict_4 = {
+            "r2": {
+                "bgp": {
+                    "address_family": {
+                        addr_type: {
+                            "unicast": {
+                                "neighbor": {
+                                    "r3": {
+                                        "dest_link": {
+                                            "r2-link0": {
+                                                "route_maps": [
+                                                    {
+                                                        "name": "rmap_pf_list_2_"
+                                                        "{}".format(addr_type),
+                                                        "direction": "out",
+                                                    }
+                                                ]
+                                            },
+                                            "r2-link1": {
+                                                "route_maps": [
+                                                    {
+                                                        "name": "rmap_pf_list_2_"
+                                                        "{}".format(addr_type),
+                                                        "direction": "out",
+                                                    }
+                                                ]
+                                            },
+                                            "r2-link2": {
+                                                "route_maps": [
+                                                    {
+                                                        "name": "rmap_pf_list_2_"
+                                                        "{}".format(addr_type),
+                                                        "direction": "out",
+                                                    }
+                                                ]
+                                            },
+                                            "r2-link3": {
+                                                "route_maps": [
+                                                    {
+                                                        "name": "rmap_pf_list_2_"
+                                                        "{}".format(addr_type),
+                                                        "direction": "out",
+                                                    }
+                                                ]
+                                            },
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        result = create_router_bgp(tgen, topo, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        step(
+            "After applying to BGP neighbors verify VM1 IPv4 and IPv6 Route"
+            " which is denied using prefix list is not present on FRR side"
+            " routing table , also not able to ping the routes show ip route"
+            " and VM4 and VM6 IPV4 and IPv6 address are present in local and"
+            " FRR routing table show ip bgp show ip route"
+        )
+
+        dut = "r1"
+        protocol = "bgp"
+        ntwk_r2_vm1 = str(
+            ipaddress.ip_interface(
+                u"{}".format(topo["routers"]["r2"]["links"]["vm1"][addr_type])
+            ).network
+        )
+        input_dict = {"r1": {"static_routes": [{"network": ntwk_r2_vm1}]}}
+        result4 = verify_rib(
+            tgen, addr_type, dut, input_dict, protocol=protocol, expected=False
+        )
+        assert result4 is not True, "Testcase {} : Failed \n" "Error: {}".format(
+            tc_name, result4
+        )
+
+        step("vm4 should be present in FRR1")
+        dut = "r1"
+        ntwk_r2_vm1 = str(
+            ipaddress.ip_interface(
+                u"{}".format(topo["routers"]["r1"]["links"]["vm4"][addr_type])
+            ).network
+        )
+        input_dict = {"r1": {"static_routes": [{"network": ntwk_r2_vm1}]}}
+        result4 = verify_rib(tgen, addr_type, dut, input_dict)
+        assert result4 is True, "Testcase {} : Failed , VM1 route is "
+        "not filtered out via prefix list. \n Error: {}".format(tc_name, result4)
+
+        step("vm4 should be present in FRR2")
+        dut = "r2"
+        ntwk_r2_vm1 = str(
+            ipaddress.ip_interface(
+                u"{}".format(topo["routers"]["r1"]["links"]["vm4"][addr_type])
+            ).network
+        )
+        input_dict = {"r1": {"static_routes": [{"network": ntwk_r2_vm1}]}}
+        result4 = verify_rib(tgen, addr_type, dut, input_dict)
+        assert result4 is True, "Testcase {} : Failed , VM1 route is "
+        "not filtered out via prefix list. \n Error: {}".format(tc_name, result4)
+
+        dut = "r3"
+        protocol = "bgp"
+        ntwk_r2_vm6 = str(
+            ipaddress.ip_interface(
+                u"{}".format(topo["routers"]["r2"]["links"]["vm6"][addr_type])
+            ).network
+        )
+        input_dict = {"r3": {"static_routes": [{"network": ntwk_r2_vm6}]}}
+        result4 = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
+        assert result4 is True, "Testcase {} : Failed.\n Error: {}".format(
+            tc_name, result4
+        )
+
+    write_test_footer(tc_name)
+
+
+def test_static_routes_tor_p0_tc5_ibgp(request):
+    """Verify Static route when FRR connected to 2 TOR."""
+    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)
+    step("Configure link between FRR to FRR1 & FRR2 as shown in the topology.")
+    step("Attach 2 VMs (vm1 & vm2) to FRR, vm3 to FRR1 ,vm4 to FRR2.")
+    step("Configure Ipv4 and ipv6 addresses on all the interfaces.")
+
+    reset_config_on_routers(tgen)
+
+    def_nw = {"ipv4": "0.0.0.0/0", "ipv6": "0::0/0"}
+    step(
+        "Configure the static route (ipv4 & ipv6) on FRR to vm3 and vm4 "
+        "with next hop as FRR1 and FRR2 respectively."
+    )
+    for addr_type in ADDR_TYPES:
+        # Enable static routes
+        for vm in ["vm1", "vm2", "vm3", "vm6"]:
+            input_dict_4 = {
+                vm: {
+                    "static_routes": [
+                        {
+                            "network": def_nw[addr_type],
+                            "next_hop": topo["routers"]["r2"]["links"][vm][
+                                addr_type
+                            ].split("/")[0],
+                        }
+                    ]
+                }
+            }
+            logger.info("Configure static routes")
+            result = create_static_routes(tgen, input_dict_4)
+            assert result is True, "Testcase {} : Failed \n Error: {}".format(
+                tc_name, result
+            )
+
+        input_dict_4 = {
+            "vm4": {
+                "static_routes": [
+                    {
+                        "network": def_nw[addr_type],
+                        "next_hop": topo["routers"]["r1"]["links"]["vm4"][
+                            addr_type
+                        ].split("/")[0],
+                    }
+                ]
+            }
+        }
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        input_dict_4 = {
+            "vm5": {
+                "static_routes": [
+                    {
+                        "network": def_nw[addr_type],
+                        "next_hop": topo["routers"]["r3"]["links"]["vm5"][
+                            addr_type
+                        ].split("/")[0],
+                    }
+                ]
+            }
+        }
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        input_dict_4 = {
+            "r1": {
+                "static_routes": [
+                    {
+                        "network": topo["routers"]["vm1"]["links"]["r2"][
+                            addr_type
+                        ].split("/")[0]
+                        + "/16",
+                        "next_hop": topo["routers"]["r2"]["links"]["r1-link0"][
+                            addr_type
+                        ].split("/")[0],
+                    },
+                    {
+                        "network": topo["routers"]["vm2"]["links"]["r2"][
+                            addr_type
+                        ].split("/")[0]
+                        + "/16",
+                        "next_hop": topo["routers"]["r2"]["links"]["r1-link0"][
+                            addr_type
+                        ].split("/")[0],
+                    },
+                ]
+            }
+        }
+
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        # Enable static routes
+        input_dict_4 = {
+            "r3": {
+                "static_routes": [
+                    {
+                        "network": topo["routers"]["vm3"]["links"]["r2"][
+                            addr_type
+                        ].split("/")[0]
+                        + "/16",
+                        "next_hop": topo["routers"]["r2"]["links"]["r3-link0"][
+                            addr_type
+                        ].split("/")[0],
+                    },
+                    {
+                        "network": topo["routers"]["vm6"]["links"]["r2"][
+                            addr_type
+                        ].split("/")[0]
+                        + "/16",
+                        "next_hop": topo["routers"]["r2"]["links"]["r3-link0"][
+                            addr_type
+                        ].split("/")[0],
+                    },
+                ]
+            }
+        }
+
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+
+        # Enable static routes
+        input_dict_4 = {
+            "r2": {
+                "static_routes": [
+                    {
+                        "network": topo["routers"]["vm4"]["links"]["r1"][
+                            addr_type
+                        ].split("/")[0]
+                        + "/16",
+                        "next_hop": topo["routers"]["r1"]["links"]["r2-link0"][
+                            addr_type
+                        ].split("/")[0],
+                    },
+                    {
+                        "network": topo["routers"]["vm5"]["links"]["r3"][
+                            addr_type
+                        ].split("/")[0]
+                        + "/16",
+                        "next_hop": topo["routers"]["r3"]["links"]["r2-link0"][
+                            addr_type
+                        ].split("/")[0],
+                    },
+                    {
+                        "network": topo["routers"]["vm4"]["links"]["r1"][addr_type],
+                        "next_hop": topo["routers"]["r1"]["links"]["r2-link0"][
+                            addr_type
+                        ].split("/")[0],
+                    },
+                    {
+                        "network": topo["routers"]["vm5"]["links"]["r3"][addr_type],
+                        "next_hop": topo["routers"]["r3"]["links"]["r2-link0"][
+                            addr_type
+                        ].split("/")[0],
+                    },
+                    {
+                        "network": topo["routers"]["r1"]["links"]["vm4"][addr_type],
+                        "next_hop": topo["routers"]["r1"]["links"]["r2-link0"][
+                            addr_type
+                        ].split("/")[0],
+                    },
+                    {
+                        "network": topo["routers"]["r3"]["links"]["vm5"][addr_type],
+                        "next_hop": topo["routers"]["r3"]["links"]["r2-link0"][
+                            addr_type
+                        ].split("/")[0],
+                    },
+                ]
+            }
+        }
+
+        logger.info("Configure static routes")
+        result = create_static_routes(tgen, input_dict_4)
+        assert result is True, "Testcase {} : Failed \n Error: {}".format(
+            tc_name, result
+        )
+        sleep(10)
+        step(
+            "Ping from all the vms for both ipv4 and ipv6 address. "
+            "All the ping should pass."
+        )
+
+        step("ping from vm4 to vm1 vm2")
+        vm4tovm1 = topo["routers"]["vm1"]["links"]["r2"][addr_type].split("/")[0]
+        result = verify_kernel_ping(tgen, "vm4", vm4tovm1, count=1, addrtype=addr_type)
+        assert result is True, "Testcase {}:Failed \n Error: {}".format(tc_name, result)
+
+        vm4tovm2 = topo["routers"]["vm2"]["links"]["r2"][addr_type].split("/")[0]
+        result = verify_kernel_ping(tgen, "vm4", vm4tovm2, count=1, addrtype=addr_type)
+        assert result is True, "Testcase {}:Failed \n Error: {}".format(tc_name, result)
+
+        step("ping from vm5 to vm3 vm6")
+        vm5tovm3 = topo["routers"]["vm3"]["links"]["r2"][addr_type].split("/")[0]
+        result = verify_kernel_ping(tgen, "vm5", vm5tovm3, count=1, addrtype=addr_type)
+        assert result is True, "Testcase {}:Failed \n Error: {}".format(tc_name, result)
+
+        vm5tovm6 = topo["routers"]["vm6"]["links"]["r2"][addr_type].split("/")[0]
+        result = verify_kernel_ping(tgen, "vm5", vm5tovm6, count=1, addrtype=addr_type)
+        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))