mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-04-29 18:10:23 +00:00
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:
parent
101ad544fa
commit
0705f3120d
@ -21,6 +21,7 @@
|
|||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
from time import sleep
|
from time import sleep
|
||||||
import traceback
|
import traceback
|
||||||
|
import ipaddr
|
||||||
import ipaddress
|
import ipaddress
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
@ -2115,8 +2116,8 @@ def verify_bgp_attributes(
|
|||||||
errormsg(str) or True
|
errormsg(str) or True
|
||||||
"""
|
"""
|
||||||
|
|
||||||
logger.debug("Entering lib API: verify_bgp_attributes()")
|
logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
|
||||||
for router, rnode in tgen.routers().items():
|
for router, rnode in tgen.routers().iteritems():
|
||||||
if router != dut:
|
if router != dut:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -2194,7 +2195,7 @@ def verify_bgp_attributes(
|
|||||||
)
|
)
|
||||||
return errormsg
|
return errormsg
|
||||||
|
|
||||||
logger.debug("Exiting lib API: verify_bgp_attributes()")
|
logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
|
||||||
return True
|
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 = []
|
additional_nexthops_in_required_nhs = []
|
||||||
list1 = []
|
list1 = []
|
||||||
list2 = []
|
list2 = []
|
||||||
|
found_hops = []
|
||||||
for routerInput in input_dict.keys():
|
for routerInput in input_dict.keys():
|
||||||
for router, rnode in router_list.items():
|
for router, rnode in router_list.items():
|
||||||
if router != dut:
|
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
|
st_found = True
|
||||||
found_routes.append(st_rt)
|
found_routes.append(st_rt)
|
||||||
|
|
||||||
if next_hop:
|
if next_hop and multi_nh and st_found:
|
||||||
if not isinstance(next_hop, list):
|
if not isinstance(next_hop, list):
|
||||||
next_hop = [next_hop]
|
next_hop = [next_hop]
|
||||||
list1 = next_hop
|
list1 = next_hop
|
||||||
|
|
||||||
found_hops = [
|
for mnh in range(
|
||||||
rib_r["ip"]
|
0, len(rib_routes_json["routes"][st_rt])
|
||||||
for rib_r in rib_routes_json["routes"][st_rt][0][
|
):
|
||||||
"nexthops"
|
found_hops.append(
|
||||||
]
|
[
|
||||||
]
|
rib_r["ip"]
|
||||||
list2 = found_hops
|
for rib_r in rib_routes_json["routes"][
|
||||||
|
st_rt
|
||||||
missing_list_of_nexthops = set(list2).difference(list1)
|
][mnh]["nexthops"]
|
||||||
|
]
|
||||||
|
)
|
||||||
|
for mnh in found_hops:
|
||||||
|
for each_nh_in_multipath in mnh:
|
||||||
|
list2.append(each_nh_in_multipath)
|
||||||
|
if found_hops[0]:
|
||||||
|
missing_list_of_nexthops = set(list2).difference(
|
||||||
|
list1
|
||||||
|
)
|
||||||
additional_nexthops_in_required_nhs = set(
|
additional_nexthops_in_required_nhs = set(
|
||||||
list1
|
list1
|
||||||
).difference(list2)
|
).difference(list2)
|
||||||
@ -2643,17 +2654,37 @@ def verify_bgp_rib(tgen, addr_type, dut, input_dict, next_hop=None, aspath=None)
|
|||||||
st_rt,
|
st_rt,
|
||||||
dut,
|
dut,
|
||||||
)
|
)
|
||||||
errormsg = (
|
|
||||||
"Nexthop {} is Missing for "
|
|
||||||
"route {} in RIB of router {}\n".format(
|
|
||||||
additional_nexthops_in_required_nhs,
|
|
||||||
st_rt,
|
|
||||||
dut,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return errormsg
|
return errormsg
|
||||||
else:
|
else:
|
||||||
nh_found = True
|
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:
|
if aspath:
|
||||||
found_paths = rib_routes_json["routes"][st_rt][0][
|
found_paths = rib_routes_json["routes"][st_rt][0][
|
||||||
"path"
|
"path"
|
||||||
|
@ -1156,10 +1156,16 @@ def generate_ips(network, no_of_ips):
|
|||||||
|
|
||||||
addr_type = validate_ip_address(start_ip)
|
addr_type = validate_ip_address(start_ip)
|
||||||
if addr_type == "ipv4":
|
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)
|
step = 2 ** (32 - mask)
|
||||||
if addr_type == "ipv6":
|
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)
|
step = 2 ** (128 - mask)
|
||||||
|
|
||||||
next_ip = start_ip
|
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)
|
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(
|
def addKernelRoute(
|
||||||
tgen, router, intf, group_addr_range, next_hop=None, src=None, del_action=None
|
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:
|
for addr_type in prefix_lists_addr:
|
||||||
if not check_address_types(addr_type):
|
if not check_address_types(addr_type):
|
||||||
continue
|
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():
|
for prefix_list in prefix_lists_addr[addr_type].keys():
|
||||||
if prefix_list in show_prefix_list:
|
if prefix_list in show_prefix_list:
|
||||||
errormsg = (
|
errormsg = (
|
||||||
|
@ -96,6 +96,7 @@ def build_topo_from_json(tgen, topo):
|
|||||||
for router in listRouters:
|
for router in listRouters:
|
||||||
topo["routers"][router]["nextIfname"] = 0
|
topo["routers"][router]["nextIfname"] = 0
|
||||||
|
|
||||||
|
router_count = 0
|
||||||
while listRouters != []:
|
while listRouters != []:
|
||||||
curRouter = listRouters.pop(0)
|
curRouter = listRouters.pop(0)
|
||||||
# Physical Interfaces
|
# Physical Interfaces
|
||||||
@ -116,13 +117,14 @@ def build_topo_from_json(tgen, topo):
|
|||||||
currRouter_lo_json = topo["routers"][curRouter]["links"][destRouterLink]
|
currRouter_lo_json = topo["routers"][curRouter]["links"][destRouterLink]
|
||||||
# Loopback interfaces
|
# Loopback interfaces
|
||||||
if "type" in data and data["type"] == "loopback":
|
if "type" in data and data["type"] == "loopback":
|
||||||
|
router_count += 1
|
||||||
if (
|
if (
|
||||||
"ipv4" in currRouter_lo_json
|
"ipv4" in currRouter_lo_json
|
||||||
and currRouter_lo_json["ipv4"] == "auto"
|
and currRouter_lo_json["ipv4"] == "auto"
|
||||||
):
|
):
|
||||||
currRouter_lo_json["ipv4"] = "{}{}.{}/{}".format(
|
currRouter_lo_json["ipv4"] = "{}{}.{}/{}".format(
|
||||||
topo["lo_prefix"]["ipv4"],
|
topo["lo_prefix"]["ipv4"],
|
||||||
number_to_row(curRouter),
|
router_count,
|
||||||
number_to_column(curRouter),
|
number_to_column(curRouter),
|
||||||
topo["lo_prefix"]["v4mask"],
|
topo["lo_prefix"]["v4mask"],
|
||||||
)
|
)
|
||||||
@ -132,7 +134,7 @@ def build_topo_from_json(tgen, topo):
|
|||||||
):
|
):
|
||||||
currRouter_lo_json["ipv6"] = "{}{}:{}/{}".format(
|
currRouter_lo_json["ipv6"] = "{}{}:{}/{}".format(
|
||||||
topo["lo_prefix"]["ipv6"],
|
topo["lo_prefix"]["ipv6"],
|
||||||
number_to_row(curRouter),
|
router_count,
|
||||||
number_to_column(curRouter),
|
number_to_column(curRouter),
|
||||||
topo["lo_prefix"]["v6mask"],
|
topo["lo_prefix"]["v6mask"],
|
||||||
)
|
)
|
||||||
@ -167,6 +169,14 @@ def build_topo_from_json(tgen, topo):
|
|||||||
destRouter, curRouter, topo["routers"][destRouter]["nextIfname"]
|
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"][curRouter]["nextIfname"] += 1
|
||||||
topo["routers"][destRouter]["nextIfname"] += 1
|
topo["routers"][destRouter]["nextIfname"] += 1
|
||||||
|
|
||||||
|
@ -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": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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
@ -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))
|
@ -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))
|
@ -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": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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
@ -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
Loading…
Reference in New Issue
Block a user