tests: adding bgp admin distance topotests.

This has bgp admin topotest automation suit.

Signed-off-by: nguggarigoud <nguggarigoud@vmware.com>
This commit is contained in:
nguggarigoud 2022-08-23 00:35:11 -07:00
parent c480bc4358
commit 3cf90b1be9
6 changed files with 3071 additions and 5 deletions

View File

@ -0,0 +1,402 @@
{
"address_types": [
"ipv4",
"ipv6"
],
"ipv4base": "10.0.0.0",
"ipv4mask": 30,
"ipv6base": "fd00::",
"ipv6mask": 64,
"link_ip_start": {
"ipv4": "10.0.0.0",
"v4mask": 30,
"ipv6": "fd00::",
"v6mask": 64
},
"lo_prefix": {
"ipv4": "1.0.",
"v4mask": 32,
"ipv6": "2001:DB8:F::",
"v6mask": 128
},
"routers": {
"r1": {
"links": {
"lo": {
"ipv4": "auto",
"ipv6": "auto",
"type": "loopback"
},
"r2": {
"ipv4": "auto",
"ipv6": "auto"
},
"r3": {
"ipv4": "auto",
"ipv6": "auto"
}
},
"bgp": {
"local_as": "100",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r2": {
"dest_link": {
"r1": {}
}
},
"r3": {
"dest_link": {
"r1": {}
}
}
},
"redistribute": [
{
"redist_type": "static"
},
{
"redist_type": "connected"
}
]
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r2": {
"dest_link": {
"r1": {}
}
},
"r3": {
"dest_link": {
"r1": {}
}
}
},
"redistribute": [
{
"redist_type": "static"
},
{
"redist_type": "connected"
}
]
}
}
}
},
"static_routes": [
{
"network": "192.168.22.1/32",
"no_of_ip": 2,
"next_hop": "10.0.0.2"
},
{
"network": "fc07:1::1/128",
"no_of_ip": 2,
"next_hop": "fd00::2"
},
{
"network": "192.168.21.1/32",
"no_of_ip": 2,
"next_hop": "blackhole"
},
{
"network": "fc07:150::1/128",
"no_of_ip": 2,
"next_hop": "blackhole"
}
]
},
"r2": {
"links": {
"lo": {
"ipv4": "auto",
"ipv6": "auto",
"type": "loopback"
},
"r1": {
"ipv4": "auto",
"ipv6": "auto"
},
"r3": {
"ipv4": "auto",
"ipv6": "auto"
}
},
"bgp": {
"local_as": "100",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r1": {
"dest_link": {
"r2": {}
}
},
"r3": {
"dest_link": {
"r2": {}
}
}
},
"redistribute": [
{
"redist_type": "static"
},
{
"redist_type": "connected"
}
]
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r1": {
"dest_link": {
"r2": {}
}
},
"r3": {
"dest_link": {
"r2": {}
}
}
},
"redistribute": [
{
"redist_type": "static"
},
{
"redist_type": "connected"
}
]
}
}
}
}
},
"r3": {
"links": {
"lo": {
"ipv4": "auto",
"ipv6": "auto",
"type": "loopback"
},
"r1": {
"ipv4": "auto",
"ipv6": "auto"
},
"r2": {
"ipv4": "auto",
"ipv6": "auto"
},
"r4": {
"ipv4": "auto",
"ipv6": "auto"
},
"r5": {
"ipv4": "auto",
"ipv6": "auto"
}
},
"bgp": {
"local_as": "100",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r1": {
"dest_link": {
"r3": {}
}
},
"r2": {
"dest_link": {
"r3": {}
}
},
"r4": {
"dest_link": {
"r3": {}
}
},
"r5": {
"dest_link": {
"r3": {}
}
}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r1": {
"dest_link": {
"r3": {}
}
},
"r2": {
"dest_link": {
"r3": {}
}
},
"r4": {
"dest_link": {
"r3": {}
}
},
"r5": {
"dest_link": {
"r3": {}
}
}
}
}
}
}
}
},
"r4": {
"links": {
"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": {}
}
}
},
"redistribute": [
{
"redist_type": "static"
},
{
"redist_type": "connected"
}
]
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r3": {
"dest_link": {
"r4": {}
}
}
},
"redistribute": [
{
"redist_type": "static"
},
{
"redist_type": "connected"
}
]
}
}
}
}
},
"r5": {
"links": {
"lo": {
"ipv4": "auto",
"ipv6": "auto",
"type": "loopback"
},
"r3": {
"ipv4": "auto",
"ipv6": "auto"
}
},
"bgp": {
"local_as": "300",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r3": {
"dest_link": {
"r5": {}
}
}
},
"redistribute": [
{
"redist_type": "static"
},
{
"redist_type": "connected"
}
]
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r3": {
"dest_link": {
"r5": {}
}
}
},
"redistribute": [
{
"redist_type": "static"
},
{
"redist_type": "connected"
}
]
}
}
}
},
"static_routes": [
{
"network": "192.168.20.1/32",
"no_of_ip": 2,
"next_hop": "blackhole"
},
{
"network": "fc07:50::1/128",
"no_of_ip": 2,
"next_hop": "blackhole"
},
{
"network": "192.168.21.1/32",
"no_of_ip": 2,
"next_hop": "blackhole"
},
{
"network": "fc07:150::1/128",
"no_of_ip": 2,
"next_hop": "blackhole"
}
]
}
}
}

