summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_bfd.c2
-rw-r--r--ospfd/ospf_nsm.c9
-rw-r--r--ospfd/ospf_te.c4
-rw-r--r--ospfd/ospf_vty.c2
-rw-r--r--tests/topotests/bgp_tcp_mss/bgp_vrf_tcp_mss.json222
-rw-r--r--tests/topotests/bgp_tcp_mss/test_bgp_vrf_tcp_mss.py766
-rw-r--r--tests/topotests/lib/bgp.py53
-rwxr-xr-xtools/frr-reload.py590
-rw-r--r--tools/valgrind.supp8
-rw-r--r--zebra/main.c2
-rw-r--r--zebra/table_manager.c6
-rw-r--r--zebra/zebra_router.c3
12 files changed, 1335 insertions, 332 deletions
diff --git a/bgpd/bgp_bfd.c b/bgpd/bgp_bfd.c
index f23e6b2e9b..ed54f42b0a 100644
--- a/bgpd/bgp_bfd.c
+++ b/bgpd/bgp_bfd.c
@@ -163,7 +163,7 @@ void bgp_peer_bfd_update_source(struct peer *p)
return;
/* Figure out the correct source to use. */
- if (CHECK_FLAG(p->flags, PEER_FLAG_UPDATE_SOURCE))
+ if (CHECK_FLAG(p->flags, PEER_FLAG_UPDATE_SOURCE) && p->update_source)
source = p->update_source;
else
source = p->su_local;
diff --git a/ospfd/ospf_nsm.c b/ospfd/ospf_nsm.c
index 865e7d37a8..e3cf1cfc8b 100644
--- a/ospfd/ospf_nsm.c
+++ b/ospfd/ospf_nsm.c
@@ -76,10 +76,11 @@ static int ospf_inactivity_timer(struct thread *thread)
*/
if (!OSPF_GR_IS_ACTIVE_HELPER(nbr))
OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_InactivityTimer);
- else if (IS_DEBUG_OSPF_GR) {
- zlog_debug(
- "%s, Acting as HELPER for this neighbour, So restart the dead timer",
- __func__);
+ else {
+ if (IS_DEBUG_OSPF_GR)
+ zlog_debug(
+ "%s, Acting as HELPER for this neighbour, So restart the dead timer",
+ __func__);
OSPF_NSM_TIMER_ON(nbr->t_inactivity, ospf_inactivity_timer,
nbr->v_inactivity);
}
diff --git a/ospfd/ospf_te.c b/ospfd/ospf_te.c
index 03fa572859..c5d1079e91 100644
--- a/ospfd/ospf_te.c
+++ b/ospfd/ospf_te.c
@@ -2171,7 +2171,7 @@ static int ospf_te_parse_te(struct ls_ted *ted, struct ospf_lsa *lsa)
if ((len == 0) || (ntohs(tlvh->type) != TE_TLV_LINK))
return 0;
- sum = 0;
+ sum = sizeof(struct tlv_header);
/* Browse sub-TLV and fulfill Link State Attributes */
for (tlvh = TLV_DATA(tlvh); sum < len; tlvh = TLV_HDR_NEXT(tlvh)) {
uint32_t val32, tab32[2];
@@ -2377,7 +2377,7 @@ static int ospf_te_delete_te(struct ls_ted *ted, struct ospf_lsa *lsa)
if (ntohs(tlvh->type) == TE_TLV_ROUTER_ADDR)
tlvh = TLV_HDR_NEXT(tlvh);
len = TLV_BODY_SIZE(tlvh);
- sum = 0;
+ sum = sizeof(struct tlv_header);
/* Browse sub-TLV to find Link ID */
for (tlvh = TLV_DATA(tlvh); sum < len; tlvh = TLV_HDR_NEXT(tlvh)) {
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index e7f18ae79c..5b9519ea59 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -4350,7 +4350,7 @@ static void show_ip_ospf_neighbor_sub(struct vty *vty,
char buf[PREFIX_STRLEN];
char timebuf[OSPF_TIME_DUMP_SIZE];
json_object *json_neighbor = NULL, *json_neigh_array = NULL;
- struct timeval res;
+ struct timeval res = {.tv_sec = 0, .tv_usec = 0};
long time_val = 0;
char uptime[OSPF_TIME_DUMP_SIZE];
diff --git a/tests/topotests/bgp_tcp_mss/bgp_vrf_tcp_mss.json b/tests/topotests/bgp_tcp_mss/bgp_vrf_tcp_mss.json
new file mode 100644
index 0000000000..17cee03fa3
--- /dev/null
+++ b/tests/topotests/bgp_tcp_mss/bgp_vrf_tcp_mss.json
@@ -0,0 +1,222 @@
+{
+ "address_types": [
+ "ipv4",
+ "ipv6"
+ ],
+ "ipv4base": "20.20.20.0",
+ "ipv4mask": 24,
+ "ipv6base": "fd00::",
+ "ipv6mask": 64,
+ "link_ip_start": {
+ "ipv4": "10.10.10.0",
+ "v4mask": 24,
+ "ipv6": "fd00::",
+ "v6mask": 64
+ },
+ "lo_prefix": {
+ "ipv4": "1.0.",
+ "v4mask": 24,
+ "ipv6": "2001:db8:f::",
+ "v6mask": 128
+ },
+ "routers": {
+ "r1": {
+ "links": {
+ "r2-link1": {
+ "ipv4": "auto",
+ "ipv6": "auto",
+ "vrf": "RED"
+ }
+ },
+ "vrfs": [
+ {
+ "name": "RED",
+ "id": "1"
+ }
+ ],
+ "bgp": [
+ {
+ "local_as": "100",
+ "vrf": "RED",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {}
+ }
+ }
+ },
+ "redistribute": [
+ {
+ "redist_type": "static"
+ }
+ ]
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1-link1": {}
+ }
+ }
+ },
+ "redistribute": [
+ {
+ "redist_type": "static"
+ }
+ ]
+ }
+ }
+ }
+ }
+ ]
+ },
+ "r2": {
+ "links": {
+ "r1-link1": {
+ "ipv4": "auto",
+ "ipv6": "auto",
+ "vrf": "RED"
+ },
+ "r3-link1": {
+ "ipv4": "auto",
+ "ipv6": "auto"
+ }
+ },
+ "vrfs": [
+ {
+ "name": "RED",
+ "id": "1"
+ }
+ ],
+ "bgp": [
+ {
+ "local_as": "200",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r2-link1": {}
+ }
+ }
+ },
+ "redistribute": [
+ {
+ "redist_type": "static"
+ }
+ ]
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r2-link1": {}
+ }
+ }
+ },
+ "redistribute": [
+ {
+ "redist_type": "static"
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "local_as": "200",
+ "vrf": "RED",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2-link1": {}
+ }
+ }
+ },
+ "redistribute": [
+ {
+ "redist_type": "static"
+ }
+ ]
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2-link1": {}
+ }
+ }
+ },
+ "redistribute": [
+ {
+ "redist_type": "static"
+ }
+ ]
+ }
+ }
+ }
+ }
+ ]
+ },
+ "r3": {
+ "links": {
+ "r2-link1": {
+ "ipv4": "auto",
+ "ipv6": "auto"
+ }
+ },
+ "bgp": [
+ {
+ "local_as": "300",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r3-link1": {}
+ }
+ }
+ },
+ "redistribute": [
+ {
+ "redist_type": "static"
+ }
+ ]
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r3-link1": {}
+ }
+ }
+ },
+ "redistribute": [
+ {
+ "redist_type": "static"
+ }
+ ]
+ }
+ }
+ }
+ }
+ ]
+ }
+ }
+} \ No newline at end of file
diff --git a/tests/topotests/bgp_tcp_mss/test_bgp_vrf_tcp_mss.py b/tests/topotests/bgp_tcp_mss/test_bgp_vrf_tcp_mss.py
new file mode 100644
index 0000000000..c48bd8a439
--- /dev/null
+++ b/tests/topotests/bgp_tcp_mss/test_bgp_vrf_tcp_mss.py
@@ -0,0 +1,766 @@
+#!/usr/bin/env python
+
+#
+# bgp_tcp_mss.py
+# Part of NetDEF Topology Tests
+#
+# Copyright (c) 2021 by
+# Shreenidhi A R <rshreenidhi@vmware.com>
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+bgp_tcp_mss_vrf.py:
+
+Need to verify if the tcp-mss value is reflected in the TCP session and in VRF.
+"""
+
+import os
+import sys
+import json
+import pytest
+import functools
+import platform
+import socket
+import subprocess
+
+# add after imports, before defining classes or functions:
+pytestmark = [pytest.mark.bgpd]
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topojson import build_config_from_json
+from lib.topolog import logger
+import time
+from lib.bgp import (
+ clear_bgp,
+ clear_bgp_and_verify,
+ create_router_bgp,
+ modify_as_number,
+ verify_as_numbers,
+ verify_bgp_convergence,
+ verify_bgp_rib,
+ verify_bgp_timers_and_functionality,
+ verify_router_id,
+ verify_tcp_mss
+)
+from lib.common_config import (
+ kill_router_daemons,
+ start_router_daemons,
+ addKernelRoute,
+ apply_raw_config,
+ check_address_types,
+ create_prefix_lists,
+ create_route_maps,
+ create_static_routes,
+ required_linux_kernel_version,
+ reset_config_on_routers,
+ start_topology,
+ step,
+ verify_admin_distance_for_static_routes,
+ verify_bgp_community,
+ verify_fib_routes,
+ verify_rib,
+ write_test_footer,
+ write_test_header
+)
+
+pytestmark = [pytest.mark.bgpd]
+# 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"}
+
+NEXT_HOP_IP = {"ipv4": "Null0", "ipv6": "Null0"}
+
+## File name
+TCPDUMP_FILE="test_tcp_packet_test.txt"
+
+def setup_module(mod):
+ """
+ Sets up the pytest environment
+
+ * `mod`: module name
+ """
+ global topo,TCPDUMP_FILE
+
+ # 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")
+
+ testsuite_run_time = time.asctime(time.localtime(time.time()))
+ step("Testsuite start time: {}".format(testsuite_run_time))
+ step("=" * 40)
+
+ step("Running setup_module to create topology")
+
+ # This function initiates the topology build with Topogen...
+ json_file = "{}/bgp_vrf_tcp_mss.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 deamons and then start routers
+ start_topology(tgen)
+ # Creating configuration from JSON
+ build_config_from_json(tgen, topo)
+
+ global ADDR_TYPES
+ global BGP_CONVERGENCE
+ ADDR_TYPES = check_address_types()
+ BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo)
+ assert BGP_CONVERGENCE is True, "setup_module :Failed \n Error: {}".format(
+ BGP_CONVERGENCE
+ )
+
+ step("Running setup_module() done")
+
+def teardown_module():
+ """Teardown the pytest environment"""
+
+ step("Running teardown_module to delete topology")
+
+ tgen = get_topogen()
+
+ # Stop toplogy and Remove tmp files
+ tgen.stop_topology()
+
+ step(
+ "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
+ )
+ step("=" * 40)
+
+
+#####################################################
+#
+# Testcases
+#
+#####################################################
+
+def test_bgp_vrf_tcp_mss(request):
+ tgen = get_topogen()
+ tc_name = request.node.name
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ step("Verify the router failures")
+ if tgen.routers_have_failure():
+ check_router_status(tgen)
+
+ step("Configuring 5 static Routes in Router R3 with NULL0 as Next hop")
+ for addr_type in ADDR_TYPES:
+ static_routes_input = {
+ "r3": {
+ "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],
+ },
+ {
+ "network": [NETWORK3_1[addr_type]] + [NETWORK3_2[addr_type]],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ },
+ {
+ "network": [NETWORK4_1[addr_type]] + [NETWORK4_2[addr_type]],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ },
+ {
+ "network": [NETWORK5_1[addr_type]] + [NETWORK5_2[addr_type]],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ },
+ ]
+ }
+ }
+ result = create_static_routes(tgen, static_routes_input)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Verify the static Routes in R3 on default VRF")
+ for addr_type in ADDR_TYPES:
+ static_routes_input = {
+ "r3": {
+ "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],
+ },
+ {
+ "network": [NETWORK3_1[addr_type]] + [NETWORK3_2[addr_type]],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ },
+ {
+ "network": [NETWORK4_1[addr_type]] + [NETWORK4_2[addr_type]],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ },
+ {
+ "network": [NETWORK5_1[addr_type]] + [NETWORK5_2[addr_type]],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ },
+ ]
+ }
+ }
+ dut = "r3"
+ result = verify_bgp_rib(tgen, addr_type, dut, static_routes_input)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ step("Verify the static Routes in R2 on default VRF")
+ for addr_type in ADDR_TYPES:
+ static_routes_input = {
+ "r3": {
+ "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],
+ },
+ {
+ "network": [NETWORK3_1[addr_type]] + [NETWORK3_2[addr_type]],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ },
+ {
+ "network": [NETWORK4_1[addr_type]] + [NETWORK4_2[addr_type]],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ },
+ {
+ "network": [NETWORK5_1[addr_type]] + [NETWORK5_2[addr_type]],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ },
+ ]
+ }
+ }
+ dut = "r2"
+ result = verify_bgp_rib(tgen, addr_type, dut, static_routes_input)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ step("importing default vrf on R2 under VRF RED Address Family")
+ for addr_type in ADDR_TYPES:
+ input_import_vrf = {
+ "r2": {
+ "bgp": [
+ {
+ "local_as": 200,
+ "vrf": "RED",
+ "address_family": {
+ addr_type: {"unicast": {"import": {"vrf": "default"}}}
+ },
+ }
+ ]
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_import_vrf)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Verify the static Routes in R2 on RED VRF")
+ for addr_type in ADDR_TYPES:
+ static_routes_input = {
+ "r3": {
+ "static_routes": [
+ {
+ "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ "vrf": "RED",
+ },
+ {
+ "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ "vrf": "RED",
+ },
+ {
+ "network": [NETWORK3_1[addr_type]] + [NETWORK3_2[addr_type]],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ "vrf": "RED",
+ },
+ {
+ "network": [NETWORK4_1[addr_type]] + [NETWORK4_2[addr_type]],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ "vrf": "RED",
+ },
+ {
+ "network": [NETWORK5_1[addr_type]] + [NETWORK5_2[addr_type]],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ "vrf": "RED",
+ },
+ ]
+ }
+ }
+ dut = "r2"
+ result = verify_bgp_rib(tgen, addr_type, dut, static_routes_input)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ step("Verify the static Routes in R1 on RED VRF")
+ for addr_type in ADDR_TYPES:
+ static_routes_input = {
+ "r3": {
+ "static_routes": [
+ {
+ "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ "vrf": "RED",
+ },
+ {
+ "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ "vrf": "RED",
+ },
+ {
+ "network": [NETWORK3_1[addr_type]] + [NETWORK3_2[addr_type]],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ "vrf": "RED",
+ },
+ {
+ "network": [NETWORK4_1[addr_type]] + [NETWORK4_2[addr_type]],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ "vrf": "RED",
+ },
+ {
+ "network": [NETWORK5_1[addr_type]] + [NETWORK5_2[addr_type]],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ "vrf": "RED",
+ },
+ ]
+ }
+ }
+ dut = "r1"
+ result = verify_bgp_rib(tgen, addr_type, dut, static_routes_input)
+ assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+
+ step("Enabling tcp-mss 150 on Router R1 in VRF RED")
+ TCP_MSS = 150
+ raw_config = {
+ "r1": {
+ "raw_config": [
+ "router bgp {} vrf {}".format(
+ topo["routers"]["r1"]["bgp"][0]["local_as"],
+ topo["routers"]["r1"]["bgp"][0]["vrf"],
+ ),
+ "neighbor {} tcp-mss {}".format(
+ topo["routers"]["r2"]["links"]["r1-link1"]["ipv4"].split("/")[0],
+ TCP_MSS,
+ ),
+ "neighbor {} tcp-mss {}".format(
+ topo["routers"]["r2"]["links"]["r1-link1"]["ipv6"].split("/")[0],
+ TCP_MSS,
+ ),
+ ]
+ },
+ }
+
+ result = apply_raw_config(tgen, raw_config)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ step("Clearing BGP on R1 and R2 ")
+ for addr_type in ADDR_TYPES:
+ clear_bgp(tgen, addr_type, "r1", vrf=topo["routers"]["r1"]["bgp"][0]["vrf"])
+ clear_bgp(tgen, addr_type, "r2", vrf=topo["routers"]["r2"]["bgp"][1]["vrf"])
+
+ step("Verify the BGP Convergence at R1 & R2 after Clear BGP")
+ r1_convergence = verify_bgp_convergence(tgen, topo, dut="r1")
+ assert (
+ r1_convergence is True
+ ), "BGP convergence after Clear BGP :Failed \n Error: {}".format(r1_convergence)
+ r2_convergence = verify_bgp_convergence(tgen, topo, dut="r2")
+ assert (
+ r2_convergence is True
+ ), "BGP convergence after Clear BGP :Failed \n Error: {}".format(r2_convergence)
+
+ step("Verify the TCP-MSS value on both Router R1 and R2")
+ for addr_type in ADDR_TYPES:
+ dut = "r1"
+ tcp_mss_result = verify_tcp_mss(
+ tgen,
+ dut,
+ topo["routers"]["r2"]["links"]["r1-link1"][addr_type].split("/")[0],
+ TCP_MSS,
+ "RED",
+ )
+ assert tcp_mss_result is True, " TCP-MSS mismatch :Failed \n Error: {}".format(
+ tcp_mss_result
+ )
+
+
+
+
+ step("Enabling tcp-mss 500 between R2 and R3 of VRF Default")
+ TCP_MSS = 500
+ raw_config = {
+ "r2": {
+ "raw_config": [
+ "router bgp {} ".format(topo["routers"]["r2"]["bgp"][0]["local_as"]),
+ "neighbor {} tcp-mss {}".format(
+ topo["routers"]["r3"]["links"]["r2-link1"]["ipv4"].split("/")[0],
+ TCP_MSS,
+ ),
+ "neighbor {} tcp-mss {}".format(
+ topo["routers"]["r3"]["links"]["r2-link1"]["ipv6"].split("/")[0],
+ TCP_MSS,
+ ),
+ ]
+ },
+ "r3": {
+ "raw_config": [
+ "router bgp {} ".format(topo["routers"]["r3"]["bgp"][0]["local_as"]),
+ "neighbor {} tcp-mss {}".format(
+ topo["routers"]["r2"]["links"]["r3-link1"]["ipv4"].split("/")[0],
+ TCP_MSS,
+ ),
+ "neighbor {} tcp-mss {}".format(
+ topo["routers"]["r2"]["links"]["r3-link1"]["ipv6"].split("/")[0],
+ TCP_MSS,
+ ),
+ ]
+ },
+ }
+ result = apply_raw_config(tgen, raw_config)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+
+
+ step("Clear BGP at router R2 and R3")
+ for addr_type in ADDR_TYPES:
+ clear_bgp(tgen, topo, "r2", addr_type)
+ clear_bgp(tgen, topo, "r3", addr_type)
+
+ step("Verify the BGP Convergence at R2 & R3 after Clear BGP")
+ r1_convergence = verify_bgp_convergence(tgen, topo, dut="r2")
+ assert (
+ r1_convergence is True
+ ), "BGP convergence after Clear BGP :Failed \n Error: {}".format(r2_convergence)
+ r2_convergence = verify_bgp_convergence(tgen, topo, dut="r3")
+ assert (
+ r2_convergence is True
+ ), "BGP convergence after Clear BGP :Failed \n Error: {}".format(r2_convergence)
+
+ step("Verify the TCP-MSS value on both Router R2 and R3")
+ for addr_type in ADDR_TYPES:
+ dut = "r2"
+ tcp_mss_result = verify_tcp_mss(
+ tgen,
+ dut,
+ topo["routers"]["r3"]["links"]["r2-link1"]["ipv4"].split("/")[0],
+ TCP_MSS,
+ )
+ assert tcp_mss_result is True, " TCP-MSS mismatch :Failed \n Error: {}".format(
+ tcp_mss_result
+ )
+
+ dut = "r3"
+ tcp_mss_result = verify_tcp_mss(
+ tgen,
+ dut,
+ topo["routers"]["r2"]["links"]["r3-link1"]["ipv4"].split("/")[0],
+ TCP_MSS,
+ )
+ assert tcp_mss_result is True, " TCP-MSS mismatch :Failed \n Error: {}".format(
+ tcp_mss_result
+ )
+
+ step("Removing tcp-mss 150 between R1 and R2 of VRF RED ")
+ TCP_MSS = 150
+ raw_config = {
+ "r1": {
+ "raw_config": [
+ "router bgp {} vrf {}".format(
+ topo["routers"]["r1"]["bgp"][0]["local_as"],
+ topo["routers"]["r1"]["bgp"][0]["vrf"],
+ ),
+ "no neighbor {} tcp-mss {}".format(
+ topo["routers"]["r2"]["links"]["r1-link1"]["ipv4"].split("/")[0],
+ TCP_MSS,
+ ),
+ "no neighbor {} tcp-mss {}".format(
+ topo["routers"]["r2"]["links"]["r1-link1"]["ipv6"].split("/")[0],
+ TCP_MSS,
+ ),
+ ]
+ }
+ }
+ result = apply_raw_config(tgen, raw_config)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+ raw_config = {
+ "r2": {
+ "raw_config": [
+ "router bgp {} vrf {}".format(
+ topo["routers"]["r2"]["bgp"][0]["local_as"],
+ topo["routers"]["r2"]["bgp"][1]["vrf"],
+ ),
+ "no neighbor {} tcp-mss {}".format(
+ topo["routers"]["r1"]["links"]["r2-link1"]["ipv4"].split("/")[0],
+ TCP_MSS,
+ ),
+ "no neighbor {} tcp-mss {}".format(
+ topo["routers"]["r1"]["links"]["r2-link1"]["ipv6"].split("/")[0],
+ TCP_MSS,
+ ),
+ ]
+ }
+ }
+ result = apply_raw_config(tgen, raw_config)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ step("Verify the TCP-MSS value cleared on both Router R1 and R2")
+ for addr_type in ADDR_TYPES:
+ dut = "r1"
+ tcp_mss_result = verify_tcp_mss(
+ tgen,
+ dut,
+ topo["routers"]["r2"]["links"]["r1-link1"][addr_type].split("/")[0],
+ TCP_MSS,
+ "RED",
+ )
+ assert (
+ tcp_mss_result is not True
+ ), " TCP-MSS mismatch :Failed \n Error: {}".format(tcp_mss_result)
+
+ dut = "r2"
+ tcp_mss_result = verify_tcp_mss(
+ tgen,
+ dut,
+ topo["routers"]["r1"]["links"]["r2-link1"]["ipv4"].split("/")[0],
+ TCP_MSS,
+ "RED",
+ )
+ assert (
+ tcp_mss_result is not True
+ ), " TCP-MSS mismatch :Failed \n Error: {}".format(tcp_mss_result)
+
+
+ step("Removing tcp-mss 500 between R2 and R3 of VRF Default ")
+ TCP_MSS = 500
+ raw_config = {
+ "r2": {
+ "raw_config": [
+ "router bgp {} ".format(topo["routers"]["r2"]["bgp"][0]["local_as"]),
+ "no neighbor {} tcp-mss {}".format(
+ topo["routers"]["r3"]["links"]["r2-link1"]["ipv4"].split("/")[0],
+ TCP_MSS,
+ ),
+ "no neighbor {} tcp-mss {}".format(
+ topo["routers"]["r3"]["links"]["r2-link1"]["ipv6"].split("/")[0],
+ TCP_MSS,
+ ),
+ ]
+ }
+ }
+ result = apply_raw_config(tgen, raw_config)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ raw_config = {
+ "r3": {
+ "raw_config": [
+ "router bgp {} ".format(topo["routers"]["r3"]["bgp"][0]["local_as"]),
+ "no neighbor {} tcp-mss {}".format(
+ topo["routers"]["r2"]["links"]["r3-link1"]["ipv4"].split("/")[0],
+ TCP_MSS,
+ ),
+ "no neighbor {} tcp-mss {}".format(
+ topo["routers"]["r2"]["links"]["r3-link1"]["ipv6"].split("/")[0],
+ TCP_MSS,
+ ),
+ ]
+ }
+ }
+ result = apply_raw_config(tgen, raw_config)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ step("Verify the TCP-MSS value got cleared on both Router R2 and R3")
+ for addr_type in ADDR_TYPES:
+ dut = "r2"
+ tcp_mss_result = verify_tcp_mss(
+ tgen,
+ dut,
+ topo["routers"]["r3"]["links"]["r2-link1"]["ipv4"].split("/")[0],
+ TCP_MSS,
+ )
+ assert (
+ tcp_mss_result is not True
+ ), " TCP-MSS mismatch :Failed \n Error: {}".format(tcp_mss_result)
+
+ dut = "r3"
+ tcp_mss_result = verify_tcp_mss(
+ tgen,
+ dut,
+ topo["routers"]["r2"]["links"]["r3-link1"]["ipv4"].split("/")[0],
+ TCP_MSS,
+ )
+ assert (
+ tcp_mss_result is not True
+ ), " TCP-MSS mismatch :Failed \n Error: {}".format(tcp_mss_result)
+
+ step("Configuring different TCP-MSS R2 and R3 ")
+ TCP_MSS = 500
+ raw_config = {
+ "r2": {
+ "raw_config": [
+ "router bgp {}".format(topo["routers"]["r2"]["bgp"][0]["local_as"]),
+ "neighbor {} tcp-mss {}".format(
+ topo["routers"]["r3"]["links"]["r2-link1"]["ipv4"].split("/")[0],
+ TCP_MSS,
+ ),
+ "neighbor {} tcp-mss {}".format(
+ topo["routers"]["r3"]["links"]["r2-link1"]["ipv6"].split("/")[0],
+ TCP_MSS,
+ ),
+ ]
+ }
+ }
+ result = apply_raw_config(tgen, raw_config)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+ TCP_MSS = 300
+ raw_config = {
+ "r3": {
+ "raw_config": [
+ "router bgp {} ".format(topo["routers"]["r3"]["bgp"][0]["local_as"]),
+ "neighbor {} tcp-mss {}".format(
+ topo["routers"]["r2"]["links"]["r3-link1"]["ipv4"].split("/")[0],
+ TCP_MSS,
+ ),
+ "neighbor {} tcp-mss {}".format(
+ topo["routers"]["r2"]["links"]["r3-link1"]["ipv6"].split("/")[0],
+ TCP_MSS,
+ ),
+ ]
+ }
+ }
+ result = apply_raw_config(tgen, raw_config)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ step("Verify the TCP-MSS value on both Router R2 and R3")
+ for addr_type in ADDR_TYPES:
+ TCP_MSS = 500
+ dut = "r2"
+ tcp_mss_result = verify_tcp_mss(
+ tgen,
+ dut,
+ topo["routers"]["r3"]["links"]["r2-link1"]["ipv4"].split("/")[0],
+ TCP_MSS,
+ )
+ assert tcp_mss_result is True, " TCP-MSS mismatch :Failed \n Error: {}".format(
+ tcp_mss_result
+ )
+
+ TCP_MSS = 300
+ dut = "r3"
+ tcp_mss_result = verify_tcp_mss(
+ tgen,
+ dut,
+ topo["routers"]["r2"]["links"]["r3-link1"]["ipv4"].split("/")[0],
+ TCP_MSS,
+ )
+ assert tcp_mss_result is True, " TCP-MSS mismatch :Failed \n Error: {}".format(
+ tcp_mss_result
+ )
+
+ step("Configure TCP_MSS > MTU on R2 and R3 and it should be 1460 ")
+ TCP_MSS = 4096
+ REF_TCP_MSS = 1460
+ raw_config = {
+ "r2": {
+ "raw_config": [
+ "router bgp {} ".format(topo["routers"]["r2"]["bgp"][0]["local_as"]),
+ "neighbor {} tcp-mss {}".format(
+ topo["routers"]["r3"]["links"]["r2-link1"]["ipv4"].split("/")[0],
+ TCP_MSS,
+ ),
+ "neighbor {} tcp-mss {}".format(
+ topo["routers"]["r3"]["links"]["r2-link1"]["ipv6"].split("/")[0],
+ TCP_MSS,
+ ),
+ ]
+ }
+ }
+ result = apply_raw_config(tgen, raw_config)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+ raw_config = {
+ "r3": {
+ "raw_config": [
+ "router bgp {} ".format(topo["routers"]["r3"]["bgp"][0]["local_as"]),
+ "neighbor {} tcp-mss {}".format(
+ topo["routers"]["r2"]["links"]["r3-link1"]["ipv4"].split("/")[0],
+ TCP_MSS,
+ ),
+ "neighbor {} tcp-mss {}".format(
+ topo["routers"]["r2"]["links"]["r3-link1"]["ipv6"].split("/")[0],
+ TCP_MSS,
+ ),
+ ]
+ }
+ }
+ result = apply_raw_config(tgen, raw_config)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ step("Restarting BGP Daemon on R3")
+
+ kill_router_daemons(tgen, "r3", ["bgpd"])
+ start_router_daemons(tgen, "r3", ["bgpd"])
+
+ step(
+ "Verify the configured TCP-MSS 4096 value on restarting both Daemon both Router R2 and R3 "
+ )
+ for addr_type in ADDR_TYPES:
+ TCP_MSS = 4096
+ dut = "r2"
+ tcp_mss_result = verify_tcp_mss(
+ tgen,
+ dut,
+ topo["routers"]["r3"]["links"]["r2-link1"]["ipv4"].split("/")[0],
+ TCP_MSS,
+ )
+ assert tcp_mss_result is True, " TCP-MSS mismatch :Failed \n Error: {}".format(
+ tcp_mss_result
+ )
+ dut = "r3"
+ tcp_mss_result = verify_tcp_mss(
+ tgen,
+ dut,
+ topo["routers"]["r2"]["links"]["r3-link1"]["ipv4"].split("/")[0],
+ TCP_MSS,
+ )
+ assert tcp_mss_result is True, " TCP-MSS mismatch :Failed \n Error: {}".format(
+ tcp_mss_result
+ )
+ write_test_footer(tc_name)
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/lib/bgp.py b/tests/topotests/lib/bgp.py
index 556240bfb5..458ae4b054 100644
--- a/tests/topotests/lib/bgp.py
+++ b/tests/topotests/lib/bgp.py
@@ -4428,3 +4428,56 @@ def verify_evpn_routes(
logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
return False
+def verify_tcp_mss(tgen, dut, neighbour, configured_tcp_mss, vrf=None):
+ """
+ This api is used to verify the tcp-mss value assigned to a neigbour of DUT
+
+ Parameters
+ ----------
+ * `tgen` : topogen object
+ * `dut`: device under test
+ * `neighbour`:neigbout IP address
+ * `configured_tcp_mss`:The TCP-MSS value to be verified
+ * `vrf`:vrf
+
+ Usage
+ -----
+ result = verify_tcp_mss(tgen, dut,neighbour,configured_tcp_mss)
+ Returns
+ -------
+ errormsg(str) or True
+ """
+
+ logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
+ rnode = tgen.routers()[dut]
+ if vrf:
+ cmd = "show bgp vrf {} neighbors {} json".format(vrf, neighbour)
+ else:
+ cmd = "show bgp neighbors {} json".format(neighbour)
+
+ # Execute the command
+ show_vrf_stats = run_frr_cmd(rnode, cmd, isjson=True)
+
+ # Verify TCP-MSS on router
+ logger.info("Verify that no core is observed")
+ if tgen.routers_have_failure():
+ errormsg = "Core observed while running CLI: %s" % (cmd)
+ return errormsg
+ else:
+ if configured_tcp_mss == show_vrf_stats.get(neighbour).get(
+ "bgpTcpMssConfigured"
+ ):
+ logger.debug(
+ "Configured TCP - MSS Found: {}".format(sys._getframe().f_code.co_name)
+ )
+ return True
+ else:
+ logger.debug(
+ "TCP-MSS Mismatch ,configured {} expecting {}".format(
+ show_vrf_stats.get(neighbour).get("bgpTcpMssConfigured"),
+ configured_tcp_mss,
+ )
+ )
+ return "TCP-MSS Mismatch"
+ logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
+ return False
diff --git a/tools/frr-reload.py b/tools/frr-reload.py
index da51c231d1..8762b956b6 100755
--- a/tools/frr-reload.py
+++ b/tools/frr-reload.py
@@ -172,7 +172,6 @@ class Vtysh(object):
class Context(object):
-
"""
A Context object represents a section of frr configuration such as:
!
@@ -234,7 +233,6 @@ def get_normalized_mac_ip_line(line):
class Config(object):
-
"""
A frr configuration is stored in a Config object. A Config object
contains a dictionary of Context objects where the Context keys
@@ -265,22 +263,20 @@ class Config(object):
if ":" in line:
line = get_normalized_mac_ip_line(line)
- """
- vrf static routes can be added in two ways. The old way is:
-
- "ip route x.x.x.x/x y.y.y.y vrf <vrfname>"
-
- but it's rendered in the configuration as the new way::
-
- vrf <vrf-name>
- ip route x.x.x.x/x y.y.y.y
- exit-vrf
-
- this difference causes frr-reload to not consider them a
- match and delete vrf static routes incorrectly.
- fix the old way to match new "show running" output so a
- proper match is found.
- """
+ # vrf static routes can be added in two ways. The old way is:
+ #
+ # "ip route x.x.x.x/x y.y.y.y vrf <vrfname>"
+ #
+ # but it's rendered in the configuration as the new way::
+ #
+ # vrf <vrf-name>
+ # ip route x.x.x.x/x y.y.y.y
+ # exit-vrf
+ #
+ # this difference causes frr-reload to not consider them a
+ # match and delete vrf static routes incorrectly.
+ # fix the old way to match new "show running" output so a
+ # proper match is found.
if (
line.startswith("ip route ") or line.startswith("ipv6 route ")
) and " vrf " in line:
@@ -326,14 +322,12 @@ class Config(object):
"""
Return the lines read in from the configuration
"""
-
return "\n".join(self.lines)
def get_contexts(self):
"""
Return the parsed context as strings for display, log etc.
"""
-
for (_, ctx) in sorted(iteritems(self.contexts)):
print(str(ctx) + "\n")
@@ -341,18 +335,15 @@ class Config(object):
"""
Save the provided key and lines as a context
"""
-
if not key:
return
- """
- IP addresses specified in "network" statements, "ip prefix-lists"
- etc. can differ in the host part of the specification the user
- provides and what the running config displays. For example, user
- can specify 11.1.1.1/24, and the running config displays this as
- 11.1.1.0/24. Ensure we don't do a needless operation for such
- lines. IS-IS & OSPFv3 have no "network" support.
- """
+ # IP addresses specified in "network" statements, "ip prefix-lists"
+ # etc. can differ in the host part of the specification the user
+ # provides and what the running config displays. For example, user can
+ # specify 11.1.1.1/24, and the running config displays this as
+ # 11.1.1.0/24. Ensure we don't do a needless operation for such lines.
+ # IS-IS & OSPFv3 have no "network" support.
re_key_rt = re.match(r"(ip|ipv6)\s+route\s+([A-Fa-f:.0-9/]+)(.*)$", key[0])
if re_key_rt:
addr = re_key_rt.group(2)
@@ -430,10 +421,8 @@ class Config(object):
newlines.append(line)
lines = newlines
- """
- More fixups in user specification and what running config shows.
- "null0" in routes must be replaced by Null0.
- """
+ # More fixups in user specification and what running config shows.
+ # "null0" in routes must be replaced by Null0.
if (
key[0].startswith("ip route")
or key[0].startswith("ipv6 route")
@@ -441,10 +430,8 @@ class Config(object):
):
key[0] = re.sub(r"\s+null0(\s*$)", " Null0", key[0])
- """
- Similar to above, but when the static is in a vrf, it turns into a
- blackhole nexthop for both null0 and Null0. Fix it accordingly
- """
+ # Similar to above, but when the static is in a vrf, it turns into a
+ # blackhole nexthop for both null0 and Null0. Fix it accordingly
if lines and key[0].startswith("vrf "):
newlines = []
for line in lines:
@@ -474,71 +461,69 @@ class Config(object):
def load_contexts(self):
"""
Parse the configuration and create contexts for each appropriate block
- """
- """
The end of a context is flagged via the 'end' keyword:
-!
-interface swp52
- ipv6 nd suppress-ra
- link-detect
-!
-end
-router bgp 10
- bgp router-id 10.0.0.1
- bgp log-neighbor-changes
- no bgp default ipv4-unicast
- neighbor EBGP peer-group
- neighbor EBGP advertisement-interval 1
- neighbor EBGP timers connect 10
- neighbor 2001:40:1:4::6 remote-as 40
- neighbor 2001:40:1:8::a remote-as 40
-!
-end
- address-family ipv6
- neighbor IBGPv6 activate
- neighbor 2001:10::2 peer-group IBGPv6
- neighbor 2001:10::3 peer-group IBGPv6
- exit-address-family
-!
-end
- address-family evpn
- neighbor LEAF activate
- advertise-all-vni
- vni 10100
- rd 65000:10100
- route-target import 10.1.1.1:10100
- route-target export 10.1.1.1:10100
- exit-vni
- exit-address-family
-!
-end
-router ospf
- ospf router-id 10.0.0.1
- log-adjacency-changes detail
- timers throttle spf 0 50 5000
-!
-end
+ !
+ interface swp52
+ ipv6 nd suppress-ra
+ link-detect
+ !
+ end
+ router bgp 10
+ bgp router-id 10.0.0.1
+ bgp log-neighbor-changes
+ no bgp default ipv4-unicast
+ neighbor EBGP peer-group
+ neighbor EBGP advertisement-interval 1
+ neighbor EBGP timers connect 10
+ neighbor 2001:40:1:4::6 remote-as 40
+ neighbor 2001:40:1:8::a remote-as 40
+ !
+ end
+ address-family ipv6
+ neighbor IBGPv6 activate
+ neighbor 2001:10::2 peer-group IBGPv6
+ neighbor 2001:10::3 peer-group IBGPv6
+ exit-address-family
+ !
+ end
+ address-family evpn
+ neighbor LEAF activate
+ advertise-all-vni
+ vni 10100
+ rd 65000:10100
+ route-target import 10.1.1.1:10100
+ route-target export 10.1.1.1:10100
+ exit-vni
+ exit-address-family
+ !
+ end
+ router ospf
+ ospf router-id 10.0.0.1
+ log-adjacency-changes detail
+ timers throttle spf 0 50 5000
+ !
+ end
+
+ The code assumes that its working on the output from the "vtysh -m"
+ command. That provides the appropriate markers to signify end of
+ a context. This routine uses that to build the contexts for the
+ config.
+
+ There are single line contexts such as "log file /media/node/zebra.log"
+ and multi-line contexts such as "router ospf" and subcontexts
+ within a context such as "address-family" within "router bgp"
+ In each of these cases, the first line of the context becomes the
+ key of the context. So "router bgp 10" is the key for the non-address
+ family part of bgp, "router bgp 10, address-family ipv6 unicast" is
+ the key for the subcontext and so on.
+
+ This dictionary contains a tree of all commands that we know start a
+ new multi-line context. All other commands are treated either as
+ commands inside a multi-line context or as single-line contexts. This
+ dictionary should be updated whenever a new node is added to FRR.
"""
-
- # The code assumes that its working on the output from the "vtysh -m"
- # command. That provides the appropriate markers to signify end of
- # a context. This routine uses that to build the contexts for the
- # config.
- #
- # There are single line contexts such as "log file /media/node/zebra.log"
- # and multi-line contexts such as "router ospf" and subcontexts
- # within a context such as "address-family" within "router bgp"
- # In each of these cases, the first line of the context becomes the
- # key of the context. So "router bgp 10" is the key for the non-address
- # family part of bgp, "router bgp 10, address-family ipv6 unicast" is
- # the key for the subcontext and so on.
-
- # This dictionary contains a tree of all commands that we know start a
- # new multi-line context. All other commands are treated either as
- # commands inside a multi-line context or as single-line contexts. This
- # dictionary should be updated whenever a new node is added to FRR.
ctx_keywords = {
"router bgp ": {
"address-family ": {
@@ -788,16 +773,12 @@ def check_for_exit_vrf(lines_to_add, lines_to_del):
return (lines_to_add, lines_to_del)
-"""
-This method handles deletion of bgp peer group config.
-The objective is to delete config lines related to peers
-associated with the peer-group and move the peer-group
-config line to the end of the lines_to_del list.
-"""
-
-
def delete_move_lines(lines_to_add, lines_to_del):
-
+ """
+ This function handles deletion of bgp peer group config. The objective is
+ to delete config lines related to peers associated with the peer-group and
+ move the peer-group config line to the end of the lines_to_del list.
+ """
del_dict = dict()
# Stores the lines to move to the end of the pending list.
lines_to_del_to_del = []
@@ -805,54 +786,51 @@ def delete_move_lines(lines_to_add, lines_to_del):
lines_to_del_to_app = []
found_pg_del_cmd = False
- """
- When "neighbor <pg_name> peer-group" under a bgp instance is removed,
- it also deletes the associated peer config. Any config line below no form of
- peer-group related to a peer are errored out as the peer no longer exists.
- To cleanup peer-group and associated peer(s) configs:
- - Remove all the peers config lines from the pending list (lines_to_del list).
- - Move peer-group deletion line to the end of the pending list, to allow
- removal of any of the peer-group specific configs.
-
- Create a dictionary of config context (i.e. router bgp vrf x).
- Under each context node, create a dictionary of a peer-group name.
- Append a peer associated to the peer-group into a list under a peer-group node.
- Remove all of the peer associated config lines from the pending list.
- Append peer-group deletion line to end of the pending list.
-
- Example:
- neighbor underlay peer-group
- neighbor underlay remote-as external
- neighbor underlay advertisement-interval 0
- neighbor underlay timers 3 9
- neighbor underlay timers connect 10
- neighbor swp1 interface peer-group underlay
- neighbor swp1 advertisement-interval 0
- neighbor swp1 timers 3 9
- neighbor swp1 timers connect 10
- neighbor swp2 interface peer-group underlay
- neighbor swp2 advertisement-interval 0
- neighbor swp2 timers 3 9
- neighbor swp2 timers connect 10
- neighbor swp3 interface peer-group underlay
- neighbor uplink1 interface remote-as internal
- neighbor uplink1 advertisement-interval 0
- neighbor uplink1 timers 3 9
- neighbor uplink1 timers connect 10
-
- New order:
- "router bgp 200 no bgp bestpath as-path multipath-relax"
- "router bgp 200 no neighbor underlay advertisement-interval 0"
- "router bgp 200 no neighbor underlay timers 3 9"
- "router bgp 200 no neighbor underlay timers connect 10"
- "router bgp 200 no neighbor uplink1 advertisement-interval 0"
- "router bgp 200 no neighbor uplink1 timers 3 9"
- "router bgp 200 no neighbor uplink1 timers connect 10"
- "router bgp 200 no neighbor underlay remote-as external"
- "router bgp 200 no neighbor uplink1 interface remote-as internal"
- "router bgp 200 no neighbor underlay peer-group"
-
- """
+ # When "neighbor <pg_name> peer-group" under a bgp instance is removed,
+ # it also deletes the associated peer config. Any config line below no form of
+ # peer-group related to a peer are errored out as the peer no longer exists.
+ # To cleanup peer-group and associated peer(s) configs:
+ # - Remove all the peers config lines from the pending list (lines_to_del list).
+ # - Move peer-group deletion line to the end of the pending list, to allow
+ # removal of any of the peer-group specific configs.
+ #
+ # Create a dictionary of config context (i.e. router bgp vrf x).
+ # Under each context node, create a dictionary of a peer-group name.
+ # Append a peer associated to the peer-group into a list under a peer-group node.
+ # Remove all of the peer associated config lines from the pending list.
+ # Append peer-group deletion line to end of the pending list.
+ #
+ # Example:
+ # neighbor underlay peer-group
+ # neighbor underlay remote-as external
+ # neighbor underlay advertisement-interval 0
+ # neighbor underlay timers 3 9
+ # neighbor underlay timers connect 10
+ # neighbor swp1 interface peer-group underlay
+ # neighbor swp1 advertisement-interval 0
+ # neighbor swp1 timers 3 9
+ # neighbor swp1 timers connect 10
+ # neighbor swp2 interface peer-group underlay
+ # neighbor swp2 advertisement-interval 0
+ # neighbor swp2 timers 3 9
+ # neighbor swp2 timers connect 10
+ # neighbor swp3 interface peer-group underlay
+ # neighbor uplink1 interface remote-as internal
+ # neighbor uplink1 advertisement-interval 0
+ # neighbor uplink1 timers 3 9
+ # neighbor uplink1 timers connect 10
+
+ # New order:
+ # "router bgp 200 no bgp bestpath as-path multipath-relax"
+ # "router bgp 200 no neighbor underlay advertisement-interval 0"
+ # "router bgp 200 no neighbor underlay timers 3 9"
+ # "router bgp 200 no neighbor underlay timers connect 10"
+ # "router bgp 200 no neighbor uplink1 advertisement-interval 0"
+ # "router bgp 200 no neighbor uplink1 timers 3 9"
+ # "router bgp 200 no neighbor uplink1 timers connect 10"
+ # "router bgp 200 no neighbor underlay remote-as external"
+ # "router bgp 200 no neighbor uplink1 interface remote-as internal"
+ # "router bgp 200 no neighbor underlay peer-group"
for (ctx_keys, line) in lines_to_del:
if (
@@ -860,37 +838,33 @@ def delete_move_lines(lines_to_add, lines_to_del):
and line
and line.startswith("neighbor ")
):
- """
- When 'neighbor <peer> remote-as <>' is removed it deletes the peer,
- there might be a peer associated config which also needs to be removed
- prior to peer.
- Append the 'neighbor <peer> remote-as <>' to the lines_to_del.
- Example:
-
- neighbor uplink1 interface remote-as internal
- neighbor uplink1 advertisement-interval 0
- neighbor uplink1 timers 3 9
- neighbor uplink1 timers connect 10
-
- Move to end:
- neighbor uplink1 advertisement-interval 0
- neighbor uplink1 timers 3 9
- neighbor uplink1 timers connect 10
- ...
-
- neighbor uplink1 interface remote-as internal
-
- """
+ # When 'neighbor <peer> remote-as <>' is removed it deletes the peer,
+ # there might be a peer associated config which also needs to be removed
+ # prior to peer.
+ # Append the 'neighbor <peer> remote-as <>' to the lines_to_del.
+ # Example:
+ #
+ # neighbor uplink1 interface remote-as internal
+ # neighbor uplink1 advertisement-interval 0
+ # neighbor uplink1 timers 3 9
+ # neighbor uplink1 timers connect 10
+
+ # Move to end:
+ # neighbor uplink1 advertisement-interval 0
+ # neighbor uplink1 timers 3 9
+ # neighbor uplink1 timers connect 10
+ # ...
+ #
+ # neighbor uplink1 interface remote-as internal
+ #
# 'no neighbor peer [interface] remote-as <>'
nb_remoteas = "neighbor (\S+) .*remote-as (\S+)"
re_nb_remoteas = re.search(nb_remoteas, line)
if re_nb_remoteas:
lines_to_del_to_app.append((ctx_keys, line))
- """
- {'router bgp 65001': {'PG': [], 'PG1': []},
- 'router bgp 65001 vrf vrf1': {'PG': [], 'PG1': []}}
- """
+ # {'router bgp 65001': {'PG': [], 'PG1': []},
+ # 'router bgp 65001 vrf vrf1': {'PG': [], 'PG1': []}}
if ctx_keys[0] not in del_dict:
del_dict[ctx_keys[0]] = dict()
# find 'no neighbor <pg_name> peer-group'
@@ -905,10 +879,8 @@ def delete_move_lines(lines_to_add, lines_to_del):
if found_pg_del_cmd == False:
return (lines_to_add, lines_to_del)
- """
- {'router bgp 65001': {'PG': ['10.1.1.2'], 'PG1': ['10.1.1.21']},
- 'router bgp 65001 vrf vrf1': {'PG': ['10.1.1.2'], 'PG1': ['10.1.1.21']}}
- """
+ # {'router bgp 65001': {'PG': ['10.1.1.2'], 'PG1': ['10.1.1.21']},
+ # 'router bgp 65001 vrf vrf1': {'PG': ['10.1.1.2'], 'PG1': ['10.1.1.21']}}
for (ctx_keys, line) in lines_to_del:
if (
ctx_keys[0].startswith("router bgp")
@@ -982,25 +954,22 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del):
if ctx_keys[0].startswith("router bgp") and line:
if line.startswith("neighbor "):
- """
- BGP changed how it displays swpX peers that are part of peer-group. Older
- versions of frr would display these on separate lines:
- neighbor swp1 interface
- neighbor swp1 peer-group FOO
-
- but today we display via a single line
- neighbor swp1 interface peer-group FOO
-
- This change confuses frr-reload.py so check to see if we are deleting
- neighbor swp1 interface peer-group FOO
-
- and adding
- neighbor swp1 interface
- neighbor swp1 peer-group FOO
-
- If so then chop the del line and the corresponding add lines
- """
-
+ # BGP changed how it displays swpX peers that are part of peer-group. Older
+ # versions of frr would display these on separate lines:
+ # neighbor swp1 interface
+ # neighbor swp1 peer-group FOO
+ #
+ # but today we display via a single line
+ # neighbor swp1 interface peer-group FOO
+ #
+ # This change confuses frr-reload.py so check to see if we are deleting
+ # neighbor swp1 interface peer-group FOO
+ #
+ # and adding
+ # neighbor swp1 interface
+ # neighbor swp1 peer-group FOO
+ #
+ # If so then chop the del line and the corresponding add lines
re_swpx_int_peergroup = re.search(
"neighbor (\S+) interface peer-group (\S+)", line
)
@@ -1052,12 +1021,10 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del):
lines_to_add_to_del.append((ctx_keys, swpx_interface))
lines_to_add_to_del.append((tmp_ctx_keys, swpx_peergroup))
- """
- Changing the bfd timers on neighbors is allowed without doing
- a delete/add process. Since doing a "no neighbor blah bfd ..."
- will cause the peer to bounce unnecessarily, just skip the delete
- and just do the add.
- """
+ # Changing the bfd timers on neighbors is allowed without doing
+ # a delete/add process. Since doing a "no neighbor blah bfd
+ # ..." will cause the peer to bounce unnecessarily, just skip
+ # the delete and just do the add.
re_nbr_bfd_timers = re.search(
r"neighbor (\S+) bfd (\S+) (\S+) (\S+)", line
)
@@ -1081,16 +1048,14 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del):
if found_add_bfd_nbr:
lines_to_del_to_del.append((ctx_keys, line))
- """
- Neighbor changes of route-maps need to be accounted for in that we
- do not want to do a `no route-map...` `route-map ....` when changing
- a route-map. This is bad mojo as that we will send/receive
- data we don't want.
- Additionally we need to ensure that if we have different afi/safi
- variants that they actually match and if we are going from a very
- old style command such that the neighbor command is under the
- `router bgp ..` node that we need to handle that appropriately
- """
+ # Neighbor changes of route-maps need to be accounted for in
+ # that we do not want to do a `no route-map...` `route-map
+ # ....` when changing a route-map. This is bad mojo as that we
+ # will send/receive data we don't want. Additionally we need
+ # to ensure that if we have different afi/safi variants that
+ # they actually match and if we are going from a very old style
+ # command such that the neighbor command is under the `router
+ # bgp ..` node that we need to handle that appropriately
re_nbr_rm = re.search("neighbor(.*)route-map(.*)(in|out)$", line)
if re_nbr_rm:
adjust_for_bgp_node = 0
@@ -1128,29 +1093,27 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del):
if save_line == dl_line:
lines_to_del_to_del.append((ctx_keys_dl, save_line))
- """
- We changed how we display the neighbor interface command. Older
- versions of frr would display the following:
- neighbor swp1 interface
- neighbor swp1 remote-as external
- neighbor swp1 capability extended-nexthop
-
- but today we display via a single line
- neighbor swp1 interface remote-as external
-
- and capability extended-nexthop is no longer needed because we
- automatically enable it when the neighbor is of type interface.
-
- This change confuses frr-reload.py so check to see if we are deleting
- neighbor swp1 interface remote-as (external|internal|ASNUM)
-
- and adding
- neighbor swp1 interface
- neighbor swp1 remote-as (external|internal|ASNUM)
- neighbor swp1 capability extended-nexthop
-
- If so then chop the del line and the corresponding add lines
- """
+ # We changed how we display the neighbor interface command. Older
+ # versions of frr would display the following:
+ # neighbor swp1 interface
+ # neighbor swp1 remote-as external
+ # neighbor swp1 capability extended-nexthop
+ #
+ # but today we display via a single line
+ # neighbor swp1 interface remote-as external
+ #
+ # and capability extended-nexthop is no longer needed because we
+ # automatically enable it when the neighbor is of type interface.
+ #
+ # This change confuses frr-reload.py so check to see if we are deleting
+ # neighbor swp1 interface remote-as (external|internal|ASNUM)
+ #
+ # and adding
+ # neighbor swp1 interface
+ # neighbor swp1 remote-as (external|internal|ASNUM)
+ # neighbor swp1 capability extended-nexthop
+ #
+ # If so then chop the del line and the corresponding add lines
re_swpx_int_remoteas = re.search(
"neighbor (\S+) interface remote-as (\S+)", line
)
@@ -1186,15 +1149,13 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del):
lines_to_add_to_del.append((ctx_keys, swpx_interface))
lines_to_add_to_del.append((tmp_ctx_keys, swpx_remoteas))
- """
- We made the 'bgp bestpath as-path multipath-relax' command
- automatically assume 'no-as-set' since the lack of this option caused
- weird routing problems. When the running config is shown in
- releases with this change, the no-as-set keyword is not shown as it
- is the default. This causes frr-reload to unnecessarily unapply
- this option only to apply it back again, causing unnecessary session
- resets.
- """
+ # We made the 'bgp bestpath as-path multipath-relax' command
+ # automatically assume 'no-as-set' since the lack of this option
+ # caused weird routing problems. When the running config is shown
+ # in releases with this change, the no-as-set keyword is not shown
+ # as it is the default. This causes frr-reload to unnecessarily
+ # unapply this option only to apply it back again, causing
+ # unnecessary session resets.
if "multipath-relax" in line:
re_asrelax_new = re.search(
"^bgp\s+bestpath\s+as-path\s+multipath-relax$", line
@@ -1207,25 +1168,21 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del):
lines_to_del_to_del.append((ctx_keys, line))
lines_to_add_to_del.append((ctx_keys, old_asrelax_cmd))
- """
- If we are modifying the BGP table-map we need to avoid a del/add and
- instead modify the table-map in place via an add. This is needed to
- avoid installing all routes in the RIB the second the 'no table-map'
- is issued.
- """
+ # If we are modifying the BGP table-map we need to avoid a del/add
+ # and instead modify the table-map in place via an add. This is
+ # needed to avoid installing all routes in the RIB the second the
+ # 'no table-map' is issued.
if line.startswith("table-map"):
found_table_map = line_exist(lines_to_add, ctx_keys, "table-map", False)
if found_table_map:
lines_to_del_to_del.append((ctx_keys, line))
- """
- More old-to-new config handling. ip import-table no longer accepts
- distance, but we honor the old syntax. But 'show running' shows only
- the new syntax. This causes an unnecessary 'no import-table' followed
- by the same old 'ip import-table' which causes perturbations in
- announced routes leading to traffic blackholes. Fix this issue.
- """
+ # More old-to-new config handling. ip import-table no longer accepts
+ # distance, but we honor the old syntax. But 'show running' shows only
+ # the new syntax. This causes an unnecessary 'no import-table' followed
+ # by the same old 'ip import-table' which causes perturbations in
+ # announced routes leading to traffic blackholes. Fix this issue.
re_importtbl = re.search("^ip\s+import-table\s+(\d+)$", ctx_keys[0])
if re_importtbl:
table_num = re_importtbl.group(1)
@@ -1236,17 +1193,16 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del):
)
lines_to_add_to_del.append((ctx[0], None))
- """
- ip/ipv6 prefix-lists and access-lists can be specified without a seq number.
- However, the running config always adds 'seq x', where x is a number
- incremented by 5 for every element of the prefix/access list.
- So, ignore such lines as well. Sample prefix-list and acces-list lines:
- ip prefix-list PR-TABLE-2 seq 5 permit 20.8.2.0/24 le 32
- ip prefix-list PR-TABLE-2 seq 10 permit 20.8.2.0/24 le 32
- ipv6 prefix-list vrfdev6-12 permit 2000:9:2::/64 gt 64
- access-list FOO seq 5 permit 2.2.2.2/32
- ipv6 access-list BAR seq 5 permit 2:2:2::2/128
- """
+ # ip/ipv6 prefix-lists and access-lists can be specified without a seq
+ # number. However, the running config always adds 'seq x', where x is
+ # a number incremented by 5 for every element of the prefix/access
+ # list. So, ignore such lines as well. Sample prefix-list and
+ # acces-list lines:
+ # ip prefix-list PR-TABLE-2 seq 5 permit 20.8.2.0/24 le 32
+ # ip prefix-list PR-TABLE-2 seq 10 permit 20.8.2.0/24 le 32
+ # ipv6 prefix-list vrfdev6-12 permit 2000:9:2::/64 gt 64
+ # access-list FOO seq 5 permit 2.2.2.2/32
+ # ipv6 access-list BAR seq 5 permit 2:2:2::2/128
re_acl_pfxlst = re.search(
"^(ip |ipv6 |)(prefix-list|access-list)(\s+\S+\s+)(seq \d+\s+)(permit|deny)(.*)$",
ctx_keys[0],
@@ -1265,12 +1221,9 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del):
lines_to_del_to_del.append((ctx_keys, None))
lines_to_add_to_del.append(((tmpline,), None))
found = True
- """
- If prefix-lists or access-lists are being deleted and
- not added (see comment above), add command with 'no' to
- lines_to_add and remove from lines_to_del to improve
- scaling performance.
- """
+ # If prefix-lists or access-lists are being deleted and not added
+ # (see comment above), add command with 'no' to lines_to_add and
+ # remove from lines_to_del to improve scaling performance.
if found is False:
add_cmd = ("no " + ctx_keys[0],)
lines_to_add.append((add_cmd, None))
@@ -1302,16 +1255,12 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del):
lines_to_add, ctx_keys, route_target_both_line
)
- """
- If the running configs has
- route-target import 1:1
- route-target export 1:1
-
- and the config we are reloading against has
- route-target both 1:1
-
- then we can ignore deleting the import/export and ignore adding the 'both'
- """
+ # If the running configs has
+ # route-target import 1:1
+ # route-target export 1:1
+ # and the config we are reloading against has
+ # route-target both 1:1
+ # then we can ignore deleting the import/export and ignore adding the 'both'
if found_route_target_export_line and found_route_target_both_line:
lines_to_del_to_del.append((ctx_keys, route_target_import_line))
lines_to_del_to_del.append((ctx_keys, route_target_export_line))
@@ -1333,23 +1282,21 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del):
lines_to_del_to_del.append((ctx_keys, line))
lines_to_add_to_del.append((ctx_keys, line))
else:
- """
- We have commands that used to be displayed in the global part
- of 'router bgp' that are now displayed under 'address-family ipv4 unicast'
-
- # old way
- router bgp 64900
- neighbor ISL advertisement-interval 0
-
- vs.
-
- # new way
- router bgp 64900
- address-family ipv4 unicast
- neighbor ISL advertisement-interval 0
-
- Look to see if we are deleting it in one format just to add it back in the other
- """
+ # We have commands that used to be displayed in the global part
+ # of 'router bgp' that are now displayed under 'address-family ipv4 unicast'
+ #
+ # # old way
+ # router bgp 64900
+ # neighbor ISL advertisement-interval 0
+ #
+ # vs.
+ #
+ # # new way
+ # router bgp 64900
+ # address-family ipv4 unicast
+ # neighbor ISL advertisement-interval 0
+ #
+ # Look to see if we are deleting it in one format just to add it back in the other
if (
ctx_keys[0].startswith("router bgp")
and len(ctx_keys) > 1
@@ -1382,19 +1329,22 @@ def ignore_unconfigurable_lines(lines_to_add, lines_to_del):
for (ctx_keys, line) in lines_to_del:
- if (
- ctx_keys[0].startswith("frr version")
- or ctx_keys[0].startswith("frr defaults")
- or ctx_keys[0].startswith("username")
- or ctx_keys[0].startswith("password")
- or ctx_keys[0].startswith("line vty")
- or
- # This is technically "no"able but if we did so frr-reload would
- # stop working so do not let the user shoot themselves in the foot
- # by removing this.
- ctx_keys[0].startswith("service integrated-vtysh-config")
+ # The integrated-vtysh-config one is technically "no"able but if we did
+ # so frr-reload would stop working so do not let the user shoot
+ # themselves in the foot by removing this.
+ if any(
+ [
+ ctx_keys[0].startswith(x)
+ for x in [
+ "frr version",
+ "frr defaults",
+ "username",
+ "password",
+ "line vty",
+ "service integrated-vtysh-config",
+ ]
+ ]
):
-
log.info('"%s" cannot be removed' % (ctx_keys[-1],))
lines_to_del_to_del.append((ctx_keys, line))
diff --git a/tools/valgrind.supp b/tools/valgrind.supp
index 88f46bf575..da3d4a8d6d 100644
--- a/tools/valgrind.supp
+++ b/tools/valgrind.supp
@@ -78,3 +78,11 @@
...
fun:yang_module_load
}
+{
+ <libyang2 lys_compile_type_range>
+ Memcheck:Leak
+ ...
+ fun:lys_compile_type_range
+ ...
+ fun:yang_module_load
+}
diff --git a/zebra/main.c b/zebra/main.c
index e4363bd899..038022ceb2 100644
--- a/zebra/main.c
+++ b/zebra/main.c
@@ -182,8 +182,6 @@ static void sigint(void)
SET_FLAG(zvrf->flags, ZEBRA_VRF_RETAIN);
}
}
- if (zrouter.lsp_process_q)
- work_queue_free_and_null(&zrouter.lsp_process_q);
vrf_terminate();
diff --git a/zebra/table_manager.c b/zebra/table_manager.c
index 82d6a0a6a2..ffc7a48eb9 100644
--- a/zebra/table_manager.c
+++ b/zebra/table_manager.c
@@ -72,7 +72,8 @@ void table_manager_enable(struct zebra_vrf *zvrf)
if (zvrf->tbl_mgr)
return;
- if (!vrf_is_backend_netns() && zvrf_id(zvrf) != VRF_DEFAULT) {
+ if (!vrf_is_backend_netns()
+ && strcmp(zvrf_name(zvrf), VRF_DEFAULT_NAME)) {
struct zebra_vrf *def = zebra_vrf_lookup_by_id(VRF_DEFAULT);
if (def)
@@ -284,7 +285,8 @@ void table_manager_disable(struct zebra_vrf *zvrf)
{
if (!zvrf->tbl_mgr)
return;
- if (!vrf_is_backend_netns() && zvrf_id(zvrf) != VRF_DEFAULT) {
+ if (!vrf_is_backend_netns()
+ && strcmp(zvrf_name(zvrf), VRF_DEFAULT_NAME)) {
zvrf->tbl_mgr = NULL;
return;
}
diff --git a/zebra/zebra_router.c b/zebra/zebra_router.c
index a80c573855..4ce756c953 100644
--- a/zebra/zebra_router.c
+++ b/zebra/zebra_router.c
@@ -235,6 +235,9 @@ void zebra_router_terminate(void)
RB_FOREACH_SAFE (zrt, zebra_router_table_head, &zrouter.tables, tmp)
zebra_router_free_table(zrt);
+ if (zrouter.lsp_process_q)
+ work_queue_free_and_null(&zrouter.lsp_process_q);
+
work_queue_free_and_null(&zrouter.ribq);
meta_queue_free(zrouter.mq);