Merge pull request #8946 from gpnaveen/bgp_lib_changes

tests: Adding lib changes for bgp peer type verification.
This commit is contained in:
Donald Sharp 2021-07-16 09:15:36 -04:00 committed by GitHub
commit c24e832ae9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 466 additions and 214 deletions

View file

@ -41,7 +41,10 @@
"neighbor": { "neighbor": {
"e1": { "e1": {
"dest_link": { "dest_link": {
"r1": {} "r1": {
"keepalivetimer": 1,
"holddowntimer": 3
}
} }
} }
} }
@ -55,7 +58,10 @@
"neighbor": { "neighbor": {
"e1": { "e1": {
"dest_link": { "dest_link": {
"r1": {} "r1": {
"keepalivetimer": 1,
"holddowntimer": 3
}
} }
} }
} }
@ -106,7 +112,10 @@
"neighbor": { "neighbor": {
"e1": { "e1": {
"dest_link": { "dest_link": {
"r2-link1": {} "r2-link1": {
"keepalivetimer": 1,
"holddowntimer": 3
}
} }
} }
} }
@ -120,7 +129,10 @@
"neighbor": { "neighbor": {
"e1": { "e1": {
"dest_link": { "dest_link": {
"r2-link1": {} "r2-link1": {
"keepalivetimer": 1,
"holddowntimer": 3
}
} }
} }
} }
@ -140,7 +152,10 @@
"neighbor": { "neighbor": {
"e1": { "e1": {
"dest_link": { "dest_link": {
"r2-link2": {} "r2-link2": {
"keepalivetimer": 1,
"holddowntimer": 3
}
} }
} }
} }
@ -154,7 +169,10 @@
"neighbor": { "neighbor": {
"e1": { "e1": {
"dest_link": { "dest_link": {
"r2-link2": {} "r2-link2": {
"keepalivetimer": 1,
"holddowntimer": 3
}
} }
} }
} }
@ -222,7 +240,10 @@
"neighbor": { "neighbor": {
"r1": { "r1": {
"dest_link": { "dest_link": {
"e1": {} "e1": {
"keepalivetimer": 1,
"holddowntimer": 3
}
} }
} }
} }
@ -233,7 +254,10 @@
"neighbor": { "neighbor": {
"r1": { "r1": {
"dest_link": { "dest_link": {
"e1": {} "e1": {
"keepalivetimer": 1,
"holddowntimer": 3
}
} }
} }
} }
@ -262,7 +286,10 @@
"neighbor": { "neighbor": {
"r2": { "r2": {
"dest_link": { "dest_link": {
"e1-link1": {} "e1-link1": {
"keepalivetimer": 1,
"holddowntimer": 3
}
} }
} }
} }
@ -273,7 +300,10 @@
"neighbor": { "neighbor": {
"r2": { "r2": {
"dest_link": { "dest_link": {
"e1-link1": {} "e1-link1": {
"keepalivetimer": 1,
"holddowntimer": 3
}
} }
} }
} }
@ -302,7 +332,10 @@
"neighbor": { "neighbor": {
"r2": { "r2": {
"dest_link": { "dest_link": {
"e1-link2": {} "e1-link2": {
"keepalivetimer": 1,
"holddowntimer": 3
}
} }
} }
} }
@ -313,7 +346,10 @@
"neighbor": { "neighbor": {
"r2": { "r2": {
"dest_link": { "dest_link": {
"e1-link2": {} "e1-link2": {
"keepalivetimer": 1,
"holddowntimer": 3
}
} }
} }
} }
@ -342,6 +378,8 @@
"d1": { "d1": {
"dest_link": { "dest_link": {
"e1-link1": { "e1-link1": {
"keepalivetimer": 1,
"holddowntimer": 3,
"deactivate": "ipv4" "deactivate": "ipv4"
} }
} }
@ -349,6 +387,8 @@
"d2": { "d2": {
"dest_link": { "dest_link": {
"e1-link1": { "e1-link1": {
"keepalivetimer": 1,
"holddowntimer": 3,
"deactivate": "ipv4" "deactivate": "ipv4"
} }
} }
@ -412,6 +452,8 @@
"e1": { "e1": {
"dest_link": { "dest_link": {
"d1-link1": { "d1-link1": {
"keepalivetimer": 1,
"holddowntimer": 3,
"deactivate": "ipv4" "deactivate": "ipv4"
} }
} }
@ -442,7 +484,10 @@
"neighbor": { "neighbor": {
"r3": { "r3": {
"dest_link": { "dest_link": {
"d1": {} "d1": {
"keepalivetimer": 1,
"holddowntimer": 3
}
} }
} }
} }
@ -453,7 +498,10 @@
"neighbor": { "neighbor": {
"r3": { "r3": {
"dest_link": { "dest_link": {
"d1": {} "d1": {
"keepalivetimer": 1,
"holddowntimer": 3
}
} }
} }
} }
@ -482,7 +530,10 @@
"neighbor": { "neighbor": {
"r4": { "r4": {
"dest_link": { "dest_link": {
"d1-link1": {} "d1-link1": {
"keepalivetimer": 1,
"holddowntimer": 3
}
} }
} }
} }
@ -493,7 +544,10 @@
"neighbor": { "neighbor": {
"r4": { "r4": {
"dest_link": { "dest_link": {
"d1-link1": {} "d1-link1": {
"keepalivetimer": 1,
"holddowntimer": 3
}
} }
} }
} }
@ -522,7 +576,10 @@
"neighbor": { "neighbor": {
"r4": { "r4": {
"dest_link": { "dest_link": {
"d1-link2": {} "d1-link2": {
"keepalivetimer": 1,
"holddowntimer": 3
}
} }
} }
} }
@ -533,7 +590,10 @@
"neighbor": { "neighbor": {
"r4": { "r4": {
"dest_link": { "dest_link": {
"d1-link2": {} "d1-link2": {
"keepalivetimer": 1,
"holddowntimer": 3
}
} }
} }
} }
@ -590,7 +650,9 @@
"e1": { "e1": {
"dest_link": { "dest_link": {
"d2-link1": { "d2-link1": {
"deactivate": "ipv4" "deactivate": "ipv4",
"keepalivetimer": 1,
"holddowntimer": 3
} }
} }
} }
@ -620,7 +682,10 @@
"neighbor": { "neighbor": {
"r3": { "r3": {
"dest_link": { "dest_link": {
"d2": {} "d2": {
"keepalivetimer": 1,
"holddowntimer": 3
}
} }
} }
} }
@ -631,7 +696,10 @@
"neighbor": { "neighbor": {
"r3": { "r3": {
"dest_link": { "dest_link": {
"d2": {} "d2": {
"keepalivetimer": 1,
"holddowntimer": 3
}
} }
} }
} }
@ -660,7 +728,10 @@
"neighbor": { "neighbor": {
"r4": { "r4": {
"dest_link": { "dest_link": {
"d2-link1": {} "d2-link1": {
"keepalivetimer": 1,
"holddowntimer": 3
}
} }
} }
} }
@ -671,7 +742,10 @@
"neighbor": { "neighbor": {
"r4": { "r4": {
"dest_link": { "dest_link": {
"d2-link1": {} "d2-link1": {
"keepalivetimer": 1,
"holddowntimer": 3
}
} }
} }
} }
@ -700,7 +774,10 @@
"neighbor": { "neighbor": {
"r4": { "r4": {
"dest_link": { "dest_link": {
"d2-link2": {} "d2-link2": {
"keepalivetimer": 1,
"holddowntimer": 3
}
} }
} }
} }
@ -711,7 +788,10 @@
"neighbor": { "neighbor": {
"r4": { "r4": {
"dest_link": { "dest_link": {
"d2-link2": {} "d2-link2": {
"keepalivetimer": 1,
"holddowntimer": 3
}
} }
} }
} }
@ -755,12 +835,18 @@
"neighbor": { "neighbor": {
"d1": { "d1": {
"dest_link": { "dest_link": {
"r3": {} "r3": {
"keepalivetimer": 1,
"holddowntimer": 3
}
} }
}, },
"d2": { "d2": {
"dest_link": { "dest_link": {
"r3": {} "r3": {
"keepalivetimer": 1,
"holddowntimer": 3
}
} }
} }
} }
@ -771,12 +857,18 @@
"neighbor": { "neighbor": {
"d1": { "d1": {
"dest_link": { "dest_link": {
"r3": {} "r3": {
"keepalivetimer": 1,
"holddowntimer": 3
}
} }
}, },
"d2": { "d2": {
"dest_link": { "dest_link": {
"r3": {} "r3": {
"keepalivetimer": 1,
"holddowntimer": 3
}
} }
} }
} }
@ -814,12 +906,18 @@
"neighbor": { "neighbor": {
"d1": { "d1": {
"dest_link": { "dest_link": {
"r4-link1": {} "r4-link1": {
"keepalivetimer": 1,
"holddowntimer": 3
}
} }
}, },
"d2": { "d2": {
"dest_link": { "dest_link": {
"r4-link1": {} "r4-link1": {
"keepalivetimer": 1,
"holddowntimer": 3
}
} }
} }
} }
@ -830,12 +928,18 @@
"neighbor": { "neighbor": {
"d1": { "d1": {
"dest_link": { "dest_link": {
"r4-link1": {} "r4-link1": {
"keepalivetimer": 1,
"holddowntimer": 3
}
} }
}, },
"d2": { "d2": {
"dest_link": { "dest_link": {
"r4-link1": {} "r4-link1": {
"keepalivetimer": 1,
"holddowntimer": 3
}
} }
} }
} }
@ -852,12 +956,18 @@
"neighbor": { "neighbor": {
"d1": { "d1": {
"dest_link": { "dest_link": {
"r4-link2": {} "r4-link2": {
"keepalivetimer": 1,
"holddowntimer": 3
}
} }
}, },
"d2": { "d2": {
"dest_link": { "dest_link": {
"r4-link2": {} "r4-link2": {
"keepalivetimer": 1,
"holddowntimer": 3
}
} }
} }
} }
@ -868,12 +978,18 @@
"neighbor": { "neighbor": {
"d1": { "d1": {
"dest_link": { "dest_link": {
"r4-link2": {} "r4-link2": {
"keepalivetimer": 1,
"holddowntimer": 3
}
} }
}, },
"d2": { "d2": {
"dest_link": { "dest_link": {
"r4-link2": {} "r4-link2": {
"keepalivetimer": 1,
"holddowntimer": 3
}
} }
} }
} }
@ -885,3 +1001,4 @@
} }
} }
} }

