Nest: Add command to request graceful restart
When 'graceful down' command is entered, protocols are shut down with regard to graceful restart. Namely Kernel protocol does not remove routes and BGP protocol does not send notification, just closes the connection.
This commit is contained in:
parent
bdf2e55d98
commit
8a68316eb9
11 changed files with 55 additions and 11 deletions
|
@ -492,19 +492,24 @@ config_init(void)
|
||||||
* for switching to an empty configuration.
|
* for switching to an empty configuration.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
order_shutdown(void)
|
order_shutdown(int gr)
|
||||||
{
|
{
|
||||||
struct config *c;
|
struct config *c;
|
||||||
|
|
||||||
if (shutting_down)
|
if (shutting_down)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
log(L_INFO "Shutting down");
|
if (!gr)
|
||||||
|
log(L_INFO "Shutting down");
|
||||||
|
else
|
||||||
|
log(L_INFO "Shutting down for graceful restart");
|
||||||
|
|
||||||
c = lp_alloc(config->mem, sizeof(struct config));
|
c = lp_alloc(config->mem, sizeof(struct config));
|
||||||
memcpy(c, config, sizeof(struct config));
|
memcpy(c, config, sizeof(struct config));
|
||||||
init_list(&c->protos);
|
init_list(&c->protos);
|
||||||
init_list(&c->tables);
|
init_list(&c->tables);
|
||||||
c->shutdown = 1;
|
c->shutdown = 1;
|
||||||
|
c->gr_down = gr;
|
||||||
|
|
||||||
config_commit(c, RECONFIG_HARD, 0);
|
config_commit(c, RECONFIG_HARD, 0);
|
||||||
shutting_down = 1;
|
shutting_down = 1;
|
||||||
|
|
|
@ -55,6 +55,7 @@ struct config {
|
||||||
struct sym_scope *root_scope; /* Scope for root symbols */
|
struct sym_scope *root_scope; /* Scope for root symbols */
|
||||||
int obstacle_count; /* Number of items blocking freeing of this config */
|
int obstacle_count; /* Number of items blocking freeing of this config */
|
||||||
int shutdown; /* This is a pseudo-config for daemon shutdown */
|
int shutdown; /* This is a pseudo-config for daemon shutdown */
|
||||||
|
int gr_down; /* This is a pseudo-config for graceful restart */
|
||||||
btime load_time; /* When we've got this configuration */
|
btime load_time; /* When we've got this configuration */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -75,7 +76,7 @@ void config_init(void);
|
||||||
void cf_error(const char *msg, ...) NORET;
|
void cf_error(const char *msg, ...) NORET;
|
||||||
void config_add_obstacle(struct config *);
|
void config_add_obstacle(struct config *);
|
||||||
void config_del_obstacle(struct config *);
|
void config_del_obstacle(struct config *);
|
||||||
void order_shutdown(void);
|
void order_shutdown(int gr);
|
||||||
|
|
||||||
#define RECONFIG_NONE 0
|
#define RECONFIG_NONE 0
|
||||||
#define RECONFIG_HARD 1
|
#define RECONFIG_HARD 1
|
||||||
|
|
|
@ -33,6 +33,7 @@ Reply codes of BIRD command-line interface
|
||||||
0022 Undo scheduled
|
0022 Undo scheduled
|
||||||
0023 Evaluation of expression
|
0023 Evaluation of expression
|
||||||
0024 Graceful restart status report
|
0024 Graceful restart status report
|
||||||
|
0025 Graceful restart ordered
|
||||||
|
|
||||||
1000 BIRD version
|
1000 BIRD version
|
||||||
1001 Interface list
|
1001 Interface list
|
||||||
|
|
|
@ -1048,6 +1048,11 @@ protos_commit(struct config *new, struct config *old, int force_reconfig, int ty
|
||||||
p->down_code = PDC_CF_REMOVE;
|
p->down_code = PDC_CF_REMOVE;
|
||||||
p->cf_new = NULL;
|
p->cf_new = NULL;
|
||||||
}
|
}
|
||||||
|
else if (new->gr_down)
|
||||||
|
{
|
||||||
|
p->down_code = PDC_CMD_GR_DOWN;
|
||||||
|
p->cf_new = NULL;
|
||||||
|
}
|
||||||
else /* global shutdown */
|
else /* global shutdown */
|
||||||
{
|
{
|
||||||
p->down_code = PDC_CMD_SHUTDOWN;
|
p->down_code = PDC_CMD_SHUTDOWN;
|
||||||
|
|
|
@ -257,6 +257,7 @@ struct proto_spec {
|
||||||
#define PDC_CMD_DISABLE 0x11 /* Result of disable command */
|
#define PDC_CMD_DISABLE 0x11 /* Result of disable command */
|
||||||
#define PDC_CMD_RESTART 0x12 /* Result of restart command */
|
#define PDC_CMD_RESTART 0x12 /* Result of restart command */
|
||||||
#define PDC_CMD_SHUTDOWN 0x13 /* Result of global shutdown */
|
#define PDC_CMD_SHUTDOWN 0x13 /* Result of global shutdown */
|
||||||
|
#define PDC_CMD_GR_DOWN 0x14 /* Result of global graceful restart */
|
||||||
#define PDC_RX_LIMIT_HIT 0x21 /* Route receive limit reached */
|
#define PDC_RX_LIMIT_HIT 0x21 /* Route receive limit reached */
|
||||||
#define PDC_IN_LIMIT_HIT 0x22 /* Route import limit reached */
|
#define PDC_IN_LIMIT_HIT 0x22 /* Route import limit reached */
|
||||||
#define PDC_OUT_LIMIT_HIT 0x23 /* Route export limit reached */
|
#define PDC_OUT_LIMIT_HIT 0x23 /* Route export limit reached */
|
||||||
|
|
|
@ -422,7 +422,7 @@ bgp_update_startup_delay(struct bgp_proto *p)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bgp_graceful_close_conn(struct bgp_conn *conn, uint subcode, byte *data, uint len)
|
bgp_graceful_close_conn(struct bgp_conn *conn, int subcode, byte *data, uint len)
|
||||||
{
|
{
|
||||||
switch (conn->state)
|
switch (conn->state)
|
||||||
{
|
{
|
||||||
|
@ -438,7 +438,13 @@ bgp_graceful_close_conn(struct bgp_conn *conn, uint subcode, byte *data, uint le
|
||||||
case BS_OPENSENT:
|
case BS_OPENSENT:
|
||||||
case BS_OPENCONFIRM:
|
case BS_OPENCONFIRM:
|
||||||
case BS_ESTABLISHED:
|
case BS_ESTABLISHED:
|
||||||
bgp_error(conn, 6, subcode, data, len);
|
if (subcode < 0)
|
||||||
|
{
|
||||||
|
bgp_conn_enter_close_state(conn);
|
||||||
|
bgp_schedule_packet(conn, NULL, PKT_SCHEDULE_CLOSE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
bgp_error(conn, 6, subcode, data, len);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -501,7 +507,7 @@ bgp_spawn(struct bgp_proto *pp, ip_addr remote_ip)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
bgp_stop(struct bgp_proto *p, uint subcode, byte *data, uint len)
|
bgp_stop(struct bgp_proto *p, int subcode, byte *data, uint len)
|
||||||
{
|
{
|
||||||
proto_notify_state(&p->p, PS_STOP);
|
proto_notify_state(&p->p, PS_STOP);
|
||||||
bgp_graceful_close_conn(&p->outgoing_conn, subcode, data, len);
|
bgp_graceful_close_conn(&p->outgoing_conn, subcode, data, len);
|
||||||
|
@ -1555,7 +1561,7 @@ static int
|
||||||
bgp_shutdown(struct proto *P)
|
bgp_shutdown(struct proto *P)
|
||||||
{
|
{
|
||||||
struct bgp_proto *p = (struct bgp_proto *) P;
|
struct bgp_proto *p = (struct bgp_proto *) P;
|
||||||
uint subcode = 0;
|
int subcode = 0;
|
||||||
|
|
||||||
char *message = NULL;
|
char *message = NULL;
|
||||||
byte *data = NULL;
|
byte *data = NULL;
|
||||||
|
@ -1576,6 +1582,7 @@ bgp_shutdown(struct proto *P)
|
||||||
|
|
||||||
case PDC_CMD_DISABLE:
|
case PDC_CMD_DISABLE:
|
||||||
case PDC_CMD_SHUTDOWN:
|
case PDC_CMD_SHUTDOWN:
|
||||||
|
shutdown:
|
||||||
subcode = 2; // Errcode 6, 2 - administrative shutdown
|
subcode = 2; // Errcode 6, 2 - administrative shutdown
|
||||||
message = P->message;
|
message = P->message;
|
||||||
break;
|
break;
|
||||||
|
@ -1585,6 +1592,14 @@ bgp_shutdown(struct proto *P)
|
||||||
message = P->message;
|
message = P->message;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PDC_CMD_GR_DOWN:
|
||||||
|
if ((p->cf->gr_mode != BGP_GR_ABLE) &&
|
||||||
|
(p->cf->llgr_mode != BGP_LLGR_ABLE))
|
||||||
|
goto shutdown;
|
||||||
|
|
||||||
|
subcode = -1; // Do not send NOTIFICATION, just close the connection
|
||||||
|
break;
|
||||||
|
|
||||||
case PDC_RX_LIMIT_HIT:
|
case PDC_RX_LIMIT_HIT:
|
||||||
case PDC_IN_LIMIT_HIT:
|
case PDC_IN_LIMIT_HIT:
|
||||||
subcode = 1; // Errcode 6, 1 - max number of prefixes reached
|
subcode = 1; // Errcode 6, 1 - max number of prefixes reached
|
||||||
|
|
|
@ -488,7 +488,7 @@ void bgp_graceful_restart_done(struct bgp_channel *c);
|
||||||
void bgp_refresh_begin(struct bgp_channel *c);
|
void bgp_refresh_begin(struct bgp_channel *c);
|
||||||
void bgp_refresh_end(struct bgp_channel *c);
|
void bgp_refresh_end(struct bgp_channel *c);
|
||||||
void bgp_store_error(struct bgp_proto *p, struct bgp_conn *c, u8 class, u32 code);
|
void bgp_store_error(struct bgp_proto *p, struct bgp_conn *c, u8 class, u32 code);
|
||||||
void bgp_stop(struct bgp_proto *p, uint subcode, byte *data, uint len);
|
void bgp_stop(struct bgp_proto *p, int subcode, byte *data, uint len);
|
||||||
|
|
||||||
struct rte_source *bgp_find_source(struct bgp_proto *p, u32 path_id);
|
struct rte_source *bgp_find_source(struct bgp_proto *p, u32 path_id);
|
||||||
struct rte_source *bgp_get_source(struct bgp_proto *p, u32 path_id);
|
struct rte_source *bgp_get_source(struct bgp_proto *p, u32 path_id);
|
||||||
|
|
|
@ -133,6 +133,10 @@ CF_CLI(CONFIGURE CHECK, cfg_name, [\"<file>\"], [[Parse configuration and check
|
||||||
CF_CLI(DOWN,,, [[Shut the daemon down]])
|
CF_CLI(DOWN,,, [[Shut the daemon down]])
|
||||||
{ cmd_shutdown(); } ;
|
{ cmd_shutdown(); } ;
|
||||||
|
|
||||||
|
CF_CLI(GRACEFUL DOWN,,, [[Shut the daemon down for graceful restart]])
|
||||||
|
{ cmd_graceful_restart(); } ;
|
||||||
|
|
||||||
|
|
||||||
cfg_name:
|
cfg_name:
|
||||||
/* empty */ { $$ = NULL; }
|
/* empty */ { $$ = NULL; }
|
||||||
| TEXT
|
| TEXT
|
||||||
|
|
|
@ -1129,7 +1129,7 @@ krt_shutdown(struct proto *P)
|
||||||
krt_scan_timer_stop(p);
|
krt_scan_timer_stop(p);
|
||||||
|
|
||||||
/* FIXME we should flush routes even when persist during reconfiguration */
|
/* FIXME we should flush routes even when persist during reconfiguration */
|
||||||
if (p->initialized && !KRT_CF->persist)
|
if (p->initialized && !KRT_CF->persist && (P->down_code != PDC_CMD_GR_DOWN))
|
||||||
krt_flush_routes(p);
|
krt_flush_routes(p);
|
||||||
|
|
||||||
p->ready = 0;
|
p->ready = 0;
|
||||||
|
|
|
@ -565,14 +565,14 @@ cmd_shutdown(void)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cli_msg(7, "Shutdown requested");
|
cli_msg(7, "Shutdown requested");
|
||||||
order_shutdown();
|
order_shutdown(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
async_shutdown(void)
|
async_shutdown(void)
|
||||||
{
|
{
|
||||||
DBG("Shutting down...\n");
|
DBG("Shutting down...\n");
|
||||||
order_shutdown();
|
order_shutdown(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -584,6 +584,17 @@ sysdep_shutdown_done(void)
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cmd_graceful_restart(void)
|
||||||
|
{
|
||||||
|
if (cli_access_restricted())
|
||||||
|
return;
|
||||||
|
|
||||||
|
cli_msg(25, "Graceful restart requested");
|
||||||
|
order_shutdown(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Signals
|
* Signals
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -28,6 +28,7 @@ void cmd_reconfig_confirm(void);
|
||||||
void cmd_reconfig_undo(void);
|
void cmd_reconfig_undo(void);
|
||||||
void cmd_reconfig_status(void);
|
void cmd_reconfig_status(void);
|
||||||
void cmd_shutdown(void);
|
void cmd_shutdown(void);
|
||||||
|
void cmd_graceful_restart(void);
|
||||||
|
|
||||||
#define UNIX_DEFAULT_CONFIGURE_TIMEOUT 300
|
#define UNIX_DEFAULT_CONFIGURE_TIMEOUT 300
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue