summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_vty.c43
-rw-r--r--bgpd/bgp_zebra.c48
-rw-r--r--bgpd/bgp_zebra.h8
-rw-r--r--bgpd/bgpd.c46
-rw-r--r--bgpd/bgpd.h6
-rw-r--r--doc/user/bgp.rst22
-rw-r--r--tests/topotests/bgp_features/r1/ip_route.json382
-rw-r--r--tests/topotests/bgp_features/r1/ip_route_norib.json296
-rw-r--r--tests/topotests/bgp_features/test_bgp_features.py129
9 files changed, 979 insertions, 1 deletions
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 3c707b41ca..4260970541 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 *);
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
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))