Merge pull request #6926 from kuldeepkash/dynamic_route_leak

tests: Add bgp_vrf_dynamic_route_leak test suite
This commit is contained in:
Martin Winter 2020-09-03 19:03:22 +02:00 committed by GitHub
commit 0c7b459c2c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 4226 additions and 19 deletions

View File

@ -0,0 +1,563 @@
{
"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": {
"r2-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "ISR"},
"r3-link1": {"ipv4": "auto", "ipv6": "auto"},
"r4-link1": {"ipv4": "auto", "ipv6": "auto"}
},
"vrfs":[
{
"name": "ISR",
"id": "1"
}
],
"bgp":
[
{
"local_as": "100",
"vrf": "ISR",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r2": {
"dest_link": {
"r1-link1": {
"keepalivetimer": 1,
"holddowntimer": 3,
"next_hop_self": true
}
}
}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r2": {
"dest_link": {
"r1-link1": {
"keepalivetimer": 1,
"holddowntimer": 3,
"next_hop_self": true,
"route_maps": [{
"name": "rmap_global",
"direction": "in"
}]
}
}
}
}
}
}
}
},
{
"local_as": "100",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r3": {
"dest_link": {
"r1-link1": {
"keepalivetimer": 1,
"holddowntimer": 3
}
}
}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r3": {
"dest_link": {
"r1-link1": {
"keepalivetimer": 1,
"holddowntimer": 3,
"route_maps": [{
"name": "rmap_global",
"direction": "in"
}]
}
}
}
}
}
}
}
},
{
"local_as": "100",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r4": {
"dest_link": {
"r1-link1": {
"keepalivetimer": 1,
"holddowntimer": 3
}
}
}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r4": {
"dest_link": {
"r1-link1": {
"keepalivetimer": 1,
"holddowntimer": 3,
"route_maps": [{
"name": "rmap_global",
"direction": "in"
}]
}
}
}
}
}
}
}
}
],
"static_routes":[
{
"network": ["11.11.11.1/32", "11.11.11.11/32"],
"next_hop":"Null0",
"vrf": "ISR"
},
{
"network": ["11:11::1/128", "11:11::11/128"],
"next_hop":"Null0",
"vrf": "ISR"
},
{
"network": ["10.10.10.10/32", "10.10.10.100/32"],
"next_hop":"Null0"
},
{
"network": ["10:10::10/128", "10:10::100/128"],
"next_hop":"Null0"
}
],
"route_maps": {
"rmap_global": [{
"action": "permit",
"set": {
"ipv6": {
"nexthop": "prefer-global"
}
}
}]
}
},
"r2": {
"links": {
"r1-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "ISR"},
"r3-link1": {"ipv4": "auto", "ipv6": "auto"},
"r4-link1": {"ipv4": "auto", "ipv6": "auto"}
},
"vrfs":[
{
"name": "ISR",
"id": "1"
}
],
"bgp":
[
{
"local_as": "100",
"vrf": "ISR",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r1": {
"dest_link": {
"r2-link1": {
"keepalivetimer": 1,
"holddowntimer": 3,
"next_hop_self": true
}
}
}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r1": {
"dest_link": {
"r2-link1": {
"keepalivetimer": 1,
"holddowntimer": 3,
"next_hop_self": true,
"route_maps": [{
"name": "rmap_global",
"direction": "in"
}]
}
}
}
}
}
}
}
},
{
"local_as": "100",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r3": {
"dest_link": {
"r2-link1": {
"keepalivetimer": 1,
"holddowntimer": 3
}
}
}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r3": {
"dest_link": {
"r2-link1": {
"keepalivetimer": 1,
"holddowntimer": 3,
"route_maps": [{
"name": "rmap_global",
"direction": "in"
}]
}
}
}
}
}
}
}
},
{
"local_as": "100",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r4": {
"dest_link": {
"r2-link1": {
"keepalivetimer": 1,
"holddowntimer": 3
}
}
}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r4": {
"dest_link": {
"r2-link1": {
"keepalivetimer": 1,
"holddowntimer": 3,
"route_maps": [{
"name": "rmap_global",
"direction": "in"
}]
}
}
}
}
}
}
}
}
],
"static_routes":[
{
"network": ["22.22.22.2/32", "22.22.22.22/32"],
"next_hop":"Null0",
"vrf": "ISR"
},
{
"network": ["22:22::2/128", "22:22::22/128"],
"next_hop":"Null0",
"vrf": "ISR"
},
{
"network": ["20.20.20.20/32", "20.20.20.200/32"],
"next_hop":"Null0"
},
{
"network": ["20:20::20/128", "20:20::200/128"],
"next_hop":"Null0"
}
],
"route_maps": {
"rmap_global": [{
"action": "permit",
"set": {
"ipv6": {
"nexthop": "prefer-global"
}
}
}]
}
},
"r3": {
"links": {
"r1-link1": {"ipv4": "auto", "ipv6": "auto"},
"r2-link1": {"ipv4": "auto", "ipv6": "auto"}
},
"bgp":
[
{
"local_as": "300",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r1": {
"dest_link": {
"r3-link1": {
"keepalivetimer": 1,
"holddowntimer": 3
}
}
}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r1": {
"dest_link": {
"r3-link1": {
"keepalivetimer": 1,
"holddowntimer": 3,
"route_maps": [{
"name": "rmap_global",
"direction": "in"
}]
}
}
}
}
}
}
}
},
{
"local_as": "300",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r2": {
"dest_link": {
"r3-link1": {
"keepalivetimer": 1,
"holddowntimer": 3
}
}
}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r2": {
"dest_link": {
"r3-link1": {
"keepalivetimer": 1,
"holddowntimer": 3,
"route_maps": [{
"name": "rmap_global",
"direction": "in"
}]
}
}
}
}
}
}
}
}
],
"static_routes":[
{
"network": ["30.30.30.3/32", "30.30.30.30/32"],
"next_hop":"Null0"
},
{
"network": ["30:30::3/128", "30:30::30/128"],
"next_hop":"Null0"
},
{
"network": ["50.50.50.5/32", "50.50.50.50/32"],
"next_hop":"Null0"
},
{
"network": ["50:50::5/128", "50:50::50/128"],
"next_hop":"Null0"
}
],
"route_maps": {
"rmap_global": [{
"action": "permit",
"set": {
"ipv6": {
"nexthop": "prefer-global"
}
}
}]
}
},
"r4": {
"links": {
"r1-link1": {"ipv4": "auto", "ipv6": "auto"},
"r2-link1": {"ipv4": "auto", "ipv6": "auto"}
},
"bgp":
[
{
"local_as": "400",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r1": {
"dest_link": {
"r4-link1": {
"keepalivetimer": 1,
"holddowntimer": 3
}
}
}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r1": {
"dest_link": {
"r4-link1": {
"keepalivetimer": 1,
"holddowntimer": 3,
"route_maps": [{
"name": "rmap_global",
"direction": "in"
}]
}
}
}
}
}
}
}
},
{
"local_as": "400",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r2": {
"dest_link": {
"r4-link1": {
"keepalivetimer": 1,
"holddowntimer": 3
}
}
}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r2": {
"dest_link": {
"r4-link1": {
"keepalivetimer": 1,
"holddowntimer": 3,
"route_maps": [{
"name": "rmap_global",
"direction": "in"
}]
}
}
}
}
}
}
}
}
],
"static_routes":[
{
"network": ["40.40.40.4/32", "40.40.40.40/32"],
"next_hop":"Null0"
},
{
"network": ["40:40::4/128", "40:40::40/128"],
"next_hop":"Null0"
},
{
"network": ["50.50.50.5/32", "50.50.50.50/32"],
"next_hop":"Null0"
},
{
"network": ["50:50::5/128", "50:50::50/128"],
"next_hop":"Null0"
}
],
"route_maps": {
"rmap_global": [{
"action": "permit",
"set": {
"ipv6": {
"nexthop": "prefer-global"
}
}
}]
}
}
}
}

