Merge pull request #6398 from kuldeepkash/bgp_multi_vrf

tests: Add bgp-multi-vrf test suites
This commit is contained in:
Donald Sharp 2020-05-21 07:40:17 -04:00 committed by GitHub
commit bda6d3729f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 11654 additions and 328 deletions

View File

@ -295,7 +295,7 @@ def test_modify_ecmp_max_paths(request, ecmp_num, test_type):
addr_type, addr_type,
dut, dut,
input_dict_1, input_dict_1,
next_hop=NEXT_HOPS[addr_type], next_hop=NEXT_HOPS[addr_type][:int(ecmp_num)],
protocol=protocol, protocol=protocol,
) )
assert result is True, "Testcase {} : Failed \n Error: {}".format( assert result is True, "Testcase {} : Failed \n Error: {}".format(

View File

@ -296,7 +296,7 @@ def test_modify_ecmp_max_paths(request, ecmp_num, test_type):
addr_type, addr_type,
dut, dut,
input_dict_1, input_dict_1,
next_hop=NEXT_HOPS[addr_type], next_hop=NEXT_HOPS[addr_type][:int(ecmp_num)],
protocol=protocol, protocol=protocol,
) )
assert result is True, "Testcase {} : Failed \n Error: {}".format( assert result is True, "Testcase {} : Failed \n Error: {}".format(

View File

@ -0,0 +1,884 @@
{
"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": {
"red1": {
"links": {
"r1-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED_A"},
"r1-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED_B"}
},
"vrfs":[
{
"name": "RED_A",
"id": "1"
},
{
"name": "RED_B",
"id": "2"
}
],
"bgp":
[
{
"local_as": "500",
"vrf": "RED_A",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r1": {
"dest_link": {
"red1-link1": {}
}
}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r1": {
"dest_link": {
"red1-link1": {}
}
}
}
}
}
}
},
{
"local_as": "500",
"vrf": "RED_B",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r1": {
"dest_link": {
"red1-link2": {}
}
}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r1": {
"dest_link": {
"red1-link2": {}
}
}
}
}
}
}
}
]
},
"blue1": {
"links": {
"r1-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE_A"},
"r1-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE_B"}
},
"vrfs":[
{
"name": "BLUE_A",
"id": "1"
},
{
"name": "BLUE_B",
"id": "2"
}
],
"bgp":
[
{
"local_as": "800",
"vrf": "BLUE_A",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r1": {
"dest_link": {
"blue1-link1": {}
}
}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r1": {
"dest_link": {
"blue1-link1": {}
}
}
}
}
}
}
},
{
"local_as": "800",
"vrf": "BLUE_B",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r1": {
"dest_link": {
"blue1-link2": {}
}
}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r1": {
"dest_link": {
"blue1-link2": {}
}
}
}
}
}
}
}
]
},
"r1": {
"links": {
"red1-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED_A"},
"red1-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED_B"},
"blue1-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE_A"},
"blue1-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE_B"},
"r2-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED_A"},
"r2-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED_B"},
"r2-link3": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE_A"},
"r2-link4": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE_B"}
},
"vrfs":[
{
"name": "RED_A",
"id": "1"
},
{
"name": "RED_B",
"id": "2"
},
{
"name": "BLUE_A",
"id": "3"
},
{
"name": "BLUE_B",
"id": "4"
}
],
"bgp":
[
{
"local_as": "100",
"vrf": "RED_A",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"red1": {
"dest_link": {
"r1-link1": {}
}
},
"r2": {
"dest_link": {
"r1-link1":
{ "next_hop_self": true }
}
}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
"red1": {
"dest_link": {
"r1-link1": {}
}
},
"r2": {
"dest_link": {
"r1-link1":
{ "next_hop_self": true }
}
}
}
}
}
}
},
{
"local_as": "100",
"vrf": "RED_B",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"red1": {
"dest_link": {
"r1-link2": {}
}
},
"r2": {
"dest_link": {
"r1-link2":
{ "next_hop_self": true }
}
}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
"red1": {
"dest_link": {
"r1-link2": {}
}
},
"r2": {
"dest_link": {
"r1-link2":
{ "next_hop_self": true }
}
}
}
}
}
}
},
{
"local_as": "100",
"vrf": "BLUE_A",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"blue1": {
"dest_link": {
"r1-link1": {}
}
},
"r2": {
"dest_link": {
"r1-link3":
{ "next_hop_self": true }
}
}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
"blue1": {
"dest_link": {
"r1-link1": {}
}
},
"r2": {
"dest_link": {
"r1-link3":
{ "next_hop_self": true }
}
}
}
}
}
}
},
{
"local_as": "100",
"vrf": "BLUE_B",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"blue1": {
"dest_link": {
"r1-link2": {}
}
},
"r2": {
"dest_link": {
"r1-link4":
{ "next_hop_self": true }
}
}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
"blue1": {
"dest_link": {
"r1-link2": {}
}
},
"r2": {
"dest_link": {
"r1-link4":
{ "next_hop_self": true }
}
}
}
}
}
}
}
]
},
"r2": {
"links": {
"r1-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED_A"},
"r1-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED_B"},
"r1-link3": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE_A"},
"r1-link4": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE_B"},
"r3-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED_A"},
"r3-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED_B"},
"r3-link3": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE_A"},
"r3-link4": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE_B"}
},
"vrfs":[
{
"name": "RED_A",
"id": "1"
},
{
"name": "RED_B",
"id": "2"
},
{
"name": "BLUE_A",
"id": "3"
},
{
"name": "BLUE_B",
"id": "4"
}
],
"bgp":
[
{
"local_as": "100",
"vrf": "RED_A",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r1": {
"dest_link": {
"r2-link1": {}
}
},
"r3": {
"dest_link": {
"r2-link1": {}
}
}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r1": {
"dest_link": {
"r2-link1": {}
}
},
"r3": {
"dest_link": {
"r2-link1": {}
}
}
}
}
}
}
},
{
"local_as": "100",
"vrf": "RED_B",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r1": {
"dest_link": {
"r2-link2": {}
}
},
"r3": {
"dest_link": {
"r2-link2": {}
}
}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r1": {
"dest_link": {
"r2-link2": {}
}
},
"r3": {
"dest_link": {
"r2-link2": {}
}
}
}
}
}
}
},
{
"local_as": "100",
"vrf": "BLUE_A",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r1": {
"dest_link": {
"r2-link3": {}
}
},
"r3": {
"dest_link": {
"r2-link3": {}
}
}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r1": {
"dest_link": {
"r2-link3": {}
}
},
"r3": {
"dest_link": {
"r2-link3": {}
}
}
}
}
}
}
},
{
"local_as": "100",
"vrf": "BLUE_B",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r1": {
"dest_link": {
"r2-link4": {}
}
},
"r3": {
"dest_link": {
"r2-link4": {}
}
}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r1": {
"dest_link": {
"r2-link4": {}
}
},
"r3": {
"dest_link": {
"r2-link4": {}
}
}
}
}
}
}
}
]
},
"r3": {
"links": {
"r2-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED_A"},
"r2-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED_B"},
"r2-link3": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE_A"},
"r2-link4": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE_B"},
"red2-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED_A"},
"red2-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED_B"},
"blue2-link1": {"ipv4": "auto", "ipv6": "autor3", "vrf": "BLUE_A"},
"blue2-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE_B"}
},
"vrfs":[
{
"name": "RED_A",
"id": "1"
},
{
"name": "RED_B",
"id": "2"
},
{
"name": "BLUE_A",
"id": "3"
},
{
"name": "BLUE_B",
"id": "4"
}
],
"bgp":
[
{
"local_as": "200",
"vrf": "RED_A",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r2": {
"dest_link": {
"r3-link1": {}
}
},
"red2": {
"dest_link": {
"r3-link1": {}
}
}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r2": {
"dest_link": {
"r3-link1": {}
}
},
"red2": {
"dest_link": {
"r3-link1": {}
}
}
}
}
}
}
},
{
"local_as": "200",
"vrf": "RED_B",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r2": {
"dest_link": {
"r3-link2": {}
}
},
"red2": {
"dest_link": {
"r3-link2": {}
}
}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r2": {
"dest_link": {
"r3-link2": {}
}
},
"red2": {
"dest_link": {
"r3-link2": {}
}
}
}
}
}
}
},
{
"local_as": "200",
"vrf": "BLUE_A",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r2": {
"dest_link": {
"r3-link3": {}
}
},
"blue2": {
"dest_link": {
"r3-link1": {}
}
}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r2": {
"dest_link": {
"r3-link3": {}
}
},
"blue2": {
"dest_link": {
"r3-link1": {}
}
}
}
}
}
}
},
{
"local_as": "200",
"vrf": "BLUE_B",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r2": {
"dest_link": {
"r3-link4": {}
}
},
"blue2": {
"dest_link": {
"r3-link2": {}
}
}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r2": {
"dest_link": {
"r3-link4": {}
}
},
"blue2": {
"dest_link": {
"r3-link2": {}
}
}
}
}
}
}
}
]
},
"red2": {
"links": {
"r3-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED_A"},
"r3-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED_B"}
},
"vrfs":[
{
"name": "RED_A",
"id": "1"
},
{
"name": "RED_B",
"id": "2"
}
],
"bgp":
[
{
"local_as": "500",
"vrf": "RED_A",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r3": {
"dest_link": {
"red2-link1": {}
}
}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r3": {
"dest_link": {
"red2-link1": {}
}
}
}
}
}
}
},
{
"local_as": "500",
"vrf": "RED_B",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r3": {
"dest_link": {
"red2-link2": {}
}
}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r3": {
"dest_link": {
"red2-link2": {}
}
}
}
}
}
}
}
]
},
"blue2": {
"links": {
"r3-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE_A"},
"r3-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE_B"}
},
"vrfs":[
{
"name": "BLUE_A",
"id": "1"
},
{
"name": "BLUE_B",
"id": "2"
}
],
"bgp":
[
{
"local_as": "800",
"vrf": "BLUE_A",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r3": {
"dest_link": {
"blue2-link1": {}
}
}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r3": {
"dest_link": {
"blue2-link1": {}
}
}
}
}
}
}
},
{
"local_as": "800",
"vrf": "BLUE_B",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r3": {
"dest_link": {
"blue2-link2": {}
}
}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r3": {
"dest_link": {
"blue2-link2": {}
}
}
}
}
}
}
}
]
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -75,8 +75,12 @@ def create_router_bgp(tgen, topo, input_dict=None, build=False, load_config=True
"address_family": { "address_family": {
"ipv4": { "ipv4": {
"unicast": { "unicast": {
"redistribute": [ "redistribute": [{
{"redist_type": "static"}, "redist_type": "static",
"attribute": {
"metric" : 123
}
},
{"redist_type": "connected"} {"redist_type": "connected"}
], ],
"advertise_networks": [ "advertise_networks": [
@ -143,15 +147,20 @@ def create_router_bgp(tgen, topo, input_dict=None, build=False, load_config=True
logger.debug("Router %s: 'bgp' not present in input_dict", router) logger.debug("Router %s: 'bgp' not present in input_dict", router)
continue continue
data_all_bgp = __create_bgp_global(tgen, input_dict, router, build) bgp_data_list = input_dict[router]["bgp"]
if data_all_bgp:
bgp_data = input_dict[router]["bgp"]
if type(bgp_data_list) is not list:
bgp_data_list = [bgp_data_list]
for bgp_data in bgp_data_list:
data_all_bgp = __create_bgp_global(tgen, bgp_data, router, build)
if data_all_bgp:
bgp_addr_data = bgp_data.setdefault("address_family", {}) bgp_addr_data = bgp_data.setdefault("address_family", {})
if not bgp_addr_data: if not bgp_addr_data:
logger.debug( logger.debug(
"Router %s: 'address_family' not present in " "input_dict for BGP", "Router %s: 'address_family' not present in "
"input_dict for BGP",
router, router,
) )
else: else:
@ -170,7 +179,7 @@ def create_router_bgp(tgen, topo, input_dict=None, build=False, load_config=True
data_all_bgp = __create_bgp_unicast_neighbor( data_all_bgp = __create_bgp_unicast_neighbor(
tgen, tgen,
topo, topo,
input_dict, bgp_data,
router, router,
afi_test, afi_test,
config_data=data_all_bgp, config_data=data_all_bgp,
@ -186,7 +195,7 @@ def create_router_bgp(tgen, topo, input_dict=None, build=False, load_config=True
logger.error(errormsg) logger.error(errormsg)
return errormsg return errormsg
logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name)) logger.debug("Exiting lib API: create_router_bgp()")
return result return result
@ -206,19 +215,16 @@ def __create_bgp_global(tgen, input_dict, router, build=False):
True or False True or False
""" """
result = False
logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name)) logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
bgp_data = input_dict[router]["bgp"] bgp_data = input_dict
del_bgp_action = bgp_data.setdefault("delete", False) del_bgp_action = bgp_data.setdefault("delete", False)
if del_bgp_action:
config_data = ["no router bgp"]
return config_data
config_data = [] config_data = []
if "local_as" not in bgp_data and build: if "local_as" not in bgp_data and build:
logger.error( logger.debug(
"Router %s: 'local_as' not present in input_dict" "for BGP", router "Router %s: 'local_as' not present in input_dict" "for BGP", router
) )
return False return False
@ -229,6 +235,12 @@ def __create_bgp_global(tgen, input_dict, router, build=False):
if vrf_id: if vrf_id:
cmd = "{} vrf {}".format(cmd, vrf_id) cmd = "{} vrf {}".format(cmd, vrf_id)
if del_bgp_action:
cmd = "no {}".format(cmd)
config_data.append(cmd)
return config_data
config_data.append(cmd) config_data.append(cmd)
config_data.append("no bgp ebgp-requires-policy") config_data.append("no bgp ebgp-requires-policy")
@ -325,12 +337,15 @@ def __create_bgp_unicast_neighbor(
* `build` : Only for initial setup phase this is set as True. * `build` : Only for initial setup phase this is set as True.
""" """
result = False
logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name)) logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
add_neigh = True add_neigh = True
bgp_data = input_dict
if "router bgp" in config_data: if "router bgp" in config_data:
add_neigh = False add_neigh = False
bgp_data = input_dict[router]["bgp"]["address_family"]
bgp_data = input_dict["address_family"]
for addr_type, addr_dict in bgp_data.iteritems(): for addr_type, addr_dict in bgp_data.iteritems():
if not addr_dict: if not addr_dict:
@ -403,14 +418,19 @@ def __create_bgp_unicast_neighbor(
if redistribute_data: if redistribute_data:
for redistribute in redistribute_data: for redistribute in redistribute_data:
if "redist_type" not in redistribute: if "redist_type" not in redistribute:
logger.error( logger.debug(
"Router %s: 'redist_type' not present in " "input_dict", router "Router %s: 'redist_type' not present in " "input_dict", router
) )
else: else:
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):
for key, value in redist_attr.items():
cmd = "{} {} {}".format(cmd, key, value)
else:
cmd = "{} {}".format(cmd, redist_attr) cmd = "{} {}".format(cmd, redist_attr)
del_action = redistribute.setdefault("delete", False) del_action = redistribute.setdefault("delete", False)
if del_action: if del_action:
cmd = "no {}".format(cmd) cmd = "no {}".format(cmd)
@ -453,13 +473,18 @@ def __create_bgp_neighbor(topo, input_dict, router, addr_type, add_neigh=True):
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))
bgp_data = input_dict[router]["bgp"]["address_family"] bgp_data = input_dict["address_family"]
neigh_data = bgp_data[addr_type]["unicast"]["neighbor"] neigh_data = bgp_data[addr_type]["unicast"]["neighbor"]
for name, peer_dict in neigh_data.iteritems(): for name, peer_dict in neigh_data.iteritems():
for dest_link, peer in peer_dict["dest_link"].iteritems(): for dest_link, peer in peer_dict["dest_link"].iteritems():
nh_details = topo[name] nh_details = topo[name]
if "vrfs" in topo[router]:
remote_as = nh_details["bgp"][0]["local_as"]
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 dest_link in nh_details["links"].keys():
@ -549,7 +574,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))
bgp_data = input_dict[router]["bgp"]["address_family"] bgp_data = input_dict["address_family"]
neigh_data = bgp_data[addr_type]["unicast"]["neighbor"] neigh_data = bgp_data[addr_type]["unicast"]["neighbor"]
for peer_name, peer_dict in deepcopy(neigh_data).iteritems(): for peer_name, peer_dict in deepcopy(neigh_data).iteritems():
@ -605,8 +630,12 @@ def __create_bgp_unicast_address_family(
allowas_in = peer.setdefault("allowas-in", None) allowas_in = peer.setdefault("allowas-in", None)
# next-hop-self # next-hop-self
if next_hop_self: if next_hop_self is not None:
if next_hop_self is True:
config_data.append("{} next-hop-self".format(neigh_cxt)) config_data.append("{} next-hop-self".format(neigh_cxt))
else:
config_data.append("no {} next-hop-self".format(neigh_cxt))
# send_community # send_community
if send_community: if send_community:
config_data.append("{} send-community".format(neigh_cxt)) config_data.append("{} send-community".format(neigh_cxt))
@ -840,40 +869,113 @@ def verify_router_id(tgen, topo, input_dict):
@retry(attempts=20, wait=2, return_is_str=True) @retry(attempts=20, wait=2, return_is_str=True)
def verify_bgp_convergence(tgen, topo): def verify_bgp_convergence(tgen, topo, dut=None):
""" """
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
* `addr_type`: ip_type, ipv4/ipv6 * `dut`: device under test
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, "ipv4") results = verify_bgp_convergence(tgen, topo, dut="r1")
Returns Returns
------- -------
errormsg(str) or True errormsg(str) or True
""" """
logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name)) logger.debug("Entering lib API: verify_bgp_convergence()")
for router, rnode in tgen.routers().iteritems(): for router, rnode in tgen.routers().iteritems():
if "bgp" not in topo["routers"][router]: if "bgp" not in topo["routers"][router]:
continue continue
logger.info("Verifying BGP Convergence on router %s", router) if dut is not None and dut != router:
show_bgp_json = run_frr_cmd(rnode, "show bgp summary json", isjson=True) continue
logger.info("Verifying BGP Convergence on router %s:", router)
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"
return errormsg return errormsg
# To find neighbor ip type # To find neighbor ip type
bgp_addr_type = topo["routers"][router]["bgp"]["address_family"] bgp_data_list = topo["routers"][router]["bgp"]
if type(bgp_data_list) is not list:
bgp_data_list = [bgp_data_list]
for bgp_data in bgp_data_list:
if "vrf" in bgp_data:
vrf = bgp_data["vrf"]
if vrf is None:
vrf = "default"
else:
vrf = "default"
# To find neighbor ip type
bgp_addr_type = bgp_data["address_family"]
if "l2vpn" in bgp_addr_type:
total_evpn_peer = 0
if "neighbor" not in bgp_addr_type["l2vpn"]["evpn"]:
continue
bgp_neighbors = bgp_addr_type["l2vpn"]["evpn"]["neighbor"]
total_evpn_peer += len(bgp_neighbors)
no_of_evpn_peer = 0
for bgp_neighbor, peer_data in bgp_neighbors.items():
for _addr_type, dest_link_dict in peer_data.items():
data = topo["routers"][bgp_neighbor]["links"]
for dest_link in dest_link_dict.keys():
if dest_link in data:
peer_details = peer_data[_addr_type][dest_link]
neighbor_ip = data[dest_link][_addr_type].split("/")[0]
nh_state = None
if (
"ipv4Unicast" in show_bgp_json[vrf]
or "ipv6Unicast" in show_bgp_json[vrf]
):
errormsg = (
"[DUT: %s] VRF: %s, "
"ipv4Unicast/ipv6Unicast"
" address-family present"
" under l2vpn" % (router, vrf)
)
return errormsg
l2VpnEvpn_data = show_bgp_json[vrf]["l2VpnEvpn"][
"peers"
]
nh_state = l2VpnEvpn_data[neighbor_ip]["state"]
if nh_state == "Established":
no_of_evpn_peer += 1
if no_of_evpn_peer == total_evpn_peer:
logger.info(
"[DUT: %s] VRF: %s, BGP is Converged for " "epvn peers",
router,
vrf,
)
else:
errormsg = (
"[DUT: %s] VRF: %s, BGP is not converged "
"for evpn peers" % (router, vrf)
)
return errormsg
else:
for addr_type in bgp_addr_type.keys(): for addr_type in bgp_addr_type.keys():
if not check_address_types(addr_type): if not check_address_types(addr_type):
continue continue
@ -890,30 +992,168 @@ def verify_bgp_convergence(tgen, topo):
bgp_neighbors = bgp_addr_type[addr_type]["unicast"]["neighbor"] bgp_neighbors = bgp_addr_type[addr_type]["unicast"]["neighbor"]
no_of_peer = 0 no_of_peer = 0
for bgp_neighbor, peer_data in bgp_neighbors.iteritems(): for bgp_neighbor, peer_data in bgp_neighbors.items():
for dest_link in peer_data["dest_link"].keys(): for dest_link in peer_data["dest_link"].keys():
data = topo["routers"][bgp_neighbor]["links"] data = topo["routers"][bgp_neighbor]["links"]
if dest_link in data: if dest_link in data:
neighbor_ip = data[dest_link][addr_type].split("/")[0] 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 addr_type == "ipv4":
ipv4_data = show_bgp_json["ipv4Unicast"]["peers"] ipv4_data = show_bgp_json[vrf]["ipv4Unicast"][
"peers"
]
nh_state = ipv4_data[neighbor_ip]["state"] nh_state = ipv4_data[neighbor_ip]["state"]
else: else:
ipv6_data = show_bgp_json["ipv6Unicast"]["peers"] ipv6_data = show_bgp_json[vrf]["ipv6Unicast"][
"peers"
]
nh_state = ipv6_data[neighbor_ip]["state"] nh_state = ipv6_data[neighbor_ip]["state"]
if nh_state == "Established": if nh_state == "Established":
no_of_peer += 1 no_of_peer += 1
if no_of_peer == total_peer: if no_of_peer == total_peer:
logger.info("BGP is Converged for router %s", router) logger.info("[DUT: %s] VRF: %s, BGP is Converged", router, vrf)
else: else:
errormsg = "BGP is not converged for router {}".format(router) 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 API: verify_bgp_convergence()")
return True return True
@retry(attempts=3, wait=4, return_is_str=True)
def verify_bgp_community(
tgen, addr_type, router, network, input_dict=None, vrf=None, bestpath=False
):
"""
API to veiryf BGP large community is attached in route for any given
DUT by running "show bgp ipv4/6 {route address} json" command.
Parameters
----------
* `tgen`: topogen object
* `addr_type` : ip type, ipv4/ipv6
* `dut`: Device Under Test
* `network`: network for which set criteria needs to be verified
* `input_dict`: having details like - for which router, community and
values needs to be verified
* `vrf`: VRF name
* `bestpath`: To check best path cli
Usage
-----
networks = ["200.50.2.0/32"]
input_dict = {
"largeCommunity": "2:1:1 2:2:2 2:3:3 2:4:4 2:5:5"
}
result = verify_bgp_community(tgen, "ipv4", dut, network, input_dict=None)
Returns
-------
errormsg(str) or True
"""
logger.debug("Entering lib API: verify_bgp_community()")
if router not in tgen.routers():
return False
rnode = tgen.routers()[router]
logger.info(
"Verifying BGP community attributes on dut %s: for %s " "network %s",
router,
addr_type,
network,
)
command = "show bgp"
sleep(5)
for net in network:
if vrf:
cmd = "{} vrf {} {} {} json".format(command, vrf, addr_type, net)
elif bestpath:
cmd = "{} {} {} bestpath json".format(command, addr_type, net)
else:
cmd = "{} {} {} json".format(command, addr_type, net)
show_bgp_json = run_frr_cmd(rnode, cmd, isjson=True)
if "paths" not in show_bgp_json:
return "Prefix {} not found in BGP table of router: {}".format(net, router)
as_paths = show_bgp_json["paths"]
found = False
for i in range(len(as_paths)):
if (
"largeCommunity" in show_bgp_json["paths"][i]
or "community" in show_bgp_json["paths"][i]
):
found = True
logger.info(
"Large Community attribute is found for route:" " %s in router: %s",
net,
router,
)
if input_dict is not None:
for criteria, comm_val in input_dict.items():
show_val = show_bgp_json["paths"][i][criteria]["string"]
if comm_val == show_val:
logger.info(
"Verifying BGP %s for prefix: %s"
" in router: %s, found expected"
" value: %s",
criteria,
net,
router,
comm_val,
)
else:
errormsg = (
"Failed: Verifying BGP attribute"
" {} for route: {} in router: {}"
", expected value: {} but found"
": {}".format(criteria, net, router, comm_val, show_val)
)
return errormsg
if not found:
errormsg = (
"Large Community attribute is not found for route: "
"{} in router: {} ".format(net, router)
)
return errormsg
logger.debug("Exiting lib API: verify_bgp_community()")
return True
def modify_as_number(tgen, topo, input_dict): def modify_as_number(tgen, topo, input_dict):
""" """
API reads local_as and remote_as from user defined input_dict and API reads local_as and remote_as from user defined input_dict and
@ -1090,6 +1330,7 @@ def clear_bgp(tgen, addr_type, router, vrf=None):
""" """
logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name)) logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
if router not in tgen.routers(): if router not in tgen.routers():
return False return False
@ -1102,9 +1343,21 @@ def clear_bgp(tgen, addr_type, router, vrf=None):
# Clearing BGP # Clearing BGP
logger.info("Clearing BGP neighborship for router %s..", router) logger.info("Clearing BGP neighborship for router %s..", router)
if addr_type == "ipv4": if addr_type == "ipv4":
if vrf:
for _vrf in vrf:
run_frr_cmd(rnode, "clear ip bgp vrf {} *".format(_vrf))
else:
run_frr_cmd(rnode, "clear ip bgp *") run_frr_cmd(rnode, "clear ip bgp *")
elif addr_type == "ipv6": elif addr_type == "ipv6":
if vrf:
for _vrf in vrf:
run_frr_cmd(rnode, "clear bgp vrf {} ipv6 *".format(_vrf))
else:
run_frr_cmd(rnode, "clear bgp ipv6 *") run_frr_cmd(rnode, "clear bgp ipv6 *")
else:
run_frr_cmd(rnode, "clear bgp *")
sleep(5)
logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name)) logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
@ -1698,7 +1951,6 @@ def verify_best_path_as_per_bgp_attribute(
"show bgp ipv4/6 json" command will be run and verify best path according "show bgp ipv4/6 json" command will be run and verify best path according
to shortest as-path, highest local-preference and med, lowest weight and to shortest as-path, highest local-preference and med, lowest weight and
route origin IGP>EGP>INCOMPLETE. route origin IGP>EGP>INCOMPLETE.
Parameters Parameters
---------- ----------
* `tgen` : topogen object * `tgen` : topogen object
@ -1707,7 +1959,6 @@ def verify_best_path_as_per_bgp_attribute(
* `attribute` : calculate best path using this attribute * `attribute` : calculate best path using this attribute
* `input_dict`: defines different routes to calculate for which route * `input_dict`: defines different routes to calculate for which route
best path is selected best path is selected
Usage Usage
----- -----
# To verify best path for routes 200.50.2.0/32 and 200.60.2.0/32 from # To verify best path for routes 200.50.2.0/32 and 200.60.2.0/32 from
@ -1741,23 +1992,48 @@ def verify_best_path_as_per_bgp_attribute(
""" """
logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name)) logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
if router not in tgen.routers(): if router not in tgen.routers():
return False return False
rnode = tgen.routers()[router] rnode = tgen.routers()[router]
command = "show bgp {} json".format(addr_type) # Verifying show bgp json
command = "show bgp"
sleep(5) sleep(2)
logger.info("Verifying router %s RIB for best path:", router) logger.info("Verifying router %s RIB for best path:", router)
sh_ip_bgp_json = run_frr_cmd(rnode, command, isjson=True)
static_route = False
advertise_network = False
for route_val in input_dict.values(): for route_val in input_dict.values():
if "static_routes" in route_val:
static_route = True
networks = route_val["static_routes"]
else:
advertise_network = True
net_data = route_val["bgp"]["address_family"][addr_type]["unicast"] net_data = route_val["bgp"]["address_family"][addr_type]["unicast"]
networks = net_data["advertise_networks"] networks = net_data["advertise_networks"]
for network in networks:
route = network["network"]
for network in networks:
_network = network["network"]
no_of_ip = network.setdefault("no_of_ip", 1)
vrf = network.setdefault("vrf", None)
if vrf:
cmd = "{} vrf {}".format(command, vrf)
else:
cmd = command
cmd = "{} {}".format(cmd, addr_type)
cmd = "{} json".format(cmd)
sh_ip_bgp_json = run_frr_cmd(rnode, cmd, isjson=True)
routes = generate_ips(_network, no_of_ip)
for route in routes:
route = str(ipaddr.IPNetwork(unicode(route)))
if route in sh_ip_bgp_json["routes"]:
route_attributes = sh_ip_bgp_json["routes"][route] route_attributes = sh_ip_bgp_json["routes"][route]
_next_hop = None _next_hop = None
compare = None compare = None
@ -1779,13 +2055,17 @@ def verify_best_path_as_per_bgp_attribute(
# LOCAL_PREF attribute # LOCAL_PREF attribute
elif attribute == "locPrf": elif attribute == "locPrf":
# Find next_hop for the route have highest local preference # Find next_hop for the route have highest local preference
_next_hop = max(attribute_dict, key=(lambda k: attribute_dict[k])) _next_hop = max(
attribute_dict, key=(lambda k: attribute_dict[k])
)
compare = "HIGHEST" compare = "HIGHEST"
# WEIGHT attribute # WEIGHT attribute
elif attribute == "weight": elif attribute == "weight":
# Find next_hop for the route have highest weight # Find next_hop for the route have highest weight
_next_hop = max(attribute_dict, key=(lambda k: attribute_dict[k])) _next_hop = max(
attribute_dict, key=(lambda k: attribute_dict[k])
)
compare = "HIGHEST" compare = "HIGHEST"
# ORIGIN attribute # ORIGIN attribute
@ -1793,23 +2073,32 @@ def verify_best_path_as_per_bgp_attribute(
# Find next_hop for the route have IGP as origin, - # Find next_hop for the route have IGP as origin, -
# - rule is IGP>EGP>INCOMPLETE # - rule is IGP>EGP>INCOMPLETE
_next_hop = [ _next_hop = [
key for (key, value) in attribute_dict.iteritems() if value == "IGP" key
for (key, value) in attribute_dict.iteritems()
if value == "IGP"
][0] ][0]
compare = "" compare = ""
# MED attribute # MED attribute
elif attribute == "metric": elif attribute == "metric":
# Find next_hop for the route have LOWEST MED # Find next_hop for the route have LOWEST MED
_next_hop = min(attribute_dict, key=(lambda k: attribute_dict[k])) _next_hop = min(
attribute_dict, key=(lambda k: attribute_dict[k])
)
compare = "LOWEST" compare = "LOWEST"
# Show ip route # Show ip route
if addr_type == "ipv4": if addr_type == "ipv4":
command = "show ip route json" command_1 = "show ip route"
else: else:
command = "show ipv6 route json" command_1 = "show ipv6 route"
rib_routes_json = run_frr_cmd(rnode, command, isjson=True) if vrf:
cmd = "{} vrf {} json".format(command_1, vrf)
else:
cmd = "{} json".format(command_1)
rib_routes_json = run_frr_cmd(rnode, cmd, isjson=True)
# Verifying output dictionary rib_routes_json is not empty # Verifying output dictionary rib_routes_json is not empty
if not bool(rib_routes_json): if not bool(rib_routes_json):
@ -1822,7 +2111,10 @@ def verify_best_path_as_per_bgp_attribute(
if route in rib_routes_json: if route in rib_routes_json:
st_found = True st_found = True
# Verify next_hop in rib_routes_json # Verify next_hop in rib_routes_json
if rib_routes_json[route][0]["nexthops"][0]["ip"] in attribute_dict: if (
rib_routes_json[route][0]["nexthops"][0]["ip"]
in attribute_dict
):
nh_found = True nh_found = True
else: else:
errormsg = ( errormsg = (
@ -1965,7 +2257,7 @@ def verify_best_path_as_per_admin_distance(
return True return True
@retry(attempts=10, wait=2, return_is_str=True, initial_wait=2) @retry(attempts=5, wait=2, return_is_str=True, initial_wait=2)
def verify_bgp_rib(tgen, addr_type, dut, input_dict, next_hop=None, aspath=None): def verify_bgp_rib(tgen, addr_type, dut, input_dict, next_hop=None, aspath=None):
""" """
This API is to verify whether bgp rib has any This API is to verify whether bgp rib has any
@ -1995,7 +2287,7 @@ def verify_bgp_rib(tgen, addr_type, dut, input_dict, next_hop=None, aspath=None)
errormsg(str) or True errormsg(str) or True
""" """
logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name)) logger.debug("Entering lib API: verify_bgp_rib()")
router_list = tgen.routers() router_list = tgen.routers()
additional_nexthops_in_required_nhs = [] additional_nexthops_in_required_nhs = []
@ -2210,7 +2502,7 @@ def verify_bgp_rib(tgen, addr_type, dut, input_dict, next_hop=None, aspath=None)
"routes are: {}\n".format(dut, found_routes) "routes are: {}\n".format(dut, found_routes)
) )
logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name)) logger.debug("Exiting lib API: verify_bgp_rib()")
return True return True

File diff suppressed because it is too large Load Diff

View File

@ -37,6 +37,7 @@ from lib.common_config import (
create_prefix_lists, create_prefix_lists,
create_route_maps, create_route_maps,
create_bgp_community_lists, create_bgp_community_lists,
create_vrf_cfg,
) )
from lib.bgp import create_router_bgp from lib.bgp import create_router_bgp
@ -49,7 +50,6 @@ def build_topo_from_json(tgen, topo):
Reads configuration from JSON file. Adds routers, creates interface Reads configuration from JSON file. Adds routers, creates interface
names dynamically and link routers as defined in JSON to create names dynamically and link routers as defined in JSON to create
topology. Assigns IPs dynamically to all interfaces of each router. topology. Assigns IPs dynamically to all interfaces of each router.
* `tgen`: Topogen object * `tgen`: Topogen object
* `topo`: json file data * `topo`: json file data
""" """
@ -203,6 +203,7 @@ def build_config_from_json(tgen, topo, save_bkup=True):
func_dict = OrderedDict( func_dict = OrderedDict(
[ [
("vrfs", create_vrf_cfg),
("links", create_interfaces_cfg), ("links", create_interfaces_cfg),
("static_routes", create_static_routes), ("static_routes", create_static_routes),
("prefix_lists", create_prefix_lists), ("prefix_lists", create_prefix_lists),