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