summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_vty.c35
-rw-r--r--bgpd/bgpd.c61
-rw-r--r--bgpd/bgpd.h6
3 files changed, 102 insertions, 0 deletions
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 <A.B.C.D|X:X::X:X|WORD> 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);