tests: Adding static routing topojson automation suites.

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>
This commit is contained in:
naveen 2020-04-13 21:24:45 +05:30 committed by Vijay Kumar Gupta
parent 101ad544fa
commit 0705f3120d
19 changed files with 13692 additions and 26 deletions

View 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 = [
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][0][
"nexthops"
for rib_r in rib_routes_json["routes"][
st_rt
][mnh]["nexthops"]
]
]
list2 = found_hops
missing_list_of_nexthops = set(list2).difference(list1)
)
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"

View 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 = (

View 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

View File

@ -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": {}
}
}
}
}
}
}
}
}
}
}

View File

@ -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": {}
}
}
}
}
}
}
}
}
}
}

View File

@ -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": {}
}
}
}
}
}
}
}
}
}
}

View File

@ -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"
}
}
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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))

View File

@ -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))

View File

@ -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": {}
}
}
}
}
}
}
}
}
}
}

View File

@ -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": {}
}
}
}
}
}
}
}
}
}
}

View File

@ -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": {}
}
}
}
}
}
}
}
}
}
}

View File

@ -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"
}
}
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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))

File diff suppressed because it is too large Load Diff