]> git.proxmox.com Git - mirror_frr.git/commitdiff
bgpd: Implement BGP-wide configuration for graceful shutdown
authorvivek <vivek@cumulusnetworks.com>
Sat, 19 Sep 2020 21:22:17 +0000 (14:22 -0700)
committervivek <vivek@cumulusnetworks.com>
Sun, 20 Sep 2020 03:38:14 +0000 (20:38 -0700)
Add support for a BGP-wide setting to enter and exit graceful shutdown.
This will apply to all BGP peers across all BGP instances. Per-instance
configuration is disallowed if the BGP-wide setting is in effect.

Signed-off-by: Vivek Venkatraman <vivek@nvidia.com>
bgpd/bgp_vty.c
bgpd/bgpd.h
doc/user/bgp.rst

index 505f743e29dfc48eafcbe7789ccc3ae09e7d5a9e..005fad1409409aadee60e9e117e7c54a265ef465 100644 (file)
@@ -2805,6 +2805,69 @@ DEFUN (no_bgp_graceful_restart_rib_stale_time,
        return CMD_SUCCESS;
 }
 
+static inline void bgp_initiate_graceful_shut_unshut(struct vty *vty,
+                                                    struct bgp *bgp)
+{
+       bgp_static_redo_import_check(bgp);
+       bgp_redistribute_redo(bgp);
+       bgp_clear_star_soft_out(vty, bgp->name);
+       bgp_clear_star_soft_in(vty, bgp->name);
+}
+
+static int bgp_global_graceful_shutdown_config_vty(struct vty *vty)
+{
+       struct listnode *node, *nnode;
+       struct bgp *bgp;
+       bool vrf_cfg = false;
+
+       if (CHECK_FLAG(bm->flags, BM_FLAG_GRACEFUL_SHUTDOWN))
+               return CMD_SUCCESS;
+
+       /* See if graceful-shutdown is set per-vrf and warn user to delete */
+       for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
+               if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN)) {
+                       vty_out(vty,
+                               "%% graceful-shutdown configuration found in vrf %s\n",
+                               bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT ?
+                                       VRF_DEFAULT_NAME : bgp->name);
+                       vrf_cfg = true;
+               }
+       }
+
+       if (vrf_cfg) {
+               vty_out(vty,
+                       "%%Failed: global graceful-shutdown not permitted\n");
+               return CMD_WARNING;
+       }
+
+       /* Set flag globally */
+       SET_FLAG(bm->flags, BM_FLAG_GRACEFUL_SHUTDOWN);
+
+       /* Initiate processing for all BGP instances. */
+       for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
+               bgp_initiate_graceful_shut_unshut(vty, bgp);
+
+       return CMD_SUCCESS;
+}
+
+static int bgp_global_graceful_shutdown_deconfig_vty(struct vty *vty)
+{
+       struct listnode *node, *nnode;
+       struct bgp *bgp;
+
+       if (!CHECK_FLAG(bm->flags, BM_FLAG_GRACEFUL_SHUTDOWN))
+               return CMD_SUCCESS;
+
+       /* Unset flag globally */
+       UNSET_FLAG(bm->flags, BM_FLAG_GRACEFUL_SHUTDOWN);
+
+       /* Initiate processing for all BGP instances. */
+       for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
+               bgp_initiate_graceful_shut_unshut(vty, bgp);
+
+       return CMD_SUCCESS;
+}
+
 /* "bgp graceful-shutdown" configuration */
 DEFUN (bgp_graceful_shutdown,
        bgp_graceful_shutdown_cmd,
@@ -2812,14 +2875,21 @@ DEFUN (bgp_graceful_shutdown,
        BGP_STR
        "Graceful shutdown parameters\n")
 {
+       if (vty->node == CONFIG_NODE)
+               return bgp_global_graceful_shutdown_config_vty(vty);
+
        VTY_DECLVAR_CONTEXT(bgp, bgp);
 
+       /* if configured globally, per-instance config is not allowed */
+       if (CHECK_FLAG(bm->flags, BM_FLAG_GRACEFUL_SHUTDOWN)) {
+               vty_out(vty,
+                       "%%Failed: per-vrf graceful-shutdown config not permitted with global graceful-shutdown\n");
+               return CMD_WARNING_CONFIG_FAILED;
+       }
+
        if (!CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN)) {
                SET_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN);
-               bgp_static_redo_import_check(bgp);
-               bgp_redistribute_redo(bgp);
-               bgp_clear_star_soft_out(vty, bgp->name);
-               bgp_clear_star_soft_in(vty, bgp->name);
+               bgp_initiate_graceful_shut_unshut(vty, bgp);
        }
 
        return CMD_SUCCESS;
@@ -2832,14 +2902,21 @@ DEFUN (no_bgp_graceful_shutdown,
        BGP_STR
        "Graceful shutdown parameters\n")
 {
+       if (vty->node == CONFIG_NODE)
+               return bgp_global_graceful_shutdown_deconfig_vty(vty);
+
        VTY_DECLVAR_CONTEXT(bgp, bgp);
 
+       /* If configured globally, cannot remove from one bgp instance */
+       if (CHECK_FLAG(bm->flags, BM_FLAG_GRACEFUL_SHUTDOWN)) {
+               vty_out(vty,
+                       "%%Failed: bgp graceful-shutdown configured globally. Delete per-vrf not permitted\n");
+               return CMD_WARNING_CONFIG_FAILED;
+       }
+
        if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN)) {
                UNSET_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN);
