From 9cf59432578d12f26c59676a709af39cdc204312 Mon Sep 17 00:00:00 2001 From: David Schweizer Date: Thu, 13 Aug 2020 17:52:49 +0200 Subject: [PATCH] bgpd: bgp instance administrative shutdown. * Changes allow administratively shutting down all peers of a BGP instance. * New CLI commands "[no] bgp shutdown" in vty shell. * For review and testing only. Signed-off-by: David Schweizer --- bgpd/bgp_vty.c | 35 +++++++++++++++++++++++++++++ bgpd/bgpd.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++ bgpd/bgpd.h | 6 +++++ 3 files changed, 102 insertions(+) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index b2a795b97d..9244e5cc56 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -3600,6 +3600,33 @@ DEFUN (bgp_default_shutdown, return CMD_SUCCESS; } +DEFPY (bgp_shutdown, + bgp_shutdown_cmd, + "bgp shutdown", + BGP_STR + "Enable administrative shutdown of the BGP instance\n") +{ + VTY_DECLVAR_CONTEXT(bgp, bgp); + + bgp_shutdown_enable(bgp); + + return CMD_SUCCESS; +} + +DEFPY (no_bgp_shutdown, + no_bgp_shutdown_cmd, + "no bgp shutdown", + NO_STR + BGP_STR + "Disable administrative shutdown of the BGP instance\n") +{ + VTY_DECLVAR_CONTEXT(bgp, bgp); + + bgp_shutdown_disable(bgp); + + return CMD_SUCCESS; +} + DEFUN (neighbor_remote_as, neighbor_remote_as_cmd, "neighbor remote-as <(1-4294967295)|internal|external>", @@ -15563,6 +15590,10 @@ int bgp_config_write(struct vty *vty) if (bgp->autoshutdown) vty_out(vty, " bgp default shutdown\n"); + /* BGP instance administrative shutdown */ + if (CHECK_FLAG(bgp->flags, BGP_FLAG_SHUTDOWN)) + vty_out(vty, " bgp shutdown\n"); + /* IPv4 unicast configuration. */ bgp_config_write_family(vty, bgp, AFI_IP, SAFI_UNICAST); @@ -16026,6 +16057,10 @@ void bgp_vty_init(void) /* "bgp default shutdown" command */ install_element(BGP_NODE, &bgp_default_shutdown_cmd); + /* "bgp shutdown" commands */ + install_element(BGP_NODE, &bgp_shutdown_cmd); + install_element(BGP_NODE, &no_bgp_shutdown_cmd); + /* "neighbor remote-as" commands. */ install_element(BGP_NODE, &neighbor_remote_as_cmd); install_element(BGP_NODE, &neighbor_interface_config_cmd); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 66f7fa1d00..5e5bb94591 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -4023,6 +4023,67 @@ static void peer_flag_modify_action(struct peer *peer, uint32_t flag) bgp_session_reset(peer); } +/* Enable global administrative shutdown of all peers of BGP instance */ +void bgp_shutdown_enable(struct bgp *bgp) +{ + struct peer *peer; + struct listnode *node; + + /* do nothing if already shut down */ + if (CHECK_FLAG(bgp->flags, BGP_FLAG_SHUTDOWN)) + return; + + /* iterate through peers of BGP instance */ + for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) { + /* continue, if peer is already in administrative shutdown. */ + if (CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN)) + continue; + + /* send a RFC 4486 notification message if necessary */ + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN); + } + + /* reset start timer to initial value */ + peer->v_start = BGP_INIT_START_TIMER; + + /* trigger a RFC 4271 ManualStop event */ + BGP_EVENT_ADD(peer, BGP_Stop); + } + + /* set the BGP instances shutdown flag */ + SET_FLAG(bgp->flags, BGP_FLAG_SHUTDOWN); +} + +/* Disable global administrative shutdown of all peers of BGP instance */ +void bgp_shutdown_disable(struct bgp *bgp) +{ + struct peer *peer; + struct listnode *node; + + /* do nothing if not shut down. */ + if (!CHECK_FLAG(bgp->flags, BGP_FLAG_SHUTDOWN)) + return; + + /* iterate through peers of BGP instance */ + for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) { + /* respect individual peer shutdown */ + if (CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN)) + continue; + + /* respect peer group shutdown */ + if (CHECK_FLAG(peer->group->conf->flags, PEER_FLAG_SHUTDOWN)) + continue; + + /* trigger a RFC 4721 ManualStart event. */ + BGP_EVENT_ADD(peer, BGP_Start); + } + + /* clear the BGP instances shutdown flag */ + UNSET_FLAG(bgp->flags, BGP_FLAG_SHUTDOWN); +} + /* Change specified peer flag. */ static int peer_flag_modify(struct peer *peer, uint32_t flag, int set) { diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index e84b0e43b9..3bedeea389 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -452,6 +452,9 @@ struct bgp { #define BGP_FLAG_EBGP_REQUIRES_POLICY (1 << 25) #define BGP_FLAG_SHOW_NEXTHOP_HOSTNAME (1 << 26) +/* This flag is set if the instance is in administrative shutdown */ +#define BGP_FLAG_SHUTDOWN (1 << 27) + enum global_mode GLOBAL_GR_FSM[BGP_GLOBAL_GR_MODE] [BGP_GLOBAL_GR_EVENT_CMD]; enum global_mode global_gr_present_state; @@ -1947,6 +1950,9 @@ extern struct peer_af *peer_af_create(struct peer *, afi_t, safi_t); extern struct peer_af *peer_af_find(struct peer *, afi_t, safi_t); extern int peer_af_delete(struct peer *, afi_t, safi_t); +extern void bgp_shutdown_enable(struct bgp *bgp); +extern void bgp_shutdown_disable(struct bgp *bgp); + extern void bgp_close(void); extern void bgp_free(struct bgp *); void bgp_gr_apply_running_config(void); -- 2.39.5