From c163f2971b38cf98653a5b1ddd123b4600c23d13 Mon Sep 17 00:00:00 2001 From: David Schweizer Date: Wed, 2 Sep 2020 18:20:08 +0200 Subject: [PATCH 1/3] bgpd: set/unset bgpd no-rib option at runtime * Added vtysh cli commands and functions to set/unset bgp daemons no-rib option during runtime and withdraw/announce routes in bgp instances RIB from/to Zebra. Signed-off-by: David Schweizer --- bgpd/bgp_vty.c | 43 +++++++++++++++++++++++++++++++++++++++++++ bgpd/bgp_zebra.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ bgpd/bgp_zebra.h | 8 ++++++++ bgpd/bgpd.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ bgpd/bgpd.h | 6 ++++++ 5 files changed, 151 insertions(+) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 005fad1409..795a4adfc7 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -1411,6 +1411,41 @@ DEFUN (no_bgp_cluster_id, return CMD_SUCCESS; } +DEFPY (bgp_norib, + bgp_norib_cmd, + "bgp no-rib", + BGP_STR + "Disable BGP route installation to RIB (Zebra)\n") +{ + if (bgp_option_check(BGP_OPT_NO_FIB)) { + vty_out(vty, + "%% No-RIB option is already set, nothing to do here.\n"); + return CMD_SUCCESS; + } + + bgp_option_norib_set_runtime(); + + return CMD_SUCCESS; +} + +DEFPY (no_bgp_norib, + no_bgp_norib_cmd, + "no bgp no-rib", + NO_STR + BGP_STR + "Disable BGP route installation to RIB (Zebra)\n") +{ + if (!bgp_option_check(BGP_OPT_NO_FIB)) { + vty_out(vty, + "%% No-RIB option is not set, nothing to do here.\n"); + return CMD_SUCCESS; + } + + bgp_option_norib_unset_runtime(); + + return CMD_SUCCESS; +} + DEFUN (bgp_confederation_identifier, bgp_confederation_identifier_cmd, "bgp confederation identifier (1-4294967295)", @@ -15607,6 +15642,10 @@ int bgp_config_write(struct vty *vty) if (CHECK_FLAG(bm->flags, BM_FLAG_GRACEFUL_SHUTDOWN)) vty_out(vty, "bgp graceful-shutdown\n"); + /* No-RIB (Zebra) option flag configuration */ + if (bgp_option_check(BGP_OPT_NO_FIB)) + vty_out(vty, "bgp no-rib\n"); + /* BGP configuration. */ for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) { @@ -16151,6 +16190,10 @@ void bgp_vty_init(void) install_element(BGP_NODE, &bgp_cluster_id_cmd); install_element(BGP_NODE, &no_bgp_cluster_id_cmd); + /* "bgp no-rib" commands. */ + install_element(CONFIG_NODE, &bgp_norib_cmd); + install_element(CONFIG_NODE, &no_bgp_norib_cmd); + /* "bgp confederation" commands. */ install_element(BGP_NODE, &bgp_confederation_identifier_cmd); install_element(BGP_NODE, &no_bgp_confederation_identifier_cmd); diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index b203238520..a32e47f446 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1543,6 +1543,30 @@ void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi) pi, bgp, afi, safi); } +/* Announce routes of any bgp subtype of a table to zebra */ +void bgp_zebra_announce_table_all_subtypes(struct bgp *bgp, afi_t afi, + safi_t safi) +{ + struct bgp_dest *dest; + struct bgp_table *table; + struct bgp_path_info *pi; + + if (!bgp_install_info_to_zebra(bgp)) + return; + + table = bgp->rib[afi][safi]; + if (!table) + return; + + for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) + for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) + if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED) && + pi->type == ZEBRA_ROUTE_BGP) + bgp_zebra_announce(dest, + bgp_dest_get_prefix(dest), + pi, bgp, afi, safi); +} + void bgp_zebra_withdraw(const struct prefix *p, struct bgp_path_info *info, struct bgp *bgp, safi_t safi) { @@ -1586,6 +1610,30 @@ void bgp_zebra_withdraw(const struct prefix *p, struct bgp_path_info *info, zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api); } +/* Withdraw all entries in a BGP instances RIB table from Zebra */ +void bgp_zebra_withdraw_table_all_subtypes(struct bgp *bgp, afi_t afi, safi_t safi) +{ + struct bgp_dest *dest; + struct bgp_table *table; + struct bgp_path_info *pi; + + if (!bgp_install_info_to_zebra(bgp)) + return; + + table = bgp->rib[afi][safi]; + if (!table) + return; + + for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) { + for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) { + if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED) + && (pi->type == ZEBRA_ROUTE_BGP)) + bgp_zebra_withdraw(bgp_dest_get_prefix(dest), + pi, bgp, safi); + } + } +} + struct bgp_redist *bgp_redist_lookup(struct bgp *bgp, afi_t afi, uint8_t type, unsigned short instance) { diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h index a068c03717..4b357c380a 100644 --- a/bgpd/bgp_zebra.h +++ b/bgpd/bgp_zebra.h @@ -43,6 +43,14 @@ extern void bgp_zebra_withdraw(const struct prefix *p, struct bgp_path_info *path, struct bgp *bgp, safi_t safi); +/* Announce routes of any bgp subtype of a table to zebra */ +extern void bgp_zebra_announce_table_all_subtypes(struct bgp *bgp, afi_t afi, + safi_t safi); + +/* Withdraw all entries of any subtype in a BGP instances RIB table from Zebra */ +extern void bgp_zebra_withdraw_table_all_subtypes(struct bgp *bgp, afi_t afi, + safi_t safi); + extern void bgp_zebra_initiate_radv(struct bgp *bgp, struct peer *peer); extern void bgp_zebra_terminate_radv(struct bgp *bgp, struct peer *peer); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index b654e85206..84d4aeb1e6 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -202,6 +202,52 @@ int bgp_option_check(int flag) return CHECK_FLAG(bm->options, flag); } +/* set the bgp no-rib option during runtime and remove installed routes */ +void bgp_option_norib_set_runtime(void) +{ + struct bgp *bgp; + struct listnode *node; + afi_t afi; + safi_t safi; + + if (bgp_option_check(BGP_OPT_NO_FIB)) + return; + + bgp_option_set(BGP_OPT_NO_FIB); + + zlog_info("Disabled BGP route installation to RIB (Zebra)"); + + for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp)) { + FOREACH_AFI_SAFI(afi, safi) + bgp_zebra_withdraw_table_all_subtypes(bgp, afi, safi); + } + + zlog_info("All routes have been withdrawn from RIB (Zebra)"); +} + +/* unset the bgp no-rib option during runtime and announce routes to Zebra */ +void bgp_option_norib_unset_runtime(void) +{ + struct bgp *bgp; + struct listnode *node; + afi_t afi; + safi_t safi; + + if (!bgp_option_check(BGP_OPT_NO_FIB)) + return; + + bgp_option_unset(BGP_OPT_NO_FIB); + + zlog_info("Enabled BGP route installation to RIB (Zebra)"); + + for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp)) { + FOREACH_AFI_SAFI(afi, safi) + bgp_zebra_announce_table_all_subtypes(bgp, afi, safi); + } + + zlog_info("All routes have been installed in RIB (Zebra)"); +} + /* Internal function to set BGP structure configureation flag. */ static void bgp_config_set(struct bgp *bgp, int config) { diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index e282e461df..9f72a3e19e 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -1807,6 +1807,12 @@ extern int bgp_option_set(int); extern int bgp_option_unset(int); extern int bgp_option_check(int); +/* set the bgp no-rib option during runtime and remove installed routes */ +extern void bgp_option_norib_set_runtime(void); + +/* unset the bgp no-rib option during runtime and reset all peers */ +extern void bgp_option_norib_unset_runtime(void); + extern int bgp_get(struct bgp **, as_t *, const char *, enum bgp_instance_type); extern void bgp_instance_up(struct bgp *); extern void bgp_instance_down(struct bgp *); From 251931afbd848bf39eb1f60a9887e7e701cb960a Mon Sep 17 00:00:00 2001 From: David Schweizer Date: Wed, 2 Sep 2020 18:20:09 +0200 Subject: [PATCH 2/3] tests: Enhance bgp_features topotest suite with tests for "bgp no-rib" Signed-off-by: Martin Winter Signed-off-by: David Schweizer --- tests/topotests/bgp_features/r1/ip_route.json | 382 ++++++++++++++++++ .../bgp_features/r1/ip_route_norib.json | 296 ++++++++++++++ .../bgp_features/test_bgp_features.py | 129 +++++- 3 files changed, 806 insertions(+), 1 deletion(-) create mode 100644 tests/topotests/bgp_features/r1/ip_route.json create mode 100644 tests/topotests/bgp_features/r1/ip_route_norib.json diff --git a/tests/topotests/bgp_features/r1/ip_route.json b/tests/topotests/bgp_features/r1/ip_route.json new file mode 100644 index 0000000000..cf1764140a --- /dev/null +++ b/tests/topotests/bgp_features/r1/ip_route.json @@ -0,0 +1,382 @@ +{ + "0.0.0.0\/0":[ + { + "prefix":"0.0.0.0\/0", + "protocol":"bgp", + "selected":true, + "destSelected":true, + "distance":20, + "metric":0, + "installed":true, + "nexthops":[ + { + "flags":3, + "fib":true, + "ip":"192.168.101.2", + "afi":"ipv4", + "interfaceIndex":4, + "interfaceName":"r1-eth3", + "active":true, + "weight":1 + } + ] + } + ], + "192.168.0.1\/32":[ + { + "prefix":"192.168.0.1\/32", + "protocol":"ospf", + "distance":110, + "metric":0, + "nexthops":[ + { + "flags":1, + "directlyConnected":true, + "interfaceIndex":1, + "interfaceName":"lo", + "active":true, + "weight":1 + } + ] + }, + { + "prefix":"192.168.0.1\/32", + "protocol":"connected", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true, + "interfaceIndex":1, + "interfaceName":"lo", + "active":true + } + ] + } + ], + "192.168.0.2\/32":[ + { + "prefix":"192.168.0.2\/32", + "protocol":"ospf", + "selected":true, + "destSelected":true, + "distance":110, + "metric":10, + "installed":true, + "nexthops":[ + { + "flags":3, + "fib":true, + "ip":"192.168.1.2", + "afi":"ipv4", + "interfaceIndex":2, + "interfaceName":"r1-eth1", + "active":true, + "weight":1 + } + ] + } + ], + "192.168.0.3\/32":[ + { + "prefix":"192.168.0.3\/32", + "protocol":"ospf", + "selected":true, + "destSelected":true, + "distance":110, + "metric":10, + "installed":true, + "nexthops":[ + { + "flags":3, + "fib":true, + "ip":"192.168.3.2", + "afi":"ipv4", + "interfaceIndex":3, + "interfaceName":"r1-eth2", + "active":true, + "weight":1 + } + ] + } + ], + "192.168.1.0\/24":[ + { + "prefix":"192.168.1.0\/24", + "protocol":"ospf", + "distance":110, + "metric":10, + "table":254, + "nexthops":[ + { + "flags":1, + "directlyConnected":true, + "interfaceIndex":2, + "interfaceName":"r1-eth1", + "active":true, + "weight":1 + } + ] + }, + { + "prefix":"192.168.1.0\/24", + "protocol":"connected", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true, + "interfaceIndex":2, + "interfaceName":"r1-eth1", + "active":true + } + ] + } + ], + "192.168.2.0\/24":[ + { + "prefix":"192.168.2.0\/24", + "protocol":"ospf", + "selected":true, + "destSelected":true, + "distance":110, + "metric":20, + "installed":true, + "nexthops":[ + { + "flags":3, + "fib":true, + "ip":"192.168.1.2", + "afi":"ipv4", + "interfaceIndex":2, + "interfaceName":"r1-eth1", + "active":true, + "weight":1 + }, + { + "flags":3, + "fib":true, + "ip":"192.168.3.2", + "afi":"ipv4", + "interfaceIndex":3, + "interfaceName":"r1-eth2", + "active":true, + "weight":1 + } + ] + } + ], + "192.168.3.0\/24":[ + { + "prefix":"192.168.3.0\/24", + "protocol":"ospf", + "distance":110, + "metric":10, + "nexthops":[ + { + "flags":1, + "directlyConnected":true, + "interfaceIndex":3, + "interfaceName":"r1-eth2", + "active":true, + "weight":1 + } + ] + }, + { + "prefix":"192.168.3.0\/24", + "protocol":"connected", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true, + "interfaceIndex":3, + "interfaceName":"r1-eth2", + "active":true + } + ] + } + ], + "192.168.6.0\/24":[ + { + "prefix":"192.168.6.0\/24", + "protocol":"ospf", + "distance":110, + "metric":10, + "nexthops":[ + { + "flags":1, + "directlyConnected":true, + "interfaceIndex":5, + "interfaceName":"r1-eth0", + "active":true, + "weight":1 + } + ] + }, + { + "prefix":"192.168.6.0\/24", + "protocol":"connected", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true, + "interfaceIndex":5, + "interfaceName":"r1-eth0", + "active":true + } + ] + } + ], + "192.168.7.0\/24":[ + { + "prefix":"192.168.7.0\/24", + "protocol":"bgp", + "distance":200, + "metric":0, + "nexthops":[ + { + "flags":5, + "ip":"192.168.0.2", + "afi":"ipv4", + "active":true, + "recursive":true, + "weight":1 + }, + { + "flags":1, + "ip":"192.168.1.2", + "afi":"ipv4", + "interfaceIndex":2, + "interfaceName":"r1-eth1", + "active":true, + "weight":1 + } + ] + }, + { + "prefix":"192.168.7.0\/24", + "protocol":"ospf", + "selected":true, + "destSelected":true, + "distance":110, + "metric":20, + "installed":true, + "nexthops":[ + { + "flags":3, + "fib":true, + "ip":"192.168.1.2", + "afi":"ipv4", + "interfaceIndex":2, + "interfaceName":"r1-eth1", + "active":true, + "weight":1 + } + ] + } + ], + "192.168.8.0\/24":[ + { + "prefix":"192.168.8.0\/24", + "protocol":"ospf", + "selected":true, + "destSelected":true, + "distance":110, + "metric":20, + "installed":true, + "nexthops":[ + { + "flags":3, + "fib":true, + "ip":"192.168.3.2", + "afi":"ipv4", + "interfaceIndex":3, + "interfaceName":"r1-eth2", + "active":true, + "weight":1 + } + ] + } + ], + "192.168.101.0\/24":[ + { + "prefix":"192.168.101.0\/24", + "protocol":"bgp", + "distance":20, + "metric":0, + "nexthops":[ + { + "flags":0, + "ip":"192.168.101.2", + "afi":"ipv4", + "weight":1 + } + ] + }, + { + "prefix":"192.168.101.0\/24", + "protocol":"connected", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true, + "interfaceIndex":4, + "interfaceName":"r1-eth3", + "active":true + } + ] + } + ], + "192.168.102.0\/24":[ + { + "prefix":"192.168.102.0\/24", + "protocol":"bgp", + "selected":true, + "destSelected":true, + "distance":20, + "metric":0, + "installed":true, + "nexthops":[ + { + "flags":3, + "fib":true, + "ip":"192.168.101.2", + "afi":"ipv4", + "interfaceIndex":4, + "interfaceName":"r1-eth3", + "active":true, + "weight":1 + } + ] + } + ] +} diff --git a/tests/topotests/bgp_features/r1/ip_route_norib.json b/tests/topotests/bgp_features/r1/ip_route_norib.json new file mode 100644 index 0000000000..30f67f53a4 --- /dev/null +++ b/tests/topotests/bgp_features/r1/ip_route_norib.json @@ -0,0 +1,296 @@ +{ + "192.168.0.1\/32":[ + { + "prefix":"192.168.0.1\/32", + "protocol":"ospf", + "distance":110, + "metric":0, + "nexthops":[ + { + "flags":1, + "directlyConnected":true, + "interfaceIndex":1, + "interfaceName":"lo", + "active":true, + "weight":1 + } + ] + }, + { + "prefix":"192.168.0.1\/32", + "protocol":"connected", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true, + "interfaceIndex":1, + "interfaceName":"lo", + "active":true + } + ] + } + ], + "192.168.0.2\/32":[ + { + "prefix":"192.168.0.2\/32", + "protocol":"ospf", + "selected":true, + "destSelected":true, + "distance":110, + "metric":10, + "installed":true, + "nexthops":[ + { + "flags":3, + "fib":true, + "ip":"192.168.1.2", + "afi":"ipv4", + "interfaceIndex":2, + "interfaceName":"r1-eth1", + "active":true, + "weight":1 + } + ] + } + ], + "192.168.0.3\/32":[ + { + "prefix":"192.168.0.3\/32", + "protocol":"ospf", + "selected":true, + "destSelected":true, + "distance":110, + "metric":10, + "installed":true, + "nexthops":[ + { + "flags":3, + "fib":true, + "ip":"192.168.3.2", + "afi":"ipv4", + "interfaceIndex":3, + "interfaceName":"r1-eth2", + "active":true, + "weight":1 + } + ] + } + ], + "192.168.1.0\/24":[ + { + "prefix":"192.168.1.0\/24", + "protocol":"ospf", + "distance":110, + "metric":10, + "nexthops":[ + { + "flags":1, + "directlyConnected":true, + "interfaceIndex":2, + "interfaceName":"r1-eth1", + "active":true, + "weight":1 + } + ] + }, + { + "prefix":"192.168.1.0\/24", + "protocol":"connected", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true, + "interfaceIndex":2, + "interfaceName":"r1-eth1", + "active":true + } + ] + } + ], + "192.168.2.0\/24":[ + { + "prefix":"192.168.2.0\/24", + "protocol":"ospf", + "selected":true, + "destSelected":true, + "distance":110, + "metric":20, + "installed":true, + "nexthops":[ + { + "flags":3, + "fib":true, + "ip":"192.168.1.2", + "afi":"ipv4", + "interfaceIndex":2, + "interfaceName":"r1-eth1", + "active":true, + "weight":1 + }, + { + "flags":3, + "fib":true, + "ip":"192.168.3.2", + "afi":"ipv4", + "interfaceIndex":3, + "interfaceName":"r1-eth2", + "active":true, + "weight":1 + } + ] + } + ], + "192.168.3.0\/24":[ + { + "prefix":"192.168.3.0\/24", + "protocol":"ospf", + "distance":110, + "metric":10, + "nexthops":[ + { + "flags":1, + "directlyConnected":true, + "interfaceIndex":3, + "interfaceName":"r1-eth2", + "active":true, + "weight":1 + } + ] + }, + { + "prefix":"192.168.3.0\/24", + "protocol":"connected", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true, + "interfaceIndex":3, + "interfaceName":"r1-eth2", + "active":true + } + ] + } + ], + "192.168.6.0\/24":[ + { + "prefix":"192.168.6.0\/24", + "protocol":"ospf", + "distance":110, + "metric":10, + "nexthops":[ + { + "flags":1, + "directlyConnected":true, + "interfaceIndex":5, + "interfaceName":"r1-eth0", + "active":true, + "weight":1 + } + ] + }, + { + "prefix":"192.168.6.0\/24", + "protocol":"connected", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true, + "interfaceIndex":5, + "interfaceName":"r1-eth0", + "active":true + } + ] + } + ], + "192.168.7.0\/24":[ + { + "prefix":"192.168.7.0\/24", + "protocol":"ospf", + "selected":true, + "destSelected":true, + "distance":110, + "metric":20, + "installed":true, + "nexthops":[ + { + "flags":3, + "fib":true, + "ip":"192.168.1.2", + "afi":"ipv4", + "interfaceIndex":2, + "interfaceName":"r1-eth1", + "active":true, + "weight":1 + } + ] + } + ], + "192.168.8.0\/24":[ + { + "prefix":"192.168.8.0\/24", + "protocol":"ospf", + "selected":true, + "destSelected":true, + "distance":110, + "metric":20, + "installed":true, + "nexthops":[ + { + "flags":3, + "fib":true, + "ip":"192.168.3.2", + "afi":"ipv4", + "interfaceIndex":3, + "interfaceName":"r1-eth2", + "active":true, + "weight":1 + } + ] + } + ], + "192.168.101.0\/24":[ + { + "prefix":"192.168.101.0\/24", + "protocol":"connected", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "nexthops":[ + { + "flags":3, + "fib":true, + "directlyConnected":true, + "interfaceIndex":4, + "interfaceName":"r1-eth3", + "active":true + } + ] + } + ] +} diff --git a/tests/topotests/bgp_features/test_bgp_features.py b/tests/topotests/bgp_features/test_bgp_features.py index 7c45ca8a29..4ec060b642 100644 --- a/tests/topotests/bgp_features/test_bgp_features.py +++ b/tests/topotests/bgp_features/test_bgp_features.py @@ -102,7 +102,7 @@ def setup_module(module): # Starting Routers router_list = tgen.routers() - for rname, router in router_list.items(): + for rname, router in router_list.iteritems(): router.load_config( TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)) ) @@ -538,6 +538,133 @@ def test_bgp_remove_metric_rmaps(): assert res is None, assertmsg +def test_bgp_norib(): + "Test BGP disable RIB (Zebra) Route Install" + + tgen = get_topogen() + + # Skip if previous fatal error condition is raised + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + logger.info("Configuring 'bgp no-rib' on router r1") + + tgen.net['r1'].cmd('vtysh -c \"conf t\" -c \"bgp no-rib\"') + + # Checking BGP config - should show the "bgp no-rib" under the router bgp section + logger.info("Checking BGP configuration for 'bgp no-rib'") + + norib_cfg = tgen.net['r1'].cmd('vtysh -c "show running bgpd" | grep "^bgp no-rib"').rstrip() + + assertmsg = "'bgp no-rib' configuration applied, but not visible in configuration" + assert norib_cfg == 'bgp no-rib', assertmsg + + +def test_bgp_norib_routes(): + "Test Routes in Zebra and BGP with the 'bgp-norib' configuration" + + tgen = get_topogen() + + # Skip if previous fatal error condition is raised + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Checking local BGP routes - they need to be gone from Zebra + logger.info("Checking Zebra routes after removing bgp shutdown on router r1") + + router = tgen.gears["r1"] + reffile = os.path.join(CWD, "r1/ip_route_norib.json") + expected = json.loads(open(reffile).read()) + + test_func = functools.partial( + topotest.router_json_cmp, router, "show ip route json", expected + ) + _, res = topotest.run_and_expect(test_func, None, count=30, wait=2) + assertmsg = "Zebra IPv4 Routes after configuring 'bgp no-rib' (There should be no BGP routes in Zebra anymore)" + assert res is None, assertmsg + + # Check BGP Summary on local and remote routers + for rtrNum in [1, 2, 4]: + logger.info("Checking BGP Summary after 'bgp no-rib' on router r1 on router r{}".format(rtrNum)) + + router = tgen.gears["r{}".format(rtrNum)] + reffile = os.path.join(CWD, "r{}/bgp_summary.json".format(rtrNum)) + expected = json.loads(open(reffile).read()) + + test_func = functools.partial( + topotest.router_json_cmp, router, "show ip bgp summary json", expected + ) + _, res = topotest.run_and_expect(test_func, None, count=30, wait=2) + assertmsg = "BGP sessions on router R{} has incorrect routes after adding 'bgp no-rib on r1'".format(rtrNum) + assert res is None, assertmsg + + # tgen.mininet_cli() + + +def test_bgp_disable_norib(): + "Test BGP disabling the no-RIB (Zebra) Route Install" + + tgen = get_topogen() + + # Skip if previous fatal error condition is raised + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + logger.info("Configuring 'no bgp no-rib' on router r1") + + tgen.net['r1'].cmd('vtysh -c \"conf t\" -c \"no bgp no-rib\"') + + # Checking BGP config - should show the "bgp no-rib" under the router bgp section + logger.info("Checking BGP configuration for 'bgp no-rib'") + + norib_cfg = tgen.net['r1'].cmd('vtysh -c "show running bgpd" | grep "^ bgp no-rib"').rstrip() + + assertmsg = "'no bgp no-rib'configuration applied, but still visible in configuration" + assert norib_cfg == '', assertmsg + + +def test_bgp_disable_norib_routes(): + "Test Routes in Zebra and BGP with the 'bgp-norib' configuration" + + tgen = get_topogen() + + # Skip if previous fatal error condition is raised + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Checking local BGP routes - they need to be gone from Zebra + logger.info("Checking Zebra routes after removing bgp shutdown on router r1") + + router = tgen.gears["r1"] + reffile = os.path.join(CWD, "r1/ip_route.json") + expected = json.loads(open(reffile).read()) + + test_func = functools.partial( + topotest.router_json_cmp, router, "show ip route json", expected + ) + _, res = topotest.run_and_expect(test_func, None, count=30, wait=2) + assertmsg = "Zebra IPv4 Routes wrong after removing the 'bgp no-rib'" + assert res is None, assertmsg + + # Check BGP Summary on local and remote routers + for rtrNum in [1, 2, 4]: + logger.info("Checking BGP Summary after removing the 'bgp no-rib' on router r1 on router r{}".format(rtrNum)) + + router = tgen.gears["r{}".format(rtrNum)] + reffile = os.path.join(CWD, "r{}/bgp_summary.json".format(rtrNum)) + expected = json.loads(open(reffile).read()) + + test_func = functools.partial( + topotest.router_json_cmp, router, "show ip bgp summary json", expected + ) + _, res = topotest.run_and_expect(test_func, None, count=30, wait=2) + assertmsg = "BGP sessions on router R{} has incorrect routes after removing 'bgp no-rib on r1'".format(rtrNum) + assert res is None, assertmsg + + # tgen.mininet_cli() + + + if __name__ == "__main__": args = ["-s"] + sys.argv[1:] sys.exit(pytest.main(args)) From 8dad2243e8b83051632d4f95378f3d9674a3604c Mon Sep 17 00:00:00 2001 From: David Schweizer Date: Wed, 2 Sep 2020 18:20:10 +0200 Subject: [PATCH 3/3] doc: user doc for bgpd no-rib option vtysh cmds * Added an entry in the user documentation for the BGP daemon no-rib option vty shell commands. Signed-off-by: David Schweizer --- doc/user/bgp.rst | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst index 723cb41f26..10eaaee9fb 100644 --- a/doc/user/bgp.rst +++ b/doc/user/bgp.rst @@ -42,6 +42,13 @@ be specified (:ref:`common-invocation-options`). processes in the same namespace. This option is different than the --no_zebra option in that a ZAPI connection is made. + This option can also be toggled during runtime by using the + ``[no] bgp no-rib`` commands in VTY shell. + + Note that this option will persist after saving the configuration during + runtime, unless unset by the ``no bgp no-rib`` command in VTY shell prior to + a configuration write operation. + .. option:: -S, --skip_runas Skip the normal process of checking capabilities and changing user and group @@ -3072,6 +3079,21 @@ by route reflectors to avoid looping. .. index:: bgp cluster-id A.B.C.D .. clicmd:: bgp cluster-id A.B.C.D +.. index:: [no] bgp no-rib +.. clicmd:: [no] bgp no-rib + +To set and unset the BGP daemon ``-n`` / ``--no_kernel`` options during runtime +to disable BGP route installation to the RIB (Zebra), the ``[no] bgp no-rib`` +commands can be used; + +Please note that setting the option during runtime will withdraw all routes in +the daemons RIB from Zebra and unsetting it will announce all routes in the +daemons RIB to Zebra. If the option is passed as a command line argument when +starting the daemon and the configuration gets saved, the option will persist +unless removed from the configuration with the negating command prior to the +configuration write operation. + + .. _routing-policy: Routing Policy