View file

@ -44,6 +44,7 @@ from lib.common_config import (
FRRCFG_FILE, FRRCFG_FILE,
retry, retry,
get_ipv6_linklocal_address, get_ipv6_linklocal_address,
get_frr_ipv6_linklocal
) )
LOGDIR = "/tmp/topotests/" LOGDIR = "/tmp/topotests/"
@ -265,6 +266,11 @@ def __create_bgp_global(tgen, input_dict, router, build=False):
config_data.append("bgp router-id {}".format(router_id)) config_data.append("bgp router-id {}".format(router_id))
config_data.append("no bgp network import-check") config_data.append("no bgp network import-check")
bgp_peer_grp_data = bgp_data.setdefault("peer-group", {})
if "peer-group" in bgp_data and bgp_peer_grp_data:
peer_grp_data = __create_bgp_peer_group(tgen, bgp_peer_grp_data, router)
config_data.extend(peer_grp_data)
bst_path = bgp_data.setdefault("bestpath", None) bst_path = bgp_data.setdefault("bestpath", None)
if bst_path: if bst_path:
@ -380,6 +386,7 @@ def __create_bgp_unicast_neighbor(
addr_data = addr_dict["unicast"] addr_data = addr_dict["unicast"]
if addr_data: if addr_data:
config_data.append("address-family {} unicast".format(addr_type)) config_data.append("address-family {} unicast".format(addr_type))
advertise_network = addr_data.setdefault("advertise_networks", []) advertise_network = addr_data.setdefault("advertise_networks", [])
for advertise_network_dict in advertise_network: for advertise_network_dict in advertise_network:
network = advertise_network_dict["network"] network = advertise_network_dict["network"]
@ -404,14 +411,29 @@ def __create_bgp_unicast_neighbor(
config_data.append(cmd) config_data.append(cmd)
import_cmd = addr_data.setdefault("import", {})
if import_cmd:
try:
if import_cmd["delete"]:
config_data.append("no import vrf {}".format(import_cmd["vrf"]))
except KeyError:
config_data.append("import vrf {}".format(import_cmd["vrf"]))
max_paths = addr_data.setdefault("maximum_paths", {}) max_paths = addr_data.setdefault("maximum_paths", {})
if max_paths: if max_paths:
ibgp = max_paths.setdefault("ibgp", None) ibgp = max_paths.setdefault("ibgp", None)
ebgp = max_paths.setdefault("ebgp", None) ebgp = max_paths.setdefault("ebgp", None)
del_cmd = max_paths.setdefault("delete", False)
if ibgp: if ibgp:
config_data.append("maximum-paths ibgp {}".format(ibgp)) if del_cmd:
config_data.append("no maximum-paths ibgp {}".format(ibgp))
else:
config_data.append("maximum-paths ibgp {}".format(ibgp))
if ebgp: if ebgp:
config_data.append("maximum-paths {}".format(ebgp)) if del_cmd:
config_data.append("no maximum-paths {}".format(ebgp))
else:
config_data.append("maximum-paths {}".format(ebgp))
aggregate_addresses = addr_data.setdefault("aggregate_address", []) aggregate_addresses = addr_data.setdefault("aggregate_address", [])
for aggregate_address in aggregate_addresses: for aggregate_address in aggregate_addresses:
@ -649,6 +671,38 @@ def __create_l2vpn_evpn_address_family(
return config_data return config_data
def __create_bgp_peer_group(topo, input_dict, router):
"""
Helper API to create neighbor specific configuration
Parameters
----------
* `topo` : json file data
* `input_dict` : Input dict data, required when configuring from testcase
* `router` : router id to be configured
"""
config_data = []
logger.debug("Entering lib API: __create_bgp_peer_group()")
for grp, grp_dict in input_dict.items():
config_data.append("neighbor {} peer-group".format(grp))
neigh_cxt = "neighbor {} ".format(grp)
update_source = grp_dict.setdefault("update-source", None)
remote_as = grp_dict.setdefault("remote-as", None)
capability = grp_dict.setdefault("capability", None)
if update_source:
config_data.append("{} update-source {}".format(neigh_cxt, update_source))
if remote_as:
config_data.append("{} remote-as {}".format(neigh_cxt, remote_as))
if capability:
config_data.append("{} capability {}".format(neigh_cxt, capability))
logger.debug("Exiting lib API: __create_bgp_peer_group()")
return config_data
def __create_bgp_neighbor(topo, input_dict, router, addr_type, add_neigh=True): def __create_bgp_neighbor(topo, input_dict, router, addr_type, add_neigh=True):
""" """
Helper API to create neighbor specific configuration Helper API to create neighbor specific configuration
@ -660,10 +714,9 @@ def __create_bgp_neighbor(topo, input_dict, router, addr_type, add_neigh=True):
* `input_dict` : Input dict data, required when configuring from testcase * `input_dict` : Input dict data, required when configuring from testcase
* `router` : router id to be configured * `router` : router id to be configured
""" """
config_data = [] config_data = []
logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name)) logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
tgen = get_topogen()
bgp_data = input_dict["address_family"] bgp_data = input_dict["address_family"]
neigh_data = bgp_data[addr_type]["unicast"]["neighbor"] neigh_data = bgp_data[addr_type]["unicast"]["neighbor"]
@ -672,35 +725,91 @@ def __create_bgp_neighbor(topo, input_dict, router, addr_type, add_neigh=True):
nh_details = topo[name] nh_details = topo[name]
if "vrfs" in topo[router] or type(nh_details["bgp"]) is list: if "vrfs" in topo[router] or type(nh_details["bgp"]) is list:
remote_as = nh_details["bgp"][0]["local_as"] for vrf_data in nh_details["bgp"]:
if "vrf" in nh_details["links"][dest_link] and "vrf" in vrf_data:
if nh_details["links"][dest_link]["vrf"] == vrf_data["vrf"]:
remote_as = vrf_data["local_as"]
break
else:
if "vrf" not in vrf_data:
remote_as = vrf_data["local_as"]
break
else: else:
remote_as = nh_details["bgp"]["local_as"] remote_as = nh_details["bgp"]["local_as"]
update_source = None update_source = None
if dest_link in nh_details["links"].keys(): if "neighbor_type" in peer and peer["neighbor_type"] == "unnumbered":
ip_addr = nh_details["links"][dest_link][addr_type].split("/")[0] ip_addr = nh_details["links"][dest_link]["peer-interface"]
elif "neighbor_type" in peer and peer["neighbor_type"] == "link-local":
intf = topo[name]["links"][dest_link]["interface"]
ip_addr = get_frr_ipv6_linklocal(tgen, name, intf)
elif dest_link in nh_details["links"].keys():
try:
ip_addr = nh_details["links"][dest_link][addr_type].split("/")[0]
except KeyError:
intf = topo[name]["links"][dest_link]["interface"]
ip_addr = get_frr_ipv6_linklocal(tgen, name, intf)
if "delete" in peer and peer["delete"]:
neigh_cxt = "no neighbor {}".format(ip_addr)
config_data.append("{}".format(neigh_cxt))
return config_data
else:
neigh_cxt = "neighbor {}".format(ip_addr)
if "peer-group" in peer:
config_data.append(
"neighbor {} interface peer-group {}".format(
ip_addr, peer["peer-group"]
)
)
# Loopback interface # Loopback interface
if "source_link" in peer and peer["source_link"] == "lo": if "source_link" in peer:
update_source = topo[router]["links"]["lo"][addr_type].split("/")[0] if peer["source_link"] == "lo":
update_source = topo[router]["links"]["lo"][addr_type].split("/")[0]
else:
update_source = topo[router]["links"][peer["source_link"]][
"interface"
]
if "peer-group" not in peer:
if "neighbor_type" in peer and peer["neighbor_type"] == "unnumbered":
config_data.append(
"{} interface remote-as {}".format(neigh_cxt, remote_as)
)
elif add_neigh:
config_data.append("{} remote-as {}".format(neigh_cxt, remote_as))
neigh_cxt = "neighbor {}".format(ip_addr)
if add_neigh:
config_data.append("{} remote-as {}".format(neigh_cxt, remote_as))
if addr_type == "ipv6": if addr_type == "ipv6":
config_data.append("address-family ipv6 unicast") config_data.append("address-family ipv6 unicast")
config_data.append("{} activate".format(neigh_cxt)) config_data.append("{} activate".format(neigh_cxt))
if "neighbor_type" in peer and peer["neighbor_type"] == "link-local":
config_data.append(
"{} update-source {}".format(
neigh_cxt, nh_details["links"][dest_link]["peer-interface"]
)
)
config_data.append(
"{} interface {}".format(
neigh_cxt, nh_details["links"][dest_link]["peer-interface"]
)
)
disable_connected = peer.setdefault("disable_connected_check", False) disable_connected = peer.setdefault("disable_connected_check", False)
keep_alive = peer.setdefault("keepalivetimer", 3) keep_alive = peer.setdefault("keepalivetimer", 3)
hold_down = peer.setdefault("holddowntimer", 10) hold_down = peer.setdefault("holddowntimer", 10)
password = peer.setdefault("password", None) password = peer.setdefault("password", None)
no_password = peer.setdefault("no_password", None) no_password = peer.setdefault("no_password", None)
capability = peer.setdefault("capability", None)
max_hop_limit = peer.setdefault("ebgp_multihop", 1) max_hop_limit = peer.setdefault("ebgp_multihop", 1)
graceful_restart = peer.setdefault("graceful-restart", None) graceful_restart = peer.setdefault("graceful-restart", None)
graceful_restart_helper = peer.setdefault("graceful-restart-helper", None) graceful_restart_helper = peer.setdefault("graceful-restart-helper", None)
graceful_restart_disable = peer.setdefault("graceful-restart-disable", None) graceful_restart_disable = peer.setdefault("graceful-restart-disable", None)
if capability:
config_data.append("{} capability {}".format(neigh_cxt, capability))
if update_source: if update_source:
config_data.append( config_data.append(
@ -718,7 +827,6 @@ def __create_bgp_neighbor(topo, input_dict, router, addr_type, add_neigh=True):
config_data.append( config_data.append(
"{} timers {} {}".format(neigh_cxt, keep_alive, hold_down) "{} timers {} {}".format(neigh_cxt, keep_alive, hold_down)
) )
if graceful_restart: if graceful_restart:
config_data.append("{} graceful-restart".format(neigh_cxt)) config_data.append("{} graceful-restart".format(neigh_cxt))
elif graceful_restart == False: elif graceful_restart == False:
@ -768,7 +876,7 @@ def __create_bgp_unicast_address_family(
config_data = [] config_data = []
logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name)) logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
tgen = get_topogen()
bgp_data = input_dict["address_family"] bgp_data = input_dict["address_family"]
neigh_data = bgp_data[addr_type]["unicast"]["neighbor"] neigh_data = bgp_data[addr_type]["unicast"]["neighbor"]
@ -784,16 +892,34 @@ def __create_bgp_unicast_address_family(
for destRouterLink, data in sorted(nh_details["links"].items()): for destRouterLink, data in sorted(nh_details["links"].items()):
if "type" in data and data["type"] == "loopback": if "type" in data and data["type"] == "loopback":
if dest_link == destRouterLink: if dest_link == destRouterLink:
ip_addr = nh_details["links"][destRouterLink][ ip_addr = (
addr_type nh_details["links"][destRouterLink][addr_type]
].split("/")[0] .split("/")[0]
.lower()
)
# Physical interface # Physical interface
else: else:
if dest_link in nh_details["links"].keys(): # check the neighbor type if un numbered nbr, use interface.
if "neighbor_type" in peer and peer["neighbor_type"] == "unnumbered":
ip_addr = nh_details["links"][dest_link][addr_type].split("/")[0] ip_addr = nh_details["links"][dest_link]["peer-interface"]
if addr_type == "ipv4" and bgp_data["ipv6"]: elif "neighbor_type" in peer and peer["neighbor_type"] == "link-local":
intf = topo[peer_name]["links"][dest_link]["interface"]
ip_addr = get_frr_ipv6_linklocal(tgen, peer_name, intf)
elif dest_link in nh_details["links"].keys():
try:
ip_addr = nh_details["links"][dest_link][addr_type].split("/")[
0
]
except KeyError:
intf = topo[peer_name]["links"][dest_link]["interface"]
ip_addr = get_frr_ipv6_linklocal(tgen, peer_name, intf)
if (
addr_type == "ipv4"
and bgp_data["ipv6"]
and check_address_types("ipv6")
and "ipv6" in nh_details["links"][dest_link]
):
deactivate = nh_details["links"][dest_link]["ipv6"].split("/")[ deactivate = nh_details["links"][dest_link]["ipv6"].split("/")[
0 0
] ]
@ -822,6 +948,7 @@ def __create_bgp_unicast_address_family(
prefix_lists = peer.setdefault("prefix_lists", {}) prefix_lists = peer.setdefault("prefix_lists", {})
route_maps = peer.setdefault("route_maps", {}) route_maps = peer.setdefault("route_maps", {})
no_send_community = peer.setdefault("no_send_community", None) no_send_community = peer.setdefault("no_send_community", None)
capability = peer.setdefault("capability", None)
allowas_in = peer.setdefault("allowas-in", None) allowas_in = peer.setdefault("allowas-in", None)
# next-hop-self # next-hop-self
@ -841,6 +968,11 @@ def __create_bgp_unicast_address_family(
"no {} send-community {}".format(neigh_cxt, no_send_community) "no {} send-community {}".format(neigh_cxt, no_send_community)
) )
# capability_ext_nh
if capability and addr_type == "ipv6":
config_data.append("address-family ipv4 unicast")
config_data.append("{} activate".format(neigh_cxt))
if "allowas_in" in peer: if "allowas_in" in peer:
allow_as_in = peer["allowas_in"] allow_as_in = peer["allowas_in"]
config_data.append("{} allowas-in {}".format(neigh_cxt, allow_as_in)) config_data.append("{} allowas-in {}".format(neigh_cxt, allow_as_in))
@ -1067,33 +1199,37 @@ def verify_bgp_convergence(tgen, topo, dut=None, expected=True):
API will verify if BGP is converged with in the given time frame. API will verify if BGP is converged with in the given time frame.
Running "show bgp summary json" command and verify bgp neighbor Running "show bgp summary json" command and verify bgp neighbor
state is established, state is established,
Parameters Parameters
---------- ----------
* `tgen`: topogen object * `tgen`: topogen object
* `topo`: input json file data * `topo`: input json file data
* `dut`: device under test * `dut`: device under test
* `expected` : expected results from API, by-default True
Usage Usage
----- -----
# To veriry is BGP is converged for all the routers used in # To veriry is BGP is converged for all the routers used in
topology topology
results = verify_bgp_convergence(tgen, topo, dut="r1") results = verify_bgp_convergence(tgen, topo, dut="r1")
Returns Returns
------- -------
errormsg(str) or True errormsg(str) or True
""" """
logger.debug("Entering lib API: verify_bgp_convergence()") result = False
logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
tgen = get_topogen()
for router, rnode in tgen.routers().items(): for router, rnode in tgen.routers().items():
if 'bgp' not in topo['routers'][router]:
continue
if dut is not None and dut != router: if dut is not None and dut != router:
continue continue
if "bgp" not in topo["routers"][router]:
continue
logger.info("Verifying BGP Convergence on router %s:", router) logger.info("Verifying BGP Convergence on router %s:", router)
show_bgp_json = run_frr_cmd(rnode, "show bgp vrf all summary json", isjson=True) show_bgp_json = run_frr_cmd(rnode, "show bgp vrf all summary json",
isjson=True)
# Verifying output dictionary show_bgp_json is empty or not # Verifying output dictionary show_bgp_json is empty or not
if not bool(show_bgp_json): if not bool(show_bgp_json):
errormsg = "BGP is not running" errormsg = "BGP is not running"
@ -1115,100 +1251,6 @@ def verify_bgp_convergence(tgen, topo, dut=None, expected=True):
# To find neighbor ip type # To find neighbor ip type
bgp_addr_type = bgp_data["address_family"] bgp_addr_type = bgp_data["address_family"]
if "ipv4" in bgp_addr_type or "ipv6" in bgp_addr_type:
for addr_type in bgp_addr_type.keys():
if not check_address_types(addr_type):
continue
total_peer = 0
bgp_neighbors = bgp_addr_type[addr_type]["unicast"]["neighbor"]
for bgp_neighbor in bgp_neighbors:
total_peer += len(bgp_neighbors[bgp_neighbor]["dest_link"])
for addr_type in bgp_addr_type.keys():
if not check_address_types(addr_type):
continue
bgp_neighbors = bgp_addr_type[addr_type]["unicast"]["neighbor"]
no_of_peer = 0
for bgp_neighbor, peer_data in bgp_neighbors.items():
for dest_link in peer_data["dest_link"].keys():
data = topo["routers"][bgp_neighbor]["links"]
if dest_link in data:
peer_details = peer_data["dest_link"][dest_link]
# for link local neighbors
if (
"neighbor_type" in peer_details
and peer_details["neighbor_type"] == "link-local"
):
neighbor_ip = get_ipv6_linklocal_address(
topo["routers"], bgp_neighbor, dest_link
)
elif "source_link" in peer_details:
neighbor_ip = topo["routers"][bgp_neighbor][
"links"
][peer_details["source_link"]][addr_type].split(
"/"
)[
0
]
elif (
"neighbor_type" in peer_details
and peer_details["neighbor_type"] == "unnumbered"
):
neighbor_ip = data[dest_link]["peer-interface"]
else:
neighbor_ip = data[dest_link][addr_type].split("/")[
0
]
nh_state = None
if addr_type == "ipv4":
if "ipv4Unicast" in show_bgp_json[vrf]:
ipv4_data = show_bgp_json[vrf]["ipv4Unicast"][
"peers"
]
nh_state = ipv4_data[neighbor_ip]["state"]
else:
if "ipv6Unicast" in show_bgp_json[vrf]:
ipv6_data = show_bgp_json[vrf]["ipv6Unicast"][
"peers"
]
nh_state = ipv6_data[neighbor_ip]["state"]
if nh_state == "Established":
no_of_peer += 1
if "l2vpn" in bgp_addr_type:
if "neighbor" not in bgp_addr_type["l2vpn"]["evpn"]:
if no_of_peer == total_peer:
logger.info(
"[DUT: %s] VRF: %s, BGP is Converged for %s address-family",
router,
vrf,
addr_type,
)
else:
errormsg = (
"[DUT: %s] VRF: %s, BGP is not converged for %s address-family"
% (router, vrf, addr_type)
)
return errormsg
else:
if no_of_peer == total_peer:
logger.info(
"[DUT: %s] VRF: %s, BGP is Converged for %s address-family",
router,
vrf,
addr_type,
)
else:
errormsg = (
"[DUT: %s] VRF: %s, BGP is not converged for %s address-family"
% (router, vrf, addr_type)
)
return errormsg
if "l2vpn" in bgp_addr_type: if "l2vpn" in bgp_addr_type:
total_evpn_peer = 0 total_evpn_peer = 0
@ -1224,46 +1266,120 @@ def verify_bgp_convergence(tgen, topo, dut=None, expected=True):
data = topo["routers"][bgp_neighbor]["links"] data = topo["routers"][bgp_neighbor]["links"]
for dest_link in dest_link_dict.keys(): for dest_link in dest_link_dict.keys():
if dest_link in data: if dest_link in data:
peer_details = peer_data[_addr_type][dest_link] peer_details = \
peer_data[_addr_type][dest_link]
neighbor_ip = data[dest_link][_addr_type].split("/")[0] neighbor_ip = \
data[dest_link][_addr_type].split(
"/")[0]
nh_state = None nh_state = None
if ( if "ipv4Unicast" in show_bgp_json[vrf] or \
"ipv4Unicast" in show_bgp_json[vrf] "ipv6Unicast" in show_bgp_json[vrf]:
or "ipv6Unicast" in show_bgp_json[vrf] errormsg = ("[DUT: %s] VRF: %s, "
): "ipv4Unicast/ipv6Unicast"
errormsg = ( " address-family present"
"[DUT: %s] VRF: %s, " " under l2vpn" % (router,
"ipv4Unicast/ipv6Unicast" vrf))
" address-family present"
" under l2vpn" % (router, vrf)
)
return errormsg return errormsg
l2VpnEvpn_data = show_bgp_json[vrf]["l2VpnEvpn"][ l2VpnEvpn_data = \
"peers" show_bgp_json[vrf]["l2VpnEvpn"][
] "peers"]
nh_state = l2VpnEvpn_data[neighbor_ip]["state"] nh_state = \
l2VpnEvpn_data[neighbor_ip]["state"]
if nh_state == "Established": if nh_state == "Established":
no_of_evpn_peer += 1 no_of_evpn_peer += 1
if no_of_evpn_peer == total_evpn_peer: if no_of_evpn_peer == total_evpn_peer:
logger.info( logger.info("[DUT: %s] VRF: %s, BGP is Converged for "
"[DUT: %s] VRF: %s, BGP is Converged for " "epvn peers", "epvn peers", router, vrf)
router, result = True
vrf,
)
else: else:
errormsg = ( errormsg = ("[DUT: %s] VRF: %s, BGP is not converged "
"[DUT: %s] VRF: %s, BGP is not converged " "for evpn peers" % (router, vrf))
"for evpn peers" % (router, vrf) return errormsg
) else:
total_peer = 0
for addr_type in bgp_addr_type.keys():
if not check_address_types(addr_type):
continue
bgp_neighbors = \
bgp_addr_type[addr_type]["unicast"]["neighbor"]
for bgp_neighbor in bgp_neighbors:
total_peer += \
len(bgp_neighbors[bgp_neighbor]["dest_link"])
no_of_peer = 0
for addr_type in bgp_addr_type.keys():
if not check_address_types(addr_type):
continue
bgp_neighbors = \
bgp_addr_type[addr_type]["unicast"]["neighbor"]
for bgp_neighbor, peer_data in bgp_neighbors.items():
for dest_link in peer_data["dest_link"].\
keys():
data = \
topo["routers"][bgp_neighbor]["links"]
if dest_link in data:
peer_details = \
peer_data['dest_link'][dest_link]
# for link local neighbors
if "neighbor_type" in peer_details and \
peer_details["neighbor_type"] == \
'link-local':
intf = topo["routers"][bgp_neighbor][
"links"][dest_link]["interface"]
neighbor_ip = get_frr_ipv6_linklocal(
tgen, bgp_neighbor, intf)
elif "source_link" in peer_details:
neighbor_ip = \
topo["routers"][bgp_neighbor][
"links"][peer_details[
'source_link']][
addr_type].\
split("/")[0]
elif "neighbor_type" in peer_details and \
peer_details["neighbor_type"] == \
'unnumbered':
neighbor_ip = \
data[dest_link]["peer-interface"]
else:
neighbor_ip = \
data[dest_link][addr_type].split(
"/")[0]
nh_state = None
neighbor_ip = neighbor_ip.lower()
if addr_type == "ipv4":
ipv4_data = show_bgp_json[vrf][
"ipv4Unicast"]["peers"]
nh_state = \
ipv4_data[neighbor_ip]["state"]
else:
ipv6_data = show_bgp_json[vrf][
"ipv6Unicast"]["peers"]
if neighbor_ip in ipv6_data:
nh_state = \
ipv6_data[neighbor_ip]["state"]
if nh_state == "Established":
no_of_peer += 1
if no_of_peer == total_peer and no_of_peer > 0:
logger.info("[DUT: %s] VRF: %s, BGP is Converged",
router, vrf)
result = True
else:
errormsg = ("[DUT: %s] VRF: %s, BGP is not converged"
% (router, vrf))
return errormsg return errormsg
logger.debug("Exiting API: verify_bgp_convergence()") logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
return True return result
@retry(retry_timeout=16) @retry(retry_timeout=16)

View file

@ -609,6 +609,7 @@ def load_config_to_router(tgen, routerName, save_bkup=False):
return True return True
def get_frr_ipv6_linklocal(tgen, router, intf=None, vrf=None): def get_frr_ipv6_linklocal(tgen, router, intf=None, vrf=None):
""" """
API to get the link local ipv6 address of a particular interface using API to get the link local ipv6 address of a particular interface using
@ -641,38 +642,48 @@ def get_frr_ipv6_linklocal(tgen, router, intf=None, vrf=None):
else: else:
cmd = "show interface" cmd = "show interface"
ifaces = router_list[router].run('vtysh -c "{}"'.format(cmd)) linklocal = []
if vrf:
cmd = "show interface vrf {}".format(vrf)
else:
cmd = "show interface"
for chk_ll in range(0, 60):
sleep(1/4)
ifaces = router_list[router].run('vtysh -c "{}"'.format(cmd))
# Fix newlines (make them all the same)
ifaces = ('\n'.join(ifaces.splitlines()) + '\n').splitlines()
# Fix newlines (make them all the same) interface = None
ifaces = ("\n".join(ifaces.splitlines()) + "\n").splitlines() ll_per_if_count = 0
for line in ifaces:
# Interface name
m = re_search('Interface ([a-zA-Z0-9-]+) is', line)
if m:
interface = m.group(1).split(" ")[0]
ll_per_if_count = 0
interface = None # Interface ip
ll_per_if_count = 0 m1 = re_search('inet6 (fe80[:a-fA-F0-9]+[\/0-9]+)',
for line in ifaces: line)
# Interface name if m1:
m = re_search("Interface ([a-zA-Z0-9-]+) is", line) local = m1.group(1)
if m: ll_per_if_count += 1
interface = m.group(1).split(" ")[0] if ll_per_if_count > 1:
ll_per_if_count = 0 linklocal += [["%s-%s" %
(interface, ll_per_if_count), local]]
else:
linklocal += [[interface, local]]
# Interface ip try:
m1 = re_search("inet6 (fe80[:a-fA-F0-9]+[/0-9]+)", line) if linklocal:
if m1: if intf:
local = m1.group(1) return [_linklocal[1] for _linklocal in linklocal if _linklocal[0]==intf][0].\
ll_per_if_count += 1 split("/")[0]
if ll_per_if_count > 1: return linklocal
linklocal += [["%s-%s" % (interface, ll_per_if_count), local]] except IndexError:
else: continue
linklocal += [[interface, local]]
if linklocal: errormsg = "Link local ip missing on router {}".format(router)
if intf:
return [_linklocal[1] for _linklocal in linklocal if _linklocal[0] == intf][
0
].split("/")[0]
return linklocal
else:
errormsg = "Link local ip missing on router {}"
return errormsg return errormsg
@ -1818,6 +1829,14 @@ def create_interfaces_cfg(tgen, topo, build=False):
else: else:
interface_data.append("ipv6 address {}".format(intf_addr)) interface_data.append("ipv6 address {}".format(intf_addr))
# Wait for vrf interfaces to get link local address once they are up
if not destRouterLink == 'lo' and 'vrf' in topo[c_router][
'links'][destRouterLink]:
vrf = topo[c_router]['links'][destRouterLink]['vrf']
intf = topo[c_router]['links'][destRouterLink]['interface']
ll = get_frr_ipv6_linklocal(tgen, c_router, intf=intf,
vrf = vrf)
if "ipv6-link-local" in data: if "ipv6-link-local" in data:
intf_addr = c_data["links"][destRouterLink]["ipv6-link-local"] intf_addr = c_data["links"][destRouterLink]["ipv6-link-local"]