View File

@ -0,0 +1,429 @@
{
"address_types": [
"ipv4",
"ipv6"
],
"ipv4base": "10.0.0.0",
"ipv4mask": 30,
"ipv6base": "fd00::",
"ipv6mask": 64,
"link_ip_start": {
"ipv4": "10.0.0.0",
"v4mask": 30,
"ipv6": "fd00::",
"v6mask": 64
},
"lo_prefix": {
"ipv4": "1.0.",
"v4mask": 32,
"ipv6": "2001:DB8:F::",
"v6mask": 128
},
"routers": {
"r1": {
"links": {
"lo": {
"ipv4": "auto",
"ipv6": "auto",
"type": "loopback",
"vrf": "RED"
},
"r2": {
"ipv4": "auto",
"ipv6": "auto",
"vrf": "RED"
},
"r3": {
"ipv4": "auto",
"ipv6": "auto",
"vrf": "RED"
}
},
"vrfs": [
{
"name": "RED",
"id": "1"
}
],
"bgp": [{
"local_as": "100",
"vrf": "RED",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r2": {
"dest_link": {
"r1": {}
}
},
"r3": {
"dest_link": {
"r1": {}
}
}
},
"redistribute": [
{
"redist_type": "static"
},
{
"redist_type": "connected"
}
]
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r2": {
"dest_link": {
"r1": {}
}
},
"r3": {
"dest_link": {
"r1": {}
}
}
},
"redistribute": [
{
"redist_type": "static"
},
{
"redist_type": "connected"
}
]
}
}
}
}],
"static_routes": [
{
"network": "192.168.22.1/32",
"no_of_ip": 2,
"next_hop": "10.0.0.2",
"vrf": "RED"
},
{
"network": "fc07:1::1/128",
"no_of_ip": 2,
"next_hop": "fd00::2",
"vrf": "RED"
},
{
"network": "192.168.21.1/32",
"no_of_ip": 2,
"next_hop": "blackhole",
"vrf": "RED"
},
{
"network": "fc07:150::1/128",
"no_of_ip": 2,
"next_hop": "blackhole",
"vrf": "RED"
}
]
},
"r2": {
"links": {
"lo": {
"ipv4": "auto",
"ipv6": "auto",
"type": "loopback",
"vrf": "RED"
},
"r1": {
"ipv4": "auto",
"ipv6": "auto",
"vrf": "RED"
},
"r3": {
"ipv4": "auto",
"ipv6": "auto",
"vrf": "RED"
}
},
"vrfs": [
{
"name": "RED",
"id": "1"
}
],
"bgp": [{
"local_as": "100",
"vrf": "RED",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r1": {
"dest_link": {
"r2": {}
}
},
"r3": {
"dest_link": {
"r2": {}
}
}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r1": {
"dest_link": {
"r2": {}
}
},
"r3": {
"dest_link": {
"r2": {}
}
}
}
}
}
}
}]
},
"r3": {
"links": {
"lo": {
"ipv4": "auto",
"ipv6": "auto",
"type": "loopback",
"vrf": "RED"
},
"r1": {
"ipv4": "auto",
"ipv6": "auto",
"vrf": "RED"
},
"r2": {
"ipv4": "auto",
"ipv6": "auto",
"vrf": "RED"
},
"r4": {
"ipv4": "auto",
"ipv6": "auto",
"vrf": "RED"
},
"r5": {
"ipv4": "auto",
"ipv6": "auto",
"vrf": "RED"
}
},
"vrfs": [
{
"name": "RED",
"id": "1"
}
],
"bgp": [{
"local_as": "100",
"vrf": "RED",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r1": {
"dest_link": {
"r3": {}
}
},
"r2": {
"dest_link": {
"r3": {}
}
},
"r4": {
"dest_link": {
"r3": {}
}
},
"r5": {
"dest_link": {
"r3": {}
}
}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r1": {
"dest_link": {
"r3": {}
}
},
"r2": {
"dest_link": {
"r3": {}
}
},
"r4": {
"dest_link": {
"r3": {}
}
},
"r5": {
"dest_link": {
"r3": {}
}
}
}
}
}
}
}]
},
"r4": {
"links": {
"lo": {
"ipv4": "auto",
"ipv6": "auto",
"type": "loopback",
"vrf": "RED"
},
"r3": {
"ipv4": "auto",
"ipv6": "auto",
"vrf": "RED"
}
},
"vrfs": [
{
"name": "RED",
"id": "1"
}
],
"bgp": [{
"local_as": "200",
"vrf": "RED",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r3": {
"dest_link": {
"r4": {}
}
}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r3": {
"dest_link": {
"r4": {}
}
}
}
}
}
}
}]
},
"r5": {
"links": {
"lo": {
"ipv4": "auto",
"ipv6": "auto",
"type": "loopback",
"vrf": "RED"
},
"r3": {
"ipv4": "auto",
"ipv6": "auto",
"vrf": "RED"
}
},
"vrfs": [
{
"name": "RED",
"id": "1"
}
],
"bgp": [{
"local_as": "300",
"vrf": "RED",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r3": {
"dest_link": {
"r5": {}
}
}
},
"redistribute": [
{
"redist_type": "static"
},
{
"redist_type": "connected"
}
]
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r3": {
"dest_link": {
"r5": {}
}
}
},
"redistribute": [
{
"redist_type": "static"
},
{
"redist_type": "connected"
}
]
}
}
}
}],
"static_routes": [
{
"network": "192.168.20.1/32",
"no_of_ip": 2,
"next_hop": "blackhole",
"vrf": "RED"
},
{
"network": "fc07:50::1/128",
"no_of_ip": 2,
"next_hop": "blackhole",
"vrf": "RED"
},
{
"network": "192.168.21.1/32",
"no_of_ip": 2,
"next_hop": "blackhole",
"vrf": "RED"
},
{
"network": "fc07:150::1/128",
"no_of_ip": 2,
"next_hop": "blackhole",
"vrf": "RED"
}
]
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,900 @@
#!/usr/bin/env python
#
# Copyright (c) 2022 by VMware, Inc. ("VMware")
# Used Copyright (c) 2018 by Network Device Education Foundation,
# Inc. ("NetDEF") in this file.
#
# Permission to use, copy, modify, and/or distribute this software
# for any purpose with or without fee is hereby granted, provided
# that the above copyright notice and this permission notice appear
# in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND VMWARE DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
# OF THIS SOFTWARE.
#
import sys
import time
import pytest
import inspect
import os
"""Following tests are covered to test bgp admin distance functionality.
TC_5:
Verify bgp admin distance functionality when static route is configured
same as bgp learnt route in user vrf.
TC_6: Verify bgp admin distance functionality with ECMP in user vrf.
TC_7:
Verify bgp admin distance functionality when routes are
imported between VRFs.
"""
#################################
# TOPOLOGY
#################################
"""
+-------+
+--------- | R2 |
| +-------+
|iBGP |
+-------+ |
| R1 | |iBGP
+-------+ |
| |
| iBGP +-------+ eBGP +-------+
+---------- | R3 |----------| R4 |
+-------+ +-------+
|
|eBGP
|
+-------+
| R5 |
+-------+
"""
# Save the Current Working Directory to find configuration files.
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
sys.path.append(os.path.join(CWD, "../lib/"))
# pylint: disable=C0413
# Import topogen and topotest helpers
from lib.topogen import Topogen, get_topogen
# Required to instantiate the topology builder class.
from lib.common_config import (
start_topology,
write_test_header,
step,
write_test_footer,
create_static_routes,
verify_rib,
check_address_types,
reset_config_on_routers,
check_router_status,
)
from lib.topolog import logger
from lib.bgp import (
verify_bgp_convergence,
create_router_bgp,
verify_best_path_as_per_admin_distance,
)
# pylint: disable=C0413
# Import topogen and topotest helpers
from lib.topogen import Topogen, get_topogen
from lib.topojson import build_config_from_json
from lib.topolog import logger
# Global variables
topo = None
bgp_convergence = False
pytestmark = [pytest.mark.bgpd, pytest.mark.staticd]
NETWORK = {
"ipv4": [
"192.168.20.1/32",
"192.168.20.2/32",
"192.168.21.1/32",
"192.168.21.2/32",
"192.168.22.1/32",
"192.168.22.2/32",
],
"ipv6": [
"fc07:50::1/128",
"fc07:50::2/128",
"fc07:150::1/128",
"fc07:150::2/128",
"fc07:1::1/128",
"fc07:1::2/128",
],
}
ADDR_TYPES = check_address_types()
def setup_module(mod):
"""
Sets up the pytest environment
* `mod`: module name
"""
global topo
testsuite_run_time = time.asctime(time.localtime(time.time()))
logger.info("Testsuite start time: {}".format(testsuite_run_time))
logger.info("=" * 40)
logger.info("Running setup_module to create topology")
# This function initiates the topology build with Topogen...
json_file = "{}/bgp_admin_dist_vrf.json".format(CWD)
tgen = Topogen(json_file, mod.__name__)
global topo
topo = tgen.json_topo
# Starting topology, create tmp files which are loaded to routers
# to start deamons and then start routers
start_topology(tgen)
# Creating configuration from JSON
build_config_from_json(tgen, topo)
# Checking BGP convergence
global bgp_convergence
global ADDR_TYPES
# Don't run this test if we have any failure.
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
# Api call verify whether BGP is converged
bgp_convergence = verify_bgp_convergence(tgen, topo)
assert bgp_convergence is True, "setup_module :Failed \n Error:" " {}".format(
bgp_convergence
)
logger.info("Running setup_module() done")
def teardown_module(mod):
"""teardown_module.
Teardown the pytest environment.
* `mod`: module name
"""
logger.info("Running teardown_module to delete topology")
tgen = get_topogen()
# Stop toplogy and Remove tmp files
tgen.stop_topology()
logger.info(
"Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
)
logger.info("=" * 40)
#####################################################
# Tests starting
#####################################################
def test_bgp_admin_distance_ebgp_vrf_p0():
"""
TC: 5
Verify bgp admin distance functionality when static route is
configured same as ebgp learnt route
"""
tgen = get_topogen()
global bgp_convergence
if bgp_convergence is not True:
pytest.skip("skipping test case because of BGP Convergence failure at setup")
# test case name
tc_name = inspect.stack()[0][3]
write_test_header(tc_name)
if tgen.routers_have_failure():
check_router_status(tgen)
step("Configure base config as per the topology")
reset_config_on_routers(tgen)
step("Configure bgp admin distance 200 with CLI in dut.")
input_dict_1 = {
"r3": {
"bgp": [
{
"vrf": "RED",
"local_as": 100,
"address_family": {
"ipv4": {
"unicast": {
"distance": {"ebgp": 200, "ibgp": 200, "local": 200}
}
},
"ipv6": {
"unicast": {
"distance": {"ebgp": 200, "ibgp": 200, "local": 200}
}
},
},
}
]
}
}
result = create_router_bgp(tgen, topo, input_dict_1)
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
step("Verify bgp routes have admin distance of 200 in dut.")
# Verifying best path
dut = "r3"
attribute = "admin_distance"
input_dict = {
"ipv4": {
"r3": {
"static_routes": [
{
"network": NETWORK["ipv4"][0],
"admin_distance": 200,
"vrf": "RED",
},
{
"network": NETWORK["ipv4"][1],
"admin_distance": 200,
"vrf": "RED",
},
]
}
},
"ipv6": {
"r3": {
"static_routes": [
{
"network": NETWORK["ipv6"][0],
"admin_distance": 200,
"vrf": "RED",
},
{
"network": NETWORK["ipv6"][1],
"admin_distance": 200,
"vrf": "RED",
},
]
}
},
}
for addr_type in ADDR_TYPES:
result = verify_best_path_as_per_admin_distance(
tgen, addr_type, dut, input_dict[addr_type], attribute, vrf="RED"
)
assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result
)
step("Modify the admin distance value to 150.")
input_dict_1 = {
"r3": {
"bgp": [
{
"local_as": 100,
"address_family": {
"ipv4": {
"unicast": {
"distance": {"ebgp": 150, "ibgp": 150, "local": 150}
}
},
"ipv6": {
"unicast": {
"distance": {"ebgp": 150, "ibgp": 150, "local": 150}
}
},
},
}
]
}
}
result = create_router_bgp(tgen, topo, input_dict_1)
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
step("Verify bgp routes have admin distance of 150 in dut.")
# Verifying best path
dut = "r3"
attribute = "admin_distance"
input_dict = {
"ipv4": {
"r3": {
"static_routes": [
{
"network": NETWORK["ipv4"][0],
"admin_distance": 150,
"vrf": "RED",
},
{
"network": NETWORK["ipv4"][1],
"admin_distance": 150,
"vrf": "RED",
},
]
}
},
"ipv6": {
"r3": {
"static_routes": [
{
"network": NETWORK["ipv6"][0],
"admin_distance": 150,
"vrf": "RED",
},
{
"network": NETWORK["ipv6"][1],
"admin_distance": 150,
"vrf": "RED",
},
]
}
},
}
for addr_type in ADDR_TYPES:
result = verify_best_path_as_per_admin_distance(
tgen, addr_type, dut, input_dict[addr_type], attribute, vrf="RED"
)
assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result
)
step("Un configure the admin distance value on DUT")
input_dict_1 = {
"r3": {
"bgp": [
{
"local_as": 100,
"address_family": {
"ipv4": {
"unicast": {
"distance": {
"ebgp": 150,
"ibgp": 150,
"local": 150,
"delete": True,
}
}
},
"ipv6": {
"unicast": {
"distance": {
"ebgp": 150,
"ibgp": 150,
"local": 150,
"delete": True,
}
}
},
},
}
]
}
}
result = create_router_bgp(tgen, topo, input_dict_1)
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
step("Verify bgp routes have default admin distance in dut.")
# Verifying best path
dut = "r3"
attribute = "admin_distance"
input_dict = {
"ipv4": {
"r3": {
"static_routes": [
{"network": NETWORK["ipv4"][0], "admin_distance": 20, "vrf": "RED"},
{"network": NETWORK["ipv4"][1], "admin_distance": 20, "vrf": "RED"},
]
}
},
"ipv6": {
"r3": {
"static_routes": [
{"network": NETWORK["ipv6"][0], "admin_distance": 20, "vrf": "RED"},
{"network": NETWORK["ipv6"][1], "admin_distance": 20, "vrf": "RED"},
]
}
},
}
for addr_type in ADDR_TYPES:
result = verify_best_path_as_per_admin_distance(
tgen, addr_type, dut, input_dict[addr_type], attribute, vrf="RED"
)
assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result
)
step("Configure static route Without any admin distance")
for addr_type in ADDR_TYPES:
# Create Static routes
input_dict = {
"r3": {
"static_routes": [
{"network": NETWORK[addr_type], "next_hop": "Null0", "vrf": "RED"}
]
}
}
result = create_static_routes(tgen, input_dict)
assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result
)
step("Verify that zebra selects static route.")
protocol = "static"
# dual stack changes
for addr_type in ADDR_TYPES:
input_dict = {
"r3": {
"static_routes": [
{"network": NETWORK[addr_type], "next_hop": "Null0", "vrf": "RED"}
]
}
}
result4 = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result4
)
step("Configure static route with admin distance of 253")
for addr_type in ADDR_TYPES:
# Create Static routes
input_dict = {
"r3": {
"static_routes": [
{
"network": NETWORK[addr_type],
"next_hop": "Null0",
"admin_distance": 253,
"vrf": "RED",
}
]
}
}
result = create_static_routes(tgen, input_dict)
assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result
)
step("Verify that zebra selects bgp route.")
protocol = "bgp"
for addr_type in ADDR_TYPES:
input_dict = {
"r3": {
"static_routes": [
{
"network": NETWORK[addr_type],
"next_hop": "Null0",
"admin_distance": 253,
"vrf": "RED",
}
]
}
}
result4 = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result4
)
step("Configure admin distance of 254 in bgp for route .")
input_dict_1 = {
"r3": {
"bgp": [
{
"local_as": 100,
"address_family": {
"ipv4": {
"unicast": {
"distance": {"ebgp": 254, "ibgp": 254, "local": 254}
}
},
"ipv6": {
"unicast": {
"distance": {"ebgp": 254, "ibgp": 254, "local": 254}
}
},
},
}
]
}
}
result = create_router_bgp(tgen, topo, input_dict_1)
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
step("Verify that zebra selects static route.")
protocol = "static"
# dual stack changes
for addr_type in ADDR_TYPES:
input_dict = {
"r3": {
"static_routes": [
{
"network": NETWORK[addr_type],
"next_hop": "Null0",
"admin_distance": 253,
"vrf": "RED",
}
]
}
}
result4 = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result4
)
step("Configure admin distance of 255 in bgp for route in vrf red")
input_dict_1 = {
"r3": {
"bgp": [
{
"local_as": 100,
"address_family": {
"ipv4": {
"unicast": {
"distance": {"ebgp": 255, "ibgp": 255, "local": 255}
}
},
"ipv6": {
"unicast": {
"distance": {"ebgp": 255, "ibgp": 255, "local": 255}
}
},
},
}
]
}
}
result = create_router_bgp(tgen, topo, input_dict_1)
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
step("Verify that zebra selects static route.")
protocol = "static"
# dual stack changes
for addr_type in ADDR_TYPES:
input_dict = {
"r3": {
"static_routes": [
{
"network": NETWORK[addr_type],
"next_hop": "Null0",
"admin_distance": 253,
"vrf": "RED",
}
]
}
}
result4 = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result4
)
step("Delete the static route.")
for addr_type in ADDR_TYPES:
# Create Static routes
input_dict = {
"r3": {
"static_routes": [
{
"network": NETWORK[addr_type],
"next_hop": "Null0",
"admin_distance": 253,
"delete": True,
"vrf": "RED",
}
]
}
}
result = create_static_routes(tgen, input_dict)
assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result
)
step("Verify that zebra selects bgp route.")
protocol = "bgp"
# dual stack changes
for addr_type in ADDR_TYPES:
result4 = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result4
)
write_test_footer(tc_name)
def test_bgp_admin_distance_ebgp_with_imported_rtes_vrf_p0():
"""
TC: 5
Verify bgp admin distance functionality when static route is configured
same as bgp learnt route in user vrf.
"""
tgen = get_topogen()
global bgp_convergence
if bgp_convergence is not True:
pytest.skip("skipping test case because of BGP Convergence failure at setup")
# test case name
tc_name = inspect.stack()[0][3]
write_test_header(tc_name)
if tgen.routers_have_failure():
check_router_status(tgen)
step("Configure base config as per the topology")
reset_config_on_routers(tgen)
step("Configure bgp admin distance 200 with CLI in dut.")
step(" Import route from vrf to default vrf")
input_dict_1 = {
"r3": {
"bgp": [
{
"vrf": "RED",
"local_as": 100,
"address_family": {
"ipv4": {
"unicast": {
"distance": {"ebgp": 200, "ibgp": 200, "local": 200}
}
},
"ipv6": {
"unicast": {
"distance": {"ebgp": 200, "ibgp": 200, "local": 200}
}
},
},
},
{
"local_as": 100,
"address_family": {
"ipv4": {
"unicast": {
"distance": {"ebgp": 200, "ibgp": 200, "local": 200},
"import": {"vrf": "RED"},
}
},
"ipv6": {
"unicast": {
"distance": {"ebgp": 200, "ibgp": 200, "local": 200},
"import": {
"vrf": "RED",
},
}
},
},
},
]
}
}
result = create_router_bgp(tgen, topo, input_dict_1)
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
step("Verify bgp routes have admin distance of 200 in dut.")
# Verifying best path
dut = "r3"
attribute = "admin_distance"
input_dict = {
"ipv4": {
"r3": {
"static_routes": [
{
"network": NETWORK["ipv4"][0],
"admin_distance": 200,
"vrf": "RED",
},
{
"network": NETWORK["ipv4"][1],
"admin_distance": 200,
"vrf": "RED",
},
]
}
},
"ipv6": {
"r3": {
"static_routes": [
{
"network": NETWORK["ipv6"][0],
"admin_distance": 200,
"vrf": "RED",
},
{
"network": NETWORK["ipv6"][1],
"admin_distance": 200,
"vrf": "RED",
},
]
}
},
}
for addr_type in ADDR_TYPES:
result = verify_best_path_as_per_admin_distance(
tgen, addr_type, dut, input_dict[addr_type], attribute, vrf="RED"
)
assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result
)
step(
"Verify that routes are getting imported without any issues and "
"routes are calculated and installed in rib."
)
input_dict = {
"ipv4": {
"r3": {
"static_routes": [
{
"network": NETWORK["ipv4"][0],
"admin_distance": 200,
},
{
"network": NETWORK["ipv4"][1],
"admin_distance": 200,
},
]
}
},
"ipv6": {
"r3": {
"static_routes": [
{
"network": NETWORK["ipv6"][0],
"admin_distance": 200,
},
{
"network": NETWORK["ipv6"][1],
"admin_distance": 200,
},
]
}
},
}
step("Verify that zebra selects bgp route.")
protocol = "bgp"
# dual stack changes
for addr_type in ADDR_TYPES:
result4 = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result4
)
step(" Un configure import route vrf red inside default vrf.")
input_dict_1 = {
"r3": {
"bgp": [
{
"vrf": "RED",
"local_as": 100,
"address_family": {
"ipv4": {
"unicast": {
"distance": {"ebgp": 200, "ibgp": 200, "local": 200}
}
},
"ipv6": {
"unicast": {
"distance": {"ebgp": 200, "ibgp": 200, "local": 200}
}
},
},
},
{
"local_as": 100,
"address_family": {
"ipv4": {
"unicast": {
"distance": {"ebgp": 200, "ibgp": 200, "local": 200},
"import": {"vrf": "RED", "delete": True},
}
},
"ipv6": {
"unicast": {
"distance": {"ebgp": 200, "ibgp": 200, "local": 200},
"import": {"vrf": "RED", "delete": True},
}
},
},
},
]
}
}
result = create_router_bgp(tgen, topo, input_dict_1)
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
input_dict = {
"ipv4": {
"r3": {
"static_routes": [
{
"network": NETWORK["ipv4"][0],
"admin_distance": 200,
},
{
"network": NETWORK["ipv4"][1],
"admin_distance": 200,
},
]
}
},
"ipv6": {
"r3": {
"static_routes": [
{
"network": NETWORK["ipv6"][0],
"admin_distance": 200,
},
{
"network": NETWORK["ipv6"][1],
"admin_distance": 200,
},
]
}
},
}
step("Verify that route withdrawal happens properly.")
protocol = "bgp"
# dual stack changes
for addr_type in ADDR_TYPES:
result4 = verify_rib(
tgen,
addr_type,
dut,
input_dict[addr_type],
protocol=protocol,
expected=False,
)
assert (
result4 is not True
), "Testcase {} : Failed \n Route is not withdrawn. Error: {}".format(
tc_name, result4
)
write_test_footer(tc_name)
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))

View File

@ -491,6 +491,25 @@ def __create_bgp_unicast_neighbor(
cmd = "no {}".format(cmd)
config_data.append(cmd)
admin_dist_data = addr_data.setdefault("distance", {})
if admin_dist_data:
if len(admin_dist_data) < 2:
logger.debug(
"Router %s: pass the admin distance values for "
"ebgp, ibgp and local routes",
router,
)
cmd = "distance bgp {} {} {}".format(
admin_dist_data["ebgp"],
admin_dist_data["ibgp"],
admin_dist_data["local"],
)
del_action = admin_dist_data.setdefault("delete", False)
if del_action:
cmd = "no distance bgp"
config_data.append(cmd)
import_vrf_data = addr_data.setdefault("import", {})
if import_vrf_data:
cmd = "import vrf {}".format(import_vrf_data["vrf"])
@ -2662,7 +2681,7 @@ def verify_best_path_as_per_bgp_attribute(
@retry(retry_timeout=10)
def verify_best_path_as_per_admin_distance(
tgen, addr_type, router, input_dict, attribute, expected=True
tgen, addr_type, router, input_dict, attribute, expected=True, vrf=None
):
"""
API is to verify best path according to admin distance for given
@ -2678,6 +2697,7 @@ def verify_best_path_as_per_admin_distance(
* `input_dict`: defines different routes with different admin distance
to calculate for which route best path is selected
* `expected` : expected results from API, by-default True
* `vrf`: Pass vrf name check for perticular vrf.
Usage
-----
@ -2710,9 +2730,14 @@ def verify_best_path_as_per_admin_distance(
# Show ip route cmd
if addr_type == "ipv4":
command = "show ip route json"
command = "show ip route"
else:
command = "show ipv6 route json"
command = "show ipv6 route"
if vrf:
command = "{} vrf {} json".format(command, vrf)
else:
command = "{} json".format(command)
for routes_from_router in input_dict.keys():
sh_ip_route_json = router_list[routes_from_router].vtysh_cmd(

View File

@ -3339,6 +3339,7 @@ def verify_rib(
metric=None,
fib=None,
count_only=False,
admin_distance=None,
):
"""
Data will be read from input_dict or input JSON file, API will generate
@ -3611,6 +3612,30 @@ def verify_rib(
)
return errormsg
if admin_distance is not None:
if "distance" not in rib_routes_json[st_rt][0]:
errormsg = (
"[DUT: {}]: admin distance is"
" not present for"
" route {} in RIB \n".format(dut, st_rt)
)
return errormsg
if (
admin_distance
!= rib_routes_json[st_rt][0]["distance"]
):
errormsg = (
"[DUT: {}]: admin distance value "
"{} is not matched for "
"route {} in RIB \n".format(
dut,
admin_distance,
st_rt,
)
)
return errormsg
if metric is not None:
if "metric" not in rib_routes_json[st_rt][0]:
errormsg = (
@ -3764,7 +3789,7 @@ def verify_rib(
@retry(retry_timeout=12)
def verify_fib_routes(tgen, addr_type, dut, input_dict, next_hop=None):
def verify_fib_routes(tgen, addr_type, dut, input_dict, next_hop=None, protocol=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
@ -3822,6 +3847,9 @@ def verify_fib_routes(tgen, addr_type, dut, input_dict, next_hop=None):
found_routes = []
missing_routes = []
if protocol:
command = "{} {}".format(command, protocol)
if "static_routes" in input_dict[routerInput]:
static_routes = input_dict[routerInput]["static_routes"]
@ -5039,7 +5067,7 @@ def verify_ip_nht(tgen, input_dict):
for nh in nh_list:
if nh in show_ip_nht:
nht = run_frr_cmd(rnode, f"show ip nht {nh}")
nht = run_frr_cmd(rnode, "show ip nht {}".format(nh))
if "unresolved" in nht:
errormsg = "Nexthop {} became unresolved on {}".format(nh, router)
return errormsg