View File

@ -0,0 +1,563 @@
{
"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": {
"r2-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "ISR"},
"r3-link1": {"ipv4": "auto", "ipv6": "auto"},
"r4-link1": {"ipv4": "auto", "ipv6": "auto"}
},
"vrfs":[
{
"name": "ISR",
"id": "1"
}
],
"bgp":
[
{
"local_as": "100",
"vrf": "ISR",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r2": {
"dest_link": {
"r1-link1": {
"keepalivetimer": 1,
"holddowntimer": 3,
"next_hop_self": true
}
}
}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r2": {
"dest_link": {
"r1-link1": {
"keepalivetimer": 1,
"holddowntimer": 3,
"next_hop_self": true,
"route_maps": [{
"name": "rmap_global",
"direction": "in"
}]
}
}
}
}
}
}
}
},
{
"local_as": "100",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r3": {
"dest_link": {
"r1-link1": {
"keepalivetimer": 1,
"holddowntimer": 3
}
}
}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r3": {
"dest_link": {
"r1-link1": {
"keepalivetimer": 1,
"holddowntimer": 3,
"route_maps": [{
"name": "rmap_global",
"direction": "in"
}]
}
}
}
}
}
}
}
},
{
"local_as": "100",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r4": {
"dest_link": {
"r1-link1": {
"keepalivetimer": 1,
"holddowntimer": 3
}
}
}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r4": {
"dest_link": {
"r1-link1": {
"keepalivetimer": 1,
"holddowntimer": 3,
"route_maps": [{
"name": "rmap_global",
"direction": "in"
}]
}
}
}
}
}
}
}
}
],
"static_routes":[
{
"network": ["11.11.11.1/32", "11.11.11.11/32"],
"next_hop":"Null0",
"vrf": "ISR"
},
{
"network": ["11:11::1/128", "11:11::11/128"],
"next_hop":"Null0",
"vrf": "ISR"
},
{
"network": ["10.10.10.10/32", "10.10.10.100/32"],
"next_hop":"Null0"
},
{
"network": ["10:10::10/128", "10:10::100/128"],
"next_hop":"Null0"
}
],
"route_maps": {
"rmap_global": [{
"action": "permit",
"set": {
"ipv6": {
"nexthop": "prefer-global"
}
}
}]
}
},
"r2": {
"links": {
"r1-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "ISR"},
"r3-link1": {"ipv4": "auto", "ipv6": "auto"},
"r4-link1": {"ipv4": "auto", "ipv6": "auto"}
},
"vrfs":[
{
"name": "ISR",
"id": "1"
}
],
"bgp":
[
{
"local_as": "100",
"vrf": "ISR",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r1": {
"dest_link": {
"r2-link1": {
"keepalivetimer": 1,
"holddowntimer": 3,
"next_hop_self": true
}
}
}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r1": {
"dest_link": {
"r2-link1": {
"keepalivetimer": 1,
"holddowntimer": 3,
"next_hop_self": true,
"route_maps": [{
"name": "rmap_global",
"direction": "in"
}]
}
}
}
}
}
}
}
},
{
"local_as": "100",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r3": {
"dest_link": {
"r2-link1": {
"keepalivetimer": 1,
"holddowntimer": 3
}
}
}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r3": {
"dest_link": {
"r2-link1": {
"keepalivetimer": 1,
"holddowntimer": 3,
"route_maps": [{
"name": "rmap_global",
"direction": "in"
}]
}
}
}
}
}
}
}
},
{
"local_as": "100",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r4": {
"dest_link": {
"r2-link1": {
"keepalivetimer": 1,
"holddowntimer": 3
}
}
}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r4": {
"dest_link": {
"r2-link1": {
"keepalivetimer": 1,
"holddowntimer": 3,
"route_maps": [{
"name": "rmap_global",
"direction": "in"
}]
}
}
}
}
}
}
}
}
],
"static_routes":[
{
"network": ["22.22.22.2/32", "22.22.22.22/32"],
"next_hop":"Null0",
"vrf": "ISR"
},
{
"network": ["22:22::2/128", "22:22::22/128"],
"next_hop":"Null0",
"vrf": "ISR"
},
{
"network": ["20.20.20.20/32", "20.20.20.200/32"],
"next_hop":"Null0"
},
{
"network": ["20:20::20/128", "20:20::200/128"],
"next_hop":"Null0"
}
],
"route_maps": {
"rmap_global": [{
"action": "permit",
"set": {
"ipv6": {
"nexthop": "prefer-global"
}
}
}]
}
},
"r3": {
"links": {
"r1-link1": {"ipv4": "auto", "ipv6": "auto"},
"r2-link1": {"ipv4": "auto", "ipv6": "auto"}
},
"bgp":
[
{
"local_as": "300",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r1": {
"dest_link": {
"r3-link1": {
"keepalivetimer": 1,
"holddowntimer": 3
}
}
}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r1": {
"dest_link": {
"r3-link1": {
"keepalivetimer": 1,
"holddowntimer": 3,
"route_maps": [{
"name": "rmap_global",
"direction": "in"
}]
}
}
}
}
}
}
}
},
{
"local_as": "300",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r2": {
"dest_link": {
"r3-link1": {
"keepalivetimer": 1,
"holddowntimer": 3
}
}
}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r2": {
"dest_link": {
"r3-link1": {
"keepalivetimer": 1,
"holddowntimer": 3,
"route_maps": [{
"name": "rmap_global",
"direction": "in"
}]
}
}
}
}
}
}
}
}
],
"static_routes":[
{
"network": ["30.30.30.3/32", "30.30.30.30/32"],
"next_hop":"Null0"
},
{
"network": ["30:30::3/128", "30:30::30/128"],
"next_hop":"Null0"
},
{
"network": ["50.50.50.5/32", "50.50.50.50/32"],
"next_hop":"Null0"
},
{
"network": ["50:50::5/128", "50:50::50/128"],
"next_hop":"Null0"
}
],
"route_maps": {
"rmap_global": [{
"action": "permit",
"set": {
"ipv6": {
"nexthop": "prefer-global"
}
}
}]
}
},
"r4": {
"links": {
"r1-link1": {"ipv4": "auto", "ipv6": "auto"},
"r2-link1": {"ipv4": "auto", "ipv6": "auto"}
},
"bgp":
[
{
"local_as": "400",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r1": {
"dest_link": {
"r4-link1": {
"keepalivetimer": 1,
"holddowntimer": 3
}
}
}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r1": {
"dest_link": {
"r4-link1": {
"keepalivetimer": 1,
"holddowntimer": 3,
"route_maps": [{
"name": "rmap_global",
"direction": "in"
}]
}
}
}
}
}
}
}
},
{
"local_as": "400",
"address_family": {
"ipv4": {
"unicast": {
"neighbor": {
"r2": {
"dest_link": {
"r4-link1": {
"keepalivetimer": 1,
"holddowntimer": 3
}
}
}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
"r2": {
"dest_link": {
"r4-link1": {
"keepalivetimer": 1,
"holddowntimer": 3,
"route_maps": [{
"name": "rmap_global",
"direction": "in"
}]
}
}
}
}
}
}
}
}
],
"static_routes":[
{
"network": ["40.40.40.4/32", "40.40.40.40/32"],
"next_hop":"Null0"
},
{
"network": ["40:40::4/128", "40:40::40/128"],
"next_hop":"Null0"
},
{
"network": ["50.50.50.5/32", "50.50.50.50/32"],
"next_hop":"Null0"
},
{
"network": ["50:50::5/128", "50:50::50/128"],
"next_hop":"Null0"
}
],
"route_maps": {
"rmap_global": [{
"action": "permit",
"set": {
"ipv6": {
"nexthop": "prefer-global"
}
}
}]
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,962 @@
#!/usr/bin/env python
#
# Copyright (c) 2020 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.
#
"""
Following tests are covered to test BGP Multi-VRF Dynamic Route Leaking:
1. Verify that Changing route-map configurations(match/set clauses) on
the fly it takes immediate effect.
2. Verify BGP best path selection algorithm works fine when
routes are imported from ISR to default vrf and vice versa.
"""
import os
import sys
import json
import time
import pytest
import platform
# 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/'))
# Required to instantiate the topology builder class.
# pylint: disable=C0413
# Import topogen and topotest helpers
from lib.topogen import Topogen, get_topogen
from lib.topotest import version_cmp
from mininet.topo import Topo
from lib.common_config import (
start_topology, write_test_header, check_address_types,
write_test_footer,
verify_rib, step, create_route_maps,
create_static_routes, stop_router, start_router,
create_prefix_lists,
create_bgp_community_lists,
check_router_status,
get_frr_ipv6_linklocal,
shutdown_bringup_interface
)
from lib.topolog import logger
from lib.bgp import (
verify_bgp_convergence, create_router_bgp,
verify_bgp_community, verify_bgp_attributes,
verify_best_path_as_per_bgp_attribute, verify_bgp_rib
)
from lib.topojson import build_topo_from_json, build_config_from_json
# Reading the data from JSON File for topology creation
jsonFile = "{}/bgp_vrf_dynamic_route_leak_topo2.json".format(CWD)
try:
with open(jsonFile, "r") as topoJson:
topo = json.load(topoJson)
except IOError:
assert False, "Could not read file {}".format(jsonFile)
# Global variables
NETWORK1_1 = {"ipv4": "11.11.11.1/32", "ipv6": "11:11::1/128"}
NETWORK3_3 = {"ipv4": "50.50.50.5/32", "ipv6": "50:50::5/128"}
NETWORK3_4 = {"ipv4": "50.50.50.50/32", "ipv6": "50:50::50/128"}
PREFERRED_NEXT_HOP = "global"
class CreateTopo(Topo):
"""
Test BasicTopo - topology 1
* `Topo`: Topology object
"""
def build(self, *_args, **_opts):
"""Build function"""
tgen = get_topogen(self)
# Building topology from json file
build_topo_from_json(tgen, topo)
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...
tgen = Topogen(CreateTopo, mod.__name__)
# ... and here it calls Mininet initialization functions.
# Starting topology, create tmp files which are loaded to routers
# to start deamons and then start routers
start_topology(tgen)
# Run these tests for kernel version 4.19 or above
if version_cmp(platform.release(), '4.19') < 0:
error_msg = ('BGP vrf dynamic route leak tests will not run '
'(have kernel "{}", but it requires >= 4.19)'.\
format(platform.release()))
pytest.skip(error_msg)
# Creating configuration from JSON
build_config_from_json(tgen, topo)
global BGP_CONVERGENCE
global ADDR_TYPES
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)
logger.info("Running setup_module() done")
def teardown_module():
"""Teardown the pytest environment"""
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)
#####################################################
#
# Testcases
#
#####################################################
def test_bgp_best_path_with_dynamic_import_p0(request):
"""
TC6_FUNC_6:
1.5.6. Verify BGP best path selection algorithm works fine when
routes are imported from ISR to default vrf and vice versa.
"""
tgen = get_topogen()
tc_name = request.node.name
write_test_header(tc_name)
build_config_from_json(tgen, topo)
if tgen.routers_have_failure():
check_router_status(tgen)
for addr_type in ADDR_TYPES:
step("Redistribute configured static routes into BGP process"
" on R1/R2 and R3")
input_dict_1={}
DUT = ["r1", "r2", "r3", "r4"]
VRFS = ["ISR", "ISR", "default", "default"]
AS_NUM = [100, 100, 300, 400]
for dut, vrf, as_num in zip(DUT, VRFS, AS_NUM):
temp = {dut: {"bgp": []}}
input_dict_1.update(temp)
temp[dut]["bgp"].append(
{
"local_as": as_num,
"vrf": vrf,
"address_family": {
addr_type: {
"unicast": {
"redistribute": [{
"redist_type": "static"
}]
}
}
}
})
result = create_router_bgp(tgen, topo, input_dict_1)
assert result is True, "Testcase {} :Failed \n Error: {}". \
format(tc_name, result)
for addr_type in ADDR_TYPES:
step("Import from default vrf into vrf ISR on R1 and R2 as below")
input_dict_vrf={}
DUT = ["r1", "r2"]
VRFS = ["ISR", "ISR"]
AS_NUM = [100, 100]
for dut, vrf, as_num in zip(DUT, VRFS, AS_NUM):
temp = {dut: {"bgp": []}}
input_dict_vrf.update(temp)
temp[dut]["bgp"].append(
{
"local_as": as_num,
"vrf": vrf,
"address_family": {
addr_type: {
"unicast": {
"import": {
"vrf": "default"
}
}
}
}
})
result = create_router_bgp(tgen, topo, input_dict_vrf)
assert result is True, "Testcase {} : Failed \n Error: {}". \
format(tc_name, result)
input_dict_default={}
DUT = ["r1", "r2"]
VRFS = ["default", "default"]
AS_NUM = [100, 100]
for dut, vrf, as_num in zip(DUT, VRFS, AS_NUM):
temp = {dut: {"bgp": []}}
input_dict_default.update(temp)
temp[dut]["bgp"].append(
{
"local_as": as_num,
"vrf": vrf,
"address_family": {
addr_type: {
"unicast": {
"import": {
"vrf": "ISR"
}
}
}
}
})
result = create_router_bgp(tgen, topo, input_dict_default)
assert result is True, "Testcase {} : Failed \n Error: {}". \
format(tc_name, result)
step("Verify ECMP/Next-hop/Imported routes Vs Locally originated "
"routes/eBGP routes vs iBGP routes --already covered in almost"
" all tests")
for addr_type in ADDR_TYPES:
step("Verify Pre-emption")
input_routes_r3 = {
"r3": {
"static_routes": [{
"network": [
NETWORK3_3[addr_type]
]
}]
}
}
intf_r3_r1 = topo["routers"]["r3"]["links"]["r1-link1"]["interface"]
intf_r4_r1 = topo["routers"]["r4"]["links"]["r1-link1"]["interface"]
if addr_type == "ipv6" and "link_local" in PREFERRED_NEXT_HOP:
nh_r3_r1 = get_frr_ipv6_linklocal(tgen, "r3", intf=intf_r3_r1)
nh_r4_r1 = get_frr_ipv6_linklocal(tgen, "r4", intf=intf_r4_r1)
else:
nh_r3_r1 = topo["routers"]["r3"]["links"]\
["r1-link1"][addr_type].split("/")[0]
nh_r4_r1 = topo["routers"]["r4"]["links"]\
["r1-link1"][addr_type].split("/")[0]
result = verify_bgp_rib(tgen, addr_type, "r1", input_routes_r3,
next_hop=[nh_r4_r1])
assert result is True, (
"Testcase {} : Failed \n Error {}". \
format(tc_name, result))
step("Shutdown interface connected to r1 from r4:")
shutdown_bringup_interface(tgen, 'r4', intf_r4_r1, False)
for addr_type in ADDR_TYPES:
input_routes_r3 = {
"r3": {
"static_routes": [{
"network": [
NETWORK3_3[addr_type]
]
}]
}
}
intf_r3_r1 = topo["routers"]["r3"]["links"]["r1-link1"]["interface"]
intf_r4_r1 = topo["routers"]["r4"]["links"]["r1-link1"]["interface"]
if addr_type == "ipv6" and "link_local" in PREFERRED_NEXT_HOP:
nh_r3_r1 = get_frr_ipv6_linklocal(tgen, "r3", intf=intf_r3_r1)
nh_r4_r1 = get_frr_ipv6_linklocal(tgen, "r4", intf=intf_r4_r1)
else:
nh_r3_r1 = topo["routers"]["r3"]["links"]\
["r1-link1"][addr_type].split("/")[0]
nh_r4_r1 = topo["routers"]["r4"]["links"]\
["r1-link1"][addr_type].split("/")[0]
step("Verify next-hop is changed")
result = verify_bgp_rib(tgen, addr_type, "r1", input_routes_r3,
next_hop=[nh_r3_r1])
assert result is True, (
"Testcase {} : Failed \n Error {}". \
format(tc_name, result))
step("Bringup interface connected to r1 from r4:")
shutdown_bringup_interface(tgen, 'r4', intf_r4_r1, True)
for addr_type in ADDR_TYPES:
input_routes_r3 = {
"r3": {
"static_routes": [{
"network": [
NETWORK3_3[addr_type]
]
}]
}
}
intf_r3_r1 = topo["routers"]["r3"]["links"]["r1-link1"]["interface"]
intf_r4_r1 = topo["routers"]["r4"]["links"]["r1-link1"]["interface"]
if addr_type == "ipv6" and "link_local" in PREFERRED_NEXT_HOP:
nh_r3_r1 = get_frr_ipv6_linklocal(tgen, "r3", intf=intf_r3_r1)
nh_r4_r1 = get_frr_ipv6_linklocal(tgen, "r4", intf=intf_r4_r1)
else:
nh_r3_r1 = topo["routers"]["r3"]["links"]\
["r1-link1"][addr_type].split("/")[0]
nh_r4_r1 = topo["routers"]["r4"]["links"]\
["r1-link1"][addr_type].split("/")[0]
step("Verify next-hop is not chnaged aftr shutdown:")
result = verify_bgp_rib(tgen, addr_type, "r1", input_routes_r3,
next_hop=[nh_r3_r1])
assert result is True, (
"Testcase {} : Failed \n Error {}". \
format(tc_name, result))
step("Active-Standby scenario(as-path prepend and Local pref)")
for addr_type in ADDR_TYPES:
step("Create prefix-list")
input_dict_pf = {
"r1": {
"prefix_lists": {
addr_type: {
"pf_ls_{}".format(addr_type): [{
"seqid": 10,
"network": NETWORK3_4[addr_type],
"action": "permit"
}]
}
}
}
}
result = create_prefix_lists(tgen, input_dict_pf)
assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
for addr_type in ADDR_TYPES:
step("Create route-map to match prefix-list and set localpref 500")
input_dict_rm = {
"r1": {
"route_maps": {
"rmap_PATH1_{}".format(addr_type): [{
"action": "permit",
"seq_id": 10,
"match": {
addr_type: {
"prefix_lists":
"pf_ls_{}".format(addr_type)
}
},
"set": {
"locPrf": 500
}
}]
}
}
}
result = create_route_maps(tgen, input_dict_rm)
assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
tc_name, result)
step("Create route-map to match prefix-list and set localpref 600")
input_dict_rm = {
"r1": {
"route_maps": {
"rmap_PATH2_{}".format(addr_type): [{
"action": "permit",
"seq_id": 20,
"match": {
addr_type: {
"prefix_lists":
"pf_ls_{}".format(addr_type)
}
},
"set": {
"locPrf": 600
}
}]
}
}
}
result = create_route_maps(tgen, input_dict_rm)
assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
tc_name, result)
input_dict_rma={
"r1": {
"bgp":
[
{
"local_as": "100",
"address_family": {
addr_type: {
"unicast": {
"neighbor": {
"r3": {
"dest_link": {
"r1-link1": {
"route_maps": [{
"name": "rmap_PATH1_{}".\
format(addr_type),
"direction": "in"
}]
}
}
},
"r4": {
"dest_link": {
"r1-link1": {
"route_maps": [{
"name": "rmap_PATH2_{}".\
format(addr_type),
"direction": "in"
}]
}
}
}
}
}
}
}
}
]}
}
result = create_router_bgp(tgen, topo, input_dict_rma)
assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
dut = "r1"
attribute = "locPrf"
for addr_type in ADDR_TYPES:
step("Verify bestpath is installed as per highest localpref")
input_routes_r3 = {
"r3": {
"static_routes": [{
"network": [
NETWORK3_3[addr_type], \
NETWORK3_4[addr_type]
]
}]
}
}
result = verify_best_path_as_per_bgp_attribute(tgen, addr_type, dut,
input_routes_r3,
attribute)
assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
for addr_type in ADDR_TYPES:
step("Create route-map to match prefix-list and set localpref 700")
input_dict_rm = {
"r1": {
"route_maps": {
"rmap_PATH1_{}".format(addr_type): [{
"action": "permit",
"seq_id": 10,
"match": {
addr_type: {
"prefix_lists":
"pf_ls_{}".format(addr_type)
}
},
"set": {
"locPrf": 700
}
}]
}
}
}
result = create_route_maps(tgen, input_dict_rm)
assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
tc_name, result)
for addr_type in ADDR_TYPES:
step("Verify bestpath is changed as per highest localpref")
input_routes_r3 = {
"r3": {
"static_routes": [{
"network": [
NETWORK3_3[addr_type], \
NETWORK3_4[addr_type]
]
}]
}
}
result = verify_best_path_as_per_bgp_attribute(tgen, addr_type, dut,
input_routes_r3,
attribute)
assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
for addr_type in ADDR_TYPES:
step("Create route-map to match prefix-list and set as-path prepend")
input_dict_rm = {
"r1": {
"route_maps": {
"rmap_PATH2_{}".format(addr_type): [{
"action": "permit",
"seq_id": 20,
"match": {
addr_type: {
"prefix_lists":
"pf_ls_{}".format(addr_type)
}
},
"set": {
"localpref": 700,
"path": {
"as_num": "111",
"as_action": "prepend"
}
}
}]
}
}
}
result = create_route_maps(tgen, input_dict_rm)
assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
tc_name, result)
attribute = "path"
for addr_type in ADDR_TYPES:
step("Verify bestpath is changed as per shortest as-path")
input_routes_r3 = {
"r3": {
"static_routes": [{
"network": [
NETWORK3_3[addr_type], \
NETWORK3_4[addr_type]
]
}]
}
}
result = verify_best_path_as_per_bgp_attribute(tgen, addr_type, dut,
input_routes_r3,
attribute)
assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
write_test_footer(tc_name)
def test_modify_route_map_match_set_clauses_p1(request):
"""
TC13_CHAOS_4:
1.5.13. Verify that Changing route-map configurations(match/set clauses) on
the fly it takes immediate effect.
"""
tgen = get_topogen()
tc_name = request.node.name
write_test_header(tc_name)
build_config_from_json(tgen, topo)
if tgen.routers_have_failure():
check_router_status(tgen)
for addr_type in ADDR_TYPES:
step("Configure route-map to set community attribute for a specific"
"prefix on R1 in vrf ISR")
input_dict_pf = {
"r1": {
"prefix_lists": {
addr_type: {
"pflist_ABC_{}".format(addr_type): [{
"seqid": 10,
"network": NETWORK1_1[addr_type],
"action": "permit"
}]
}
}
}
}
result = create_prefix_lists(tgen, input_dict_pf)
assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
input_dict_cl = {
"r1": {
"bgp_community_lists": [
{
"community_type": "expanded",
"action": "permit",
"name": "COMM",
"value": "100:100"
}
]
}
}
result = create_bgp_community_lists(tgen, input_dict_cl)
assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
tc_name, result)
for addr_type in ADDR_TYPES:
input_dict_rm = {
"r1": {
"route_maps": {
"rmap_XYZ_{}".format(addr_type): [{
"action": "permit",
"match": {
addr_type: {
"prefix_lists":
"pflist_ABC_{}".format(addr_type)
}
},
"set": {
"community": {"num": "100:100"}
}
}]
}
}
}
result = create_route_maps(tgen, input_dict_rm)
assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
tc_name, result)
for addr_type in ADDR_TYPES:
step("Apply this route-map on R1 to vrf ISR while redistributing the"
" prefixes into BGP")
input_dict_1={}
DUT = ["r1"]
VRFS = ["ISR"]
AS_NUM = [100]
for dut, vrf, as_num in zip(DUT, VRFS, AS_NUM):
temp = {dut: {"bgp": []}}
input_dict_1.update(temp)
temp[dut]["bgp"].append(
{
"local_as": as_num,
"vrf": vrf,
"address_family": {
addr_type: {
"unicast": {
"redistribute": [{
"redist_type": "static",
"attribute": {
"route-map" : "rmap_XYZ_{}".\
format(addr_type)
}
}
]
}
}
}
})
result = create_router_bgp(tgen, topo, input_dict_1)
assert result is True, "Testcase {} :Failed \n Error: {}". \
format(tc_name, result)
for addr_type in ADDR_TYPES:
step("Configure another route-map for filtering the prefixes based on"
" community attribute while importing into default vrf")
input_dict_rm = {
"r1": {
"route_maps": {
"rmap_IMP_{}".format(addr_type): [{
"action": "permit",
"seq_id": 10,
"match": {
"community_list": {"id": "COMM"}
},
"set": {
"community": {"num": "none"}
}
}]
}
}
}
result = create_route_maps(tgen, input_dict_rm)
assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
tc_name, result)
for addr_type in ADDR_TYPES:
step("Apply the route-map while Importing vrf ISR's prefixes into "
"default vrf on router R1:")
input_dict_isr={}
DUT = ["r1"]
VRFS = ["default"]
AS_NUM = [100]
for dut, vrf, as_num in zip(DUT, VRFS, AS_NUM):
temp = {dut: {"bgp": []}}
input_dict_isr.update(temp)
temp[dut]["bgp"].append(
{
"local_as": as_num,
"vrf": vrf,
"address_family": {
addr_type: {
"unicast": {
"import": {
"vrf": "ISR"
}
}
}
}
})
temp[dut]["bgp"].append(
{
"local_as": as_num,
"vrf": vrf,
"address_family": {
addr_type: {
"unicast": {
"import": {
"vrf": "route-map rmap_IMP_{}".format(addr_type)
}
}
}
}
})
result = create_router_bgp(tgen, topo, input_dict_isr)
assert result is True, "Testcase {} : Failed \n Error: {}". \
format(tc_name, result)
for addr_type in ADDR_TYPES:
step("Verify on R1 that only prefixes with community value 100:100"
"in vrf ISR are imported to vrf default. While importing, the"
" community value has been stripped off:")
input_routes_r1 = {
"r1": {
"static_routes": [{
"network": [
NETWORK1_1[addr_type]
],
"vrf": "default"
}]
}
}
result = verify_bgp_rib(tgen, addr_type, "r1", input_routes_r1)
assert result is True, \
"Testcase {} : Failed \n Error {}". \
format(tc_name, result)
for addr_type in ADDR_TYPES:
step("Add set clause in route-map IMP:")
input_dict_rm = {
"r1": {
"route_maps": {
"rmap_IMP_{}".format(addr_type): [{
"action": "permit",
"seq_id": 10,
"match": {
"community_list": {"id": "COMM"}
},
"set": {
"large_community": {"num": "100:100:100"},
"locPrf": 500,
"path": {
"as_num": "100 100",
"as_action": "prepend"
}
}
}]
}
}
}
result = create_route_maps(tgen, input_dict_rm)
assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
tc_name, result)
for addr_type in ADDR_TYPES:
step("Verify that as we continue adding different attributes "
"step-by-step in route-map IMP those attributes gets "
"attached to prefixes:")
input_routes_r1 = {
"r1": {
"static_routes": [{
"network": [
NETWORK1_1[addr_type]
],
"vrf": "default"
}]
}
}
input_dict_comm = {
"largeCommunity": "100:100:100"
}
result = verify_bgp_community(tgen, addr_type, dut, [NETWORK1_1[addr_type]],
input_dict_comm)
assert result is True, (
"Testcase {} : Failed \n Error {}".format(
tc_name, result))
input_rmap = {
"r1": {
"route_maps": {
"rmap_IMP_{}".format(addr_type): [
{
"set": {
"locPrf": 500
}
}
]
}
}
}
result = verify_bgp_attributes(tgen, addr_type, "r1",\
[NETWORK1_1[addr_type]],
rmap_name="rmap_IMP_{}".format(addr_type),\
input_dict=input_rmap)
assert result is True, "Testcase : Failed \n Error: {}".format(
tc_name, result)
step("Change community-list to match a different value then "
"100:100.")
input_dict_cl = {
"r1": {
"bgp_community_lists": [
{
"community_type": "expanded",
"action": "permit",
"name": "COMM",
"value": "100:100",
"delete": True
}
]
}
}
result = create_bgp_community_lists(tgen, input_dict_cl)
assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
tc_name, result)
for addr_type in ADDR_TYPES:
input_routes_r1 = {
"r1": {
"static_routes": [{
"network": [
NETWORK1_1[addr_type]
],
"vrf": "default"
}]
}
}
result = verify_bgp_rib(tgen, addr_type, "r1", input_routes_r1,
expected=False)
assert result is not True, (
"Testcase {} : Failed \n Error : Routes are still "
"present {}".\
format(tc_name, result))
write_test_footer(tc_name)
if __name__ == '__main__':
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))

