summaryrefslogtreecommitdiffstats
path: root/tests/topotests/bgp_always_compare_med
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-09 13:16:35 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-09 13:16:35 +0000
commite2bbf175a2184bd76f6c54ccf8456babeb1a46fc (patch)
treef0b76550d6e6f500ada964a3a4ee933a45e5a6f1 /tests/topotests/bgp_always_compare_med
parentInitial commit. (diff)
downloadfrr-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_always_compare_med')
-rw-r--r--tests/topotests/bgp_always_compare_med/bgp_always_compare_med_topo1.json152
-rw-r--r--tests/topotests/bgp_always_compare_med/test_bgp_always_compare_med_topo1.py1118
2 files changed, 1270 insertions, 0 deletions
diff --git a/tests/topotests/bgp_always_compare_med/bgp_always_compare_med_topo1.json b/tests/topotests/bgp_always_compare_med/bgp_always_compare_med_topo1.json
new file mode 100644
index 0000000..4156c6d
--- /dev/null
+++ b/tests/topotests/bgp_always_compare_med/bgp_always_compare_med_topo1.json
@@ -0,0 +1,152 @@
+{
+ "address_types": ["ipv4", "ipv6"],
+ "ipv4base": "192.168.0.0",
+ "ipv4mask": 30,
+ "ipv6base": "fd00::",
+ "ipv6mask": 64,
+ "link_ip_start":{"ipv4":"192.168.0.0", "v4mask":24, "ipv6":"fd00::", "v6mask":64},
+ "lo_prefix":{"ipv4":"1.0.", "v4mask":32, "ipv6":"2001:DB8:F::", "v6mask":128},
+ "routers": {
+ "r1": {
+ "links": {
+ "lo": {"ipv4": "auto", "ipv6": "auto", "type": "loopback"},
+ "r2": {"ipv4": "auto", "ipv6": "auto"},
+ "r3": {"ipv4": "auto", "ipv6": "auto"}
+ },
+ "bgp": {
+ "local_as": "100",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {"dest_link": {"r1": {}}},
+ "r3": {"dest_link": {"r1": {}}}
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {"dest_link": {"r1": {
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }}},
+ "r3": {"dest_link": {"r1": {
+ "route_maps": [{
+ "name": "rmap_global",
+ "direction": "in"
+ }]
+ }}}
+ }
+ }
+ }
+ }
+ },
+ "route_maps": {
+ "rmap_global": [{
+ "action": "permit",
+ "set": {
+ "ipv6": {
+ "nexthop": "prefer-global"
+ }
+ }
+ }]
+ },
+ "static_routes":[
+ {
+ "network":"192.168.20.1/32",
+ "next_hop":"Null0"
+ },
+ {
+ "network":"192:168:20::1/128",
+ "next_hop":"Null0"
+ }]
+ },
+ "r2": {
+ "links": {
+ "lo": {"ipv4": "auto", "ipv6": "auto", "type": "loopback"},
+ "r1": {"ipv4": "auto", "ipv6": "auto"},
+ "r4": {"ipv4": "auto", "ipv6": "auto"}
+ },
+ "bgp": {
+ "local_as": "200",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {"dest_link": {"r2": {}}},
+ "r4": {"dest_link": {"r2": {}}}
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {"dest_link": {"r2": {}}},
+ "r4": {"dest_link": {"r2": {}}}
+ }
+ }
+ }
+ }
+ }
+ },
+ "r3": {
+ "links": {
+ "lo": {"ipv4": "auto", "ipv6": "auto", "type": "loopback"},
+ "r1": {"ipv4": "auto", "ipv6": "auto"},
+ "r4": {"ipv4": "auto", "ipv6": "auto"}
+ },
+ "bgp": {
+ "local_as": "300",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {"dest_link": {"r3": {}}},
+ "r4": {"dest_link": {"r3": {}}}
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {"dest_link": {"r3": {}}},
+ "r4": {"dest_link": {"r3": {}}}
+ }
+ }
+ }
+ }
+ }
+ },
+ "r4": {
+ "links": {
+ "lo": {"ipv4": "auto", "ipv6": "auto", "type": "loopback"},
+ "r2": {"ipv4": "auto", "ipv6": "auto"},
+ "r3": {"ipv4": "auto", "ipv6": "auto"}
+ },
+ "bgp": {
+ "local_as": "400",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {"dest_link": {"r4": {}}},
+ "r3": {"dest_link": {"r4": {}}}
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {"dest_link": {"r4": {}}},
+ "r3": {"dest_link": {"r4": {}}}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tests/topotests/bgp_always_compare_med/test_bgp_always_compare_med_topo1.py b/tests/topotests/bgp_always_compare_med/test_bgp_always_compare_med_topo1.py
new file mode 100644
index 0000000..fb72f43
--- /dev/null
+++ b/tests/topotests/bgp_always_compare_med/test_bgp_always_compare_med_topo1.py
@@ -0,0 +1,1118 @@
+#!/usr/bin/env python3
+#
+# SPDX-License-Identifier: ISC
+#
+# Copyright (c) 2023 by VMware, Inc. ("VMware")
+#
+#
+################################################################################
+# Following tests are performed to validate BGP always compare MED functionality
+################################################################################
+"""
+1. Verify the BGP always compare MED functionality in between eBGP Peers
+2. Verify the BGP always compare MED functionality in between eBGP Peers with by changing different AD values
+3. Verify the BGP always compare MED functionality in between eBGP Peers by changing MED values in middle routers
+4. Verify that BGP Always compare MED functionality by restarting BGP, Zebra and FRR services and clear BGP and
+ shutdown BGP neighbor
+5. Verify BGP always compare MED functionality by performing shut/noshut on the interfaces in between BGP neighbors
+"""
+
+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/"))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib.topogen import Topogen, get_topogen
+
+from lib.common_config import (
+ start_topology,
+ write_test_header,
+ create_static_routes,
+ write_test_footer,
+ reset_config_on_routers,
+ verify_rib,
+ step,
+ check_address_types,
+ check_router_status,
+ create_static_routes,
+ create_prefix_lists,
+ create_route_maps,
+ kill_router_daemons,
+ shutdown_bringup_interface,
+ stop_router,
+ start_router,
+ delete_route_maps,
+)
+
+from lib.topolog import logger
+from lib.bgp import verify_bgp_convergence, verify_bgp_rib, create_router_bgp, clear_bgp
+from lib.topojson import build_config_from_json
+
+pytestmark = [pytest.mark.bgpd, pytest.mark.staticd]
+
+# Reading the data from JSON File for topology creation
+topo = None
+
+# Global variables
+ADDR_TYPES = check_address_types()
+NETWORK1_1 = {"ipv4": "192.168.20.1/32", "ipv6": "192:168:20::1/128"}
+NETWORK1_2 = {"ipv4": "192.168.30.1/32", "ipv6": "192:168:30::1/128"}
+NETWORK1_3 = {"ipv4": "192.168.40.1/32", "ipv6": "192:168:40::1/128"}
+NEXT_HOP_IP = {"ipv4": "Null0", "ipv6": "Null0"}
+
+
+def setup_module(mod):
+ """
+ Sets up the pytest environment
+
+ * `mod`: module name
+ """
+
+ 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_always_compare_med_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 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)
+
+
+##########################################################################################################
+#
+# Local API
+#
+##########################################################################################################
+
+
+def initial_configuration(tgen, tc_name):
+ """
+ API to do initial set of configuration
+ """
+
+ step(
+ "Configure IPv4 and IPv6, eBGP neighbors between R1,R2 and R3 routers as per base config"
+ )
+
+ step("Configure static routes in R4")
+ for addr_type in ADDR_TYPES:
+ input_static_r4 = {
+ "r4": {
+ "static_routes": [
+ {
+ "network": NETWORK1_1[addr_type],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ }
+ ]
+ }
+ }
+
+ logger.info("Configure static routes")
+ result = create_static_routes(tgen, input_static_r4)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Configure redistribute static in R4")
+ input_static_redist_r4 = {
+ "r4": {
+ "bgp": {
+ "address_family": {
+ addr_type: {
+ "unicast": {"redistribute": [{"redist_type": "static"}]}
+ }
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_static_redist_r4)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ # Create prefix list
+ input_dict_23 = {
+ "r2": {
+ "prefix_lists": {
+ addr_type: {
+ "pf_ls_r2_{}".format(addr_type): [
+ {"network": NETWORK1_1[addr_type], "action": "permit"}
+ ]
+ }
+ }
+ },
+ "r3": {
+ "prefix_lists": {
+ "ipv4": {
+ "pf_ls_r3_{}".format(addr_type): [
+ {"network": NETWORK1_1[addr_type], "action": "permit"}
+ ]
+ }
+ }
+ },
+ }
+ result = create_prefix_lists(tgen, input_dict_23)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ # Create route map
+ input_dict_23 = {
+ "r2": {
+ "route_maps": {
+ "RMAP_MED_R2": [
+ {
+ "action": "permit",
+ "match": {
+ addr_type: {
+ "prefix_lists": "pf_ls_r2_{}".format(addr_type)
+ }
+ },
+ "set": {"med": 300},
+ }
+ ]
+ }
+ },
+ "r3": {
+ "route_maps": {
+ "RMAP_MED_R3": [
+ {
+ "action": "permit",
+ "match": {
+ addr_type: {
+ "prefix_lists": "pf_ls_r3_{}".format(addr_type)
+ }
+ },
+ "set": {"med": 200},
+ }
+ ]
+ }
+ },
+ }
+ result = create_route_maps(tgen, input_dict_23)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ input_dict_r2_r3 = {
+ "r2": {
+ "bgp": {
+ "address_family": {
+ addr_type: {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2": {
+ "route_maps": [
+ {
+ "name": "RMAP_MED_R2",
+ "direction": "out",
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "r3": {
+ "bgp": {
+ "address_family": {
+ addr_type: {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [
+ {
+ "name": "RMAP_MED_R3",
+ "direction": "out",
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ }
+ result = create_router_bgp(tgen, topo, input_dict_r2_r3)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+
+##########################################################################################################
+#
+# Testcases
+#
+##########################################################################################################
+
+
+def test_verify_bgp_always_compare_med_functionality_bw_eBGP_peers_p0(request):
+ """
+ Verify the BGP always compare MED functionality in between eBGP Peers
+ """
+
+ # test case name
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ check_router_status(tgen)
+ reset_config_on_routers(tgen)
+ initial_configuration(tgen, tc_name)
+
+ step(
+ "Configure IPv4 and IPv6, eBGP neighbors between R1,R2 and R3 routers as per base config"
+ )
+ step(
+ "Verify that IPv4 and IPv6 eBGP neighbors are configured in between routers by following "
+ "commands and verify that best path chosen by lowest MED value"
+ )
+
+ result = verify_bgp_convergence(tgen, topo)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ input_static_r1 = {
+ "r1": {"static_routes": [{"network": NETWORK1_1[addr_type]}]}
+ }
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_static_r1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_static_r1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Configure 'multi-path as-path relax' command at R1.")
+ configure_bgp = {
+ "r1": {"bgp": {"local_as": "100", "bestpath": {"aspath": "multipath-relax"}}}
+ }
+ result = create_router_bgp(tgen, topo, configure_bgp)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ step(
+ "Verify that after applying 'multi-path as-path relax' command, "
+ "its also chooses lowest MED to reach destination."
+ )
+ for addr_type in ADDR_TYPES:
+ input_static_r1 = {
+ "r1": {"static_routes": [{"network": NETWORK1_1[addr_type]}]}
+ }
+ nh1 = topo["routers"]["r2"]["links"]["r1"][addr_type].split("/")[0]
+ nh2 = topo["routers"]["r3"]["links"]["r1"][addr_type].split("/")[0]
+
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_static_r1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_static_r1, next_hop=[nh1, nh2])
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Configure 'bgp always-compare-med' command at R1.")
+ input_dict_r1 = {"r1": {"bgp": {"local_as": "100", "bgp_always_compare_med": True}}}
+ result = create_router_bgp(tgen, topo, input_dict_r1)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step(
+ "Verify that after applying 'bgp always-compare-med', its chooses lowest MED value path"
+ )
+ for addr_type in ADDR_TYPES:
+ input_static_r1 = {
+ "r1": {"static_routes": [{"network": NETWORK1_1[addr_type]}]}
+ }
+ nh = topo["routers"]["r3"]["links"]["r1"][addr_type].split("/")[0]
+
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_static_r1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_static_r1, next_hop=nh)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Remove 'bgp always-compare-med' command at R1.")
+ input_dict_r1 = {
+ "r1": {"bgp": {"local_as": "100", "bgp_always_compare_med": False}}
+ }
+ result = create_router_bgp(tgen, topo, input_dict_r1)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("Verify that 'bgp always-compare-med' command is removed")
+ for addr_type in ADDR_TYPES:
+ input_static_r1 = {
+ "r1": {"static_routes": [{"network": NETWORK1_1[addr_type]}]}
+ }
+ nh1 = topo["routers"]["r2"]["links"]["r1"][addr_type].split("/")[0]
+ nh2 = topo["routers"]["r3"]["links"]["r1"][addr_type].split("/")[0]
+
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_static_r1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_static_r1, next_hop=[nh1, nh2])
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Remove 'multi-path as-path relax' command at R1")
+ configure_bgp = {
+ "r1": {
+ "bgp": {
+ "local_as": "100",
+ "bestpath": {"aspath": "multipath-relax", "delete": True},
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, configure_bgp)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ step("Verify route selection after removing 'multi-path as-path relax' command")
+ for addr_type in ADDR_TYPES:
+ input_static_r1 = {
+ "r1": {"static_routes": [{"network": NETWORK1_1[addr_type]}]}
+ }
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_static_r1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_static_r1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ write_test_footer(tc_name)
+
+
+def test_verify_bgp_always_compare_med_functionality_bw_eBGP_peers_by_changing_AD_values_p0(
+ request,
+):
+ """
+ Verify the BGP always compare MED functionality in between eBGP Peers with by changing different AD values.
+ """
+
+ # test case name
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ check_router_status(tgen)
+ reset_config_on_routers(tgen)
+ initial_configuration(tgen, tc_name)
+
+ step(
+ "Configure IPv4 and IPv6, eBGP neighbors between R1,R2 and R3 routers as per base config"
+ )
+ step(
+ "Verify that IPv4 and IPv6 eBGP neighbors are configured in between routers by following "
+ "commands and verify that best path chosen by lowest MED value"
+ )
+
+ result = verify_bgp_convergence(tgen, topo)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ input_static_r1 = {
+ "r1": {"static_routes": [{"network": NETWORK1_1[addr_type]}]}
+ }
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_static_r1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_static_r1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Configure 'bgp always-compare-med' command at R1.")
+ input_dict_r1 = {"r1": {"bgp": {"local_as": "100", "bgp_always_compare_med": True}}}
+ result = create_router_bgp(tgen, topo, input_dict_r1)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step(
+ "Verify that after applying 'bgp always-compare-med', its chooses lowest MED value path"
+ )
+ for addr_type in ADDR_TYPES:
+ input_static_r1 = {
+ "r1": {"static_routes": [{"network": NETWORK1_1[addr_type]}]}
+ }
+ nh = topo["routers"]["r2"]["links"]["r1"][addr_type].split("/")[0]
+
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_static_r1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_static_r1, next_hop=nh)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Configure AD value=100 at R2 and AD value=200 at R3 towards R1")
+ input_dict_1 = {
+ "r2": {
+ "bgp": {
+ "local_as": 200,
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "distance": {"ebgp": 100, "ibgp": 100, "local": 100}
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "distance": {"ebgp": 100, "ibgp": 100, "local": 100}
+ }
+ },
+ },
+ }
+ },
+ "r3": {
+ "bgp": {
+ "local_as": 300,
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "distance": {"ebgp": 200, "ibgp": 200, "local": 200}
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "distance": {"ebgp": 200, "ibgp": 200, "local": 200}
+ }
+ },
+ },
+ }
+ },
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ step(
+ "Verify that inspite of AD values, always lowest MED value is getting "
+ "selected at destination router R1"
+ )
+ for addr_type in ADDR_TYPES:
+ input_static_r1 = {
+ "r1": {"static_routes": [{"network": NETWORK1_1[addr_type]}]}
+ }
+ nh = topo["routers"]["r2"]["links"]["r1"][addr_type].split("/")[0]
+
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_static_r1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_static_r1, next_hop=nh)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ write_test_footer(tc_name)
+
+
+def test_verify_bgp_always_compare_med_functionality_bw_eBGP_peers_by_changing_MED_values_p1(
+ request,
+):
+ """
+ Verify the BGP always compare MED functionality in between eBGP Peers by changing MED values in middle routers
+ """
+
+ # test case name
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ check_router_status(tgen)
+ reset_config_on_routers(tgen)
+ initial_configuration(tgen, tc_name)
+
+ step(
+ "Configure IPv4 and IPv6, eBGP neighbors between R1,R2 and R3 routers as per base config"
+ )
+ step(
+ "Verify that IPv4 and IPv6 eBGP neighbors are configured in between routers by following "
+ "commands and verify that best path chosen by lowest MED value"
+ )
+
+ result = verify_bgp_convergence(tgen, topo)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ input_static_r1 = {
+ "r1": {"static_routes": [{"network": NETWORK1_1[addr_type]}]}
+ }
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_static_r1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_static_r1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Configure 'multi-path as-path relax' command at R1.")
+ configure_bgp = {
+ "r1": {"bgp": {"local_as": "100", "bestpath": {"aspath": "multipath-relax"}}}
+ }
+ result = create_router_bgp(tgen, topo, configure_bgp)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ step(
+ "Verify that after applying 'multi-path as-path relax' command, "
+ "its also chooses lowest MED to reach destination."
+ )
+ for addr_type in ADDR_TYPES:
+ input_static_r1 = {
+ "r1": {"static_routes": [{"network": NETWORK1_1[addr_type]}]}
+ }
+ nh1 = topo["routers"]["r2"]["links"]["r1"][addr_type].split("/")[0]
+ nh2 = topo["routers"]["r3"]["links"]["r1"][addr_type].split("/")[0]
+
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_static_r1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_static_r1, next_hop=[nh1, nh2])
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Configure 'bgp always-compare-med' command at R1.")
+ input_dict_r1 = {"r1": {"bgp": {"local_as": "100", "bgp_always_compare_med": True}}}
+ result = create_router_bgp(tgen, topo, input_dict_r1)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step(
+ "Verify that after applying 'bgp always-compare-med', its chooses lowest MED value path"
+ )
+ for addr_type in ADDR_TYPES:
+ input_static_r1 = {
+ "r1": {"static_routes": [{"network": NETWORK1_1[addr_type]}]}
+ }
+ nh = topo["routers"]["r3"]["links"]["r1"][addr_type].split("/")[0]
+
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_static_r1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_static_r1, next_hop=nh)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Change the MED value 150 in R2 router.")
+ input_dict = {"r2": {"route_maps": ["RMAP_MED_R2"]}}
+ result = delete_route_maps(tgen, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ input_dict_2 = {
+ "r2": {
+ "route_maps": {
+ "RMAP_MED_R2": [
+ {
+ "action": "permit",
+ "match": {
+ addr_type: {
+ "prefix_lists": "pf_ls_r2_{}".format(addr_type)
+ }
+ },
+ "set": {"med": 150},
+ }
+ ]
+ }
+ }
+ }
+ result = create_route_maps(tgen, input_dict_2)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Verify that after changing MED, its chooses lowest MED value path")
+ for addr_type in ADDR_TYPES:
+ input_static_r1 = {
+ "r1": {"static_routes": [{"network": NETWORK1_1[addr_type]}]}
+ }
+ nh = topo["routers"]["r2"]["links"]["r1"][addr_type].split("/")[0]
+
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_static_r1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_static_r1, next_hop=nh)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Change the MED value 100 in R3 router.")
+ input_dict = {"r3": {"route_maps": ["RMAP_MED_R3"]}}
+ result = delete_route_maps(tgen, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ input_dict_3 = {
+ "r3": {
+ "route_maps": {
+ "RMAP_MED_R3": [
+ {
+ "action": "permit",
+ "match": {
+ addr_type: {
+ "prefix_lists": "pf_ls_r3_{}".format(addr_type)
+ }
+ },
+ "set": {"med": 100},
+ }
+ ]
+ }
+ }
+ }
+ result = create_route_maps(tgen, input_dict_3)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Verify that after changing MED, its chooses lowest MED value path")
+ for addr_type in ADDR_TYPES:
+ input_static_r1 = {
+ "r1": {"static_routes": [{"network": NETWORK1_1[addr_type]}]}
+ }
+ nh = topo["routers"]["r3"]["links"]["r1"][addr_type].split("/")[0]
+
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_static_r1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_static_r1, next_hop=nh)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ write_test_footer(tc_name)
+
+
+def test_verify_bgp_always_compare_med_functionality_by_restarting_daemons_clear_bgp_shut_neighbors_p1(
+ request,
+):
+ """
+ Verify that BGP Always compare MED functionality by restarting BGP, Zebra and FRR services and clear BGP and shutdown BGP neighbor
+ """
+
+ # test case name
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ check_router_status(tgen)
+ reset_config_on_routers(tgen)
+ initial_configuration(tgen, tc_name)
+
+ step(
+ "Configure IPv4 and IPv6, eBGP neighbors between R1,R2 and R3 routers as per base config"
+ )
+ step(
+ "Verify that IPv4 and IPv6 eBGP neighbors are configured in between routers by following "
+ "commands and verify that best path chosen by lowest MED value"
+ )
+
+ result = verify_bgp_convergence(tgen, topo)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ input_static_r1 = {
+ "r1": {"static_routes": [{"network": NETWORK1_1[addr_type]}]}
+ }
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_static_r1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_static_r1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Configure 'multi-path as-path relax' command at R1.")
+ configure_bgp = {
+ "r1": {"bgp": {"local_as": "100", "bestpath": {"aspath": "multipath-relax"}}}
+ }
+ result = create_router_bgp(tgen, topo, configure_bgp)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ step(
+ "Verify that after applying 'multi-path as-path relax' command, "
+ "its also chooses lowest MED to reach destination."
+ )
+ for addr_type in ADDR_TYPES:
+ input_static_r1 = {
+ "r1": {"static_routes": [{"network": NETWORK1_1[addr_type]}]}
+ }
+ nh1 = topo["routers"]["r2"]["links"]["r1"][addr_type].split("/")[0]
+ nh2 = topo["routers"]["r3"]["links"]["r1"][addr_type].split("/")[0]
+
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_static_r1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_static_r1, next_hop=[nh1, nh2])
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Configure 'bgp always-compare-med' command at R1.")
+ input_dict_r1 = {"r1": {"bgp": {"local_as": "100", "bgp_always_compare_med": True}}}
+ result = create_router_bgp(tgen, topo, input_dict_r1)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step(
+ "Verify that after applying 'bgp always-compare-med', its chooses lowest MED value path"
+ )
+ for addr_type in ADDR_TYPES:
+ input_static_r1 = {
+ "r1": {"static_routes": [{"network": NETWORK1_1[addr_type]}]}
+ }
+ nh = topo["routers"]["r3"]["links"]["r1"][addr_type].split("/")[0]
+
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_static_r1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_static_r1, next_hop=nh)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Restart the BGPd/Zebra/FRR service on R1")
+ for daemon in ["bgpd", "zebra", "frr"]:
+ if daemon == "frr":
+ stop_router(tgen, "r1")
+ start_router(tgen, "r1")
+ else:
+ kill_router_daemons(tgen, "r1", daemon)
+
+ step(
+ "Verify after restarting dameons and frr services, its chooses lowest MED value path"
+ )
+ for addr_type in ADDR_TYPES:
+ input_static_r1 = {
+ "r1": {"static_routes": [{"network": NETWORK1_1[addr_type]}]}
+ }
+ nh = topo["routers"]["r3"]["links"]["r1"][addr_type].split("/")[0]
+
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_static_r1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_static_r1, next_hop=nh)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Clear bgp on R1")
+ clear_bgp(tgen, None, "r1")
+
+ step("Verify after clearing BGP, its chooses lowest MED value path")
+ for addr_type in ADDR_TYPES:
+ input_static_r1 = {
+ "r1": {"static_routes": [{"network": NETWORK1_1[addr_type]}]}
+ }
+ nh = topo["routers"]["r3"]["links"]["r1"][addr_type].split("/")[0]
+
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_static_r1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_static_r1, next_hop=nh)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Perform BGP neighborship shut/no shut")
+ for action, keyword in zip([True, False], ["shut", "noshut"]):
+ for addr_type in ADDR_TYPES:
+ input_dict = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ addr_type: {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {"r1": {"shutdown": action}}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Verify after {} BGP, its chooses lowest MED value path".format(keyword))
+ if action:
+ for addr_type in ADDR_TYPES:
+ input_static_r1 = {
+ "r1": {"static_routes": [{"network": NETWORK1_1[addr_type]}]}
+ }
+ nh = topo["routers"]["r2"]["links"]["r1"][addr_type].split("/")[0]
+
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_static_r1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_static_r1, next_hop=nh)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+ else:
+ for addr_type in ADDR_TYPES:
+ input_static_r1 = {
+ "r1": {"static_routes": [{"network": NETWORK1_1[addr_type]}]}
+ }
+ nh = topo["routers"]["r3"]["links"]["r1"][addr_type].split("/")[0]
+
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_static_r1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_static_r1, next_hop=nh)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ write_test_footer(tc_name)
+
+
+def test_verify_bgp_always_compare_med_functionality_by_shut_noshut_interfaces_bw_bgp_neighbors_p1(
+ request,
+):
+ """
+ Verify BGP always compare MED functionality by performing shut/noshut on the interfaces in between BGP neighbors
+ """
+
+ # test case name
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ check_router_status(tgen)
+ reset_config_on_routers(tgen)
+ initial_configuration(tgen, tc_name)
+
+ step(
+ "Configure IPv4 and IPv6, eBGP neighbors between R1,R2 and R3 routers as per base config"
+ )
+ step(
+ "Verify that IPv4 and IPv6 eBGP neighbors are configured in between routers by following "
+ "commands and verify that best path chosen by lowest MED value"
+ )
+
+ result = verify_bgp_convergence(tgen, topo)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ input_static_r1 = {
+ "r1": {"static_routes": [{"network": NETWORK1_1[addr_type]}]}
+ }
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_static_r1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_static_r1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Configure 'multi-path as-path relax' command at R1.")
+ configure_bgp = {
+ "r1": {"bgp": {"local_as": "100", "bestpath": {"aspath": "multipath-relax"}}}
+ }
+ result = create_router_bgp(tgen, topo, configure_bgp)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ step(
+ "Verify that after applying 'multi-path as-path relax' command, "
+ "its also chooses lowest MED to reach destination."
+ )
+ for addr_type in ADDR_TYPES:
+ input_static_r1 = {
+ "r1": {"static_routes": [{"network": NETWORK1_1[addr_type]}]}
+ }
+ nh1 = topo["routers"]["r2"]["links"]["r1"][addr_type].split("/")[0]
+ nh2 = topo["routers"]["r3"]["links"]["r1"][addr_type].split("/")[0]
+
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_static_r1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_static_r1, next_hop=[nh1, nh2])
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Configure 'bgp always-compare-med' command at R1.")
+ input_dict_r1 = {"r1": {"bgp": {"local_as": "100", "bgp_always_compare_med": True}}}
+ result = create_router_bgp(tgen, topo, input_dict_r1)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step(
+ "Verify that after applying 'bgp always-compare-med', its chooses lowest MED value path"
+ )
+ for addr_type in ADDR_TYPES:
+ input_static_r1 = {
+ "r1": {"static_routes": [{"network": NETWORK1_1[addr_type]}]}
+ }
+ nh = topo["routers"]["r3"]["links"]["r1"][addr_type].split("/")[0]
+
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_static_r1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_static_r1, next_hop=nh)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ for action, keyword in zip([False, True], ["Shut", "No Shut"]):
+ step(
+ "{} the interface on the link between R3 & R4 and R2 & R4 routers".format(
+ keyword
+ )
+ )
+ intf2_4 = topo["routers"]["r2"]["links"]["r4"]["interface"]
+ intf3_4 = topo["routers"]["r3"]["links"]["r4"]["interface"]
+ for dut, intf in zip(["r2", "r3"], [intf2_4, intf3_4]):
+ shutdown_bringup_interface(tgen, dut, intf, action)
+
+ for addr_type in ADDR_TYPES:
+ input_static_r1 = {
+ "r1": {"static_routes": [{"network": NETWORK1_1[addr_type]}]}
+ }
+ nh = topo["routers"]["r3"]["links"]["r1"][addr_type].split("/")[0]
+
+ if action:
+ result = verify_bgp_rib(tgen, addr_type, "r1", input_static_r1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(tgen, addr_type, "r1", input_static_r1, next_hop=nh)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ else:
+ result = verify_bgp_rib(
+ tgen, addr_type, "r1", input_static_r1, expected=False
+ )
+ assert (
+ result is not True
+ ), "Testcase {} :Failed \n Routes are still present in BGP table\n Error {}".format(
+ tc_name, result
+ )
+
+ result = verify_rib(
+ tgen, addr_type, "r1", input_static_r1, next_hop=nh, expected=False
+ )
+ assert (
+ result is not True
+ ), "Testcase {} :Failed \n Routes are still present in FIB \n Error {}".format(
+ tc_name, result
+ )
+
+ write_test_footer(tc_name)
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))