-               bgp_static_redo_import_check(bgp);
-               bgp_redistribute_redo(bgp);
-               bgp_clear_star_soft_out(vty, bgp->name);
-               bgp_clear_star_soft_in(vty, bgp->name);
+               bgp_initiate_graceful_shut_unshut(vty, bgp);
        }
 
        return CMD_SUCCESS;
@@ -6386,7 +6463,6 @@ DEFUN (no_bgp_set_route_map_delay_timer,
        return CMD_SUCCESS;
 }
 
-
 /* neighbor interface */
 static int peer_interface_vty(struct vty *vty, const char *ip_str,
                              const char *str)
@@ -15528,6 +15604,9 @@ int bgp_config_write(struct vty *vty)
                vty_out(vty, "\n");
        }
 
+       if (CHECK_FLAG(bm->flags, BM_FLAG_GRACEFUL_SHUTDOWN))
+               vty_out(vty, "bgp graceful-shutdown\n");
+
        /* BGP configuration. */
        for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
 
@@ -15679,6 +15758,14 @@ int bgp_config_write(struct vty *vty)
                /* coalesce time */
                bgp_config_write_coalesce_time(vty, bgp);
 
+               /* BGP per-instance graceful-shutdown */
+               /* BGP-wide settings and per-instance settings are mutually
+                * exclusive.
+                */
+               if (!CHECK_FLAG(bm->flags, BM_FLAG_GRACEFUL_SHUTDOWN))
+                       if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN))
+                               vty_out(vty, " bgp graceful-shutdown\n");
+
                /* BGP graceful-restart. */
                if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
                        vty_out(vty,
@@ -15700,10 +15787,6 @@ int bgp_config_write(struct vty *vty)
                if (bgp_global_gr_mode_get(bgp) == GLOBAL_DISABLE)
                        vty_out(vty, " bgp graceful-restart-disable\n");
 
-               /* BGP graceful-shutdown */
-               if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN))
-                       vty_out(vty, " bgp graceful-shutdown\n");
-
                /* BGP graceful-restart Preserve State F bit. */
                if (CHECK_FLAG(bgp->flags, BGP_FLAG_GR_PRESERVE_FWD))
                        vty_out(vty,
@@ -16046,6 +16129,10 @@ void bgp_vty_init(void)
        install_element(CONFIG_NODE, &bgp_global_update_delay_cmd);
        install_element(CONFIG_NODE, &no_bgp_global_update_delay_cmd);
 
+       /* global bgp graceful-shutdown command */
+       install_element(CONFIG_NODE, &bgp_graceful_shutdown_cmd);
+       install_element(CONFIG_NODE, &no_bgp_graceful_shutdown_cmd);
+
        /* Dummy commands (Currently not supported) */
        install_element(BGP_NODE, &no_synchronization_cmd);
        install_element(BGP_NODE, &no_auto_summary_cmd);
index 6293c4136c936b348c74f0bd1b3e3a038ce6b35d..e282e461dfeb6ce618a9861de4a1d24f8537c464 100644 (file)
@@ -173,6 +173,9 @@ struct bgp_master {
        uint16_t v_update_delay;
        uint16_t v_establish_wait;
 
+       uint32_t flags;
+#define BM_FLAG_GRACEFUL_SHUTDOWN        (1 << 0)
+
        bool terminating;       /* global flag that sigint terminate seen */
        QOBJ_FIELDS
 };
@@ -2159,7 +2162,9 @@ static inline void bgp_vrf_unlink(struct bgp *bgp, struct vrf *vrf)
 
 static inline bool bgp_in_graceful_shutdown(struct bgp *bgp)
 {
-       return !!CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN);
+       /* True if either set for this instance or globally */
+       return (!!CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN) ||
+               !!CHECK_FLAG(bm->flags, BM_FLAG_GRACEFUL_SHUTDOWN));
 }
 
 extern void bgp_unset_redist_vrf_bitmaps(struct bgp *, vrf_id_t);
index 764428cb0ae72267c68c375d796cec143c2c3ccb..723cb41f26775524d08c63c24ef436ec76d80daf 100644 (file)
@@ -2732,6 +2732,32 @@ The following are available in the ``router bgp`` mode:
    at a time in a loop. This setting controls how many iterations the loop runs
    for. As with write-quanta, it is best to leave this setting on the default.
 
+The following command is available in ``config`` mode as well as in the
+``router bgp`` mode:
+
+.. index:: bgp graceful-shutdown
+.. clicmd:: bgp graceful-shutdown
+
+   The purpose of this command is to initiate BGP Graceful Shutdown which
+   is described in :rfc:`8326`. The use case for this is to minimize or
+   eliminate the amount of traffic loss in a network when a planned
+   maintenance activity such as software upgrade or hardware replacement
+   is to be performed on a router. The feature works by re-announcing
+   routes to eBGP peers with the GRACEFUL_SHUTDOWN community included.
+   Peers are then expected to treat such paths with the lowest preference.
+   This happens automatically on a receiver running FRR; with other
+   routing protocol stacks, an inbound policy may have to be configured.
+   In FRR, triggering graceful shutdown also results in announcing a
+   LOCAL_PREF of 0 to iBGP peers.
+
+   Graceful shutdown can be configured per BGP instance or globally for
+   all of BGP. These two options are mutually exclusive. The no form of
+   the command causes graceful shutdown to be stopped, and routes will
+   be re-announced without the GRACEFUL_SHUTDOWN community and/or with
+   the usual LOCAL_PREF value. Note that if this option is saved to
+   the startup configuration, graceful shutdown will remain in effect
+   across restarts of *bgpd* and will need to be explicitly disabled.
+
 .. _bgp-displaying-bgp-information:
 
 Displaying BGP Information