diff options
| -rw-r--r-- | bgpd/bgp_route.c | 6 | ||||
| -rw-r--r-- | bgpd/bgp_updgrp.c | 1 | ||||
| -rw-r--r-- | bgpd/bgp_vty.c | 29 | ||||
| -rw-r--r-- | bgpd/bgpd.c | 11 | ||||
| -rw-r--r-- | bgpd/bgpd.h | 1 | ||||
| -rw-r--r-- | doc/user/bgp.rst | 6 | ||||
| -rw-r--r-- | tests/topotests/bgp_default_originate_timer/__init__.py | 0 | ||||
| -rw-r--r-- | tests/topotests/bgp_default_originate_timer/r1/bgpd.conf | 18 | ||||
| -rw-r--r-- | tests/topotests/bgp_default_originate_timer/r1/zebra.conf | 7 | ||||
| -rw-r--r-- | tests/topotests/bgp_default_originate_timer/r2/bgpd.conf | 6 | ||||
| -rw-r--r-- | tests/topotests/bgp_default_originate_timer/r2/zebra.conf | 4 | ||||
| -rw-r--r-- | tests/topotests/bgp_default_originate_timer/r3/bgpd.conf | 12 | ||||
| -rw-r--r-- | tests/topotests/bgp_default_originate_timer/r3/zebra.conf | 7 | ||||
| -rw-r--r-- | tests/topotests/bgp_default_originate_timer/test_bgp_default_originate_timer.py | 123 |
14 files changed, 218 insertions, 13 deletions
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 7b7a7ad207..7737738d28 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -3288,14 +3288,12 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, if (old_select || new_select) { bgp_bump_version(dest); - if (!bgp->t_rmap_def_originate_eval) { - bgp_lock(bgp); + if (!bgp->t_rmap_def_originate_eval) event_add_timer( bm->master, update_group_refresh_default_originate_route_map, - bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER, + bgp, bgp->rmap_def_originate_eval_timer, &bgp->t_rmap_def_originate_eval); - } } if (old_select) diff --git a/bgpd/bgp_updgrp.c b/bgpd/bgp_updgrp.c index 0b1e54916a..a642be935d 100644 --- a/bgpd/bgp_updgrp.c +++ b/bgpd/bgp_updgrp.c @@ -2106,7 +2106,6 @@ void update_group_refresh_default_originate_route_map(struct event *thread) update_group_walk(bgp, update_group_default_originate_route_map_walkcb, reason); EVENT_OFF(bgp->t_rmap_def_originate_eval); - bgp_unlock(bgp); } /* diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 7063bc26ab..6d7b745713 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -7959,6 +7959,26 @@ DEFPY (bgp_condadv_period, return CMD_SUCCESS; } +DEFPY (bgp_def_originate_eval, + bgp_def_originate_eval_cmd, + "[no$no] bgp default-originate timer (0-3600)$timer", + NO_STR + BGP_STR + "Control default-originate\n" + "Set period to rescan BGP table to check if default-originate condition is met\n" + "Period between BGP table scans, in seconds; default 5\n") +{ + VTY_DECLVAR_CONTEXT(bgp, bgp); + + bgp->rmap_def_originate_eval_timer = + no ? RMAP_DEFAULT_ORIGINATE_EVAL_TIMER : timer; + + if (bgp->t_rmap_def_originate_eval) + EVENT_OFF(bgp->t_rmap_def_originate_eval); + + return CMD_SUCCESS; +} + DEFPY (neighbor_advertise_map, neighbor_advertise_map_cmd, "[no$no] neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor advertise-map RMAP_NAME$advertise_str <exist-map|non-exist-map>$exist RMAP_NAME$condition_str", @@ -18622,6 +18642,12 @@ int bgp_config_write(struct vty *vty) " bgp conditional-advertisement timer %u\n", bgp->condition_check_period); + /* default-originate timer configuration */ + if (bgp->rmap_def_originate_eval_timer != + RMAP_DEFAULT_ORIGINATE_EVAL_TIMER) + vty_out(vty, " bgp default-originate timer %u\n", + bgp->rmap_def_originate_eval_timer); + /* peer-group */ for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) { bgp_config_write_peer_global(vty, bgp, group->conf); @@ -20250,6 +20276,9 @@ void bgp_vty_init(void) install_element(BGP_VPNV4_NODE, &neighbor_advertise_map_cmd); install_element(BGP_VPNV6_NODE, &neighbor_advertise_map_cmd); + /* bgp default-originate timer */ + install_element(BGP_NODE, &bgp_def_originate_eval_cmd); + /* neighbor maximum-prefix-out commands. */ install_element(BGP_NODE, &neighbor_maximum_prefix_out_cmd); install_element(BGP_NODE, &no_neighbor_maximum_prefix_out_cmd); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 99c6a46e7c..ba2985d304 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -3330,6 +3330,7 @@ static struct bgp *bgp_create(as_t *as, const char *name, bgp_addpath_init_bgp_data(&bgp->tx_addpath); bgp->fast_convergence = false; bgp->llgr_stale_time = BGP_DEFAULT_LLGR_STALE_TIME; + bgp->rmap_def_originate_eval_timer = RMAP_DEFAULT_ORIGINATE_EVAL_TIMER; #ifdef ENABLE_BGP_VNC if (inst_type != BGP_INSTANCE_TYPE_VRF) { @@ -3703,11 +3704,8 @@ void bgp_instance_down(struct bgp *bgp) struct listnode *next; /* Stop timers. */ - if (bgp->t_rmap_def_originate_eval) { + if (bgp->t_rmap_def_originate_eval) EVENT_OFF(bgp->t_rmap_def_originate_eval); - bgp_unlock(bgp); /* TODO - This timer is started with a lock - - why? */ - } /* Bring down peers, so corresponding routes are purged. */ for (ALL_LIST_ELEMENTS(bgp->peer, node, next, peer)) { @@ -3810,11 +3808,8 @@ int bgp_delete(struct bgp *bgp) vpn_leak_zebra_vrf_label_withdraw(bgp, AFI_IP6); /* Stop timers. */ - if (bgp->t_rmap_def_originate_eval) { + if (bgp->t_rmap_def_originate_eval) EVENT_OFF(bgp->t_rmap_def_originate_eval); - bgp_unlock(bgp); /* TODO - This timer is started with a lock - - why? */ - } /* Inform peers we're going down. */ for (ALL_LIST_ELEMENTS(bgp->peer, node, next, peer)) diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 9cb1d51088..ecd122fee2 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -601,6 +601,7 @@ struct bgp { /* timer to re-evaluate neighbor default-originate route-maps */ struct event *t_rmap_def_originate_eval; + uint16_t rmap_def_originate_eval_timer; #define RMAP_DEFAULT_ORIGINATE_EVAL_TIMER 5 /* BGP distance configuration. */ diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst index 52bfa5b295..a2585f3a57 100644 --- a/doc/user/bgp.rst +++ b/doc/user/bgp.rst @@ -1729,6 +1729,12 @@ Configuring Peers and will not be displayed as part of a `show run`. The no form of the command turns off this ability. +.. clicmd:: bgp default-originate timer (0-3600) + + Set the period to rerun the default-originate route-map scanner process. The + default is 5 seconds. With a full routing table, it might be useful to increase + this setting to avoid scanning the whole BGP table aggressively. + .. clicmd:: bgp default ipv4-unicast This command allows the user to specify that the IPv4 Unicast address diff --git a/tests/topotests/bgp_default_originate_timer/__init__.py b/tests/topotests/bgp_default_originate_timer/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/topotests/bgp_default_originate_timer/__init__.py diff --git a/tests/topotests/bgp_default_originate_timer/r1/bgpd.conf b/tests/topotests/bgp_default_originate_timer/r1/bgpd.conf new file mode 100644 index 0000000000..f2a1c9005a --- /dev/null +++ b/tests/topotests/bgp_default_originate_timer/r1/bgpd.conf @@ -0,0 +1,18 @@ +router bgp 65001 + no bgp ebgp-requires-policy + bgp default-originate timer 3600 + neighbor 192.168.1.2 remote-as external + neighbor 192.168.1.2 timers 1 3 + neighbor 192.168.1.2 timers connect 1 + neighbor 192.168.2.2 remote-as external + neighbor 192.168.2.2 timers 1 3 + neighbor 192.168.2.2 timers connect 1 + address-family ipv4 + neighbor 192.168.1.2 default-originate route-map default + exit-address-family +! +bgp community-list standard r3 seq 5 permit 65003:1 +! +route-map default permit 10 + match community r3 +exit diff --git a/tests/topotests/bgp_default_originate_timer/r1/zebra.conf b/tests/topotests/bgp_default_originate_timer/r1/zebra.conf new file mode 100644 index 0000000000..3692361fb3 --- /dev/null +++ b/tests/topotests/bgp_default_originate_timer/r1/zebra.conf @@ -0,0 +1,7 @@ +! +interface r1-eth0 + ip address 192.168.1.1/24 +! +interface r1-eth1 + ip address 192.168.2.1/24 +! diff --git a/tests/topotests/bgp_default_originate_timer/r2/bgpd.conf b/tests/topotests/bgp_default_originate_timer/r2/bgpd.conf new file mode 100644 index 0000000000..7ca65a94a1 --- /dev/null +++ b/tests/topotests/bgp_default_originate_timer/r2/bgpd.conf @@ -0,0 +1,6 @@ +router bgp 65002 + no bgp ebgp-requires-policy + neighbor 192.168.1.1 remote-as external + neighbor 192.168.1.1 timers 1 3 + neighbor 192.168.1.1 timers connect 1 +! diff --git a/tests/topotests/bgp_default_originate_timer/r2/zebra.conf b/tests/topotests/bgp_default_originate_timer/r2/zebra.conf new file mode 100644 index 0000000000..0c95656663 --- /dev/null +++ b/tests/topotests/bgp_default_originate_timer/r2/zebra.conf @@ -0,0 +1,4 @@ +! +interface r2-eth0 + ip address 192.168.1.2/24 +! diff --git a/tests/topotests/bgp_default_originate_timer/r3/bgpd.conf b/tests/topotests/bgp_default_originate_timer/r3/bgpd.conf new file mode 100644 index 0000000000..0a37913d73 --- /dev/null +++ b/tests/topotests/bgp_default_originate_timer/r3/bgpd.conf @@ -0,0 +1,12 @@ +router bgp 65003 + no bgp ebgp-requires-policy + neighbor 192.168.2.1 remote-as external + neighbor 192.168.2.1 timers 1 3 + neighbor 192.168.2.1 timers connect 1 + address-family ipv4 unicast + redistribute connected route-map r1 + exit-address-family +! +route-map r1 permit 10 + set community 65003:1 +exit diff --git a/tests/topotests/bgp_default_originate_timer/r3/zebra.conf b/tests/topotests/bgp_default_originate_timer/r3/zebra.conf new file mode 100644 index 0000000000..20801f937e --- /dev/null +++ b/tests/topotests/bgp_default_originate_timer/r3/zebra.conf @@ -0,0 +1,7 @@ +! +interface lo + ip address 10.10.10.10/32 +! +interface r3-eth0 + ip address 192.168.2.2/24 +! diff --git a/tests/topotests/bgp_default_originate_timer/test_bgp_default_originate_timer.py b/tests/topotests/bgp_default_originate_timer/test_bgp_default_originate_timer.py new file mode 100644 index 0000000000..b2ba936fb1 --- /dev/null +++ b/tests/topotests/bgp_default_originate_timer/test_bgp_default_originate_timer.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: ISC + +# +# Copyright (c) 2023 by +# Donatas Abraitis <donatas@opensourcerouting.org> +# + +""" +Check if `bgp default-originate timer` commands takes an effect: +1. Set bgp default-originate timer 3600 +2. No default route is advertised because the timer is running for 3600 seconds +3. We reduce it to 10 seconds +4. Default route is advertised +""" + +import os +import sys +import json +import pytest +import functools + +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.common_config import step + +pytestmark = [pytest.mark.bgpd] + + +def build_topo(tgen): + for routern in range(1, 4): + tgen.add_router("r{}".format(routern)) + + switch = tgen.add_switch("s1") + switch.add_link(tgen.gears["r1"]) + switch.add_link(tgen.gears["r2"]) + + switch = tgen.add_switch("s2") + switch.add_link(tgen.gears["r1"]) + switch.add_link(tgen.gears["r3"]) + + +def setup_module(mod): + tgen = Topogen(build_topo, mod.__name__) + tgen.start_topology() + + router_list = tgen.routers() + + for i, (rname, router) in enumerate(router_list.items(), 1): + router.load_config( + TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)) + ) + router.load_config( + TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname)) + ) + + tgen.start_router() + + +def teardown_module(mod): + tgen = get_topogen() + tgen.stop_topology() + + +def test_bgp_default_originate_timer(): + tgen = get_topogen() + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + r1 = tgen.gears["r1"] + r2 = tgen.gears["r2"] + r3 = tgen.gears["r3"] + + def _bgp_default_received_from_r1(): + output = json.loads(r2.vtysh_cmd("show bgp ipv4 unicast 0.0.0.0/0 json")) + expected = { + "paths": [ + { + "nexthops": [ + { + "hostname": "r1", + "ip": "192.168.1.1", + } + ], + } + ], + } + return topotest.json_cmp(output, expected) + + test_func = functools.partial(_bgp_default_received_from_r1) + _, result = topotest.run_and_expect(test_func, not None, count=30, wait=1) + assert result is not None, "Seen default route received from r1, but should not" + + step("Set BGP default-originate timer to 10 seconds") + r1.vtysh_cmd( + """ + configure terminal + router bgp + bgp default-originate timer 10 + """ + ) + + step("Trigger BGP UPDATE from r3") + r3.vtysh_cmd( + """ + configure terminal + route-map r1 permit 10 + set metric 1 + """ + ) + + test_func = functools.partial(_bgp_default_received_from_r1) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) + assert result is None, "Did not see default route received from r1, but should" + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) |
