diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-09 13:16:35 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-09 13:16:35 +0000 |
commit | e2bbf175a2184bd76f6c54ccf8456babeb1a46fc (patch) | |
tree | f0b76550d6e6f500ada964a3a4ee933a45e5a6f1 /tests/topotests/bgp_multi_vrf_topo1 | |
parent | Initial commit. (diff) | |
download | frr-e2bbf175a2184bd76f6c54ccf8456babeb1a46fc.tar.xz frr-e2bbf175a2184bd76f6c54ccf8456babeb1a46fc.zip |
Adding upstream version 9.1.upstream/9.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tests/topotests/bgp_multi_vrf_topo1')
-rw-r--r-- | tests/topotests/bgp_multi_vrf_topo1/bgp_multi_vrf_topo1.json | 884 | ||||
-rw-r--r-- | tests/topotests/bgp_multi_vrf_topo1/test_bgp_multi_vrf_topo1.py | 6277 |
2 files changed, 7161 insertions, 0 deletions
diff --git a/tests/topotests/bgp_multi_vrf_topo1/bgp_multi_vrf_topo1.json b/tests/topotests/bgp_multi_vrf_topo1/bgp_multi_vrf_topo1.json new file mode 100644 index 0000000..327744d --- /dev/null +++ b/tests/topotests/bgp_multi_vrf_topo1/bgp_multi_vrf_topo1.json @@ -0,0 +1,884 @@ +{ + "address_types": ["ipv4","ipv6"], + "ipv4base": "10.0.0.0", + "ipv4mask": 30, + "ipv6base": "fd00::", + "ipv6mask": 64, + "link_ip_start": { + "ipv4": "10.0.0.0", + "v4mask": 30, + "ipv6": "fd00::", + "v6mask": 64 + }, + "lo_prefix": { + "ipv4": "1.0.", + "v4mask": 32, + "ipv6": "2001:db8:f::", + "v6mask": 128 + }, + "routers": { + "red1": { + "links": { + "r1-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED_A"}, + "r1-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED_B"} + }, + "vrfs":[ + { + "name": "RED_A", + "id": "1" + }, + { + "name": "RED_B", + "id": "2" + } + ], + "bgp": + [ + { + "local_as": "500", + "vrf": "RED_A", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "red1-link1": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "red1-link1": {} + } + } + } + } + } + } + }, + { + "local_as": "500", + "vrf": "RED_B", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "red1-link2": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "red1-link2": {} + } + } + } + } + } + } + } + ] + }, + "blue1": { + "links": { + "r1-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE_A"}, + "r1-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE_B"} + }, + "vrfs":[ + { + "name": "BLUE_A", + "id": "1" + }, + { + "name": "BLUE_B", + "id": "2" + } + ], + "bgp": + [ + { + "local_as": "800", + "vrf": "BLUE_A", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "blue1-link1": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "blue1-link1": {} + } + } + } + } + } + } + }, + { + "local_as": "800", + "vrf": "BLUE_B", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "blue1-link2": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "blue1-link2": {} + } + } + } + } + } + } + } + ] + }, + "r1": { + "links": { + "red1-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED_A"}, + "red1-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED_B"}, + "blue1-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE_A"}, + "blue1-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE_B"}, + "r2-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED_A"}, + "r2-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED_B"}, + "r2-link3": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE_A"}, + "r2-link4": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE_B"} + }, + "vrfs":[ + { + "name": "RED_A", + "id": "1" + }, + { + "name": "RED_B", + "id": "2" + }, + { + "name": "BLUE_A", + "id": "3" + }, + { + "name": "BLUE_B", + "id": "4" + } + ], + "bgp": + [ + { + "local_as": "100", + "vrf": "RED_A", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "red1": { + "dest_link": { + "r1-link1": {} + } + }, + "r2": { + "dest_link": { + "r1-link1": + { "next_hop_self": true } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "red1": { + "dest_link": { + "r1-link1": {} + } + }, + "r2": { + "dest_link": { + "r1-link1": + { "next_hop_self": true } + } + } + } + } + } + } + }, + { + "local_as": "100", + "vrf": "RED_B", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "red1": { + "dest_link": { + "r1-link2": {} + } + }, + "r2": { + "dest_link": { + "r1-link2": + { "next_hop_self": true } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "red1": { + "dest_link": { + "r1-link2": {} + } + }, + "r2": { + "dest_link": { + "r1-link2": + { "next_hop_self": true } + } + } + } + } + } + } + }, + { + "local_as": "100", + "vrf": "BLUE_A", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "blue1": { + "dest_link": { + "r1-link1": {} + } + }, + "r2": { + "dest_link": { + "r1-link3": + { "next_hop_self": true } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "blue1": { + "dest_link": { + "r1-link1": {} + } + }, + "r2": { + "dest_link": { + "r1-link3": + { "next_hop_self": true } + } + } + } + } + } + } + }, + { + "local_as": "100", + "vrf": "BLUE_B", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "blue1": { + "dest_link": { + "r1-link2": {} + } + }, + "r2": { + "dest_link": { + "r1-link4": + { "next_hop_self": true } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "blue1": { + "dest_link": { + "r1-link2": {} + } + }, + "r2": { + "dest_link": { + "r1-link4": + { "next_hop_self": true } + } + } + } + } + } + } + } + ] + }, + "r2": { + "links": { + "r1-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED_A"}, + "r1-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED_B"}, + "r1-link3": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE_A"}, + "r1-link4": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE_B"}, + "r3-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED_A"}, + "r3-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED_B"}, + "r3-link3": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE_A"}, + "r3-link4": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE_B"} + }, + "vrfs":[ + { + "name": "RED_A", + "id": "1" + }, + { + "name": "RED_B", + "id": "2" + }, + { + "name": "BLUE_A", + "id": "3" + }, + { + "name": "BLUE_B", + "id": "4" + } + ], + "bgp": + [ + { + "local_as": "100", + "vrf": "RED_A", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link1": {} + } + }, + "r3": { + "dest_link": { + "r2-link1": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link1": {} + } + }, + "r3": { + "dest_link": { + "r2-link1": {} + } + } + } + } + } + } + }, + { + "local_as": "100", + "vrf": "RED_B", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link2": {} + } + }, + "r3": { + "dest_link": { + "r2-link2": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link2": {} + } + }, + "r3": { + "dest_link": { + "r2-link2": {} + } + } + } + } + } + } + }, + { + "local_as": "100", + "vrf": "BLUE_A", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link3": {} + } + }, + "r3": { + "dest_link": { + "r2-link3": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link3": {} + } + }, + "r3": { + "dest_link": { + "r2-link3": {} + } + } + } + } + } + } + }, + { + "local_as": "100", + "vrf": "BLUE_B", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link4": {} + } + }, + "r3": { + "dest_link": { + "r2-link4": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link4": {} + } + }, + "r3": { + "dest_link": { + "r2-link4": {} + } + } + } + } + } + } + } + ] + }, + "r3": { + "links": { + "r2-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED_A"}, + "r2-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED_B"}, + "r2-link3": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE_A"}, + "r2-link4": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE_B"}, + "red2-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED_A"}, + "red2-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED_B"}, + "blue2-link1": {"ipv4": "auto", "ipv6": "autor3", "vrf": "BLUE_A"}, + "blue2-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE_B"} + }, + "vrfs":[ + { + "name": "RED_A", + "id": "1" + }, + { + "name": "RED_B", + "id": "2" + }, + { + "name": "BLUE_A", + "id": "3" + }, + { + "name": "BLUE_B", + "id": "4" + } + ], + "bgp": + [ + { + "local_as": "200", + "vrf": "RED_A", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r3-link1": {} + } + }, + "red2": { + "dest_link": { + "r3-link1": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r3-link1": {} + } + }, + "red2": { + "dest_link": { + "r3-link1": {} + } + } + } + } + } + } + }, + { + "local_as": "200", + "vrf": "RED_B", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r3-link2": {} + } + }, + "red2": { + "dest_link": { + "r3-link2": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r3-link2": {} + } + }, + "red2": { + "dest_link": { + "r3-link2": {} + } + } + } + } + } + } + }, + { + "local_as": "200", + "vrf": "BLUE_A", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r3-link3": {} + } + }, + "blue2": { + "dest_link": { + "r3-link1": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r3-link3": {} + } + }, + "blue2": { + "dest_link": { + "r3-link1": {} + } + } + } + } + } + } + }, + { + "local_as": "200", + "vrf": "BLUE_B", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r3-link4": {} + } + }, + "blue2": { + "dest_link": { + "r3-link2": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r3-link4": {} + } + }, + "blue2": { + "dest_link": { + "r3-link2": {} + } + } + } + } + } + } + } + ] + }, + "red2": { + "links": { + "r3-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED_A"}, + "r3-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "RED_B"} + }, + "vrfs":[ + { + "name": "RED_A", + "id": "1" + }, + { + "name": "RED_B", + "id": "2" + } + ], + "bgp": + [ + { + "local_as": "500", + "vrf": "RED_A", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "red2-link1": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "red2-link1": {} + } + } + } + } + } + } + }, + { + "local_as": "500", + "vrf": "RED_B", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "red2-link2": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "red2-link2": {} + } + } + } + } + } + } + } + ] + }, + "blue2": { + "links": { + "r3-link1": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE_A"}, + "r3-link2": {"ipv4": "auto", "ipv6": "auto", "vrf": "BLUE_B"} + }, + "vrfs":[ + { + "name": "BLUE_A", + "id": "1" + }, + { + "name": "BLUE_B", + "id": "2" + } + ], + "bgp": + [ + { + "local_as": "800", + "vrf": "BLUE_A", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "blue2-link1": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "blue2-link1": {} + } + } + } + } + } + } + }, + { + "local_as": "800", + "vrf": "BLUE_B", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "blue2-link2": {} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "blue2-link2": {} + } + } + } + } + } + } + } + ] + } + } +} diff --git a/tests/topotests/bgp_multi_vrf_topo1/test_bgp_multi_vrf_topo1.py b/tests/topotests/bgp_multi_vrf_topo1/test_bgp_multi_vrf_topo1.py new file mode 100644 index 0000000..0d92a3c --- /dev/null +++ b/tests/topotests/bgp_multi_vrf_topo1/test_bgp_multi_vrf_topo1.py @@ -0,0 +1,6277 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: ISC + +# +# Copyright (c) 2020 by VMware, Inc. ("VMware") +# Used Copyright (c) 2018 by Network Device Education Foundation, +# Inc. ("NetDEF") in this file. +# + +""" +Following tests are covered to test BGP Multi-VRF: + +FUNC_1: + Within each VRF, each address must be unambiguous on DUT. +FUNC_2: + Different VRFs can have ambiguous/overlapping + addresses on DUT. +FUNC_3: + Create static routes(IPv4+IPv6) associated to specific VRFs + and verify on DUT that same prefixes are present in corresponding + routing table. +FUNC_4_&_5: + Each VRF should be mapped with a unique VLAN on DUT + for traffic segregation, when using a single physical interface. +FUNC_6: + Advertise same set of prefixes from different VRFs + and verify on remote router that these prefixes are not + leaking to each other +FUNC_7: + Redistribute Static routes and verify on remote routers + that routes are advertised within specific VRF instance, which + those static routes belong to. +FUNC_8: + Test end to end traffic isolation based on VRF tables. +FUNC_9: + Use static routes for inter-vrf communication + (route-leaking) on DUT. +FUNC_10: + Verify intra-vrf and inter-vrf communication between + iBGP peers. +FUNC_11: + Verify intra-vrf and inter-vrf communication + between eBGP peers. +FUNC_12_a: + Configure route-maps within a VRF, to alter BGP attributes. + Verify that route-map doesn't affect any other VRF instances' + routing on DUT. +FUNC_12_b: + Configure route-maps within a VRF, to alter BGP attributes. + Verify that route-map doesn't affect any other VRF instances' + routing on DUT. +FUNC_12_c: + Configure route-maps within a VRF, to alter BGP attributes. + Verify that route-map doesn't affect any other VRF instances' + routing on DUT. +FUNC_12_d: + Configure route-maps within a VRF, to alter BGP attributes. + Verify that route-map doesn't affect any other VRF instances' + routing on DUT. +FUNC_12_e: + Configure route-maps within a VRF, to alter BGP attributes. + Verify that route-map doesn't affect any other VRF instances' + routing on DUT. +FUNC_12_f: + Configure route-maps within a VRF, to alter BGP attributes. + Verify that route-map doesn't affect any other VRF instances' + routing on DUT. +FUNC_13: + Configure a route-map on DUT to match traffic based + on a VRF interfaces. +FUNC_14: + Test VRF-lite with Static+BGP originated routes. +FUNC_15: + Configure prefix-lists on DUT and apply to BGP peers to + permit/deny prefixes. +FUNC_16_1: + Configure a route-map on DUT to match traffic based various + match/set causes. +FUNC_16_2: + Configure a route-map on DUT to match traffic based various + match/set causes. +FUNC_16_3: + Configure a route-map on DUT to match traffic based various + match/set causes. +""" + +import os +import sys +import time +import pytest + +# 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 iproute2_is_vrf_capable +from lib.common_config import ( + step, + verify_rib, + start_topology, + write_test_header, + check_address_types, + write_test_footer, + reset_config_on_routers, + create_route_maps, + create_static_routes, + create_prefix_lists, + create_interface_in_kernel, + create_bgp_community_lists, + check_router_status, + apply_raw_config, + required_linux_kernel_version, +) + +from lib.topolog import logger +from lib.bgp import ( + verify_bgp_rib, + create_router_bgp, + verify_bgp_community, + verify_bgp_convergence, + verify_best_path_as_per_bgp_attribute, +) +from lib.topojson import build_config_from_json + + +pytestmark = [pytest.mark.bgpd, pytest.mark.staticd] + + +# Global variables +NETWORK1_1 = {"ipv4": "1.1.1.1/32", "ipv6": "1::1/128"} +NETWORK1_2 = {"ipv4": "1.1.1.2/32", "ipv6": "1::2/128"} +NETWORK2_1 = {"ipv4": "2.1.1.1/32", "ipv6": "2::1/128"} +NETWORK2_2 = {"ipv4": "2.1.1.2/32", "ipv6": "2::2/128"} +NETWORK3_1 = {"ipv4": "3.1.1.1/32", "ipv6": "3::1/128"} +NETWORK3_2 = {"ipv4": "3.1.1.2/32", "ipv6": "3::2/128"} +NETWORK4_1 = {"ipv4": "4.1.1.1/32", "ipv6": "4::1/128"} +NETWORK4_2 = {"ipv4": "4.1.1.2/32", "ipv6": "4::2/128"} +NETWORK5_1 = {"ipv4": "5.1.1.1/32", "ipv6": "5::1/128"} +NETWORK5_2 = {"ipv4": "5.1.1.2/32", "ipv6": "5::2/128"} +NETWORK6_1 = {"ipv4": "6.1.1.1/32", "ipv6": "6::1/128"} +NETWORK6_2 = {"ipv4": "6.1.1.2/32", "ipv6": "6::2/128"} +NETWORK7_1 = {"ipv4": "7.1.1.1/32", "ipv6": "7::1/128"} +NETWORK7_2 = {"ipv4": "7.1.1.2/32", "ipv6": "7::2/128"} +NETWORK8_1 = {"ipv4": "8.1.1.1/32", "ipv6": "8::1/128"} +NETWORK8_2 = {"ipv4": "8.1.1.2/32", "ipv6": "8::2/128"} + +NEXT_HOP_IP = {"ipv4": "Null0", "ipv6": "Null0"} + +LOOPBACK_1 = { + "ipv4": "10.10.10.10/32", + "ipv6": "10::10:10/128", +} +LOOPBACK_2 = { + "ipv4": "20.20.20.20/32", + "ipv6": "20::20:20/128", +} + + +def setup_module(mod): + """ + Sets up the pytest environment + + * `mod`: module name + """ + # Required linux kernel version for this suite to run. + result = required_linux_kernel_version("4.15") + if result is not True: + pytest.skip("Kernel requirements are not met") + + # iproute2 needs to support VRFs for this suite to run. + if not iproute2_is_vrf_capable(): + pytest.skip("Installed iproute2 version does not support VRFs") + + 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_multi_vrf_topo1.json".format(CWD) + tgen = Topogen(json_file, mod.__name__) + global topo + topo = tgen.json_topo + # ... and here it calls Mininet initialization functions. + + # Starting topology, create tmp files which are loaded to routers + # to start daemons and then start routers + start_topology(tgen) + + # 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_address_unambiguous_within_each_vrf_p0(request): + """ + FUNC_1: + Within each VRF, each address must be unambiguous on DUT. + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + + if tgen.routers_have_failure(): + check_router_status(tgen) + + step("Configure a set of static routes(IPv4+IPv6) in " "RED_A on router RED-1") + + for addr_type in ADDR_TYPES: + input_dict_1 = { + "red1": { + "static_routes": [ + { + "network": NETWORK1_1[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_A", + } + ] + } + } + result = create_static_routes(tgen, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step( + "Configure the same static routes(IPv4+IPv6) with a TAG value" + "of 500 in RED_A on router RED-1" + ) + + for addr_type in ADDR_TYPES: + input_dict_2 = { + "red1": { + "static_routes": [ + { + "network": NETWORK1_1[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "tag": 500, + "vrf": "RED_A", + } + ] + } + } + result = create_static_routes(tgen, input_dict_2) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step("Redistribute static..") + + input_dict_3 = { + "red1": { + "bgp": { + "local_as": "500", + "vrf": "RED_A", + "address_family": { + "ipv4": {"unicast": {"redistribute": [{"redist_type": "static"}]}}, + "ipv6": {"unicast": {"redistribute": [{"redist_type": "static"}]}}, + }, + } + } + } + + result = create_router_bgp(tgen, topo, input_dict_3) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step( + "Verify that static routes(IPv4+IPv6) is overridden and doesn't" + " have duplicate entries within VRF RED_A on router RED-1" + ) + + for addr_type in ADDR_TYPES: + dut = "red1" + input_dict_2 = { + "red1": { + "static_routes": [ + { + "network": NETWORK1_1[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + "tag": 500, + "vrf": "RED_A", + } + ] + } + } + + result = verify_rib(tgen, addr_type, dut, input_dict_2, tag=500) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + step("Make sure routes are not present in global routing table") + + for addr_type in ADDR_TYPES: + dut = "red1" + input_dict_2 = { + "red1": { + "static_routes": [ + { + "network": NETWORK1_1[addr_type], + "next_hop": NEXT_HOP_IP[addr_type], + } + ] + } + } + + result = verify_rib(tgen, addr_type, dut, input_dict_2, expected=False) + assert result is not True, ( + "Testcase {} : Failed \n Expected Behaviour: Routes are not " + "present on Global Routing table \n Error {}".format(tc_name, result) + ) + + write_test_footer(tc_name) + + +def test_ambiguous_overlapping_addresses_in_different_vrfs_p0(request): + """ + FUNC_2: + Different VRFs can have ambiguous/overlapping + addresses on DUT. + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + reset_config_on_routers(tgen) + + if tgen.routers_have_failure(): + check_router_status(tgen) + + step("Configure a set of static routes(IPv4+IPv6) in vrf RED_A" "on router RED-1") + + for addr_type in ADDR_TYPES: + input_dict_1 = { + "red1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_A", + } + ] + } + } + result = create_static_routes(tgen, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step( + "Configure the same static routes(IPv4+IPv6) with a" + " TAG value of 500 in vrf RED_B on router RED-1" + ) + + for addr_type in ADDR_TYPES: + input_dict_2 = { + "red1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "tag": 500, + "vrf": "RED_B", + } + ] + } + } + result = create_static_routes(tgen, input_dict_2) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step("Redistribute static..") + + input_dict_3 = {} + for dut in ["red1"]: + temp = {dut: {"bgp": []}} + input_dict_3.update(temp) + + if "red" in dut: + VRFS = ["RED_A", "RED_B"] + AS_NUM = [500, 500] + elif "blue" in dut: + VRFS = ["BLUE_A", "BLUE_B"] + AS_NUM = [800, 800] + + for vrf, as_num in zip(VRFS, AS_NUM): + temp[dut]["bgp"].append( + { + "local_as": as_num, + "vrf": vrf, + "address_family": { + "ipv4": { + "unicast": {"redistribute": [{"redist_type": "static"}]} + }, + "ipv6": { + "unicast": {"redistribute": [{"redist_type": "static"}]} + }, + }, + } + ) + + result = create_router_bgp(tgen, topo, input_dict_3) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Verify that RED_A has the static routes without any" " TAG value") + + for addr_type in ADDR_TYPES: + dut = "red1" + input_dict_1 = { + "red1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_A", + } + ] + } + } + + result = verify_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + result = verify_rib(tgen, addr_type, dut, input_dict_1, tag=500, expected=False) + assert result is not True, ( + "Testcase {} : Failed \n " + "Routes are present with tag value 500 \n Error: {}".format(tc_name, result) + ) + logger.info("Expected Behavior: {}".format(result)) + + step( + "Verify that RED_B has the same routes with TAG value " + "500 on same device RED-1" + ) + + for addr_type in ADDR_TYPES: + dut = "red1" + input_dict_2 = { + "red1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "tag": 500, + "vrf": "RED_B", + } + ] + } + } + + result = verify_rib(tgen, addr_type, dut, input_dict_2, tag=500) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + step("Make sure routes are not present in global routing table") + + for addr_type in ADDR_TYPES: + dut = "red1" + input_dict_2 = { + "red1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + } + ] + } + } + + result = verify_rib(tgen, addr_type, dut, input_dict_2, expected=False) + assert result is not True, ( + "Testcase {} : Failed \n Expected Behaviour: Routes are not " + "present on Global Routing table \n Error {}".format(tc_name, result) + ) + + write_test_footer(tc_name) + + +def test_static_routes_associated_to_specific_vrfs_p0(request): + """ + FUNC_3: + Create static routes(IPv4+IPv6) associated to specific VRFs + and verify on DUT that same prefixes are present in corresponding + routing table. + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + reset_config_on_routers(tgen) + + if tgen.routers_have_failure(): + check_router_status(tgen) + + step( + "Configure a set of unique static(IPv4+IPv6) routes in vrf" + " RED_A on router RED-1" + ) + + for addr_type in ADDR_TYPES: + input_dict_1 = { + "red1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_B", + }, + ] + } + } + result = create_static_routes(tgen, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step( + "Configure set of unique static routes(IPv4+IPv6) in vrf " + "RED_B on router RED-1" + ) + + for addr_type in ADDR_TYPES: + input_dict_2 = { + "blue1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_B", + }, + ] + } + } + result = create_static_routes(tgen, input_dict_2) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step("Redistribute static..") + + input_dict_3 = {} + for dut in ["red1", "blue1"]: + temp = {dut: {"bgp": []}} + input_dict_3.update(temp) + + if "red" in dut: + VRFS = ["RED_A", "RED_B"] + AS_NUM = [500, 500] + elif "blue" in dut: + VRFS = ["BLUE_A", "BLUE_B"] + AS_NUM = [800, 800] + + for vrf, as_num in zip(VRFS, AS_NUM): + temp[dut]["bgp"].append( + { + "local_as": as_num, + "vrf": vrf, + "address_family": { + "ipv4": { + "unicast": {"redistribute": [{"redist_type": "static"}]} + }, + "ipv6": { + "unicast": {"redistribute": [{"redist_type": "static"}]} + }, + }, + } + ) + + result = create_router_bgp(tgen, topo, input_dict_3) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step( + "Verify that static routes 1.x.x.x/32 and 1::x/128 appear " "in VRF RED_A table" + ) + step( + "Verify that static routes 2.x.x.x/32 and 2::x/128 appear " "in VRF RED_B table" + ) + + for addr_type in ADDR_TYPES: + dut = "red1" + input_dict_1 = { + "red1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_B", + }, + ] + } + } + + result = verify_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + step( + "Verify that static routes 1.x.x.x/32 and 1::x/128 appear " + "in VRF BLUE_A table" + ) + step( + "Verify that static routes 2.x.x.x/32 and 2::x/128 appear " + "in VRF BLUE_B table" + ) + + for addr_type in ADDR_TYPES: + dut = "blue1" + input_dict_2 = { + "blue1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_B", + }, + ] + } + } + + result = verify_rib(tgen, addr_type, dut, input_dict_2) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + step("Make sure routes are not present in global routing table") + + for addr_type in ADDR_TYPES: + dut = "blue1" + input_dict_2 = { + "blue1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + }, + ] + } + } + + result = verify_rib(tgen, addr_type, dut, input_dict_2, expected=False) + assert result is not True, ( + "Testcase {} : Failed \n Expected Behaviour: Routes are not " + "present on Global Routing table \n Error {}".format(tc_name, result) + ) + + write_test_footer(tc_name) + + +def test_vrf_with_unique_physical_interface_p0(request): + """ + FUNC_4_&_5: + Each VRF should be mapped with a unique VLAN on DUT + for traffic segregation, when using a single physical interface. + + Each VRF should be mapped to a unique physical + interface(without VLAN tagging) on DUT for traffic segregation. + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + reset_config_on_routers(tgen) + + if tgen.routers_have_failure(): + check_router_status(tgen) + + step( + "R1 is receiving routes in 4 VRFs instances " + "(RED_A, RED_B, BLUE_A, BLUE_B) from RED_1 and BLUE_1." + ) + + for addr_type in ADDR_TYPES: + input_dict_1 = { + "red1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_B", + }, + ] + } + } + result = create_static_routes(tgen, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step( + "Advertise a set of unique BGP prefixes(IPv4+IPv6) from " + "routers RED_1 & BLUE_1 in each VRF using static redistribution" + ) + + for addr_type in ADDR_TYPES: + input_dict_2 = { + "blue1": { + "static_routes": [ + { + "network": [NETWORK3_1[addr_type]] + [NETWORK3_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_A", + }, + { + "network": [NETWORK4_1[addr_type]] + [NETWORK4_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_B", + }, + ] + } + } + result = create_static_routes(tgen, input_dict_2) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step("Redistribute static..") + + input_dict_3 = {} + for dut in ["red1", "blue1"]: + temp = {dut: {"bgp": []}} + input_dict_3.update(temp) + + if "red" in dut: + VRFS = ["RED_A", "RED_B"] + AS_NUM = [500, 500] + elif "blue" in dut: + VRFS = ["BLUE_A", "BLUE_B"] + AS_NUM = [800, 800] + + for vrf, as_num in zip(VRFS, AS_NUM): + temp[dut]["bgp"].append( + { + "local_as": as_num, + "vrf": vrf, + "address_family": { + "ipv4": { + "unicast": {"redistribute": [{"redist_type": "static"}]} + }, + "ipv6": { + "unicast": {"redistribute": [{"redist_type": "static"}]} + }, + }, + } + ) + + result = create_router_bgp(tgen, topo, input_dict_3) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step( + "Each VRF table on R2 should maintain it's associated " + "routes and and accordingly install in zebra" + ) + + for addr_type in ADDR_TYPES: + dut = "r2" + input_dict_1 = { + "red1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_B", + }, + ] + } + } + + input_dict_2 = { + "blue1": { + "static_routes": [ + { + "network": [NETWORK3_1[addr_type]] + [NETWORK3_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_A", + }, + { + "network": [NETWORK4_1[addr_type]] + [NETWORK4_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_B", + }, + ] + } + } + + result = verify_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + result = verify_rib(tgen, addr_type, dut, input_dict_2) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + write_test_footer(tc_name) + + +def test_prefixes_leaking_p0(request): + """ + FUNC_6: + Advertise same set of prefixes from different VRFs + and verify on remote router that these prefixes are not + leaking to each other + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + reset_config_on_routers(tgen) + + if tgen.routers_have_failure(): + check_router_status(tgen) + + step("Configure a set of static routes(IPv4+IPv6) in vrf " "RED_A on router RED-1") + + for addr_type in ADDR_TYPES: + input_dict_1 = { + "red1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_A", + } + ] + }, + "blue1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_A", + } + ] + }, + } + result = create_static_routes(tgen, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step( + "Configure a set of static routes(IPv4+IPv6) in vrf " "BLUE_A on router BLUE-1" + ) + + for addr_type in ADDR_TYPES: + input_dict_2 = { + "red1": { + "static_routes": [ + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_B", + } + ] + }, + "blue1": { + "static_routes": [ + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_B", + } + ] + }, + } + result = create_static_routes(tgen, input_dict_2) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step( + "Configure the same set of static routes with a " + "metric value of 123 in vrf RED_B on router RED-1" + ) + step( + "Configure the same set of static routes with a " + "metric value of 123 in vrf BLUE_B on router BLUE-1" + ) + + input_dict_3 = { + "red1": { + "bgp": [ + { + "local_as": "500", + "vrf": "RED_A", + "address_family": { + "ipv4": { + "unicast": {"redistribute": [{"redist_type": "static"}]} + }, + "ipv6": { + "unicast": {"redistribute": [{"redist_type": "static"}]} + }, + }, + }, + { + "local_as": "500", + "vrf": "RED_B", + "address_family": { + "ipv4": { + "unicast": { + "redistribute": [ + { + "redist_type": "static", + "attribute": {"metric": 123}, + } + ] + } + }, + "ipv6": { + "unicast": { + "redistribute": [ + { + "redist_type": "static", + "attribute": {"metric": 123}, + } + ] + } + }, + }, + }, + ] + }, + "blue1": { + "bgp": [ + { + "local_as": "800", + "vrf": "BLUE_A", + "address_family": { + "ipv4": { + "unicast": {"redistribute": [{"redist_type": "static"}]} + }, + "ipv6": { + "unicast": {"redistribute": [{"redist_type": "static"}]} + }, + }, + }, + { + "local_as": "800", + "vrf": "BLUE_B", + "address_family": { + "ipv4": { + "unicast": { + "redistribute": [ + { + "redist_type": "static", + "attribute": {"metric": 123}, + } + ] + } + }, + "ipv6": { + "unicast": { + "redistribute": [ + { + "redist_type": "static", + "attribute": {"metric": 123}, + } + ] + } + }, + }, + }, + ] + }, + } + + result = create_router_bgp(tgen, topo, input_dict_3) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step( + "Verify on R1 that RED_A doesn't receive any static " + "route with metric value 123" + ) + + for addr_type in ADDR_TYPES: + dut = "r1" + input_dict_1 = { + "red1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_A", + } + ] + }, + "blue1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_A", + } + ] + }, + } + + input_dict_2 = { + "red1": { + "static_routes": [ + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_B", + } + ] + }, + "blue1": { + "static_routes": [ + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_B", + } + ] + }, + } + + result = verify_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + result = verify_rib( + tgen, addr_type, dut, input_dict_1, metric=123, expected=False + ) + assert result is not True, ( + "Testcase {} : Failed \n " + "Routes are present with metric value 123 \n Error: {}".format( + tc_name, result + ) + ) + logger.info("Expected Behavior: {}".format(result)) + + result = verify_rib(tgen, addr_type, dut, input_dict_2, metric=123) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + result = verify_rib( + tgen, addr_type, dut, input_dict_2, metric=0, expected=False + ) + assert result is not True, ( + "Testcase {} : Failed \n " + "Routes are present with metric value 0 \n Error: {}".format( + tc_name, result + ) + ) + logger.info("Expected Behavior: {}".format(result)) + + write_test_footer(tc_name) + + +def test_static_routes_advertised_within_specific_vrf_p0(request): + """ + FUNC_7: + Redistribute Static routes and verify on remote routers + that routes are advertised within specific VRF instance, which + those static routes belong to. + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + reset_config_on_routers(tgen) + + if tgen.routers_have_failure(): + check_router_status(tgen) + + step( + "Advertise a set of unique BGP prefixes(IPv4+IPv6) " + "through static redistribution into VRF RED_A and RED_B" + " from router RED-1." + ) + + for addr_type in ADDR_TYPES: + input_dict_1 = { + "red1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_B", + }, + ] + } + } + result = create_static_routes(tgen, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step( + "Advertise same as above set of BGP prefixes(IPv4+IPv6) " + "through static redistribution into VRF BLUE_A and BLUE_B" + " from router BLUE-1." + ) + + for addr_type in ADDR_TYPES: + input_dict_2 = { + "blue1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_B", + }, + ] + } + } + result = create_static_routes(tgen, input_dict_2) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step("Redistribute static..") + + input_dict_3 = {} + for dut in ["red1", "blue1"]: + temp = {dut: {"bgp": []}} + input_dict_3.update(temp) + + if "red" in dut: + VRFS = ["RED_A", "RED_B"] + AS_NUM = [500, 500] + elif "blue" in dut: + VRFS = ["BLUE_A", "BLUE_B"] + AS_NUM = [800, 800] + + for vrf, as_num in zip(VRFS, AS_NUM): + temp[dut]["bgp"].append( + { + "local_as": as_num, + "vrf": vrf, + "address_family": { + "ipv4": { + "unicast": {"redistribute": [{"redist_type": "static"}]} + }, + "ipv6": { + "unicast": {"redistribute": [{"redist_type": "static"}]} + }, + }, + } + ) + + result = create_router_bgp(tgen, topo, input_dict_3) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step( + "Verify that static routes are installed into vrfs RED_A" + "and RED_B tables only, not in global routing table of RED_1" + ) + + for addr_type in ADDR_TYPES: + dut = "red1" + input_dict_1 = { + "red1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_B", + }, + ] + } + } + + result = verify_rib(tgen, addr_type, dut, input_dict_1, protocol="static") + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + step( + "Verify that static routes are installed into vrfs BLUE_A and" + "BLUE_B tables only, not in global routing table of BLUE_1." + ) + + for addr_type in ADDR_TYPES: + dut = "blue1" + input_dict_2 = { + "blue1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_B", + }, + ] + } + } + + result = verify_rib(tgen, addr_type, dut, input_dict_2, protocol="static") + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + step( + "Verify on router R1, that each set of prefixes is received" + " into associated vrf tables only." + ) + + result = verify_bgp_convergence(tgen, topo) + assert result is True, "Testcase {} : Failed \n Error {}".format(tc_name, result) + + for addr_type in ADDR_TYPES: + dut = "r1" + input_dict_1 = { + "red1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_B", + }, + ] + } + } + + input_dict_2 = { + "blue1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_B", + }, + ] + } + } + + result = verify_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + result = verify_rib(tgen, addr_type, dut, input_dict_2) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + write_test_footer(tc_name) + + +def test_end_to_end_traffic_isolation_p0(request): + """ + FUNC_8: + Test end to end traffic isolation based on VRF tables. + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + reset_config_on_routers(tgen) + + if tgen.routers_have_failure(): + check_router_status(tgen) + + step( + "Advertise unique BGP prefixes(IPv4+IPv6) from RED_1 " + "in vrf instances(RED_A and RED_B)." + ) + + for addr_type in ADDR_TYPES: + input_dict_1 = { + "red1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_B", + }, + ] + } + } + result = create_static_routes(tgen, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step( + "Advertise unique BGP prefixes(IPv4+IPv6) from from BLUE_1 in" + " vrf instances(BLUE_A and BLUE_B)." + ) + + for addr_type in ADDR_TYPES: + input_dict_2 = { + "blue1": { + "static_routes": [ + { + "network": [NETWORK3_1[addr_type]] + [NETWORK3_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_A", + }, + { + "network": [NETWORK4_1[addr_type]] + [NETWORK4_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_B", + }, + ] + } + } + result = create_static_routes(tgen, input_dict_2) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step("Redistribute static..") + + input_dict_3 = {} + for dut in ["red1", "blue1"]: + temp = {dut: {"bgp": []}} + input_dict_3.update(temp) + + if "red" in dut: + VRFS = ["RED_A", "RED_B"] + AS_NUM = [500, 500] + elif "blue" in dut: + VRFS = ["BLUE_A", "BLUE_B"] + AS_NUM = [800, 800] + + for vrf, as_num in zip(VRFS, AS_NUM): + temp[dut]["bgp"].append( + { + "local_as": as_num, + "vrf": vrf, + "address_family": { + "ipv4": { + "unicast": {"redistribute": [{"redist_type": "static"}]} + }, + "ipv6": { + "unicast": {"redistribute": [{"redist_type": "static"}]} + }, + }, + } + ) + + result = create_router_bgp(tgen, topo, input_dict_3) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step( + "Use below commands to send prefixes with as-path prepend" + "VRF BLUE_A and BLUE_B from router BLUE-1." + ) + + for addr_type in ADDR_TYPES: + input_dict_4 = { + "blue1": { + "route_maps": { + "ASP_{}".format(addr_type): [ + { + "action": "permit", + "set": {"path": {"as_num": 123, "as_action": "prepend"}}, + } + ] + } + } + } + result = create_route_maps(tgen, input_dict_4) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step("Apply route-map to neighbours") + + input_dict_5 = { + "blue1": { + "bgp": [ + { + "local_as": "800", + "vrf": "BLUE_A", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "blue1-link1": { + "route_maps": [ + { + "name": "ASP_ipv4", + "direction": "out", + } + ] + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "blue1-link1": { + "route_maps": [ + { + "name": "ASP_ipv6", + "direction": "out", + } + ] + } + } + } + } + } + }, + }, + }, + { + "local_as": "800", + "vrf": "BLUE_B", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "blue1-link2": { + "route_maps": [ + { + "name": "ASP_ipv4", + "direction": "out", + } + ] + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "blue1-link2": { + "route_maps": [ + { + "name": "ASP_ipv6", + "direction": "out", + } + ] + } + } + } + } + } + }, + }, + }, + ] + } + } + + result = create_router_bgp(tgen, topo, input_dict_5) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step( + "Verify on R1 that BLUE_A and BLUE_B VRFs are receiving the" + " prefixes with as-path 123 prepended." + ) + + for addr_type in ADDR_TYPES: + dut = "r1" + input_dict_6 = { + "red1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_A", + }, + { + "network": [NETWORK3_1[addr_type]] + [NETWORK3_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_A", + }, + ] + } + } + + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_6) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + result = verify_rib(tgen, addr_type, dut, input_dict_6) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + for addr_type in ADDR_TYPES: + dut = "r1" + input_dict_7 = { + "red1": { + "static_routes": [ + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_B", + }, + { + "network": [NETWORK4_1[addr_type]] + [NETWORK4_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_B", + }, + ] + } + } + + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_7) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + result = verify_rib(tgen, addr_type, dut, input_dict_7) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + step( + "Use below commands to send prefixes with as-path prepend VRF" + " BLUE_A and BLUE_B from router BLUE-1." + ) + + input_dict_6 = { + "red2": { + "bgp": [ + { + "local_as": "500", + "vrf": "RED_A", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "red2-link1": { + "allowas-in": {"number_occurences": 2} + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "red2-link1": { + "allowas-in": {"number_occurences": 2} + } + } + } + } + } + }, + }, + }, + { + "local_as": "500", + "vrf": "RED_B", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "red2-link2": { + "allowas-in": {"number_occurences": 2} + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "red2-link2": { + "allowas-in": {"number_occurences": 2} + } + } + } + } + } + }, + }, + }, + ] + }, + "blue2": { + "bgp": [ + { + "local_as": "800", + "vrf": "BLUE_A", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "blue2-link1": { + "allowas-in": {"number_occurences": 2} + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "blue2-link1": { + "allowas-in": {"number_occurences": 2} + } + } + } + } + } + }, + }, + }, + { + "local_as": "800", + "vrf": "BLUE_B", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "blue2-link2": { + "allowas-in": {"number_occurences": 2} + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "blue2-link2": { + "allowas-in": {"number_occurences": 2} + } + } + } + } + } + }, + }, + }, + ] + }, + } + + result = create_router_bgp(tgen, topo, input_dict_6) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Verify that router RED-2 receives the prefixes in respective" " VRF tables.") + + for addr_type in ADDR_TYPES: + dut = "red2" + input_dict_6 = { + "red1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_B", + }, + ] + } + } + + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_6) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_6) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + for addr_type in ADDR_TYPES: + dut = "blue2" + input_dict_7 = { + "red1": { + "static_routes": [ + { + "network": [NETWORK3_1[addr_type]] + [NETWORK3_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_A", + }, + { + "network": [NETWORK4_1[addr_type]] + [NETWORK4_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_B", + }, + ] + } + } + + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_7) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_7) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + write_test_footer(tc_name) + + +def test_static_routes_for_inter_vrf_route_leaking_p0(request): + """ + FUNC_9: + Use static routes for inter-vrf communication + (route-leaking) on DUT. + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + reset_config_on_routers(tgen) + + if tgen.routers_have_failure(): + check_router_status(tgen) + + step( + "Configure unique loopback interfaces in VRFs RED_A " + "and RED_B on router RED_1." + ) + + for addr_type in ADDR_TYPES: + create_interface_in_kernel( + tgen, + "red1", + "loopback1", + LOOPBACK_1[addr_type], + "RED_A", + ) + create_interface_in_kernel( + tgen, + "red1", + "loopback2", + LOOPBACK_2[addr_type], + "RED_B", + ) + + step( + "Create a static routes in vrf RED_B on router RED_1 pointing" + " next-hop as interface's IP in vrf RED_A" + ) + + intf_red1_r11 = topo["routers"]["red1"]["links"]["r1-link1"]["interface"] + intf_red1_r10 = topo["routers"]["red1"]["links"]["r1-link2"]["interface"] + for addr_type in ADDR_TYPES: + input_dict_1 = { + "red1": { + "static_routes": [ + { + "network": LOOPBACK_1[addr_type], + "interface": intf_red1_r10, + "nexthop_vrf": "RED_B", + "vrf": "RED_A", + }, + { + "network": LOOPBACK_2[addr_type], + "interface": intf_red1_r11, + "nexthop_vrf": "RED_A", + "vrf": "RED_B", + }, + ] + } + } + result = create_static_routes(tgen, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step("Redistribute static..") + + input_dict_3 = {} + for dut in ["red1"]: + temp = {dut: {"bgp": []}} + input_dict_3.update(temp) + + if "red" in dut: + VRFS = ["RED_A", "RED_B"] + AS_NUM = [500, 500] + elif "blue" in dut: + VRFS = ["BLUE_A", "BLUE_B"] + AS_NUM = [800, 800] + + for vrf, as_num in zip(VRFS, AS_NUM): + temp[dut]["bgp"].append( + { + "local_as": as_num, + "vrf": vrf, + "address_family": { + "ipv4": { + "unicast": {"redistribute": [{"redist_type": "static"}]} + }, + "ipv6": { + "unicast": {"redistribute": [{"redist_type": "static"}]} + }, + }, + } + ) + + result = create_router_bgp(tgen, topo, input_dict_3) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step( + "Verify that static routes are installed into vrfs RED_A" + "and RED_B tables only, not in global routing table of RED_1" + ) + for addr_type in ADDR_TYPES: + dut = "red1" + input_dict_1 = { + "red1": { + "static_routes": [ + { + "network": LOOPBACK_1[addr_type], + "interface": intf_red1_r10, + "nexthop_vrf": "RED_B", + "vrf": "RED_A", + }, + { + "network": LOOPBACK_2[addr_type], + "interface": intf_red1_r11, + "nexthop_vrf": "RED_A", + "vrf": "RED_B", + }, + ] + } + } + + result = verify_rib(tgen, addr_type, dut, input_dict_1, protocol="static") + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + write_test_footer(tc_name) + + +def test_inter_vrf_and_intra_vrf_communication_iBGP_p0(request): + """ + FUNC_10: + Verify intra-vrf and inter-vrf communication between + iBGP peers. + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + reset_config_on_routers(tgen) + + if tgen.routers_have_failure(): + check_router_status(tgen) + + step( + "Configure unique loopback IP(IPv4+IPv6) in vrf RED_A on router" + " R1 and advertise it in BGP process using redistribute " + "connected command." + ) + + for addr_type in ADDR_TYPES: + create_interface_in_kernel( + tgen, + "r1", + "loopback1", + LOOPBACK_1[addr_type], + "RED_A", + ) + + create_interface_in_kernel( + tgen, + "r1", + "loopback2", + LOOPBACK_2[addr_type], + "BLUE_A", + ) + + step( + "Create a static routes in vrf RED_B on router RED_1 pointing" + " next-hop as interface's IP in vrf RED_A" + ) + + intf_r2_r12 = topo["routers"]["r2"]["links"]["r1-link1"]["interface"] + intf_r2_r10 = topo["routers"]["r2"]["links"]["r1-link3"]["interface"] + for addr_type in ADDR_TYPES: + input_dict_1 = { + "r2": { + "static_routes": [ + { + "network": LOOPBACK_2[addr_type], + "interface": intf_r2_r10, + "nexthop_vrf": "BLUE_A", + "vrf": "RED_A", + }, + { + "network": LOOPBACK_1[addr_type], + "interface": intf_r2_r12, + "nexthop_vrf": "RED_A", + "vrf": "BLUE_A", + }, + ] + } + } + result = create_static_routes(tgen, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step("Redistribute connected..") + + input_dict_3 = {} + for dut in ["r1"]: + temp = {dut: {"bgp": []}} + input_dict_3.update(temp) + + VRFS = ["RED_A", "BLUE_A"] + AS_NUM = [100, 100] + + for vrf, as_num in zip(VRFS, AS_NUM): + temp[dut]["bgp"].append( + { + "local_as": as_num, + "vrf": vrf, + "address_family": { + "ipv4": { + "unicast": {"redistribute": [{"redist_type": "connected"}]} + }, + "ipv6": { + "unicast": {"redistribute": [{"redist_type": "connected"}]} + }, + }, + } + ) + + result = create_router_bgp(tgen, topo, input_dict_3) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Redistribute static..") + + input_dict_3 = {} + for dut in ["r2"]: + temp = {dut: {"bgp": []}} + input_dict_3.update(temp) + + VRFS = ["RED_A", "BLUE_A"] + AS_NUM = [100, 100] + + for vrf, as_num in zip(VRFS, AS_NUM): + temp[dut]["bgp"].append( + { + "local_as": as_num, + "vrf": vrf, + "address_family": { + "ipv4": { + "unicast": {"redistribute": [{"redist_type": "static"}]} + }, + "ipv6": { + "unicast": {"redistribute": [{"redist_type": "static"}]} + }, + }, + } + ) + + result = create_router_bgp(tgen, topo, input_dict_3) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step( + "Verify that static routes are installed into vrfs RED_A" + "and RED_B tables only, not in global routing table of RED_1" + ) + + for addr_type in ADDR_TYPES: + dut = "r2" + input_dict = { + "r2": { + "static_routes": [ + { + "network": LOOPBACK_2[addr_type], + "interface": intf_r2_r10, + "nexthop_vrf": "BLUE_A", + "vrf": "RED_A", + }, + { + "network": LOOPBACK_1[addr_type], + "interface": intf_r2_r12, + "nexthop_vrf": "RED_A", + "vrf": "BLUE_A", + }, + ] + } + } + + result = verify_rib(tgen, addr_type, dut, input_dict) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + write_test_footer(tc_name) + + +def test_inter_vrf_and_intra_vrf_communication_eBGP_p0(request): + """ + FUNC_11: + Verify intra-vrf and inter-vrf communication + between eBGP peers. + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + reset_config_on_routers(tgen) + + if tgen.routers_have_failure(): + check_router_status(tgen) + + step( + "Configure unique loopback IP(IPv4+IPv6) in vrf RED_A on router" + " R2 and advertise it in BGP process using redistribute " + "connected command." + ) + + step( + "Configure unique loopback IP(IPv4+IPv6) in vrf BLUE_A on router" + " R2 and advertise it in BGP process using redistribute " + "connected command." + ) + + for addr_type in ADDR_TYPES: + create_interface_in_kernel( + tgen, + "r2", + "loopback1", + LOOPBACK_1[addr_type], + "RED_A", + ) + create_interface_in_kernel( + tgen, + "r2", + "loopback2", + LOOPBACK_2[addr_type], + "BLUE_A", + ) + + step( + "Create a static routes in vrf RED_B on router RED_1 pointing" + " next-hop as interface's IP in vrf RED_A" + ) + + intf_r3_r21 = topo["routers"]["r3"]["links"]["r2-link1"]["interface"] + intf_r3_r23 = topo["routers"]["r3"]["links"]["r2-link3"]["interface"] + for addr_type in ADDR_TYPES: + input_dict_1 = { + "r3": { + "static_routes": [ + { + "network": LOOPBACK_2[addr_type], + "interface": intf_r3_r23, + "nexthop_vrf": "BLUE_A", + "vrf": "RED_A", + }, + { + "network": LOOPBACK_1[addr_type], + "interface": intf_r3_r21, + "nexthop_vrf": "RED_A", + "vrf": "BLUE_A", + }, + ] + } + } + result = create_static_routes(tgen, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step("Redistribute static..") + + input_dict_3 = {} + for dut in ["r3"]: + temp = {dut: {"bgp": []}} + input_dict_3.update(temp) + + VRFS = ["RED_A", "BLUE_A"] + AS_NUM = [200, 200] + + for vrf, as_num in zip(VRFS, AS_NUM): + temp[dut]["bgp"].append( + { + "local_as": as_num, + "vrf": vrf, + "address_family": { + "ipv4": { + "unicast": {"redistribute": [{"redist_type": "static"}]} + }, + "ipv6": { + "unicast": {"redistribute": [{"redist_type": "static"}]} + }, + }, + } + ) + + result = create_router_bgp(tgen, topo, input_dict_3) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Redistribute connected..") + + input_dict_3 = {} + for dut in ["r2"]: + temp = {dut: {"bgp": []}} + input_dict_3.update(temp) + + VRFS = ["RED_A", "BLUE_A"] + AS_NUM = [100, 100] + + for vrf, as_num in zip(VRFS, AS_NUM): + temp[dut]["bgp"].append( + { + "local_as": as_num, + "vrf": vrf, + "address_family": { + "ipv4": { + "unicast": {"redistribute": [{"redist_type": "connected"}]} + }, + "ipv6": { + "unicast": {"redistribute": [{"redist_type": "connected"}]} + }, + }, + } + ) + + result = create_router_bgp(tgen, topo, input_dict_3) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step( + "Verify that static routes are installed into vrfs RED_A" + "and RED_B tables only, not in global routing table of RED_1" + ) + + for addr_type in ADDR_TYPES: + dut = "r3" + input_dict = { + "r3": { + "static_routes": [ + { + "network": LOOPBACK_2[addr_type], + "interface": intf_r3_r23, + "nexthop_vrf": "BLUE_A", + "vrf": "RED_A", + }, + { + "network": LOOPBACK_1[addr_type], + "interface": intf_r3_r21, + "nexthop_vrf": "RED_A", + "vrf": "BLUE_A", + }, + ] + } + } + + result = verify_rib(tgen, addr_type, dut, input_dict) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + write_test_footer(tc_name) + + +def test_route_map_within_vrf_to_alter_bgp_attribute_nexthop_p0(request): + """ + FUNC_12_a: + Configure route-maps within a VRF, to alter BGP attributes. + Verify that route-map doesn't affect any other VRF instances' + routing on DUT. + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + reset_config_on_routers(tgen) + + if tgen.routers_have_failure(): + check_router_status(tgen) + + step( + "Advertise a set of BGP prefixes(IPv4+IPv6) from RED_1 and" + " RED_2 in vrf instances(RED_A and RED_B)." + ) + + for addr_type in ADDR_TYPES: + input_dict_1 = { + "red1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_B", + }, + ] + } + } + result = create_static_routes(tgen, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step( + "Advertise same set of BGP prefixes(IPv4+IPv6) from BLUE_1 and" + "BLUE_2 in vrf instances(BLUE_A and BLUE_B)" + ) + + for addr_type in ADDR_TYPES: + input_dict_2 = { + "blue1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_B", + }, + ] + } + } + result = create_static_routes(tgen, input_dict_2) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step("Redistribute static..") + + input_dict_3 = {} + for dut in ["red1", "blue1"]: + temp = {dut: {"bgp": []}} + input_dict_3.update(temp) + + if "red" in dut: + VRFS = ["RED_A", "RED_B"] + AS_NUM = [500, 500] + elif "blue" in dut: + VRFS = ["BLUE_A", "BLUE_B"] + AS_NUM = [800, 800] + + for vrf, as_num in zip(VRFS, AS_NUM): + temp[dut]["bgp"].append( + { + "local_as": as_num, + "vrf": vrf, + "address_family": { + "ipv4": { + "unicast": {"redistribute": [{"redist_type": "static"}]} + }, + "ipv6": { + "unicast": {"redistribute": [{"redist_type": "static"}]} + }, + }, + } + ) + + result = create_router_bgp(tgen, topo, input_dict_3) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step( + "Verify that within vrf instances, BGP best path selection" + " algorithm remains intact and doesn't affect any other VRFs" + " routing decision." + ) + + for addr_type in ADDR_TYPES: + dut = "r2" + input_dict_1 = { + "red1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_B", + }, + ] + } + } + + input_dict_2 = { + "blue1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_B", + }, + ] + } + } + + result = verify_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + result = verify_rib(tgen, addr_type, dut, input_dict_2) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + step("Delete nexthop-self configure from r1") + + input_dict_4 = { + "r1": { + "bgp": [ + { + "local_as": "100", + "vrf": "RED_A", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": {"next_hop_self": False} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link1": {"next_hop_self": False} + } + } + } + } + }, + }, + }, + { + "local_as": "100", + "vrf": "RED_B", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link2": {"next_hop_self": False} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link2": {"next_hop_self": False} + } + } + } + } + }, + }, + }, + { + "local_as": "100", + "vrf": "BLUE_A", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link3": {"next_hop_self": False} + } + }, + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link3": {"next_hop_self": False} + } + } + } + } + }, + }, + }, + { + "local_as": "100", + "vrf": "BLUE_B", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link4": {"next_hop_self": False} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r2": { + "dest_link": { + "r1-link4": {"next_hop_self": False} + } + } + } + } + }, + }, + }, + ] + } + } + + result = create_router_bgp(tgen, topo, input_dict_4) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step( + "Verify that within vrf instances, BGP best path selection" + " algorithm remains intact and doesn't affect any other VRFs" + " routing decision." + ) + + for addr_type in ADDR_TYPES: + dut = "r2" + input_dict_1 = { + "red1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_B", + }, + ] + } + } + + input_dict_2 = { + "blue1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_B", + }, + ] + } + } + + result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False) + assert ( + result is not True + ), "Testcase {} : Failed \n Expected Behaviour: Routes are rejected because nexthop-self config is deleted \n Error {}".format( + tc_name, result + ) + + result = verify_rib(tgen, addr_type, dut, input_dict_2, expected=False) + assert ( + result is not True + ), "Testcase {} : Failed \n Expected Behaviour: Routes are rejected because nexthop-self config is deleted \n Error {}".format( + tc_name, result + ) + + write_test_footer(tc_name) + + +@pytest.mark.parametrize("attribute", ["locPrf", "weight", "metric"]) +def test_route_map_within_vrf_to_alter_bgp_attribute_p0(request, attribute): + """ + FUNC_12_b/c/d: + Configure route-maps within a VRF, to alter BGP attributes. + Verify that route-map doesn't affect any other VRF instances' + routing on DUT. + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + reset_config_on_routers(tgen) + + if tgen.routers_have_failure(): + check_router_status(tgen) + + step( + "Advertise a set of BGP prefixes(IPv4+IPv6) from RED_1 and" + " RED_2 in vrf instances(RED_A and RED_B)." + ) + + for addr_type in ADDR_TYPES: + input_dict_1 = { + "red1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_B", + }, + ] + }, + "red2": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_B", + }, + ] + }, + } + result = create_static_routes(tgen, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step( + "Advertise same set of BGP prefixes(IPv4+IPv6) from BLUE_1 and" + "BLUE_2 in vrf instances(BLUE_A and BLUE_B)" + ) + + for addr_type in ADDR_TYPES: + input_dict_2 = { + "blue1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_B", + }, + ] + }, + "blue2": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_B", + }, + ] + }, + } + result = create_static_routes(tgen, input_dict_2) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step("Redistribute static..") + + input_dict_3 = {} + for dut in ["red1", "red2", "blue1", "blue2"]: + temp = {dut: {"bgp": []}} + input_dict_3.update(temp) + + if "red" in dut: + VRFS = ["RED_A", "RED_B"] + AS_NUM = [500, 500] + elif "blue" in dut: + VRFS = ["BLUE_A", "BLUE_B"] + AS_NUM = [800, 800] + + for vrf, as_num in zip(VRFS, AS_NUM): + temp[dut]["bgp"].append( + { + "local_as": as_num, + "vrf": vrf, + "address_family": { + "ipv4": { + "unicast": {"redistribute": [{"redist_type": "static"}]} + }, + "ipv6": { + "unicast": {"redistribute": [{"redist_type": "static"}]} + }, + }, + } + ) + + result = create_router_bgp(tgen, topo, input_dict_3) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Configure a route-maps to influence BGP parameters - " " Local Preference") + + for addr_type in ADDR_TYPES: + input_dict_4 = { + "r2": { + "route_maps": { + "rmap_r1_{}".format(addr_type): [ + {"action": "permit", "set": {attribute: 120}} + ], + "rmap_r3_{}".format(addr_type): [ + {"action": "permit", "set": {attribute: 150}} + ], + } + } + } + + result = create_route_maps(tgen, input_dict_4) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step("Configure neighbor for route map") + input_dict_4 = { + "r2": { + "bgp": [ + { + "local_as": "100", + "vrf": "RED_A", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link1": { + "route_maps": [ + { + "name": "rmap_r1_ipv4", + "direction": "in", + } + ] + } + } + }, + "r3": { + "dest_link": { + "r2-link1": { + "route_maps": [ + { + "name": "rmap_r3_ipv4", + "direction": "in", + } + ] + } + } + }, + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link1": { + "route_maps": [ + { + "name": "rmap_r1_ipv6", + "direction": "in", + } + ] + } + } + }, + "r3": { + "dest_link": { + "r2-link1": { + "route_maps": [ + { + "name": "rmap_r3_ipv6", + "direction": "in", + } + ] + } + } + }, + } + } + }, + }, + }, + { + "local_as": "100", + "vrf": "RED_B", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link2": { + "route_maps": [ + { + "name": "rmap_r1_ipv4", + "direction": "in", + } + ] + } + } + }, + "r3": { + "dest_link": { + "r2-link2": { + "route_maps": [ + { + "name": "rmap_r3_ipv4", + "direction": "in", + } + ] + } + } + }, + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link2": { + "route_maps": [ + { + "name": "rmap_r1_ipv6", + "direction": "in", + } + ] + } + } + }, + "r3": { + "dest_link": { + "r2-link2": { + "route_maps": [ + { + "name": "rmap_r3_ipv6", + "direction": "in", + } + ] + } + } + }, + } + } + }, + }, + }, + { + "local_as": "100", + "vrf": "BLUE_A", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link3": { + "route_maps": [ + { + "name": "rmap_r1_ipv4", + "direction": "in", + } + ] + } + } + }, + "r3": { + "dest_link": { + "r2-link3": { + "route_maps": [ + { + "name": "rmap_r3_ipv4", + "direction": "in", + } + ] + } + } + }, + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link3": { + "route_maps": [ + { + "name": "rmap_r1_ipv6", + "direction": "in", + } + ] + } + } + }, + "r3": { + "dest_link": { + "r2-link3": { + "route_maps": [ + { + "name": "rmap_r3_ipv6", + "direction": "in", + } + ] + } + } + }, + } + } + }, + }, + }, + { + "local_as": "100", + "vrf": "BLUE_B", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link4": { + "route_maps": [ + { + "name": "rmap_r1_ipv4", + "direction": "in", + } + ] + } + } + }, + "r3": { + "dest_link": { + "r2-link4": { + "route_maps": [ + { + "name": "rmap_r3_ipv4", + "direction": "in", + } + ] + } + } + }, + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link4": { + "route_maps": [ + { + "name": "rmap_r1_ipv6", + "direction": "in", + } + ] + } + } + }, + "r3": { + "dest_link": { + "r2-link4": { + "route_maps": [ + { + "name": "rmap_r3_ipv6", + "direction": "in", + } + ] + } + } + }, + } + } + }, + }, + }, + ] + } + } + + result = create_router_bgp(tgen, topo, input_dict_4) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step( + "Verify that within vrf instances, BGP best path selection" + " algorithm remains intact and doesn't affect any other VRFs" + " routing decision." + ) + + dut = "r2" + for addr_type in ADDR_TYPES: + input_dict_1 = { + "red1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_B", + }, + ] + } + } + + input_dict_2 = { + "blue1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_B", + }, + ] + } + } + + result = verify_best_path_as_per_bgp_attribute( + tgen, addr_type, dut, input_dict_1, attribute + ) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + result = verify_best_path_as_per_bgp_attribute( + tgen, addr_type, dut, input_dict_2, attribute + ) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + write_test_footer(tc_name) + + +def test_route_map_within_vrf_to_alter_bgp_attribute_aspath_p0(request): + """ + FUNC_12_e: + Configure route-maps within a VRF, to alter BGP attributes. + Verify that route-map doesn't affect any other VRF instances' + routing on DUT. + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + reset_config_on_routers(tgen) + + if tgen.routers_have_failure(): + check_router_status(tgen) + + step( + "Advertise a set of BGP prefixes(IPv4+IPv6) from RED_1 and" + " RED_2 in vrf instances(RED_A and RED_B)." + ) + + for addr_type in ADDR_TYPES: + input_dict_1 = { + "red1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_B", + }, + ] + }, + "red2": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_B", + }, + ] + }, + } + result = create_static_routes(tgen, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step( + "Advertise same set of BGP prefixes(IPv4+IPv6) from BLUE_1 and" + "BLUE_2 in vrf instances(BLUE_A and BLUE_B)" + ) + + for addr_type in ADDR_TYPES: + input_dict_2 = { + "blue1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_B", + }, + ] + }, + "blue2": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_B", + }, + ] + }, + } + result = create_static_routes(tgen, input_dict_2) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step("Redistribute static..") + + input_dict_3 = {} + for dut in ["red1", "red2", "blue1", "blue2"]: + temp = {dut: {"bgp": []}} + input_dict_3.update(temp) + + if "red" in dut: + VRFS = ["RED_A", "RED_B"] + AS_NUM = [500, 500] + elif "blue" in dut: + VRFS = ["BLUE_A", "BLUE_B"] + AS_NUM = [800, 800] + + for vrf, as_num in zip(VRFS, AS_NUM): + temp[dut]["bgp"].append( + { + "local_as": as_num, + "vrf": vrf, + "address_family": { + "ipv4": { + "unicast": {"redistribute": [{"redist_type": "static"}]} + }, + "ipv6": { + "unicast": {"redistribute": [{"redist_type": "static"}]} + }, + }, + } + ) + + result = create_router_bgp(tgen, topo, input_dict_3) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Configure a route-maps to influence BGP parameters - " " Local Preference") + + for addr_type in ADDR_TYPES: + input_dict_4 = { + "r2": { + "route_maps": { + "rmap_r1_{}".format(addr_type): [ + { + "action": "permit", + "set": { + "path": {"as_num": "111 222", "as_action": "prepend"} + }, + } + ] + } + } + } + result = create_route_maps(tgen, input_dict_4) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step("Configure neighbor for route map") + input_dict_4 = { + "r2": { + "bgp": [ + { + "local_as": "100", + "vrf": "RED_A", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link1": { + "route_maps": [ + { + "name": "rmap_r1_ipv4", + "direction": "in", + } + ] + } + } + }, + "r3": {"dest_link": {"r2-link1": {}}}, + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link1": { + "route_maps": [ + { + "name": "rmap_r1_ipv6", + "direction": "in", + } + ] + } + } + }, + "r3": {"dest_link": {"r2-link1": {}}}, + } + } + }, + }, + }, + { + "local_as": "100", + "vrf": "RED_B", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link2": { + "route_maps": [ + { + "name": "rmap_r1_ipv4", + "direction": "in", + } + ] + } + } + }, + "r3": {"dest_link": {"r2-link2": {}}}, + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link2": { + "route_maps": [ + { + "name": "rmap_r1_ipv6", + "direction": "in", + } + ] + } + } + }, + "r3": {"dest_link": {"r2-link2": {}}}, + } + } + }, + }, + }, + { + "local_as": "100", + "vrf": "BLUE_A", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link3": { + "route_maps": [ + { + "name": "rmap_r1_ipv4", + "direction": "in", + } + ] + } + } + }, + "r3": {"dest_link": {"r2-link3": {}}}, + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link3": { + "route_maps": [ + { + "name": "rmap_r1_ipv6", + "direction": "in", + } + ] + } + } + }, + "r3": {"dest_link": {"r2-link3": {}}}, + } + } + }, + }, + }, + { + "local_as": "100", + "vrf": "BLUE_B", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link4": { + "route_maps": [ + { + "name": "rmap_r1_ipv4", + "direction": "in", + } + ] + } + } + }, + "r3": {"dest_link": {"r2-link4": {}}}, + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link4": { + "route_maps": [ + { + "name": "rmap_r1_ipv6", + "direction": "in", + } + ] + } + } + }, + "r3": {"dest_link": {"r2-link4": {}}}, + } + } + }, + }, + }, + ] + } + } + + result = create_router_bgp(tgen, topo, input_dict_4) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step( + "Verify that within vrf instances, BGP best path selection" + " algorithm remains intact and doesn't affect any other VRFs" + " routing decision." + ) + + dut = "r2" + attribute = "path" + for addr_type in ADDR_TYPES: + input_dict_1 = { + "red1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_B", + }, + ] + } + } + + input_dict_2 = { + "blue1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_B", + }, + ] + } + } + + result = verify_best_path_as_per_bgp_attribute( + tgen, addr_type, dut, input_dict_1, attribute + ) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + result = verify_best_path_as_per_bgp_attribute( + tgen, addr_type, dut, input_dict_2, attribute + ) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + write_test_footer(tc_name) + + +def test_route_map_within_vrf_to_alter_bgp_attribute_lcomm_p0(request): + """ + FUNC_12_f: + Configure route-maps within a VRF, to alter BGP attributes. + Verify that route-map doesn't affect any other VRF instances' + routing on DUT. + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + reset_config_on_routers(tgen) + + if tgen.routers_have_failure(): + check_router_status(tgen) + + step( + "Advertise a set of BGP prefixes(IPv4+IPv6) from RED_1 and" + " RED_2 in vrf instances(RED_A and RED_B)." + ) + + for addr_type in ADDR_TYPES: + input_dict_1 = { + "red1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_B", + }, + ] + }, + "red2": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_B", + }, + ] + }, + } + result = create_static_routes(tgen, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step( + "Advertise same set of BGP prefixes(IPv4+IPv6) from BLUE_1 and" + "BLUE_2 in vrf instances(BLUE_A and BLUE_B)" + ) + + for addr_type in ADDR_TYPES: + input_dict_2 = { + "blue1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_B", + }, + ] + }, + "blue2": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_B", + }, + ] + }, + } + result = create_static_routes(tgen, input_dict_2) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step("Redistribute static..") + + input_dict_3 = {} + for dut in ["red1", "red2", "blue1", "blue2"]: + temp = {dut: {"bgp": []}} + input_dict_3.update(temp) + + if "red" in dut: + VRFS = ["RED_A", "RED_B"] + AS_NUM = [500, 500] + elif "blue" in dut: + VRFS = ["BLUE_A", "BLUE_B"] + AS_NUM = [800, 800] + + for vrf, as_num in zip(VRFS, AS_NUM): + temp[dut]["bgp"].append( + { + "local_as": as_num, + "vrf": vrf, + "address_family": { + "ipv4": { + "unicast": {"redistribute": [{"redist_type": "static"}]} + }, + "ipv6": { + "unicast": {"redistribute": [{"redist_type": "static"}]} + }, + }, + } + ) + + result = create_router_bgp(tgen, topo, input_dict_3) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Configure a route-maps to influence BGP parameters - " " Large-community") + + step("Create standard large commumity-list in r2") + + for addr_type in ADDR_TYPES: + input_dict_1 = { + "r2": { + "bgp_community_lists": [ + { + "community_type": "standard", + "action": "permit", + "name": "rmap_lcomm_{}".format(addr_type), + "value": "1:1:1 1:2:3 2:1:1 2:2:2", + "large": True, + } + ] + } + } + result = create_bgp_community_lists(tgen, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step("Create route-maps in red1 and r1") + + for addr_type in ADDR_TYPES: + input_dict_4 = { + "red1": { + "route_maps": { + "rmap_red1_{}".format(addr_type): [ + { + "action": "permit", + "set": { + "large_community": {"num": "1:1:1 1:2:3 2:1:1 2:2:2"} + }, + } + ] + } + }, + "r2": { + "route_maps": { + "rmap_r1_{}".format(addr_type): [ + { + "action": "permit", + "match": { + "large_community_list": { + "id": "rmap_lcomm_" + addr_type + } + }, + } + ] + } + }, + } + result = create_route_maps(tgen, input_dict_4) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step("Configure neighbor for route map in red1") + + input_dict_4 = { + "red1": { + "bgp": [ + { + "local_as": "500", + "vrf": "RED_A", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "red1-link1": { + "route_maps": [ + { + "name": "rmap_red1_ipv4", + "direction": "out", + } + ] + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "red1-link1": { + "route_maps": [ + { + "name": "rmap_red1_ipv6", + "direction": "out", + } + ] + } + } + } + } + } + }, + }, + }, + { + "local_as": "500", + "vrf": "RED_B", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "red1-link2": { + "route_maps": [ + { + "name": "rmap_red1_ipv4", + "direction": "out", + } + ] + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "red1-link2": { + "route_maps": [ + { + "name": "rmap_red1_ipv6", + "direction": "out", + } + ] + } + } + } + } + } + }, + }, + }, + ] + } + } + + result = create_router_bgp(tgen, topo, input_dict_4) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Configure neighbor for route map in r2") + + input_dict_4 = { + "r2": { + "bgp": [ + { + "local_as": "100", + "vrf": "RED_A", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link1": { + "route_maps": [ + { + "name": "rmap_r1_ipv4", + "direction": "in", + } + ] + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link1": { + "route_maps": [ + { + "name": "rmap_r1_ipv6", + "direction": "in", + } + ] + } + } + } + } + } + }, + }, + }, + { + "local_as": "100", + "vrf": "RED_B", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link2": { + "route_maps": [ + { + "name": "rmap_r1_ipv4", + "direction": "in", + } + ] + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link2": { + "route_maps": [ + { + "name": "rmap_r1_ipv6", + "direction": "in", + } + ] + } + } + } + } + } + }, + }, + }, + { + "local_as": "100", + "vrf": "BLUE_A", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link3": { + "route_maps": [ + { + "name": "rmap_r1_ipv4", + "direction": "in", + } + ] + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link3": { + "route_maps": [ + { + "name": "rmap_r1_ipv6", + "direction": "in", + } + ] + } + } + } + } + } + }, + }, + }, + { + "local_as": "100", + "vrf": "BLUE_B", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link4": { + "route_maps": [ + { + "name": "rmap_r1_ipv4", + "direction": "in", + } + ] + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "r2-link4": { + "route_maps": [ + { + "name": "rmap_r1_ipv6", + "direction": "in", + } + ] + } + } + } + } + } + }, + }, + }, + ] + } + } + + result = create_router_bgp(tgen, topo, input_dict_4) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step( + "All the prefixes advertised from RED_1 and BLUE_1 should carry" + " attributes set by outbound route-maps within specific vrfs. " + "Router R1 should be able to match and permit/deny those " + "prefixes based on received attributes. Please use below " + "commands to verify." + ) + + input_dict = { + "largeCommunity": "1:1:1 1:2:3 2:1:1 2:2:2", + } + + for addr_type in ADDR_TYPES: + vrf = "RED_A" + routes = [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]] + result = verify_bgp_community(tgen, addr_type, "r2", routes, input_dict, vrf) + assert result is True, "Test case {} : Failed \n Error: {}".format( + tc_name, result + ) + + for addr_type in ADDR_TYPES: + vrf = "RED_B" + routes = [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]] + result = verify_bgp_community(tgen, addr_type, "r2", routes, input_dict, vrf) + assert result is True, "Test case {} : Failed \n Error: {}".format( + tc_name, result + ) + + write_test_footer(tc_name) + + +def test_route_map_match_traffic_based_on_vrf_p0(request): + """ + FUNC_13: + Configure a route-map on DUT to match traffic based + on a VRF interfaces. + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + reset_config_on_routers(tgen) + + if tgen.routers_have_failure(): + check_router_status(tgen) + + step( + "Advertise unique BGP prefixes(IPv4+IPv6) from RED_1 " + "in vrf instances(RED_A and RED_B)." + ) + + for addr_type in ADDR_TYPES: + input_dict_1 = { + "red1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_B", + }, + ] + } + } + result = create_static_routes(tgen, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step( + "Advertise unique BGP prefixes(IPv4+IPv6) from from BLUE_1 in" + " vrf instances(BLUE_A and BLUE_B)." + ) + + for addr_type in ADDR_TYPES: + input_dict_2 = { + "blue1": { + "static_routes": [ + { + "network": [NETWORK3_1[addr_type]] + [NETWORK3_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_A", + }, + { + "network": [NETWORK4_1[addr_type]] + [NETWORK4_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_B", + }, + ] + } + } + result = create_static_routes(tgen, input_dict_2) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step("Redistribute static..") + + input_dict_3 = {} + for dut in ["red1", "blue1"]: + temp = {dut: {"bgp": []}} + input_dict_3.update(temp) + + if "red" in dut: + VRFS = ["RED_A", "RED_B"] + AS_NUM = [500, 500] + elif "blue" in dut: + VRFS = ["BLUE_A", "BLUE_B"] + AS_NUM = [800, 800] + + for vrf, as_num in zip(VRFS, AS_NUM): + temp[dut]["bgp"].append( + { + "local_as": as_num, + "vrf": vrf, + "address_family": { + "ipv4": { + "unicast": {"redistribute": [{"redist_type": "static"}]} + }, + "ipv6": { + "unicast": {"redistribute": [{"redist_type": "static"}]} + }, + }, + } + ) + + result = create_router_bgp(tgen, topo, input_dict_3) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step( + "Configure a route-map on R1 to match the prefixes " + "coming from vrf RED_A and set as-prepend to these routes." + ) + + input_dict_4 = { + "r1": { + "route_maps": { + "ABC": [ + { + "action": "permit", + "match": {"source-vrf": "RED_A"}, + "set": {"path": {"as_num": 1, "as_action": "prepend"}}, + } + ] + } + } + } + result = create_route_maps(tgen, input_dict_4) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step( + "On R1, import the routes form vrf RED_A and RED_B to BLUE_A and" + " apply the route-map under vrf BLUE_A while importing" + ) + + raw_config = { + "r1": { + "raw_config": [ + "router bgp 100 vrf BLUE_A", + "address-family ipv4 unicast", + "import vrf RED_A", + "import vrf RED_B", + "import vrf route-map ABC", + "address-family ipv6 unicast", + "import vrf RED_A", + "import vrf RED_B", + "import vrf route-map ABC", + ] + } + } + result = apply_raw_config(tgen, raw_config) + assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result) + + step( + "All the prefixes advertised from RED_1 and BLUE_1 in vrfs " + "RED_B and BLUE_B must prepend the AS number in as-path on R2." + ) + + for addr_type in ADDR_TYPES: + input_dict_7 = { + "red1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_A", + }, + { + "network": [NETWORK3_1[addr_type]] + [NETWORK3_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_A", + }, + ] + } + } + + result = verify_bgp_rib(tgen, addr_type, "r1", input_dict_7) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + write_test_footer(tc_name) + + +def test_vrf_lite_with_static_bgp_originated_routes_p0(request): + """ + FUNC_14: + Test VRF-lite with Static+BGP originated routes. + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + reset_config_on_routers(tgen) + + if tgen.routers_have_failure(): + check_router_status(tgen) + + step( + "Advertise unique BGP prefixes(IPv4+IPv6) from from RED_1" + " in vrf instances(RED_A and RED_B)." + ) + + for addr_type in ADDR_TYPES: + input_dict_1 = { + "red1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_B", + }, + ] + } + } + result = create_static_routes(tgen, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step( + "Advertise unique BGP prefixes(IPv4+IPv6) from from BLUE_1 in" + " vrf instances(BLUE_A and BLUE_B)." + ) + + for addr_type in ADDR_TYPES: + input_dict_2 = { + "blue1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_B", + }, + ] + } + } + result = create_static_routes(tgen, input_dict_2) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + input_dict_3 = { + "red1": { + "bgp": [ + { + "local_as": "500", + "vrf": "RED_A", + "address_family": { + "ipv4": { + "unicast": { + "advertise_networks": [ + { + "network": [NETWORK5_1["ipv4"]] + + [NETWORK5_2["ipv4"]] + } + ], + "redistribute": [{"redist_type": "static"}], + } + }, + "ipv6": { + "unicast": { + "advertise_networks": [ + { + "network": [NETWORK5_1["ipv6"]] + + [NETWORK5_2["ipv6"]] + } + ], + "redistribute": [{"redist_type": "static"}], + } + }, + }, + }, + { + "local_as": "500", + "vrf": "RED_B", + "address_family": { + "ipv4": { + "unicast": { + "advertise_networks": [ + { + "network": [NETWORK6_1["ipv4"]] + + [NETWORK6_2["ipv4"]] + } + ], + "redistribute": [{"redist_type": "static"}], + } + }, + "ipv6": { + "unicast": { + "advertise_networks": [ + { + "network": [NETWORK6_1["ipv6"]] + + [NETWORK6_2["ipv6"]] + } + ], + "redistribute": [{"redist_type": "static"}], + } + }, + }, + }, + ] + }, + "blue1": { + "bgp": [ + { + "local_as": "800", + "vrf": "BLUE_A", + "address_family": { + "ipv4": { + "unicast": { + "advertise_networks": [ + { + "network": [NETWORK7_1["ipv4"]] + + [NETWORK7_2["ipv4"]] + } + ], + "redistribute": [{"redist_type": "static"}], + } + }, + "ipv6": { + "unicast": { + "advertise_networks": [ + { + "network": [NETWORK7_1["ipv6"]] + + [NETWORK7_2["ipv6"]] + } + ], + "redistribute": [{"redist_type": "static"}], + } + }, + }, + }, + { + "local_as": "800", + "vrf": "BLUE_B", + "address_family": { + "ipv4": { + "unicast": { + "advertise_networks": [ + { + "network": [NETWORK8_1["ipv4"]] + + [NETWORK8_2["ipv4"]] + } + ], + "redistribute": [{"redist_type": "static"}], + } + }, + "ipv6": { + "unicast": { + "advertise_networks": [ + { + "network": [NETWORK8_1["ipv6"]] + + [NETWORK8_2["ipv6"]] + } + ], + "redistribute": [{"redist_type": "static"}], + } + }, + }, + }, + ] + }, + } + + result = create_router_bgp(tgen, topo, input_dict_3) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Static routes must be installed in associated VRF" " table only.") + + for addr_type in ADDR_TYPES: + dut = "r1" + result = verify_bgp_rib(tgen, addr_type, dut, input_dict_3) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + step( + "All the routers must receive advertised as well as " + "redistributed(static) prefixes in associated VRF tables." + ) + + for addr_type in ADDR_TYPES: + dut = "r1" + input_dict_1 = { + "red1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_B", + }, + ] + } + } + + input_dict_2 = { + "blue1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_B", + }, + ] + } + } + + result = verify_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + result = verify_rib(tgen, addr_type, dut, input_dict_2) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + write_test_footer(tc_name) + + +def test_prefix_list_to_permit_deny_prefixes_p0(request): + """ + FUNC_15: + Configure prefix-lists on DUT and apply to BGP peers to + permit/deny prefixes. + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + reset_config_on_routers(tgen) + + if tgen.routers_have_failure(): + check_router_status(tgen) + + step( + "Advertise unique BGP prefixes(IPv4+IPv6) from from RED_1" + " in vrf instances(RED_A and RED_B)." + ) + + for addr_type in ADDR_TYPES: + input_dict_1 = { + "red1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_B", + }, + ] + } + } + result = create_static_routes(tgen, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step( + "Advertise unique BGP prefixes(IPv4+IPv6) from from BLUE_1 in" + " vrf instances(BLUE_A and BLUE_B)." + ) + + for addr_type in ADDR_TYPES: + input_dict_2 = { + "blue1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_B", + }, + ] + } + } + result = create_static_routes(tgen, input_dict_2) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step("Redistribute static..") + + input_dict_3 = {} + for dut in ["red1", "blue1"]: + temp = {dut: {"bgp": []}} + input_dict_3.update(temp) + + if "red" in dut: + VRFS = ["RED_A", "RED_B"] + AS_NUM = [500, 500] + elif "blue" in dut: + VRFS = ["BLUE_A", "BLUE_B"] + AS_NUM = [800, 800] + + for vrf, as_num in zip(VRFS, AS_NUM): + temp[dut]["bgp"].append( + { + "local_as": as_num, + "vrf": vrf, + "address_family": { + "ipv4": { + "unicast": {"redistribute": [{"redist_type": "static"}]} + }, + "ipv6": { + "unicast": {"redistribute": [{"redist_type": "static"}]} + }, + }, + } + ) + + result = create_router_bgp(tgen, topo, input_dict_3) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Verify routes are present before applying prefix-list") + for addr_type in ADDR_TYPES: + dut = "r1" + input_dict_1 = { + "red1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_B", + }, + ] + } + } + + input_dict_2 = { + "blue1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_B", + }, + ] + } + } + + result = verify_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + result = verify_rib(tgen, addr_type, dut, input_dict_2) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + step( + "On routers RED_1 and BLUE_1, configure prefix-lists to permit" + " 4 prefixes and deny 1 prefix x.x.x.5. Apply these in outbound" + "direction for each neighbour." + ) + + for addr_type in ADDR_TYPES: + input_dict_4 = { + "red1": { + "prefix_lists": { + addr_type: { + "pflist_red1_{}".format(addr_type): [ + { + "seqid": 10, + "network": NETWORK1_1[addr_type], + "action": "permit", + }, + { + "seqid": 11, + "network": NETWORK2_1[addr_type], + "action": "permit", + }, + { + "seqid": 12, + "network": NETWORK1_2[addr_type], + "action": "deny", + }, + { + "seqid": 13, + "network": NETWORK2_2[addr_type], + "action": "deny", + }, + ] + } + } + }, + "blue1": { + "prefix_lists": { + addr_type: { + "pflist_blue1_{}".format(addr_type): [ + { + "seqid": 10, + "network": NETWORK1_1[addr_type], + "action": "permit", + }, + { + "seqid": 11, + "network": NETWORK2_1[addr_type], + "action": "permit", + }, + { + "seqid": 12, + "network": NETWORK1_2[addr_type], + "action": "deny", + }, + { + "seqid": 13, + "network": NETWORK2_2[addr_type], + "action": "deny", + }, + ] + } + } + }, + "r1": { + "prefix_lists": { + addr_type: { + "pflist_r1_{}".format(addr_type): [ + { + "seqid": 10, + "network": NETWORK1_1[addr_type], + "action": "permit", + }, + { + "seqid": 11, + "network": NETWORK2_1[addr_type], + "action": "deny", + }, + ] + } + } + }, + } + result = create_prefix_lists(tgen, input_dict_4) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + input_dict_5 = { + "red1": { + "bgp": [ + { + "local_as": "500", + "vrf": "RED_A", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "red1-link1": { + "prefix_lists": [ + { + "name": "pflist_red1_ipv4", + "direction": "out", + } + ] + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "red1-link1": { + "prefix_lists": [ + { + "name": "pflist_red1_ipv6", + "direction": "out", + } + ] + } + } + } + } + } + }, + }, + }, + { + "local_as": "500", + "vrf": "RED_B", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "red1-link2": { + "prefix_lists": [ + { + "name": "pflist_red1_ipv4", + "direction": "out", + } + ] + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "red1-link2": { + "prefix_lists": [ + { + "name": "pflist_red1_ipv6", + "direction": "out", + } + ] + } + } + } + } + } + }, + }, + }, + ] + }, + "blue1": { + "bgp": [ + { + "local_as": "800", + "vrf": "BLUE_A", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "blue1-link1": { + "prefix_lists": [ + { + "name": "pflist_blue1_ipv4", + "direction": "out", + } + ] + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "blue1-link1": { + "prefix_lists": [ + { + "name": "pflist_blue1_ipv6", + "direction": "out", + } + ] + } + } + } + } + } + }, + }, + }, + { + "local_as": "800", + "vrf": "BLUE_B", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "blue1-link2": { + "prefix_lists": [ + { + "name": "pflist_blue1_ipv4", + "direction": "out", + } + ] + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "blue1-link2": { + "prefix_lists": [ + { + "name": "pflist_blue1_ipv6", + "direction": "out", + } + ] + } + } + } + } + } + }, + }, + }, + ] + }, + } + + result = create_router_bgp(tgen, topo, input_dict_5) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step( + "Verify that within vrf instances, each BGP neighbor receives 1" + " prefixes in routing table and drops (x.x.x.2)." + ) + + for addr_type in ADDR_TYPES: + dut = "r1" + permitted_routes = { + "red1": { + "static_routes": [ + {"network": [NETWORK1_1[addr_type]], "vrf": "RED_A"}, + {"network": [NETWORK2_1[addr_type]], "vrf": "RED_B"}, + ] + } + } + + denied_routes = { + "red1": { + "static_routes": [ + {"network": [NETWORK1_2[addr_type]], "vrf": "RED_A"}, + {"network": [NETWORK2_2[addr_type]], "vrf": "RED_B"}, + ] + } + } + + result = verify_rib(tgen, addr_type, dut, permitted_routes) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + result = verify_rib(tgen, addr_type, dut, denied_routes, expected=False) + assert result is not True, "Testcase {} : Failed \n" + "{}:Expected behaviour: Routes are denied by prefix-list \nError {}".format( + tc_name, result + ) + + step( + "On router R1, configure prefix-lists to permit 2 " + "prefixes(x.x.x.1-2) and deny 2 prefix(x.x.x.3-4). Apply" + " these in inbound direction for each neighbour." + ) + + input_dict_6 = { + "r1": { + "bgp": [ + { + "local_as": "100", + "vrf": "RED_A", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "red1": { + "dest_link": { + "r1-link1": { + "prefix_lists": [ + { + "name": "pflist_r1_ipv4", + "direction": "in", + } + ] + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "red1": { + "dest_link": { + "r1-link1": { + "prefix_lists": [ + { + "name": "pflist_r1_ipv6", + "direction": "in", + } + ] + } + } + } + } + } + }, + }, + }, + { + "local_as": "100", + "vrf": "RED_B", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "red1": { + "dest_link": { + "r1-link2": { + "prefix_lists": [ + { + "name": "pflist_r1_ipv4", + "direction": "in", + } + ] + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "red1": { + "dest_link": { + "r1-link2": { + "prefix_lists": [ + { + "name": "pflist_r1_ipv6", + "direction": "in", + } + ] + } + } + } + } + } + }, + }, + }, + { + "local_as": "100", + "vrf": "BLUE_A", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "blue1": { + "dest_link": { + "r1-link1": { + "prefix_lists": [ + { + "name": "pflist_r1_ipv4", + "direction": "in", + } + ] + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "blue1": { + "dest_link": { + "r1-link1": { + "prefix_lists": [ + { + "name": "pflist_r1_ipv6", + "direction": "in", + } + ] + } + } + } + } + } + }, + }, + }, + { + "local_as": "100", + "vrf": "BLUE_B", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "blue1": { + "dest_link": { + "r1-link2": { + "prefix_lists": [ + { + "name": "pflist_r1_ipv4", + "direction": "in", + } + ] + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "blue1": { + "dest_link": { + "r1-link2": { + "prefix_lists": [ + { + "name": "pflist_r1_ipv6", + "direction": "in", + } + ] + } + } + } + } + } + }, + }, + }, + ] + } + } + + result = create_router_bgp(tgen, topo, input_dict_6) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step( + "Verify that within vrf instances, each BGP neighbor installs" + " only 1 prefix (x.x.x.1)." + ) + for addr_type in ADDR_TYPES: + dut = "r2" + permitted_routes = { + "red1": { + "static_routes": [{"network": [NETWORK1_1[addr_type]], "vrf": "RED_A"}] + } + } + + denied_routes = { + "red1": { + "static_routes": [{"network": [NETWORK2_1[addr_type]], "vrf": "RED_A"}] + } + } + + result = verify_rib(tgen, addr_type, dut, permitted_routes) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + result = verify_rib(tgen, addr_type, dut, denied_routes, expected=False) + assert ( + result is not True + ), "Testcase {} : Failed \nExpected behaviour: Routes are denied by prefix-list \nError {}".format( + tc_name, result + ) + + write_test_footer(tc_name) + + +def test_route_map_set_and_match_tag_p0(request): + """ + FUNC_16_1: + Configure a route-map on DUT to match traffic based various + match/set causes. + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + reset_config_on_routers(tgen) + + if tgen.routers_have_failure(): + check_router_status(tgen) + + step( + "Advertise unique BGP prefixes(IPv4+IPv6) from RED_1" + " in vrf instances(RED_A and RED_B)." + ) + + for addr_type in ADDR_TYPES: + input_dict_1 = { + "red1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "tag": 4001, + "vrf": "RED_A", + }, + { + "network": [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_B", + }, + ] + } + } + result = create_static_routes(tgen, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step( + "Advertise same set of BGP prefixes(IPv4+IPv6) from BLUE_1 and" + "BLUE_2 in vrf instances(BLUE_A and BLUE_B)" + ) + + for addr_type in ADDR_TYPES: + input_dict_2 = { + "blue1": { + "static_routes": [ + { + "network": [NETWORK3_1[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "tag": 4001, + "vrf": "BLUE_A", + }, + { + "network": [NETWORK3_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_A", + }, + { + "network": [NETWORK4_1[addr_type]] + [NETWORK4_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_B", + }, + ] + } + } + result = create_static_routes(tgen, input_dict_2) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step("Redistribute static..") + + input_dict_3 = {} + for dut in ["red1", "blue1"]: + temp = {dut: {"bgp": []}} + input_dict_3.update(temp) + + if "red" in dut: + VRFS = ["RED_A", "RED_B"] + AS_NUM = [500, 500] + elif "blue" in dut: + VRFS = ["BLUE_A", "BLUE_B"] + AS_NUM = [800, 800] + + for vrf, as_num in zip(VRFS, AS_NUM): + temp[dut]["bgp"].append( + { + "local_as": as_num, + "vrf": vrf, + "address_family": { + "ipv4": { + "unicast": {"redistribute": [{"redist_type": "static"}]} + }, + "ipv6": { + "unicast": {"redistribute": [{"redist_type": "static"}]} + }, + }, + } + ) + + result = create_router_bgp(tgen, topo, input_dict_3) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Configure a route-maps to match tag") + + for addr_type in ADDR_TYPES: + input_dict_4 = { + "red1": { + "route_maps": { + "rmap1_{}".format(addr_type): [ + {"action": "permit", "match": {addr_type: {"tag": "4001"}}} + ] + } + } + } + result = create_route_maps(tgen, input_dict_4) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step("Configure neighbor for route map") + input_dict_4 = { + "red1": { + "bgp": [ + { + "local_as": "500", + "vrf": "RED_A", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "red1-link1": { + "route_maps": [ + { + "name": "rmap1_ipv4", + "direction": "out", + } + ] + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "red1-link1": { + "route_maps": [ + { + "name": "rmap1_ipv6", + "direction": "out", + } + ] + } + } + } + } + } + }, + }, + }, + { + "local_as": "500", + "vrf": "RED_B", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "red1-link2": { + "route_maps": [ + { + "name": "rmap1_ipv4", + "direction": "out", + } + ] + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "red1-link2": { + "route_maps": [ + { + "name": "rmap1_ipv6", + "direction": "out", + } + ] + } + } + } + } + } + }, + }, + }, + ] + } + } + + result = create_router_bgp(tgen, topo, input_dict_4) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step( + "Verify that within vrf instances, BGP best path selection" + " algorithm remains intact and doesn't affect any other VRFs" + " routing decision." + ) + + dut = "r1" + for addr_type in ADDR_TYPES: + input_dict_1 = { + "red1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "tag": 4001, + "vrf": "RED_A", + } + ] + } + } + + result = verify_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + for addr_type in ADDR_TYPES: + input_dict_2 = { + "red1": { + "static_routes": [ + { + "network": [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_B", + }, + ] + } + } + + result = verify_rib(tgen, addr_type, dut, input_dict_2, expected=False) + assert ( + result is not True + ), "Testcase {} : Failed \n Expected Behavior: Routes are denied \nError {}".format( + tc_name, result + ) + + write_test_footer(tc_name) + + +def test_route_map_set_and_match_metric_p0(request): + """ + FUNC_16_2: + Configure a route-map on DUT to match traffic based various + match/set causes. + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + reset_config_on_routers(tgen) + + if tgen.routers_have_failure(): + check_router_status(tgen) + + step( + "Advertise unique BGP prefixes(IPv4+IPv6) from RED_1" + " in vrf instances(RED_A and RED_B)." + ) + + for addr_type in ADDR_TYPES: + input_dict_1 = { + "red1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_B", + }, + ] + } + } + result = create_static_routes(tgen, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step( + "Advertise same set of BGP prefixes(IPv4+IPv6) from BLUE_1 and" + "BLUE_2 in vrf instances(BLUE_A and BLUE_B)" + ) + + for addr_type in ADDR_TYPES: + input_dict_2 = { + "blue1": { + "static_routes": [ + { + "network": [NETWORK3_1[addr_type]] + [NETWORK3_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_A", + }, + { + "network": [NETWORK4_1[addr_type]] + [NETWORK4_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_B", + }, + ] + } + } + result = create_static_routes(tgen, input_dict_2) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step("Redistribute static..") + + input_dict_3 = { + "red1": { + "bgp": [ + { + "local_as": "500", + "vrf": "RED_A", + "address_family": { + "ipv4": { + "unicast": { + "redistribute": [ + { + "redist_type": "static", + "attribute": {"metric": 123}, + } + ] + } + }, + "ipv6": { + "unicast": { + "redistribute": [ + { + "redist_type": "static", + "attribute": {"metric": 123}, + } + ] + } + }, + }, + }, + { + "local_as": "500", + "vrf": "RED_B", + "address_family": { + "ipv4": { + "unicast": {"redistribute": [{"redist_type": "static"}]} + }, + "ipv6": { + "unicast": {"redistribute": [{"redist_type": "static"}]} + }, + }, + }, + ] + }, + "blue1": { + "bgp": [ + { + "local_as": "800", + "vrf": "BLUE_A", + "address_family": { + "ipv4": { + "unicast": { + "redistribute": [ + { + "redist_type": "static", + "attribute": {"metric": 123}, + } + ] + } + }, + "ipv6": { + "unicast": { + "redistribute": [ + { + "redist_type": "static", + "attribute": {"metric": 123}, + } + ] + } + }, + }, + }, + { + "local_as": "800", + "vrf": "BLUE_B", + "address_family": { + "ipv4": { + "unicast": {"redistribute": [{"redist_type": "static"}]} + }, + "ipv6": { + "unicast": {"redistribute": [{"redist_type": "static"}]} + }, + }, + }, + ] + }, + } + + result = create_router_bgp(tgen, topo, input_dict_3) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Configure a route-maps to match tag") + + for addr_type in ADDR_TYPES: + input_dict_4 = { + "r1": { + "route_maps": { + "rmap1_{}".format(addr_type): [ + {"action": "permit", "match": {"metric": 123}} + ] + } + } + } + result = create_route_maps(tgen, input_dict_4) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step("Configure neighbor for route map") + input_dict_4 = { + "r1": { + "bgp": [ + { + "local_as": "100", + "vrf": "RED_A", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "red1": { + "dest_link": { + "r1-link1": { + "route_maps": [ + { + "name": "rmap1_ipv4", + "direction": "in", + } + ] + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "red1": { + "dest_link": { + "r1-link1": { + "route_maps": [ + { + "name": "rmap1_ipv6", + "direction": "in", + } + ] + } + } + } + } + } + }, + }, + }, + { + "local_as": "100", + "vrf": "RED_B", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "red1": { + "dest_link": { + "r1-link2": { + "route_maps": [ + { + "name": "rmap1_ipv4", + "direction": "in", + } + ] + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "red1": { + "dest_link": { + "r1-link2": { + "route_maps": [ + { + "name": "rmap1_ipv6", + "direction": "in", + } + ] + } + } + } + } + } + }, + }, + }, + { + "local_as": "100", + "vrf": "BLUE_A", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "blue1": { + "dest_link": { + "r1-link1": { + "route_maps": [ + { + "name": "rmap1_ipv4", + "direction": "in", + } + ] + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "blue1": { + "dest_link": { + "r1-link1": { + "route_maps": [ + { + "name": "rmap1_ipv6", + "direction": "in", + } + ] + } + } + } + } + } + }, + }, + }, + { + "local_as": "100", + "vrf": "BLUE_B", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "blue1": { + "dest_link": { + "r1-link2": { + "route_maps": [ + { + "name": "rmap1_ipv4", + "direction": "in", + } + ] + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "blue1": { + "dest_link": { + "r1-link2": { + "route_maps": [ + { + "name": "rmap1_ipv6", + "direction": "in", + } + ] + } + } + } + } + } + }, + }, + }, + ] + } + } + + result = create_router_bgp(tgen, topo, input_dict_4) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step( + "Verify that within vrf instances, BGP best path selection" + " algorithm remains intact and doesn't affect any other VRFs" + " routing decision." + ) + + dut = "r1" + for addr_type in ADDR_TYPES: + input_dict_1 = { + "red1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_A", + } + ] + } + } + + result = verify_rib(tgen, addr_type, dut, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error {}".format( + tc_name, result + ) + + for addr_type in ADDR_TYPES: + input_dict_2 = { + "red1": { + "static_routes": [ + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_B", + } + ] + } + } + + result = verify_rib(tgen, addr_type, dut, input_dict_2, expected=False) + assert ( + result is not True + ), "Testcase {} : Failed \n Expected Behavior: Routes are denied \nError {}".format( + tc_name, result + ) + + write_test_footer(tc_name) + + +def test_route_map_set_and_match_community_p0(request): + """ + FUNC_16_3: + Configure a route-map on DUT to match traffic based various + match/set causes. + """ + + tgen = get_topogen() + tc_name = request.node.name + write_test_header(tc_name) + reset_config_on_routers(tgen) + + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + step( + "Advertise unique BGP prefixes(IPv4+IPv6) from RED_1" + " in vrf instances(RED_A and RED_B)." + ) + + for addr_type in ADDR_TYPES: + input_dict_1 = { + "red1": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_A", + }, + { + "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "RED_B", + }, + ] + } + } + result = create_static_routes(tgen, input_dict_1) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step( + "Advertise same set of BGP prefixes(IPv4+IPv6) from BLUE_1 and" + "BLUE_2 in vrf instances(BLUE_A and BLUE_B)" + ) + + for addr_type in ADDR_TYPES: + input_dict_2 = { + "blue1": { + "static_routes": [ + { + "network": [NETWORK3_1[addr_type]] + [NETWORK3_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_A", + }, + { + "network": [NETWORK4_1[addr_type]] + [NETWORK4_2[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "vrf": "BLUE_B", + }, + ] + } + } + result = create_static_routes(tgen, input_dict_2) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step("Redistribute static..") + + input_dict_3 = {} + for dut in ["red1", "blue1"]: + temp = {dut: {"bgp": []}} + input_dict_3.update(temp) + + if "red" in dut: + VRFS = ["RED_A", "RED_B"] + AS_NUM = [500, 500] + elif "blue" in dut: + VRFS = ["BLUE_A", "BLUE_B"] + AS_NUM = [800, 800] + + for vrf, as_num in zip(VRFS, AS_NUM): + temp[dut]["bgp"].append( + { + "local_as": as_num, + "vrf": vrf, + "address_family": { + "ipv4": { + "unicast": {"redistribute": [{"redist_type": "static"}]} + }, + "ipv6": { + "unicast": {"redistribute": [{"redist_type": "static"}]} + }, + }, + } + ) + + result = create_router_bgp(tgen, topo, input_dict_3) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Create community-list") + + for addr_type in ADDR_TYPES: + input_dict_4 = { + "r1": { + "bgp_community_lists": [ + { + "community_type": "standard", + "action": "permit", + "name": "rmap_lcomm_{}".format(addr_type), + "value": "1:1 1:2 1:3 1:4 1:5", + } + ] + } + } + result = create_bgp_community_lists(tgen, input_dict_4) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step("Configure a route-maps to match tag") + + step("Create route-maps in red1 and r1") + + for addr_type in ADDR_TYPES: + input_dict_4 = { + "red1": { + "route_maps": { + "rmap_red1_{}".format(addr_type): [ + { + "action": "permit", + "set": {"community": {"num": "1:1 1:2 1:3 1:4 1:5"}}, + } + ] + } + }, + "r1": { + "route_maps": { + "rmap1_{}".format(addr_type): [ + { + "action": "permit", + "match": { + "community_list": {"id": "rmap_lcomm_" + addr_type} + }, + } + ] + } + }, + } + result = create_route_maps(tgen, input_dict_4) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step("Configure neighbor for route map") + input_dict_4 = { + "red1": { + "bgp": [ + { + "local_as": "500", + "vrf": "RED_A", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "red1-link1": { + "route_maps": [ + { + "name": "rmap_red1_ipv4", + "direction": "out", + } + ] + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "red1-link1": { + "route_maps": [ + { + "name": "rmap_red1_ipv6", + "direction": "out", + } + ] + } + } + } + } + } + }, + }, + }, + { + "local_as": "500", + "vrf": "RED_B", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "red1-link2": { + "route_maps": [ + { + "name": "rmap_red1_ipv4", + "direction": "out", + } + ] + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r1": { + "dest_link": { + "red1-link2": { + "route_maps": [ + { + "name": "rmap_red1_ipv6", + "direction": "out", + } + ] + } + } + } + } + } + }, + }, + }, + ] + }, + "r1": { + "bgp": [ + { + "local_as": "100", + "vrf": "RED_A", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "red1": { + "dest_link": { + "r1-link1": { + "route_maps": [ + { + "name": "rmap1_ipv4", + "direction": "in", + } + ] + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "red1": { + "dest_link": { + "r1-link1": { + "route_maps": [ + { + "name": "rmap1_ipv6", + "direction": "in", + } + ] + } + } + } + } + } + }, + }, + }, + { + "local_as": "100", + "vrf": "RED_B", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "red1": { + "dest_link": { + "r1-link2": { + "route_maps": [ + { + "name": "rmap1_ipv4", + "direction": "in", + } + ] + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "red1": { + "dest_link": { + "r1-link2": { + "route_maps": [ + { + "name": "rmap1_ipv6", + "direction": "in", + } + ] + } + } + } + } + } + }, + }, + }, + { + "local_as": "100", + "vrf": "BLUE_A", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "blue1": { + "dest_link": { + "r1-link1": { + "route_maps": [ + { + "name": "rmap1_ipv4", + "direction": "in", + } + ] + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "blue1": { + "dest_link": { + "r1-link1": { + "route_maps": [ + { + "name": "rmap1_ipv6", + "direction": "in", + } + ] + } + } + } + } + } + }, + }, + }, + { + "local_as": "100", + "vrf": "BLUE_B", + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "blue1": { + "dest_link": { + "r1-link2": { + "route_maps": [ + { + "name": "rmap1_ipv4", + "direction": "in", + } + ] + } + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "blue1": { + "dest_link": { + "r1-link2": { + "route_maps": [ + { + "name": "rmap1_ipv6", + "direction": "in", + } + ] + } + } + } + } + } + }, + }, + }, + ] + }, + } + + result = create_router_bgp(tgen, topo, input_dict_4) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step( + "All the prefixes advertised from RED_1 and BLUE_1 should carry" + " attributes set by outbound route-maps within specific vrfs. " + "Router R1 should be able to match and permit/deny those " + "prefixes based on received attributes. Please use below " + "commands to verify." + ) + + input_dict = { + "community": "1:1 1:2 1:3 1:4 1:5", + } + + for addr_type in ADDR_TYPES: + vrf = "RED_A" + routes = [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]] + result = verify_bgp_community(tgen, addr_type, "r1", routes, input_dict, vrf) + assert result is True, "Test case {} : Failed \n Error: {}".format( + tc_name, result + ) + + for addr_type in ADDR_TYPES: + vrf = "RED_B" + routes = [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]] + result = verify_bgp_community(tgen, addr_type, "r1", routes, input_dict, vrf) + assert result is True, "Test case {} : Failed \n Error: {}".format( + tc_name, result + ) + + write_test_footer(tc_name) + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) |