From 953fc0c6cb7b757cb24b2f5d7b3d3bd174f91479 Mon Sep 17 00:00:00 2001 From: Donatas Abraitis Date: Wed, 4 Dec 2024 08:54:18 +0200 Subject: [PATCH 1/4] Revert "tests: Add topotest for OSPF multi-instance default origination." This reverts commit f10d2388693fc6904fb7ad4cf1570dd8eae8c213. Reverting because it causes failures for stable/10.2 due to multi OSPF instances support for frr.conf (unified configuration). Signed-off-by: Donatas Abraitis --- .../topotests/ospf_multi_instance/r1/frr.conf | 19 - .../topotests/ospf_multi_instance/r2/frr.conf | 37 -- .../topotests/ospf_multi_instance/r3/frr.conf | 19 - .../test_ospf_multi_instance.py | 403 ------------------ 4 files changed, 478 deletions(-) delete mode 100644 tests/topotests/ospf_multi_instance/r1/frr.conf delete mode 100644 tests/topotests/ospf_multi_instance/r2/frr.conf delete mode 100644 tests/topotests/ospf_multi_instance/r3/frr.conf delete mode 100644 tests/topotests/ospf_multi_instance/test_ospf_multi_instance.py diff --git a/tests/topotests/ospf_multi_instance/r1/frr.conf b/tests/topotests/ospf_multi_instance/r1/frr.conf deleted file mode 100644 index c341a7176a..0000000000 --- a/tests/topotests/ospf_multi_instance/r1/frr.conf +++ /dev/null @@ -1,19 +0,0 @@ -! -hostname r1 -password zebra -log file /tmp/r1-frr.log -ip forwarding -! -interface lo - ip address 1.1.1.1/32 - ip ospf area 0 -! -interface r1-eth0 - ip address 10.1.1.1/24 - ip ospf area 0 -! -! -router ospf - ospf router-id 1.1.1.1 - distance 20 -! diff --git a/tests/topotests/ospf_multi_instance/r2/frr.conf b/tests/topotests/ospf_multi_instance/r2/frr.conf deleted file mode 100644 index 8501e0edc0..0000000000 --- a/tests/topotests/ospf_multi_instance/r2/frr.conf +++ /dev/null @@ -1,37 +0,0 @@ -! -hostname r2 -password zebra -! debug ospf event -! debug ospf lsa -! debug ospf default-information -! debug ospf zebra redistribute - -ip forwarding -! -interface lo1 - ip address 2.2.2.1/32 - ip ospf 1 area 0 - no shut -! -interface lo2 - ip address 2.2.2.2/32 - ip ospf 2 area 0 - no shut -! -interface r2-eth0 - ip address 10.1.1.2/24 - ip ospf 1 area 0 -! -interface r2-eth1 - ip address 10.1.2.2/24 - ip ospf 2 area 0 -! -router ospf 1 - ospf router-id 2.2.2.1 - distance 20 -! -router ospf 2 - ospf router-id 2.2.2.2 - distance 20 -! - diff --git a/tests/topotests/ospf_multi_instance/r3/frr.conf b/tests/topotests/ospf_multi_instance/r3/frr.conf deleted file mode 100644 index 97a3e19c9b..0000000000 --- a/tests/topotests/ospf_multi_instance/r3/frr.conf +++ /dev/null @@ -1,19 +0,0 @@ -! -hostname r3 -password zebra -log file /tmp/r3-frr.log -ip forwarding -! -interface lo - ip address 3.3.3.1/32 - ip ospf area 0 -! -interface r3-eth0 - ip address 10.1.2.3/24 - ip ospf area 0 -! -! -router ospf - ospf router-id 3.3.3.1 - distance 20 -! diff --git a/tests/topotests/ospf_multi_instance/test_ospf_multi_instance.py b/tests/topotests/ospf_multi_instance/test_ospf_multi_instance.py deleted file mode 100644 index de44140c09..0000000000 --- a/tests/topotests/ospf_multi_instance/test_ospf_multi_instance.py +++ /dev/null @@ -1,403 +0,0 @@ -#!/usr/bin/env python -# SPDX-License-Identifier: ISC - -# -# test_ospf_multi_instance.py -# -# Copyright (c) 2024 LabN Consulting -# Acee Lindem -# - -import os -import sys -from functools import partial -import pytest - -# pylint: disable=C0413 -# Import topogen and topotest helpers -from lib import topotest -from lib.topogen import Topogen, TopoRouter, get_topogen -from lib.topolog import logger - -from lib.common_config import ( - step, - create_interface_in_kernel, -) - - -""" -test_ospf_metric_propagation.py: Test OSPF/BGP metric propagation -""" - -TOPOLOGY = """ - - +---------+ +--------------------+ +---------+ - | r1 | | r2 | r2 | | r3 | - | | | ospf 1 | ospf 2 | | | - | 1.1.1.1 | eth0 eth0| 2.2.2.1 | 2.2.2.2 |eth1 eth0| 3.3.3.1 | - | +-------------+ | +-------------+ | - | | 10.1.1.0/24 | | | 10.1.2.0/24 | | - +---------+ +--------------------+ +---------+ - - -""" - -# Save the Current Working Directory to find configuration files. -CWD = os.path.dirname(os.path.realpath(__file__)) -sys.path.append(os.path.join(CWD, "../")) - -# Required to instantiate the topology builder class. - -pytestmark = [pytest.mark.ospfd, pytest.mark.bgpd] - - -def build_topo(tgen): - "Build function" - - # Create 3 routers - tgen.add_router("r1") - tgen.add_router("r2") - tgen.add_router("r3") - - # Interconect router 1, 2 (0) - switch = tgen.add_switch("s1-1-2") - switch.add_link(tgen.gears["r1"]) - switch.add_link(tgen.gears["r2"]) - - # Interconect router 2, 3 (1) - switch = tgen.add_switch("s2-2-3") - switch.add_link(tgen.gears["r2"]) - switch.add_link(tgen.gears["r3"]) - - # Add more loopbacks to r2 - create_interface_in_kernel( - tgen, "r2", "lo1", "2.2.2.1", netmask="255.255.255.255", create=True - ) - create_interface_in_kernel( - tgen, "r2", "lo2", "2.2.2.2", netmask="255.255.255.255", create=True - ) - - -def setup_module(mod): - logger.info("OSPF Multi-Instance:\n {}".format(TOPOLOGY)) - - tgen = Topogen(build_topo, mod.__name__) - tgen.start_topology() - - # Starting Routers - router_list = tgen.routers() - - for rname, router in router_list.items(): - logger.info("Loading router %s" % rname) - router.load_frr_config(os.path.join(CWD, "{}/frr.conf".format(rname))) - - # Initialize all routers. - tgen.start_router() - - -def teardown_module(): - "Teardown the pytest environment" - tgen = get_topogen() - tgen.stop_topology() - - -def test_multi_instance_default_origination(): - tgen = get_topogen() - - if tgen.routers_have_failure(): - pytest.skip("Skipped because of router(s) failure") - - step("Configure a local default route") - r1 = tgen.gears["r1"] - r1.vtysh_cmd("conf t\nip route 0.0.0.0/0 Null0") - - step("Verify the R1 configuration and install of 'ip route 0.0.0.0/0 Null0'") - prefix_suppression_cfg = ( - tgen.net["r1"] - .cmd('vtysh -c "show running" | grep "^ip route 0.0.0.0/0 Null0"') - .rstrip() - ) - assertmsg = "'ip route 0.0.0.0/0 Null0' applied, but not present in configuration" - assert prefix_suppression_cfg == "ip route 0.0.0.0/0 Null0", assertmsg - - input_dict = { - "0.0.0.0/0": [ - { - "prefix": "0.0.0.0/0", - "prefixLen": 0, - "protocol": "static", - "nexthops": [ - { - "blackhole": True, - } - ], - } - ] - } - test_func = partial( - topotest.router_json_cmp, r1, "show ip route 0.0.0.0/0 json", input_dict - ) - _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) - assertmsg = "0.0.0.0/0 not installed on router r1" - assert result is None, assertmsg - - step( - "Verify the R1 configuration and advertisement of 'default-information originate'" - ) - r1.vtysh_cmd("conf t\nrouter ospf\n default-information originate") - - input_dict = { - "asExternalLinkStates": [ - { - "lsaType": "AS-external-LSA", - "linkStateId": "0.0.0.0", - "advertisingRouter": "1.1.1.1", - "networkMask": 0, - "metricType": "E2 (Larger than any link state path)", - "metric": 10, - "forwardAddress": "0.0.0.0", - "externalRouteTag": 0, - } - ] - } - test_func = partial( - topotest.router_json_cmp, r1, "show ip ospf database json", input_dict - ) - - r2 = tgen.gears["r2"] - step("Verify the OSPF instance 1 installation of default route on router 2") - input_dict = { - "0.0.0.0/0": [ - { - "prefix": "0.0.0.0/0", - "prefixLen": 0, - "protocol": "ospf", - "instance": 1, - "nexthops": [ - { - "ip": "10.1.1.1", - "interfaceName": "r2-eth0", - } - ], - } - ] - } - test_func = partial( - topotest.router_json_cmp, r2, "show ip route 0.0.0.0/0 json", input_dict - ) - _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) - assertmsg = "0.0.0.0/0 not installed on router r2" - assert result is None, assertmsg - - step("Configure OSPF 'default-intformation originate' on router r2 instance 2") - r2.vtysh_cmd("conf t\nrouter ospf 2\n default-information originate") - - step("Verify r2 instance 2 AS-External default origination") - input_dict = { - "ospfInstance": 2, - "routerId": "2.2.2.2", - "asExternalLinkStates": [ - { - "lsaType": "AS-external-LSA", - "linkStateId": "0.0.0.0", - "advertisingRouter": "2.2.2.2", - "networkMask": 0, - "metricType": "E2 (Larger than any link state path)", - "tos": 0, - "metric": 10, - "forwardAddress": "0.0.0.0", - "externalRouteTag": 0, - } - ], - } - test_func = partial( - topotest.router_json_cmp, - r2, - "show ip ospf 2 database external json", - input_dict, - ) - _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) - assertmsg = "AS-External default not originated by router r2 OSPF instance 2" - assert result is None, assertmsg - - step("Update the OSPF instance 2 distance so it will be preferred over instance 1") - r2.vtysh_cmd("conf t\nrouter ospf 2\n distance 15") - - step("Generate a default route from OSPF on r3") - r3 = tgen.gears["r3"] - r3.vtysh_cmd("conf t\nrouter ospf\n default-information originate") - r3.vtysh_cmd("conf t\nip route 0.0.0.0/0 Null0") - - step("Verify r3 AS-External default origination on r2") - input_dict = { - "ospfInstance": 2, - "routerId": "2.2.2.2", - "asExternalLinkStates": [ - { - "lsaType": "AS-external-LSA", - "linkStateId": "0.0.0.0", - "advertisingRouter": "3.3.3.1", - "length": 36, - "networkMask": 0, - "metricType": "E2 (Larger than any link state path)", - "tos": 0, - "metric": 10, - "forwardAddress": "0.0.0.0", - "externalRouteTag": 0, - } - ], - } - test_func = partial( - topotest.router_json_cmp, - r2, - "show ip ospf 2 database external json", - input_dict, - ) - _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) - assertmsg = "AS-External default not originated by router r3 OSPF" - assert result is None, assertmsg - - step("Verify r3's default installed by OSPF instance 2 is preferred on r2") - input_dict = { - "0.0.0.0/0": [ - { - "prefix": "0.0.0.0/0", - "prefixLen": 0, - "protocol": "ospf", - "instance": 2, - "distance": 15, - "nexthops": [ - { - "ip": "10.1.2.3", - "interfaceName": "r2-eth1", - } - ], - } - ] - } - test_func = partial( - topotest.router_json_cmp, r2, "show ip route 0.0.0.0/0 json", input_dict - ) - _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) - assertmsg = "0.0.0.0/0 from r3 not installed on router r2" - assert result is None, assertmsg - - step( - "Verify that r2's OSPF instance 2 AS-External LSA default is flushed due to default from r3" - ) - input_dict = { - "ospfInstance": 2, - "routerId": "2.2.2.2", - "asExternalLinkStates": [ - { - "lsaAge": 3600, - "lsaType": "AS-external-LSA", - "linkStateId": "0.0.0.0", - "advertisingRouter": "2.2.2.2", - "networkMask": 0, - "metricType": "E2 (Larger than any link state path)", - "tos": 0, - "metric": 10, - "forwardAddress": "0.0.0.0", - "externalRouteTag": 0, - } - ], - } - test_func = partial( - topotest.router_json_cmp, - r2, - "show ip ospf 2 database external json", - input_dict, - ) - _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) - assertmsg = "AS-External default not flushed by router r2 OSPF instance 2" - assert result is None, assertmsg - - step("Remove r3's default route and verify that its advertisement is flushed") - r3.vtysh_cmd("conf t\nno ip route 0.0.0.0/0 Null0") - input_dict = { - "routerId": "3.3.3.1", - "asExternalLinkStates": [ - { - "lsaAge": 3600, - "lsaType": "AS-external-LSA", - "linkStateId": "0.0.0.0", - "advertisingRouter": "3.3.3.1", - "networkMask": 0, - "metricType": "E2 (Larger than any link state path)", - "tos": 0, - "metric": 10, - "forwardAddress": "0.0.0.0", - "externalRouteTag": 0, - } - ], - } - test_func = partial( - topotest.router_json_cmp, r3, "show ip ospf database external json", input_dict - ) - _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) - assertmsg = "AS-External default not flushed by router r3 OSPF" - assert result is None, assertmsg - - step( - "Verify that r2's OSPF instance 2 AS-External default is advertised and installed by r3" - ) - input_dict = { - "routerId": "3.3.3.1", - "asExternalLinkStates": [ - { - "lsaType": "AS-external-LSA", - "linkStateId": "0.0.0.0", - "advertisingRouter": "2.2.2.2", - "networkMask": 0, - "metricType": "E2 (Larger than any link state path)", - "tos": 0, - "metric": 10, - "forwardAddress": "0.0.0.0", - "externalRouteTag": 0, - } - ], - } - test_func = partial( - topotest.router_json_cmp, r3, "show ip ospf database external json", input_dict - ) - assertmsg = "AS-External default not originated by r2 OSPF instance 2" - assert result is None, assertmsg - - step("Verify r2's OSPF instance 2 is AS-External default is installed on r3") - input_dict = { - "0.0.0.0/0": [ - { - "prefix": "0.0.0.0/0", - "prefixLen": 0, - "protocol": "ospf", - "distance": 20, - "nexthops": [ - { - "ip": "10.1.2.2", - "interfaceName": "r3-eth0", - } - ], - } - ] - } - test_func = partial( - topotest.router_json_cmp, r3, "show ip route 0.0.0.0/0 json", input_dict - ) - _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) - assertmsg = "0.0.0.0/0 from router r2 not installed on r3" - assert result is None, assertmsg - - -def test_memory_leak(): - "Run the memory leak test and report results." - tgen = get_topogen() - if not tgen.is_memleak_enabled(): - pytest.skip("Memory leak test/report is disabled") - - tgen.report_memory_leaks() - - -if __name__ == "__main__": - args = ["-s"] + sys.argv[1:] - sys.exit(pytest.main(args)) From 86b10095a788d0d6cacd1557a5d7d4758db88903 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 3 Dec 2024 12:08:12 -0500 Subject: [PATCH 2/4] lib: Fix session re-establishment Currently if you have this sequence of events: a) BGP starts b) BGP reads cli that has bfd configuration c) BGP attempts to install bfd configuration but fails because zebra is not connected to yet d) BGP connects to zebra e) BGP receives resend bfd code from bfdd f) BGP was not sending down the unsent data to bfd, never causing the bfd session to be established. So effectively bfd was attempting to install but failed and then when it was asked to replay everything it decided that the bfd information for a particular peer was actually installed and does not need to be resent. Modify the code such that the bfd code now tracks failed installation and allows the resend of data to bfdd. Signed-off-by: Donald Sharp --- lib/bfd.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/bfd.c b/lib/bfd.c index 4535fc1233..bc4b1c5b51 100644 --- a/lib/bfd.c +++ b/lib/bfd.c @@ -32,6 +32,8 @@ enum bfd_session_event { BSE_UNINSTALL, /** Install the BFD session configuration. */ BSE_INSTALL, + /** We should install but it couldn't because of a error talking to zebra */ + BSE_VALID_FOR_INSTALL, }; /** @@ -527,6 +529,10 @@ static void _bfd_sess_send(struct event *t) vrf_id_to_name(bsp->args.vrf_id), bsp->args.vrf_id, bsp->lastev == BSE_INSTALL ? "installed" : "uninstalled"); + + bsp->installed = false; + if (bsp->lastev == BSE_INSTALL) + bsp->lastev = BSE_VALID_FOR_INSTALL; } } @@ -883,7 +889,7 @@ int zclient_bfd_session_replay(ZAPI_CALLBACK_ARGS) /* Replay all activated peers. */ TAILQ_FOREACH (bsp, &bsglobal.bsplist, entry) { /* Skip not installed sessions. */ - if (!bsp->installed) + if (!bsp->installed && bsp->lastev != BSE_VALID_FOR_INSTALL) continue; /* We are reconnecting, so we must send installation. */ From 93e7c2ea81f8ad3b9b772984476c1902ebb80cce Mon Sep 17 00:00:00 2001 From: Corey Siltala Date: Tue, 26 Nov 2024 10:04:14 -0600 Subject: [PATCH 3/4] pimd: Fix access-list memory leak in pimd Reset access-lists in pimd on terminate Signed-off-by: Corey Siltala (cherry picked from commit d21a993f16dc23df6a1f1a7c81e9f562446437a0) --- pimd/pimd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pimd/pimd.c b/pimd/pimd.c index db61974800..1a9ef0ce41 100644 --- a/pimd/pimd.c +++ b/pimd/pimd.c @@ -17,6 +17,7 @@ #include "vrf.h" #include "lib_errors.h" #include "bfd.h" +#include "filter.h" #include "pimd.h" #if PIM_IPV == 4 @@ -143,6 +144,7 @@ void pim_terminate(void) prefix_list_add_hook(NULL); prefix_list_delete_hook(NULL); prefix_list_reset(); + access_list_reset(); pim_vxlan_terminate(); pim_vrf_terminate(); From 595a608498f85b3e35fe6530681fefb2b119e727 Mon Sep 17 00:00:00 2001 From: Donatas Abraitis Date: Sun, 1 Dec 2024 14:32:08 +0200 Subject: [PATCH 4/4] bgpd: Initialize as_type for peer-group as AS_UNSPECIFIED Previously AS_UNSPECIFIED was treated as 0, but with now it's 1 after renumbering peer_asn_type enum. Fixes: 0dfe25697f5299326046fcfb66f2c6beca7c423c ("bgpd: Implement neighbor X remote-as auto") Signed-off-by: Donatas Abraitis (cherry picked from commit e57fb3282a6dce0835bb6d0f2a2f83fa54a35df4) --- bgpd/bgpd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 6a788d752a..e08e72e01c 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -2906,6 +2906,7 @@ struct peer_group *peer_group_get(struct bgp *bgp, const char *name) group->conf->host = XSTRDUP(MTYPE_BGP_PEER_HOST, name); group->conf->group = group; group->conf->as = 0; + group->conf->as_type = AS_UNSPECIFIED; group->conf->ttl = BGP_DEFAULT_TTL; group->conf->gtsm_hops = BGP_GTSM_HOPS_DISABLED; group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;