PATCH: backport of graceful restart to 1.6.8
Mathew Heard
me at mheard.com
Sun Jul 11 12:20:17 CEST 2021
Attached is a backport of graceful restart to 1.6.8 (legacy branch).
I am aware that this branch is no longer getting feature updates.
However I would request this patch inclusion on the basis it's
valuable for anyone looking to move from 1.x to 2.x.
Regards,
Mathew
-------------- next part --------------
diff --git a/conf/conf.c b/conf/conf.c
index 4e6354b2..e294fa6e 100644
--- a/conf/conf.c
+++ b/conf/conf.c
@@ -477,19 +477,24 @@ config_init(void)
* for switching to an empty configuration.
*/
void
-order_shutdown(void)
+order_shutdown(int gr)
{
struct config *c;
if (shutting_down)
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));
memcpy(c, config, sizeof(struct config));
init_list(&c->protos);
init_list(&c->tables);
c->shutdown = 1;
+ c->gr_down = gr;
config_commit(c, RECONFIG_HARD, 0);
shutting_down = 1;
diff --git a/conf/conf.h b/conf/conf.h
index 6d8ed5ca..234fdaf2 100644
--- a/conf/conf.h
+++ b/conf/conf.h
@@ -56,6 +56,7 @@ struct config {
struct config *fallback; /* Link to regular config for CLI parsing */
int obstacle_count; /* Number of items blocking freeing of this config */
int shutdown; /* This is a pseudo-config for daemon shutdown */
+ int gr_down; /* This is a pseudo-config for graceful restart */
bird_clock_t load_time; /* When we've got this configuration */
};
@@ -74,7 +75,7 @@ void config_init(void);
void cf_error(char *msg, ...) NORET;
void config_add_obstacle(struct config *);
void config_del_obstacle(struct config *);
-void order_shutdown(void);
+void order_shutdown(int gr);
#define RECONFIG_NONE 0
#define RECONFIG_HARD 1
diff --git a/doc/reply_codes b/doc/reply_codes
index 3a7f2c90..02f4e656 100644
--- a/doc/reply_codes
+++ b/doc/reply_codes
@@ -33,6 +33,7 @@ Reply codes of BIRD command-line interface
0022 Undo scheduled
0023 Evaluation of expression
0024 Graceful restart status report
+0025 Graceful restart ordered
1000 BIRD version
1001 Interface list
diff --git a/nest/proto.c b/nest/proto.c
index 66cb937d..d7c1cffe 100644
--- a/nest/proto.c
+++ b/nest/proto.c
@@ -557,6 +557,11 @@ protos_commit(struct config *new, struct config *old, int force_reconfig, int ty
p->down_code = PDC_CF_REMOVE;
p->cf_new = NULL;
}
+ else if (new->gr_down)
+ {
+ p->down_code = PDC_CMD_GR_DOWN;
+ p->cf_new = NULL;
+ }
else /* global shutdown */
{
p->down_code = PDC_CMD_SHUTDOWN;
diff --git a/nest/protocol.h b/nest/protocol.h
index 02fd8d96..72b1a0a3 100644
--- a/nest/protocol.h
+++ b/nest/protocol.h
@@ -246,6 +246,7 @@ struct proto_spec {
#define PDC_CMD_DISABLE 0x11 /* Result of disable command */
#define PDC_CMD_RESTART 0x12 /* Result of restart command */
#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_IN_LIMIT_HIT 0x22 /* Route import limit reached */
#define PDC_OUT_LIMIT_HIT 0x23 /* Route export limit reached */
diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c
index 664a38ed..344b50e8 100644
--- a/proto/bgp/bgp.c
+++ b/proto/bgp/bgp.c
@@ -306,7 +306,7 @@ bgp_update_startup_delay(struct bgp_proto *p)
}
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)
{
@@ -320,7 +320,14 @@ bgp_graceful_close_conn(struct bgp_conn *conn, uint subcode, byte *data, uint le
case BS_OPENSENT:
case BS_OPENCONFIRM:
case BS_ESTABLISHED:
- bgp_error(conn, 6, subcode, data, len);
+ if (subcode < 0)
+ {
+ bgp_conn_enter_close_state(conn);
+ bgp_schedule_packet(conn, PKT_SCHEDULE_CLOSE);
+ }
+ else
+ bgp_error(conn, 6, subcode, data, len);
+
return;
default:
bug("bgp_graceful_close_conn: Unknown state %d", conn->state);
@@ -356,7 +363,7 @@ bgp_decision(void *vp)
}
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);
bgp_graceful_close_conn(&p->outgoing_conn, subcode, data, len);
@@ -1277,7 +1284,7 @@ static int
bgp_shutdown(struct proto *P)
{
struct bgp_proto *p = (struct bgp_proto *) P;
- uint subcode = 0;
+ int subcode = 0;
char *message = NULL;
byte *data = NULL;
@@ -1298,6 +1305,7 @@ bgp_shutdown(struct proto *P)
case PDC_CMD_DISABLE:
case PDC_CMD_SHUTDOWN:
+ shutdown:
subcode = 2; // Errcode 6, 2 - administrative shutdown
message = P->message;
break;
@@ -1307,6 +1315,15 @@ bgp_shutdown(struct proto *P)
message = P->message;
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_IN_LIMIT_HIT:
subcode = 1; // Errcode 6, 1 - max number of prefixes reached
diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h
index dd66c86b..3925a64f 100644
--- a/proto/bgp/bgp.h
+++ b/proto/bgp/bgp.h
@@ -233,7 +233,7 @@ void bgp_graceful_restart_done(struct bgp_proto *p);
void bgp_refresh_begin(struct bgp_proto *p);
void bgp_refresh_end(struct bgp_proto *p);
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_get_source(struct bgp_proto *p, u32 path_id);
diff --git a/sysdep/unix/config.Y b/sysdep/unix/config.Y
index dc5804ed..d044aeff 100644
--- a/sysdep/unix/config.Y
+++ b/sysdep/unix/config.Y
@@ -16,6 +16,7 @@ CF_DECLS
CF_KEYWORDS(LOG, SYSLOG, ALL, DEBUG, TRACE, INFO, REMOTE, WARNING, ERROR, AUTH, FATAL, BUG, STDERR, SOFT)
CF_KEYWORDS(TIMEFORMAT, ISO, OLD, SHORT, LONG, BASE, NAME, CONFIRM, UNDO, CHECK, TIMEOUT)
CF_KEYWORDS(DEBUG, LATENCY, LIMIT, WATCHDOG, WARNING, TIMEOUT)
+CF_KEYWORDS(GRACEFUL, RESTART)
%type <i> log_mask log_mask_list log_cat cfg_timeout
%type <g> log_file
@@ -143,6 +144,9 @@ CF_CLI(CONFIGURE CHECK, cfg_name, [\"<file>\"], [[Parse configuration and check
CF_CLI(DOWN,,, [[Shut the daemon down]])
{ cmd_shutdown(); } ;
+CF_CLI(GRACEFUL RESTART,,, [[Graceful restart]])
+{ cmd_graceful_restart(); } ;
+
cfg_name:
/* empty */ { $$ = NULL; }
| TEXT
diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c
index 526c0cab..eb1b1f85 100644
--- a/sysdep/unix/krt.c
+++ b/sysdep/unix/krt.c
@@ -1161,7 +1161,7 @@ krt_shutdown(struct proto *P)
krt_scan_timer_stop(p);
/* 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);
p->ready = 0;
diff --git a/sysdep/unix/main.c b/sysdep/unix/main.c
index 01c0dedb..10e962e7 100644
--- a/sysdep/unix/main.c
+++ b/sysdep/unix/main.c
@@ -551,14 +551,24 @@ cmd_shutdown(void)
return;
cli_msg(7, "Shutdown requested");
- order_shutdown();
+ order_shutdown(0);
}
void
async_shutdown(void)
{
DBG("Shutting down...\n");
- order_shutdown();
+ order_shutdown(0);
+}
+
+void
+cmd_graceful_restart(void)
+{
+ if (cli_access_restricted())
+ return;
+
+ cli_msg(25, "Graceful restart requested");
+ order_shutdown(1);
}
void
diff --git a/sysdep/unix/unix.h b/sysdep/unix/unix.h
index c71f7940..e5f4c165 100644
--- a/sysdep/unix/unix.h
+++ b/sysdep/unix/unix.h
@@ -27,6 +27,7 @@ void cmd_reconfig(char *name, int type, int timeout);
void cmd_reconfig_confirm(void);
void cmd_reconfig_undo(void);
void cmd_shutdown(void);
+void cmd_graceful_restart(void);
#define UNIX_DEFAULT_CONFIGURE_TIMEOUT 300
More information about the Bird-users
mailing list