mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-03 00:13:40 +00:00
bgpd: Implement BGP-wide configuration for graceful shutdown
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>
This commit is contained in:
parent
637e5ba492
commit
05bd726cfe
113
bgpd/bgp_vty.c
113
bgpd/bgp_vty.c
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user