mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-07 09:22:03 +00:00
Merge pull request #8280 from kuldeepkash/bgp_convergence_test
tests: Fix bgp convergence issue mentioned in #8279
This commit is contained in:
commit
cb39b2d4aa
@ -43,6 +43,7 @@ from lib.common_config import (
|
|||||||
run_frr_cmd,
|
run_frr_cmd,
|
||||||
FRRCFG_FILE,
|
FRRCFG_FILE,
|
||||||
retry,
|
retry,
|
||||||
|
get_ipv6_linklocal_address
|
||||||
)
|
)
|
||||||
|
|
||||||
LOGDIR = "/tmp/topotests/"
|
LOGDIR = "/tmp/topotests/"
|
||||||
@ -446,7 +447,7 @@ def __create_bgp_unicast_neighbor(
|
|||||||
cmd = "redistribute {}".format(redistribute["redist_type"])
|
cmd = "redistribute {}".format(redistribute["redist_type"])
|
||||||
redist_attr = redistribute.setdefault("attribute", None)
|
redist_attr = redistribute.setdefault("attribute", None)
|
||||||
if redist_attr:
|
if redist_attr:
|
||||||
if isinstance(redist_attr, dict):
|
if type(redist_attr) is dict:
|
||||||
for key, value in redist_attr.items():
|
for key, value in redist_attr.items():
|
||||||
cmd = "{} {} {}".format(cmd, key, value)
|
cmd = "{} {} {}".format(cmd, key, value)
|
||||||
else:
|
else:
|
||||||
@ -528,7 +529,7 @@ def __create_l2vpn_evpn_address_family(
|
|||||||
if advertise_data:
|
if advertise_data:
|
||||||
for address_type, unicast_type in advertise_data.items():
|
for address_type, unicast_type in advertise_data.items():
|
||||||
|
|
||||||
if isinstance(unicast_type, dict):
|
if type(unicast_type) is dict:
|
||||||
for key, value in unicast_type.items():
|
for key, value in unicast_type.items():
|
||||||
cmd = "advertise {} {}".format(address_type, key)
|
cmd = "advertise {} {}".format(address_type, key)
|
||||||
|
|
||||||
@ -555,7 +556,7 @@ def __create_l2vpn_evpn_address_family(
|
|||||||
"ipv4"
|
"ipv4"
|
||||||
].split("/")[0]
|
].split("/")[0]
|
||||||
|
|
||||||
if isinstance(action, dict):
|
if type(action) is dict:
|
||||||
next_hop_self = action.setdefault("next_hop_self", None)
|
next_hop_self = action.setdefault("next_hop_self", None)
|
||||||
route_maps = action.setdefault("route_maps", {})
|
route_maps = action.setdefault("route_maps", {})
|
||||||
|
|
||||||
@ -977,10 +978,6 @@ def modify_bgp_config_when_bgpd_down(tgen, topo, input_dict):
|
|||||||
router_list[router].run(cmd)
|
router_list[router].run(cmd)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# handle any exception
|
|
||||||
logger.error("Error %s occured. Arguments %s.", e.message, e.args)
|
|
||||||
|
|
||||||
# Traceback
|
|
||||||
errormsg = traceback.format_exc()
|
errormsg = traceback.format_exc()
|
||||||
logger.error(errormsg)
|
logger.error(errormsg)
|
||||||
return errormsg
|
return errormsg
|
||||||
@ -1085,10 +1082,10 @@ def verify_bgp_convergence(tgen, topo, dut=None):
|
|||||||
|
|
||||||
logger.debug("Entering lib API: verify_bgp_convergence()")
|
logger.debug("Entering lib API: verify_bgp_convergence()")
|
||||||
for router, rnode in tgen.routers().items():
|
for router, rnode in tgen.routers().items():
|
||||||
if "bgp" not in topo["routers"][router]:
|
if dut is not None and dut != router:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if dut is not None and dut != router:
|
if "bgp" not in topo["routers"][router]:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
logger.info("Verifying BGP Convergence on router %s:", router)
|
logger.info("Verifying BGP Convergence on router %s:", router)
|
||||||
@ -1114,6 +1111,100 @@ def verify_bgp_convergence(tgen, topo, dut=None):
|
|||||||
|
|
||||||
# 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
|
||||||
|
|
||||||
@ -1166,82 +1257,6 @@ def verify_bgp_convergence(tgen, topo, dut=None):
|
|||||||
"for evpn peers" % (router, vrf)
|
"for evpn peers" % (router, vrf)
|
||||||
)
|
)
|
||||||
return errormsg
|
return errormsg
|
||||||
else:
|
|
||||||
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":
|
|
||||||
ipv4_data = show_bgp_json[vrf]["ipv4Unicast"][
|
|
||||||
"peers"
|
|
||||||
]
|
|
||||||
nh_state = ipv4_data[neighbor_ip]["state"]
|
|
||||||
else:
|
|
||||||
ipv6_data = show_bgp_json[vrf]["ipv6Unicast"][
|
|
||||||
"peers"
|
|
||||||
]
|
|
||||||
nh_state = ipv6_data[neighbor_ip]["state"]
|
|
||||||
|
|
||||||
if nh_state == "Established":
|
|
||||||
no_of_peer += 1
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
logger.debug("Exiting API: verify_bgp_convergence()")
|
logger.debug("Exiting API: verify_bgp_convergence()")
|
||||||
return True
|
return True
|
||||||
@ -1400,10 +1415,6 @@ def modify_as_number(tgen, topo, input_dict):
|
|||||||
create_router_bgp(tgen, new_topo)
|
create_router_bgp(tgen, new_topo)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# handle any exception
|
|
||||||
logger.error("Error %s occured. Arguments %s.", e.message, e.args)
|
|
||||||
|
|
||||||
# Traceback
|
|
||||||
errormsg = traceback.format_exc()
|
errormsg = traceback.format_exc()
|
||||||
logger.error(errormsg)
|
logger.error(errormsg)
|
||||||
return errormsg
|
return errormsg
|
||||||
@ -2621,7 +2632,7 @@ def verify_bgp_rib(
|
|||||||
found_routes.append(st_rt)
|
found_routes.append(st_rt)
|
||||||
|
|
||||||
if next_hop and multi_nh and st_found:
|
if next_hop and multi_nh and st_found:
|
||||||
if not isinstance(next_hop, list):
|
if type(next_hop) is not list:
|
||||||
next_hop = [next_hop]
|
next_hop = [next_hop]
|
||||||
list1 = next_hop
|
list1 = next_hop
|
||||||
|
|
||||||
@ -2661,7 +2672,7 @@ def verify_bgp_rib(
|
|||||||
nh_found = True
|
nh_found = True
|
||||||
|
|
||||||
elif next_hop and multi_nh is None:
|
elif next_hop and multi_nh is None:
|
||||||
if not isinstance(next_hop, list):
|
if type(next_hop) is not list:
|
||||||
next_hop = [next_hop]
|
next_hop = [next_hop]
|
||||||
list1 = next_hop
|
list1 = next_hop
|
||||||
found_hops = [
|
found_hops = [
|
||||||
@ -4092,7 +4103,7 @@ def verify_attributes_for_evpn_routes(
|
|||||||
errormsg = (
|
errormsg = (
|
||||||
"[DUT: %s] RD: %s, Route : %s "
|
"[DUT: %s] RD: %s, Route : %s "
|
||||||
"is not present in cli json "
|
"is not present in cli json "
|
||||||
"output " % (dut, route)
|
"output " % (dut, _rd, route)
|
||||||
)
|
)
|
||||||
return errormsg
|
return errormsg
|
||||||
|
|
||||||
@ -4170,7 +4181,7 @@ def verify_evpn_routes(
|
|||||||
return errormsg
|
return errormsg
|
||||||
|
|
||||||
for key, route_data_json in evpn_value_json.items():
|
for key, route_data_json in evpn_value_json.items():
|
||||||
if isinstance(route_data_json, dict):
|
if type(route_data_json) is dict:
|
||||||
rd_keys += 1
|
rd_keys += 1
|
||||||
if prefix not in route_data_json:
|
if prefix not in route_data_json:
|
||||||
missing_routes[key] = prefix
|
missing_routes[key] = prefix
|
||||||
@ -4184,7 +4195,7 @@ def verify_evpn_routes(
|
|||||||
return errormsg
|
return errormsg
|
||||||
|
|
||||||
for key, route_data_json in evpn_value_json.items():
|
for key, route_data_json in evpn_value_json.items():
|
||||||
if isinstance(route_data_json, dict):
|
if type(route_data_json) is dict:
|
||||||
if prefix not in route_data_json:
|
if prefix not in route_data_json:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
@ -1373,13 +1373,13 @@ def generate_ips(network, no_of_ips):
|
|||||||
if start_ip == "0.0.0.0" and mask == 0 and no_of_ips == 1:
|
if start_ip == "0.0.0.0" and mask == 0 and no_of_ips == 1:
|
||||||
ipaddress_list.append("{}/{}".format(start_ip, mask))
|
ipaddress_list.append("{}/{}".format(start_ip, mask))
|
||||||
return ipaddress_list
|
return ipaddress_list
|
||||||
start_ip = ipaddress.IPv4Address(unicode(start_ip))
|
start_ip = ipaddress.IPv4Address(frr_unicode(start_ip))
|
||||||
step = 2 ** (32 - mask)
|
step = 2 ** (32 - mask)
|
||||||
elif addr_type == "ipv6":
|
elif addr_type == "ipv6":
|
||||||
if start_ip == "0::0" and mask == 0 and no_of_ips == 1:
|
if start_ip == "0::0" and mask == 0 and no_of_ips == 1:
|
||||||
ipaddress_list.append("{}/{}".format(start_ip, mask))
|
ipaddress_list.append("{}/{}".format(start_ip, mask))
|
||||||
return ipaddress_list
|
return ipaddress_list
|
||||||
start_ip = ipaddress.IPv6Address(unicode(start_ip))
|
start_ip = ipaddress.IPv6Address(frr_unicode(start_ip))
|
||||||
step = 2 ** (128 - mask)
|
step = 2 ** (128 - mask)
|
||||||
else:
|
else:
|
||||||
return []
|
return []
|
||||||
@ -1480,10 +1480,6 @@ def interface_status(tgen, topo, input_dict):
|
|||||||
load_config_to_router(tgen, router)
|
load_config_to_router(tgen, router)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# handle any exception
|
|
||||||
logger.error("Error %s occured. Arguments %s.", e.message, e.args)
|
|
||||||
|
|
||||||
# Traceback
|
|
||||||
errormsg = traceback.format_exc()
|
errormsg = traceback.format_exc()
|
||||||
logger.error(errormsg)
|
logger.error(errormsg)
|
||||||
return errormsg
|
return errormsg
|
||||||
@ -2442,51 +2438,6 @@ 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 daemon and router and its daemons 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 daemon
|
|
||||||
|
|
||||||
* `tgen` : topogen object
|
|
||||||
* `router`: Device under test
|
|
||||||
"""
|
|
||||||
|
|
||||||
logger.debug("Entering lib API: start_router")
|
|
||||||
|
|
||||||
try:
|
|
||||||
router_list = tgen.routers()
|
|
||||||
|
|
||||||
# Router and its daemons would be started and config would
|
|
||||||
# be loaded to router for each daemon 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
|
||||||
):
|
):
|
||||||
@ -3754,6 +3705,43 @@ def verify_bgp_community(tgen, addr_type, router, network, input_dict=None):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def get_ipv6_linklocal_address(topo, node, intf):
|
||||||
|
"""
|
||||||
|
API to get the link local ipv6 address of a perticular interface
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
* `node`: node on which link local ip to be fetched.
|
||||||
|
* `intf` : interface for which link local ip needs to be returned.
|
||||||
|
* `topo` : base topo
|
||||||
|
|
||||||
|
Usage
|
||||||
|
-----
|
||||||
|
result = get_ipv6_linklocal_address(topo, 'r1', 'r2')
|
||||||
|
|
||||||
|
Returns link local ip of interface between r1 and r2.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
1) link local ipv6 address from the interface
|
||||||
|
2) errormsg - when link local ip not found
|
||||||
|
"""
|
||||||
|
tgen = get_topogen()
|
||||||
|
ext_nh = tgen.net[node].get_ipv6_linklocal()
|
||||||
|
req_nh = topo[node]['links'][intf]['interface']
|
||||||
|
llip = None
|
||||||
|
for llips in ext_nh:
|
||||||
|
if llips[0] == req_nh:
|
||||||
|
llip = llips[1]
|
||||||
|
logger.info("Link local ip found = %s", llip)
|
||||||
|
return llip
|
||||||
|
|
||||||
|
errormsg = "Failed: Link local ip not found on router {}, "\
|
||||||
|
"interface {}".format(node, intf)
|
||||||
|
|
||||||
|
return errormsg
|
||||||
|
|
||||||
|
|
||||||
def verify_create_community_list(tgen, input_dict):
|
def verify_create_community_list(tgen, input_dict):
|
||||||
"""
|
"""
|
||||||
API is to verify if large community list is created for any given DUT in
|
API is to verify if large community list is created for any given DUT in
|
||||||
|
Loading…
Reference in New Issue
Block a user