View File

@ -456,6 +456,15 @@ def __create_bgp_unicast_neighbor(
cmd = "no {}".format(cmd)
config_data.append(cmd)
import_vrf_data = addr_data.setdefault("import", {})
if import_vrf_data:
cmd = "import vrf {}".format(import_vrf_data["vrf"])
del_action = import_vrf_data.setdefault("delete", False)
if del_action:
cmd = "no {}".format(cmd)
config_data.append(cmd)
if "neighbor" in addr_data:
neigh_data = __create_bgp_neighbor(
topo, input_dict, router, addr_type, add_neigh
@ -2610,6 +2619,7 @@ def verify_bgp_rib(tgen, addr_type, dut, input_dict, next_hop=None, aspath=None)
if not isinstance(next_hop, list):
next_hop = [next_hop]
list1 = next_hop
found_hops = [
rib_r["ip"]
for rib_r in rib_routes_json["routes"][st_rt][0][
@ -2617,6 +2627,7 @@ def verify_bgp_rib(tgen, addr_type, dut, input_dict, next_hop=None, aspath=None)
]
]
list2 = found_hops
missing_list_of_nexthops = set(list2).difference(list1)
additional_nexthops_in_required_nhs = set(
list1

View File

@ -32,6 +32,7 @@ from tempfile import mkdtemp
import os
import sys
import ConfigParser
import traceback
import socket
import ipaddress
@ -1237,7 +1238,8 @@ def interface_status(tgen, topo, input_dict):
return True
def retry(attempts=3, wait=2, return_is_str=True, initial_wait=0, return_is_dict=False):
def retry(attempts=3, wait=2, return_is_str=True, initial_wait=0,
return_is_dict=False):
"""
Retries function execution, if return is an errormsg or exception
@ -1249,11 +1251,13 @@ def retry(attempts=3, wait=2, return_is_str=True, initial_wait=0, return_is_dict
"""
def _retry(func):
@wraps(func)
def func_retry(*args, **kwargs):
_wait = kwargs.pop("wait", wait)
_attempts = kwargs.pop("attempts", attempts)
_wait = kwargs.pop('wait', wait)
_attempts = kwargs.pop('attempts', attempts)
_attempts = int(_attempts)
expected = True
if _attempts < 0:
raise ValueError("attempts must be 0 or greater")
@ -1261,40 +1265,40 @@ def retry(attempts=3, wait=2, return_is_str=True, initial_wait=0, return_is_dict
logger.info("Waiting for [%s]s as initial delay", initial_wait)
sleep(initial_wait)
_return_is_str = kwargs.pop("return_is_str", return_is_str)
_return_is_dict = kwargs.pop("return_is_str", return_is_dict)
_return_is_str = kwargs.pop('return_is_str', return_is_str)
_return_is_dict = kwargs.pop('return_is_str', return_is_dict)
for i in range(1, _attempts + 1):
try:
_expected = kwargs.setdefault("expected", True)
kwargs.pop("expected")
_expected = kwargs.setdefault('expected', True)
if _expected is False:
expected = _expected
kwargs.pop('expected')
ret = func(*args, **kwargs)
logger.debug("Function returned %s" % ret)
logger.debug("Function returned %s", ret)
if _return_is_str and isinstance(ret, bool) and _expected:
return ret
if (
isinstance(ret, str) or isinstance(ret, unicode)
) and _expected is False:
if (isinstance(ret, str) or isinstance(ret, unicode)) and _expected is False:
return ret
if _return_is_dict and isinstance(ret, dict):
return ret
if _attempts == i:
if _attempts == i and expected:
generate_support_bundle()
return ret
except Exception as err:
if _attempts == i:
if _attempts == i and expected:
generate_support_bundle()
logger.info("Max number of attempts (%r) reached", _attempts)
logger.info("Max number of attempts (%r) reached",
_attempts)
raise
else:
logger.info("Function returned %s", err)
if i < _attempts:
logger.info("Retry [#%r] after sleeping for %ss" % (i, _wait))
logger.info("Retry [#%r] after sleeping for %ss"
% (i, _wait))
sleep(_wait)
func_retry._original = func
return func_retry
return _retry
@ -2517,7 +2521,7 @@ def verify_rib(
errormsg(str) or True
"""
logger.info("Entering lib API: verify_rib()")
logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
router_list = tgen.routers()
additional_nexthops_in_required_nhs = []
@ -2832,7 +2836,263 @@ def verify_rib(
" routes are: {}\n".format(addr_type, dut, found_routes)
)
logger.info("Exiting lib API: verify_rib()")
logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
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)))
#st_rt = str(ipaddr.IPNetwork(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(ipaddr.IPNetwork(unicode(st_rt)))
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