mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-08 11:18:43 +00:00
tests: Add new tests to bgp-basic-functionality-topo1
1. Added new tests to bgp-basic-functionality-topo1 3. Execution time increased by 55 sec Signed-off-by: Kuldeep Kashyap <kashyapk@vmware.com>
This commit is contained in:
parent
5c2bb61763
commit
19f4da0bec
@ -1,36 +1,17 @@
|
||||
{
|
||||
"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
|
||||
},
|
||||
"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": {
|
||||
"ipv4": "auto",
|
||||
"ipv6": "auto"
|
||||
},
|
||||
"r3": {
|
||||
"ipv4": "auto",
|
||||
"ipv6": "auto"
|
||||
}
|
||||
"lo": {"ipv4": "auto", "ipv6": "auto", "type": "loopback"},
|
||||
"r2": {"ipv4": "auto", "ipv6": "auto"},
|
||||
"r3": {"ipv4": "auto", "ipv6": "auto"}
|
||||
},
|
||||
"bgp": {
|
||||
"local_as": "100",
|
||||
@ -38,16 +19,16 @@
|
||||
"ipv4": {
|
||||
"unicast": {
|
||||
"neighbor": {
|
||||
"r2": {
|
||||
"dest_link": {
|
||||
"r1": {}
|
||||
"r2": {"dest_link": {"r1": {}}},
|
||||
"r3": {"dest_link": {"r1": {}}}
|
||||
}
|
||||
}
|
||||
},
|
||||
"r3": {
|
||||
"dest_link": {
|
||||
"r1": {}
|
||||
}
|
||||
}
|
||||
"ipv6": {
|
||||
"unicast": {
|
||||
"neighbor": {
|
||||
"r2": {"dest_link": {"r1": {}}},
|
||||
"r3": {"dest_link": {"r1": {}}}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -56,19 +37,9 @@
|
||||
},
|
||||
"r2": {
|
||||
"links": {
|
||||
"lo": {
|
||||
"ipv4": "auto",
|
||||
"ipv6": "auto",
|
||||
"type": "loopback"
|
||||
},
|
||||
"r1": {
|
||||
"ipv4": "auto",
|
||||
"ipv6": "auto"
|
||||
},
|
||||
"r3": {
|
||||
"ipv4": "auto",
|
||||
"ipv6": "auto"
|
||||
}
|
||||
"lo": {"ipv4": "auto", "ipv6": "auto", "type": "loopback"},
|
||||
"r1": {"ipv4": "auto", "ipv6": "auto"},
|
||||
"r3": {"ipv4": "auto", "ipv6": "auto"}
|
||||
},
|
||||
"bgp": {
|
||||
"local_as": "100",
|
||||
@ -76,16 +47,16 @@
|
||||
"ipv4": {
|
||||
"unicast": {
|
||||
"neighbor": {
|
||||
"r1": {
|
||||
"dest_link": {
|
||||
"r2": {}
|
||||
"r1": {"dest_link": {"r2": {}}},
|
||||
"r3": {"dest_link": {"r2": {}}}
|
||||
}
|
||||
}
|
||||
},
|
||||
"r3": {
|
||||
"dest_link": {
|
||||
"r2": {}
|
||||
}
|
||||
}
|
||||
"ipv6": {
|
||||
"unicast": {
|
||||
"neighbor": {
|
||||
"r1": {"dest_link": {"r2": {}}},
|
||||
"r3": {"dest_link": {"r2": {}}}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -94,23 +65,10 @@
|
||||
},
|
||||
"r3": {
|
||||
"links": {
|
||||
"lo": {
|
||||
"ipv4": "auto",
|
||||
"ipv6": "auto",
|
||||
"type": "loopback"
|
||||
},
|
||||
"r1": {
|
||||
"ipv4": "auto",
|
||||
"ipv6": "auto"
|
||||
},
|
||||
"r2": {
|
||||
"ipv4": "auto",
|
||||
"ipv6": "auto"
|
||||
},
|
||||
"r4": {
|
||||
"ipv4": "auto",
|
||||
"ipv6": "auto"
|
||||
}
|
||||
"lo": {"ipv4": "auto", "ipv6": "auto", "type": "loopback"},
|
||||
"r1": {"ipv4": "auto", "ipv6": "auto"},
|
||||
"r2": {"ipv4": "auto", "ipv6": "auto"},
|
||||
"r4": {"ipv4": "auto", "ipv6": "auto"}
|
||||
},
|
||||
"bgp": {
|
||||
"local_as": "100",
|
||||
@ -118,21 +76,18 @@
|
||||
"ipv4": {
|
||||
"unicast": {
|
||||
"neighbor": {
|
||||
"r1": {
|
||||
"dest_link": {
|
||||
"r3": {}
|
||||
"r1": {"dest_link": {"r3": {}}},
|
||||
"r2": {"dest_link": {"r3": {}}},
|
||||
"r4": {"dest_link": {"r3": {}}}
|
||||
}
|
||||
}
|
||||
},
|
||||
"r2": {
|
||||
"dest_link": {
|
||||
"r3": {}
|
||||
}
|
||||
},
|
||||
"r4": {
|
||||
"dest_link": {
|
||||
"r3": {}
|
||||
}
|
||||
}
|
||||
"ipv6": {
|
||||
"unicast": {
|
||||
"neighbor": {
|
||||
"r1": {"dest_link": {"r3": {}}},
|
||||
"r2": {"dest_link": {"r3": {}}},
|
||||
"r4": {"dest_link": {"r3": {}}}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -141,29 +96,17 @@
|
||||
},
|
||||
"r4": {
|
||||
"links": {
|
||||
"lo": {
|
||||
"ipv4": "auto",
|
||||
"ipv6": "auto",
|
||||
"type": "loopback"
|
||||
},
|
||||
"r3": {
|
||||
"ipv4": "auto",
|
||||
"ipv6": "auto"
|
||||
}
|
||||
"lo": {"ipv4": "auto", "ipv6": "auto", "type": "loopback"},
|
||||
"r3": {"ipv4": "auto", "ipv6": "auto"}
|
||||
},
|
||||
"bgp": {
|
||||
"local_as": "200",
|
||||
"address_family": {
|
||||
"ipv4": {
|
||||
"unicast": {
|
||||
"neighbor": {
|
||||
"r3": {
|
||||
"dest_link": {
|
||||
"r4": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"unicast": {"neighbor": {"r3": {"dest_link": {"r4": {}}}}}
|
||||
},
|
||||
"ipv6": {
|
||||
"unicast": {"neighbor": {"r3": {"dest_link": {"r4": {}}}}}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -37,6 +37,8 @@ Test steps
|
||||
- Verify clear bgp
|
||||
- Test bgp convergence with loopback interface
|
||||
- Test advertise network using network command
|
||||
- Verify routes not installed in zebra when /32 routes received
|
||||
with loopback BGP session subnet
|
||||
"""
|
||||
|
||||
import os
|
||||
@ -59,6 +61,7 @@ from lib.topogen import Topogen, get_topogen
|
||||
from mininet.topo import Topo
|
||||
|
||||
from lib.common_config import (
|
||||
step,
|
||||
start_topology,
|
||||
write_test_header,
|
||||
write_test_footer,
|
||||
@ -66,6 +69,13 @@ from lib.common_config import (
|
||||
create_static_routes,
|
||||
verify_rib,
|
||||
verify_admin_distance_for_static_routes,
|
||||
check_address_types,
|
||||
apply_raw_config,
|
||||
addKernelRoute,
|
||||
verify_fib_routes,
|
||||
create_prefix_lists,
|
||||
create_route_maps,
|
||||
verify_bgp_community,
|
||||
)
|
||||
from lib.topolog import logger
|
||||
from lib.bgp import (
|
||||
@ -76,6 +86,7 @@ from lib.bgp import (
|
||||
verify_as_numbers,
|
||||
clear_bgp_and_verify,
|
||||
verify_bgp_timers_and_functionality,
|
||||
verify_bgp_rib,
|
||||
)
|
||||
from lib.topojson import build_topo_from_json, build_config_from_json
|
||||
|
||||
@ -90,6 +101,18 @@ except IOError:
|
||||
# Global Variable
|
||||
KEEPALIVETIMER = 2
|
||||
HOLDDOWNTIMER = 6
|
||||
r1_ipv4_loopback = "1.0.1.0/24"
|
||||
r2_ipv4_loopback = "1.0.2.0/24"
|
||||
r3_ipv4_loopback = "1.0.3.0/24"
|
||||
r4_ipv4_loopback = "1.0.4.0/24"
|
||||
r1_ipv6_loopback = "2001:db8:f::1:0/120"
|
||||
r2_ipv6_loopback = "2001:db8:f::2:0/120"
|
||||
r3_ipv6_loopback = "2001:db8:f::3:0/120"
|
||||
r4_ipv6_loopback = "2001:db8:f::4:0/120"
|
||||
NETWORK = {
|
||||
"ipv4": ["100.1.1.1/32", "100.1.1.2/32"],
|
||||
"ipv6": ["100::1/128", "100::2/128"],
|
||||
}
|
||||
|
||||
|
||||
class CreateTopo(Topo):
|
||||
@ -131,7 +154,9 @@ def setup_module(mod):
|
||||
# Creating configuration from JSON
|
||||
build_config_from_json(tgen, topo)
|
||||
|
||||
global ADDR_TYPES
|
||||
global BGP_CONVERGENCE
|
||||
ADDR_TYPES = check_address_types()
|
||||
BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo)
|
||||
assert BGP_CONVERGENCE is True, "setup_module :Failed \n Error: {}".format(
|
||||
BGP_CONVERGENCE
|
||||
@ -522,6 +547,243 @@ def test_clear_bgp_and_verify(request):
|
||||
write_test_footer(tc_name)
|
||||
|
||||
|
||||
def test_BGP_attributes_with_vrf_default_keyword_p0(request):
|
||||
"""
|
||||
TC_9:
|
||||
Verify BGP functionality for default vrf with
|
||||
"vrf default" keyword.
|
||||
"""
|
||||
|
||||
tc_name = request.node.name
|
||||
write_test_header(tc_name)
|
||||
tgen = get_topogen()
|
||||
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip(tgen.errors)
|
||||
|
||||
#reset_config_on_routers(tgen)
|
||||
|
||||
step("Configure static routes and redistribute in BGP on R3")
|
||||
for addr_type in ADDR_TYPES:
|
||||
input_dict = {
|
||||
"r3": {
|
||||
"static_routes": [
|
||||
{
|
||||
"network": NETWORK[addr_type][0],
|
||||
"no_of_ip": 4,
|
||||
"next_hop": "Null0",
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
result = create_static_routes(tgen, input_dict)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(
|
||||
tc_name, result
|
||||
)
|
||||
|
||||
input_dict_2 = {
|
||||
"r3": {
|
||||
"bgp": {
|
||||
"address_family": {
|
||||
"ipv4": {"unicast": {"redistribute": [{"redist_type": "static"}]}},
|
||||
"ipv6": {"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(
|
||||
"Create a route-map to match a specific prefix and modify"
|
||||
"BGP attributes for matched prefix"
|
||||
)
|
||||
input_dict_2 = {
|
||||
"r3": {
|
||||
"prefix_lists": {
|
||||
"ipv4": {
|
||||
"ABC": [
|
||||
{
|
||||
"seqid": 10,
|
||||
"action": "permit",
|
||||
"network": NETWORK["ipv4"][0],
|
||||
}
|
||||
]
|
||||
},
|
||||
"ipv6": {
|
||||
"XYZ": [
|
||||
{
|
||||
"seqid": 100,
|
||||
"action": "permit",
|
||||
"network": NETWORK["ipv6"][0],
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
result = create_prefix_lists(tgen, input_dict_2)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
for addr_type in ADDR_TYPES:
|
||||
if addr_type == "ipv4":
|
||||
pf_list = "ABC"
|
||||
else:
|
||||
pf_list = "XYZ"
|
||||
|
||||
input_dict_6 = {
|
||||
"r3": {
|
||||
"route_maps": {
|
||||
"BGP_ATTR_{}".format(addr_type): [
|
||||
{
|
||||
"action": "permit",
|
||||
"seq_id": 10,
|
||||
"match": {addr_type: {"prefix_lists": pf_list}},
|
||||
"set": {
|
||||
"aspath": {"as_num": 500, "as_action": "prepend"},
|
||||
"localpref": 500,
|
||||
"origin": "egp",
|
||||
"community": {"num": "500:500", "action": "additive"},
|
||||
"large_community": {
|
||||
"num": "500:500:500",
|
||||
"action": "additive",
|
||||
},
|
||||
},
|
||||
},
|
||||
{"action": "permit", "seq_id": 20},
|
||||
]
|
||||
},
|
||||
"BGP_ATTR_{}".format(addr_type): [
|
||||
{
|
||||
"action": "permit",
|
||||
"seq_id": 100,
|
||||
"match": {addr_type: {"prefix_lists": pf_list}},
|
||||
"set": {
|
||||
"aspath": {"as_num": 500, "as_action": "prepend"},
|
||||
"localpref": 500,
|
||||
"origin": "egp",
|
||||
"community": {"num": "500:500", "action": "additive"},
|
||||
"large_community": {
|
||||
"num": "500:500:500",
|
||||
"action": "additive",
|
||||
},
|
||||
},
|
||||
},
|
||||
{"action": "permit", "seq_id": 200},
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
result = create_route_maps(tgen, input_dict_6)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(
|
||||
tc_name, result
|
||||
)
|
||||
|
||||
step("Apply the route-map on R3 in outbound direction for peer R4")
|
||||
|
||||
input_dict_7 = {
|
||||
"r3": {
|
||||
"bgp": {
|
||||
"address_family": {
|
||||
"ipv4": {
|
||||
"unicast": {
|
||||
"neighbor": {
|
||||
"r4": {
|
||||
"dest_link": {
|
||||
"r3": {
|
||||
"route_maps": [
|
||||
{
|
||||
"name": "BGP_ATTR_ipv4",
|
||||
"direction": "out",
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"ipv6": {
|
||||
"unicast": {
|
||||
"neighbor": {
|
||||
"r4": {
|
||||
"dest_link": {
|
||||
"r3": {
|
||||
"route_maps": [
|
||||
{
|
||||
"name": "BGP_ATTR_ipv6",
|
||||
"direction": "out",
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = create_router_bgp(tgen, topo, input_dict_7)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step(
|
||||
"verify modified attributes for specific prefix with 'vrf default'"
|
||||
"keyword on R4"
|
||||
)
|
||||
for addr_type in ADDR_TYPES:
|
||||
dut = "r4"
|
||||
input_dict = {
|
||||
"r3": {
|
||||
"static_routes": [
|
||||
{
|
||||
"network": NETWORK[addr_type][0],
|
||||
"vrf": "default",
|
||||
"largeCommunity": "500:500:500",
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
result = verify_bgp_rib(tgen, addr_type, dut, input_dict)
|
||||
assert result is True, "Testcase : Failed \n Error: {}".format(tc_name, result)
|
||||
result = verify_rib(tgen, addr_type, dut, input_dict)
|
||||
assert result is True, "Testcase : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
for addr_type in ADDR_TYPES:
|
||||
dut = "r4"
|
||||
input_dict = {
|
||||
"r3": {
|
||||
"static_routes": [
|
||||
{
|
||||
"network": NETWORK[addr_type][0],
|
||||
"vrf": "default",
|
||||
"community": "500:500",
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
result = verify_bgp_rib(tgen, addr_type, dut, input_dict)
|
||||
assert result is True, "Testcase : Failed \n Error: {}".format(tc_name, result)
|
||||
result = verify_rib(tgen, addr_type, dut, input_dict)
|
||||
assert result is True, "Testcase : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
input_dict_4 = {"largeCommunity": "500:500:500", "community": "500:500"}
|
||||
|
||||
result = verify_bgp_community(
|
||||
tgen, addr_type, dut, [NETWORK[addr_type][0]], input_dict_4
|
||||
)
|
||||
assert result is True, "Test case {} : Should fail \n Error: {}".format(
|
||||
tc_name, result
|
||||
)
|
||||
|
||||
write_test_footer(tc_name)
|
||||
|
||||
|
||||
def test_bgp_with_loopback_interface(request):
|
||||
"""
|
||||
Test BGP with loopback interface
|
||||
@ -588,6 +850,298 @@ def test_bgp_with_loopback_interface(request):
|
||||
write_test_footer(tc_name)
|
||||
|
||||
|
||||
def test_bgp_with_loopback_with_same_subnet_p1(request):
|
||||
"""
|
||||
Verify routes not installed in zebra when /32 routes received
|
||||
with loopback BGP session subnet
|
||||
"""
|
||||
|
||||
tgen = get_topogen()
|
||||
if BGP_CONVERGENCE is not True:
|
||||
pytest.skip("skipped because of BGP Convergence failure")
|
||||
|
||||
# test case name
|
||||
tc_name = request.node.name
|
||||
write_test_header(tc_name)
|
||||
|
||||
# Creating configuration from JSON
|
||||
reset_config_on_routers(tgen)
|
||||
step("Delete BGP seesion created initially")
|
||||
input_dict_r1 = {
|
||||
"r1": {"bgp": {"delete": True}},
|
||||
"r2": {"bgp": {"delete": True}},
|
||||
"r3": {"bgp": {"delete": True}},
|
||||
"r4": {"bgp": {"delete": True}},
|
||||
}
|
||||
result = create_router_bgp(tgen, topo, input_dict_r1)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("Create BGP session over loop address")
|
||||
topo_modify = deepcopy(topo)
|
||||
|
||||
for routerN in sorted(topo["routers"].keys()):
|
||||
for addr_type in ADDR_TYPES:
|
||||
for bgp_neighbor in topo_modify["routers"][routerN]["bgp"][
|
||||
"address_family"
|
||||
][addr_type]["unicast"]["neighbor"].keys():
|
||||
|
||||
# Adding ['source_link'] = 'lo' key:value pair
|
||||
topo_modify["routers"][routerN]["bgp"]["address_family"][addr_type][
|
||||
"unicast"
|
||||
]["neighbor"][bgp_neighbor]["dest_link"] = {
|
||||
"lo": {"source_link": "lo", "ebgp_multihop": 2}
|
||||
}
|
||||
|
||||
result = create_router_bgp(tgen, topo_modify["routers"])
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("Disable IPv6 BGP nbr from ipv4 address family")
|
||||
raw_config = {
|
||||
"r1": {
|
||||
"raw_config": [
|
||||
"router bgp {}".format(topo["routers"]["r1"]["bgp"]["local_as"]),
|
||||
"address-family ipv4 unicast",
|
||||
"no neighbor {} activate".format(
|
||||
topo["routers"]["r2"]["links"]["lo"]["ipv6"].split("/")[0]
|
||||
),
|
||||
"no neighbor {} activate".format(
|
||||
topo["routers"]["r3"]["links"]["lo"]["ipv6"].split("/")[0]
|
||||
),
|
||||
]
|
||||
},
|
||||
"r2": {
|
||||
"raw_config": [
|
||||
"router bgp {}".format(topo["routers"]["r2"]["bgp"]["local_as"]),
|
||||
"address-family ipv4 unicast",
|
||||
"no neighbor {} activate".format(
|
||||
topo["routers"]["r1"]["links"]["lo"]["ipv6"].split("/")[0]
|
||||
),
|
||||
"no neighbor {} activate".format(
|
||||
topo["routers"]["r3"]["links"]["lo"]["ipv6"].split("/")[0]
|
||||
),
|
||||
]
|
||||
},
|
||||
"r3": {
|
||||
"raw_config": [
|
||||
"router bgp {}".format(topo["routers"]["r3"]["bgp"]["local_as"]),
|
||||
"address-family ipv4 unicast",
|
||||
"no neighbor {} activate".format(
|
||||
topo["routers"]["r1"]["links"]["lo"]["ipv6"].split("/")[0]
|
||||
),
|
||||
"no neighbor {} activate".format(
|
||||
topo["routers"]["r2"]["links"]["lo"]["ipv6"].split("/")[0]
|
||||
),
|
||||
"no neighbor {} activate".format(
|
||||
topo["routers"]["r4"]["links"]["lo"]["ipv6"].split("/")[0]
|
||||
),
|
||||
]
|
||||
},
|
||||
"r4": {
|
||||
"raw_config": [
|
||||
"router bgp {}".format(topo["routers"]["r4"]["bgp"]["local_as"]),
|
||||
"address-family ipv4 unicast",
|
||||
"no neighbor {} activate".format(
|
||||
topo["routers"]["r3"]["links"]["lo"]["ipv6"].split("/")[0]
|
||||
),
|
||||
]
|
||||
},
|
||||
}
|
||||
|
||||
step("Configure kernel routes")
|
||||
result = apply_raw_config(tgen, raw_config)
|
||||
assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
|
||||
|
||||
r1_ipv4_lo = topo["routers"]["r1"]["links"]["lo"]["ipv4"]
|
||||
r1_ipv6_lo = topo["routers"]["r1"]["links"]["lo"]["ipv6"]
|
||||
r2_ipv4_lo = topo["routers"]["r2"]["links"]["lo"]["ipv4"]
|
||||
r2_ipv6_lo = topo["routers"]["r2"]["links"]["lo"]["ipv6"]
|
||||
r3_ipv4_lo = topo["routers"]["r3"]["links"]["lo"]["ipv4"]
|
||||
r3_ipv6_lo = topo["routers"]["r3"]["links"]["lo"]["ipv6"]
|
||||
r4_ipv4_lo = topo["routers"]["r4"]["links"]["lo"]["ipv4"]
|
||||
r4_ipv6_lo = topo["routers"]["r4"]["links"]["lo"]["ipv6"]
|
||||
|
||||
r1_r2 = topo["routers"]["r1"]["links"]["r2"]["ipv6"].split("/")[0]
|
||||
r2_r1 = topo["routers"]["r2"]["links"]["r1"]["ipv6"].split("/")[0]
|
||||
r1_r3 = topo["routers"]["r1"]["links"]["r3"]["ipv6"].split("/")[0]
|
||||
r3_r1 = topo["routers"]["r3"]["links"]["r1"]["ipv6"].split("/")[0]
|
||||
r2_r3 = topo["routers"]["r2"]["links"]["r3"]["ipv6"].split("/")[0]
|
||||
r3_r2 = topo["routers"]["r3"]["links"]["r2"]["ipv6"].split("/")[0]
|
||||
r3_r4 = topo["routers"]["r3"]["links"]["r4"]["ipv6"].split("/")[0]
|
||||
r4_r3 = topo["routers"]["r4"]["links"]["r3"]["ipv6"].split("/")[0]
|
||||
|
||||
r1_r2_ipv4 = topo["routers"]["r1"]["links"]["r2"]["ipv4"].split("/")[0]
|
||||
r2_r1_ipv4 = topo["routers"]["r2"]["links"]["r1"]["ipv4"].split("/")[0]
|
||||
r1_r3_ipv4 = topo["routers"]["r1"]["links"]["r3"]["ipv4"].split("/")[0]
|
||||
r3_r1_ipv4 = topo["routers"]["r3"]["links"]["r1"]["ipv4"].split("/")[0]
|
||||
r2_r3_ipv4 = topo["routers"]["r2"]["links"]["r3"]["ipv4"].split("/")[0]
|
||||
r3_r2_ipv4 = topo["routers"]["r3"]["links"]["r2"]["ipv4"].split("/")[0]
|
||||
r3_r4_ipv4 = topo["routers"]["r3"]["links"]["r4"]["ipv4"].split("/")[0]
|
||||
r4_r3_ipv4 = topo["routers"]["r4"]["links"]["r3"]["ipv4"].split("/")[0]
|
||||
|
||||
r1_r2_intf = topo["routers"]["r1"]["links"]["r2"]["interface"]
|
||||
r2_r1_intf = topo["routers"]["r2"]["links"]["r1"]["interface"]
|
||||
r1_r3_intf = topo["routers"]["r1"]["links"]["r3"]["interface"]
|
||||
r3_r1_intf = topo["routers"]["r3"]["links"]["r1"]["interface"]
|
||||
r2_r3_intf = topo["routers"]["r2"]["links"]["r3"]["interface"]
|
||||
r3_r2_intf = topo["routers"]["r3"]["links"]["r2"]["interface"]
|
||||
r3_r4_intf = topo["routers"]["r3"]["links"]["r4"]["interface"]
|
||||
r4_r3_intf = topo["routers"]["r4"]["links"]["r3"]["interface"]
|
||||
|
||||
ipv4_list = [
|
||||
("r1", r1_r2_intf, r2_ipv4_loopback),
|
||||
("r1", r1_r3_intf, r3_ipv4_loopback),
|
||||
("r2", r2_r1_intf, r1_ipv4_loopback),
|
||||
("r2", r2_r3_intf, r3_ipv4_loopback),
|
||||
("r3", r3_r1_intf, r1_ipv4_loopback),
|
||||
("r3", r3_r2_intf, r2_ipv4_loopback),
|
||||
("r3", r3_r4_intf, r4_ipv4_loopback),
|
||||
("r4", r4_r3_intf, r3_ipv4_loopback),
|
||||
]
|
||||
|
||||
ipv6_list = [
|
||||
("r1", r1_r2_intf, r2_ipv6_loopback, r2_r1),
|
||||
("r1", r1_r3_intf, r3_ipv6_loopback, r3_r1),
|
||||
("r2", r2_r1_intf, r1_ipv6_loopback, r1_r2),
|
||||
("r2", r2_r3_intf, r3_ipv6_loopback, r3_r2),
|
||||
("r3", r3_r1_intf, r1_ipv6_loopback, r1_r3),
|
||||
("r3", r3_r2_intf, r2_ipv6_loopback, r2_r3),
|
||||
("r3", r3_r4_intf, r4_ipv6_loopback, r4_r3),
|
||||
("r4", r4_r3_intf, r3_ipv6_loopback, r3_r4),
|
||||
]
|
||||
|
||||
for dut, intf, loop_addr in ipv4_list:
|
||||
result = addKernelRoute(tgen, dut, intf, loop_addr)
|
||||
assert result is True, "Testcase {}:Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
for dut, intf, loop_addr, next_hop in ipv6_list:
|
||||
result = addKernelRoute(tgen, dut, intf, loop_addr, next_hop)
|
||||
assert result is True, "Testcase {}:Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("Configure static routes")
|
||||
|
||||
input_dict = {
|
||||
"r1": {
|
||||
"static_routes": [
|
||||
{"network": r2_ipv4_loopback, "next_hop": r2_r1_ipv4},
|
||||
{"network": r3_ipv4_loopback, "next_hop": r3_r1_ipv4},
|
||||
{"network": r2_ipv6_loopback, "next_hop": r2_r1},
|
||||
{"network": r3_ipv6_loopback, "next_hop": r3_r1},
|
||||
]
|
||||
},
|
||||
"r2": {
|
||||
"static_routes": [
|
||||
{"network": r1_ipv4_loopback, "next_hop": r1_r2_ipv4},
|
||||
{"network": r3_ipv4_loopback, "next_hop": r3_r2_ipv4},
|
||||
{"network": r1_ipv6_loopback, "next_hop": r1_r2},
|
||||
{"network": r3_ipv6_loopback, "next_hop": r3_r2},
|
||||
]
|
||||
},
|
||||
"r3": {
|
||||
"static_routes": [
|
||||
{"network": r1_ipv4_loopback, "next_hop": r1_r3_ipv4},
|
||||
{"network": r2_ipv4_loopback, "next_hop": r2_r3_ipv4},
|
||||
{"network": r4_ipv4_loopback, "next_hop": r4_r3_ipv4},
|
||||
{"network": r1_ipv6_loopback, "next_hop": r1_r3},
|
||||
{"network": r2_ipv6_loopback, "next_hop": r2_r3},
|
||||
{"network": r4_ipv6_loopback, "next_hop": r4_r3},
|
||||
]
|
||||
},
|
||||
"r4": {
|
||||
"static_routes": [
|
||||
{"network": r3_ipv4_loopback, "next_hop": r3_r4_ipv4},
|
||||
{"network": r3_ipv6_loopback, "next_hop": r3_r4},
|
||||
]
|
||||
},
|
||||
}
|
||||
result = create_static_routes(tgen, input_dict)
|
||||
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("Verify BGP session convergence")
|
||||
|
||||
result = verify_bgp_convergence(tgen, topo_modify)
|
||||
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("Configure redistribute connected on R2 and R4")
|
||||
input_dict_1 = {
|
||||
"r2": {
|
||||
"bgp": {
|
||||
"address_family": {
|
||||
"ipv4": {
|
||||
"unicast": {"redistribute": [{"redist_type": "connected"}]}
|
||||
},
|
||||
"ipv6": {
|
||||
"unicast": {"redistribute": [{"redist_type": "connected"}]}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
"r4": {
|
||||
"bgp": {
|
||||
"address_family": {
|
||||
"ipv4": {
|
||||
"unicast": {"redistribute": [{"redist_type": "connected"}]}
|
||||
},
|
||||
"ipv6": {
|
||||
"unicast": {"redistribute": [{"redist_type": "connected"}]}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
result = create_router_bgp(tgen, topo, input_dict_1)
|
||||
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("Verify Ipv4 and Ipv6 network installed in R1 RIB but not in FIB")
|
||||
input_dict_r1 = {
|
||||
"r1": {
|
||||
"static_routes": [
|
||||
{"network": "1.0.2.17/32"},
|
||||
{"network": "2001:db8:f::2:17/128"},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
dut = "r1"
|
||||
protocol = "bgp"
|
||||
for addr_type in ADDR_TYPES:
|
||||
result = verify_rib(tgen, addr_type, dut, input_dict_r1, protocol=protocol)
|
||||
assert result is True, "Testcase {} :Failed \n Error: {}".format(
|
||||
tc_name, result
|
||||
)
|
||||
|
||||
result = verify_fib_routes(tgen, addr_type, dut, input_dict_r1, expected=False)
|
||||
assert result is not True, "Testcase {} : Failed \n"
|
||||
"Expected behavior: routes should not present in fib \n"
|
||||
"Error: {}".format(tc_name, result)
|
||||
|
||||
step("Verify Ipv4 and Ipv6 network installed in r3 RIB but not in FIB")
|
||||
input_dict_r3 = {
|
||||
"r3": {
|
||||
"static_routes": [
|
||||
{"network": "1.0.4.17/32"},
|
||||
{"network": "2001:db8:f::4:17/128"},
|
||||
]
|
||||
}
|
||||
}
|
||||
dut = "r3"
|
||||
protocol = "bgp"
|
||||
for addr_type in ADDR_TYPES:
|
||||
result = verify_rib(
|
||||
tgen, addr_type, dut, input_dict_r3, protocol=protocol, fib=None
|
||||
)
|
||||
assert result is True, "Testcase {} :Failed \n Error: {}".format(
|
||||
tc_name, result
|
||||
)
|
||||
|
||||
result = verify_fib_routes(tgen, addr_type, dut, input_dict_r1, expected=False)
|
||||
assert result is not True, "Testcase {} : Failed \n"
|
||||
"Expected behavior: routes should not present in fib \n"
|
||||
"Error: {}".format(tc_name, result)
|
||||
|
||||
write_test_footer(tc_name)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
args = ["-s"] + sys.argv[1:]
|
||||
sys.exit(pytest.main(args))
|
||||
|
@ -46,6 +46,7 @@ from lib.common_config import (
|
||||
LOGDIR = "/tmp/topotests/"
|
||||
TMPDIR = None
|
||||
|
||||
|
||||
def create_router_bgp(tgen, topo, input_dict=None, build=False, load_config=True):
|
||||
"""
|
||||
API to configure bgp on router
|
||||
@ -1219,11 +1220,17 @@ def verify_bgp_convergence(tgen, topo, dut=None):
|
||||
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)
|
||||
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))
|
||||
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()")
|
||||
@ -2553,10 +2560,19 @@ def verify_bgp_rib(tgen, addr_type, dut, input_dict, next_hop=None, aspath=None)
|
||||
missing_routes = []
|
||||
st_found = False
|
||||
nh_found = False
|
||||
|
||||
vrf = static_route.setdefault("vrf", None)
|
||||
community = static_route.setdefault("community", None)
|
||||
largeCommunity = static_route.setdefault("largeCommunity", None)
|
||||
|
||||
if vrf:
|
||||
cmd = "{} vrf {} {}".format(command, vrf, addr_type)
|
||||
|
||||
if community:
|
||||
cmd = "{} community {}".format(cmd, community)
|
||||
|
||||
if largeCommunity:
|
||||
cmd = "{} large-community {}".format(cmd, largeCommunity)
|
||||
else:
|
||||
cmd = "{} {}".format(command, addr_type)
|
||||
|
||||
|
@ -2352,7 +2352,9 @@ def configure_brctl(tgen, topo, input_dict):
|
||||
):
|
||||
|
||||
ip_cmd_list = []
|
||||
cmd = "ip link add name {} type bridge stp_state {}".format(brctl_name, stp)
|
||||
cmd = "ip link add name {} type bridge stp_state {}".format(
|
||||
brctl_name, stp
|
||||
)
|
||||
|
||||
logger.info("[DUT: %s]: Running command: %s", dut, cmd)
|
||||
rnode.run(cmd)
|
||||
@ -2821,6 +2823,260 @@ def verify_rib(
|
||||
return True
|
||||
|
||||
|
||||
@retry(attempts=5, wait=2, return_is_str=True, initial_wait=2)
|
||||
def verify_fib_routes(tgen, addr_type, dut, input_dict, next_hop=None):
|
||||
"""
|
||||
Data will be read from input_dict or input JSON file, API will generate
|
||||
same prefixes, which were redistributed by either create_static_routes() or
|
||||
advertise_networks_using_network_command() and will verify next_hop and
|
||||
each prefix/routes is present in "show ip/ipv6 fib json"
|
||||
command o/p.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
* `tgen` : topogen object
|
||||
* `addr_type` : ip type, ipv4/ipv6
|
||||
* `dut`: Device Under Test, for which user wants to test the data
|
||||
* `input_dict` : input dict, has details of static routes
|
||||
* `next_hop`[optional]: next_hop which needs to be verified,
|
||||
default: static
|
||||
|
||||
Usage
|
||||
-----
|
||||
input_routes_r1 = {
|
||||
"r1": {
|
||||
"static_routes": [{
|
||||
"network": ["1.1.1.1/32],
|
||||
"next_hop": "Null0",
|
||||
"vrf": "RED"
|
||||
}]
|
||||
}
|
||||
}
|
||||
result = result = verify_fib_routes(tgen, "ipv4, "r1", input_routes_r1)
|
||||
|
||||
Returns
|
||||
-------
|
||||
errormsg(str) or True
|
||||
"""
|
||||
|
||||
logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
|
||||
|
||||
router_list = tgen.routers()
|
||||
for routerInput in input_dict.keys():
|
||||
for router, rnode in router_list.iteritems():
|
||||
if router != dut:
|
||||
continue
|
||||
|
||||
logger.info("Checking router %s FIB routes:", router)
|
||||
|
||||
# Verifying RIB routes
|
||||
if addr_type == "ipv4":
|
||||
command = "show ip fib"
|
||||
else:
|
||||
command = "show ipv6 fib"
|
||||
|
||||
found_routes = []
|
||||
missing_routes = []
|
||||
|
||||
if "static_routes" in input_dict[routerInput]:
|
||||
static_routes = input_dict[routerInput]["static_routes"]
|
||||
|
||||
for static_route in static_routes:
|
||||
if "vrf" in static_route and static_route["vrf"] is not None:
|
||||
|
||||
logger.info(
|
||||
"[DUT: {}]: Verifying routes for VRF:"
|
||||
" {}".format(router, static_route["vrf"])
|
||||
)
|
||||
|
||||
cmd = "{} vrf {}".format(command, static_route["vrf"])
|
||||
|
||||
else:
|
||||
cmd = "{}".format(command)
|
||||
|
||||
cmd = "{} json".format(cmd)
|
||||
|
||||
rib_routes_json = run_frr_cmd(rnode, cmd, isjson=True)
|
||||
|
||||
# Verifying output dictionary rib_routes_json is not empty
|
||||
if bool(rib_routes_json) is False:
|
||||
errormsg = "[DUT: {}]: No route found in fib".format(router)
|
||||
return errormsg
|
||||
|
||||
network = static_route["network"]
|
||||
if "no_of_ip" in static_route:
|
||||
no_of_ip = static_route["no_of_ip"]
|
||||
else:
|
||||
no_of_ip = 1
|
||||
|
||||
# Generating IPs for verification
|
||||
ip_list = generate_ips(network, no_of_ip)
|
||||
st_found = False
|
||||
nh_found = False
|
||||
|
||||
for st_rt in ip_list:
|
||||
st_rt = str(ipaddress.ip_network(unicode(st_rt)))
|
||||
|
||||
_addr_type = validate_ip_address(st_rt)
|
||||
if _addr_type != addr_type:
|
||||
continue
|
||||
|
||||
if st_rt in rib_routes_json:
|
||||
st_found = True
|
||||
found_routes.append(st_rt)
|
||||
|
||||
if next_hop:
|
||||
if type(next_hop) is not list:
|
||||
next_hop = [next_hop]
|
||||
|
||||
count = 0
|
||||
for nh in next_hop:
|
||||
for nh_dict in rib_routes_json[st_rt][0][
|
||||
"nexthops"
|
||||
]:
|
||||
if nh_dict["ip"] != nh:
|
||||
continue
|
||||
else:
|
||||
count += 1
|
||||
|
||||
if count == len(next_hop):
|
||||
nh_found = True
|
||||
else:
|
||||
missing_routes.append(st_rt)
|
||||
errormsg = (
|
||||
"Nexthop {} is Missing"
|
||||
" for route {} in "
|
||||
"RIB of router {}\n".format(
|
||||
next_hop, st_rt, dut
|
||||
)
|
||||
)
|
||||
return errormsg
|
||||
|
||||
else:
|
||||
missing_routes.append(st_rt)
|
||||
|
||||
if len(missing_routes) > 0:
|
||||
errormsg = "[DUT: {}]: Missing route in FIB:" " {}".format(
|
||||
dut, missing_routes
|
||||
)
|
||||
return errormsg
|
||||
|
||||
if nh_found:
|
||||
logger.info(
|
||||
"Found next_hop {} for all routes in RIB"
|
||||
" of router {}\n".format(next_hop, dut)
|
||||
)
|
||||
|
||||
if found_routes:
|
||||
logger.info(
|
||||
"[DUT: %s]: Verified routes in FIB, found" " routes are: %s\n",
|
||||
dut,
|
||||
found_routes,
|
||||
)
|
||||
|
||||
continue
|
||||
|
||||
if "bgp" in input_dict[routerInput]:
|
||||
if (
|
||||
"advertise_networks"
|
||||
not in input_dict[routerInput]["bgp"]["address_family"][addr_type][
|
||||
"unicast"
|
||||
]
|
||||
):
|
||||
continue
|
||||
|
||||
found_routes = []
|
||||
missing_routes = []
|
||||
advertise_network = input_dict[routerInput]["bgp"]["address_family"][
|
||||
addr_type
|
||||
]["unicast"]["advertise_networks"]
|
||||
|
||||
# Continue if there are no network advertise
|
||||
if len(advertise_network) == 0:
|
||||
continue
|
||||
|
||||
for advertise_network_dict in advertise_network:
|
||||
if "vrf" in advertise_network_dict:
|
||||
cmd = "{} vrf {} json".format(command, static_route["vrf"])
|
||||
else:
|
||||
cmd = "{} json".format(command)
|
||||
|
||||
rib_routes_json = run_frr_cmd(rnode, cmd, isjson=True)
|
||||
|
||||
# Verifying output dictionary rib_routes_json is not empty
|
||||
if bool(rib_routes_json) is False:
|
||||
errormsg = "No route found in rib of router {}..".format(router)
|
||||
return errormsg
|
||||
|
||||
start_ip = advertise_network_dict["network"]
|
||||
if "no_of_network" in advertise_network_dict:
|
||||
no_of_network = advertise_network_dict["no_of_network"]
|
||||
else:
|
||||
no_of_network = 1
|
||||
|
||||
# Generating IPs for verification
|
||||
ip_list = generate_ips(start_ip, no_of_network)
|
||||
st_found = False
|
||||
nh_found = False
|
||||
|
||||
for st_rt in ip_list:
|
||||
st_rt = str(ipaddress.ip_network(unicode(st_rt)))
|
||||
|
||||
_addr_type = validate_ip_address(st_rt)
|
||||
if _addr_type != addr_type:
|
||||
continue
|
||||
|
||||
if st_rt in rib_routes_json:
|
||||
st_found = True
|
||||
found_routes.append(st_rt)
|
||||
|
||||
if next_hop:
|
||||
if type(next_hop) is not list:
|
||||
next_hop = [next_hop]
|
||||
|
||||
count = 0
|
||||
for nh in next_hop:
|
||||
for nh_dict in rib_routes_json[st_rt][0]["nexthops"]:
|
||||
if nh_dict["ip"] != nh:
|
||||
continue
|
||||
else:
|
||||
count += 1
|
||||
|
||||
if count == len(next_hop):
|
||||
nh_found = True
|
||||
else:
|
||||
missing_routes.append(st_rt)
|
||||
errormsg = (
|
||||
"Nexthop {} is Missing"
|
||||
" for route {} in "
|
||||
"RIB of router {}\n".format(next_hop, st_rt, dut)
|
||||
)
|
||||
return errormsg
|
||||
else:
|
||||
missing_routes.append(st_rt)
|
||||
|
||||
if len(missing_routes) > 0:
|
||||
errormsg = "[DUT: {}]: Missing route in FIB: " "{} \n".format(
|
||||
dut, missing_routes
|
||||
)
|
||||
return errormsg
|
||||
|
||||
if nh_found:
|
||||
logger.info(
|
||||
"Found next_hop {} for all routes in RIB"
|
||||
" of router {}\n".format(next_hop, dut)
|
||||
)
|
||||
|
||||
if found_routes:
|
||||
logger.info(
|
||||
"[DUT: {}]: Verified routes FIB"
|
||||
", found routes are: {}\n".format(dut, found_routes)
|
||||
)
|
||||
|
||||
logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
|
||||
return True
|
||||
|
||||
|
||||
def verify_admin_distance_for_static_routes(tgen, input_dict):
|
||||
"""
|
||||
API to verify admin distance for static routes as defined in input_dict/
|
||||
|
Loading…
Reference in New Issue
Block a user