]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Nest: Add command to request graceful restart
authorOndrej Zajicek (work) <santiago@crfreenet.org>
Sun, 30 Jun 2019 20:15:24 +0000 (22:15 +0200)
committerOndrej Zajicek (work) <santiago@crfreenet.org>
Sun, 30 Jun 2019 20:15:24 +0000 (22:15 +0200)
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.

conf/conf.c
conf/conf.h
doc/reply_codes
nest/proto.c
nest/protocol.h
proto/bgp/bgp.c
proto/bgp/bgp.h
sysdep/unix/config.Y
sysdep/unix/krt.c
sysdep/unix/main.c
sysdep/unix/unix.h

index 885e2e7e0ebf2b17ed85494d76239875cd729c0c..7a11668870176245b057c77816879a7dd5551c59 100644 (file)
@@ -474,19 +474,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;
index a2c09282d21ed0f26829f844bed95a33f0d244d8..5c4f94faf6ecdd22459ea9c275f16027247a283c 100644 (file)
@@ -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 */
   btime load_time;                     /* When we've got this configuration */
 };
 
@@ -74,7 +75,7 @@ void config_init(void);
 void cf_error(const 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
index e8704335de6a4420d29379118651ce29a8c24736..8015b4ec86c3e1fdd015485eea97afa5bfb0e6c5 100644 (file)
@@ -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
index 38c251a50204288034c07fb24c5085c20fecb63a..4aeec01e0bc08ee56929511f6ea4cffbe16cb4e1 100644 (file)
@@ -993,6 +993,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;
index 8c8700848bedc8fb02103216cc391f8e4843861f..d67ba9e23c5494307f63a3f92982fd5ca06938e4 100644 (file)
@@ -234,6 +234,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 */
index 6a6205f57e6abc6dccb0638b521938c47e5d69bd..6528723b0ab61b122387309ba708b2248bc42934 100644 (file)
@@ -406,7 +406,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)
   {
@@ -422,7 +422,13 @@ 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, NULL, PKT_SCHEDULE_CLOSE);
+    }
+    else
+      bgp_error(conn, 6, subcode, data, len);
     return;
 
   default:
@@ -462,7 +468,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);
@@ -1379,7 +1385,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;
@@ -1400,6 +1406,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;
@@ -1409,6 +1416,13 @@ bgp_shutdown(struct proto *P)
     message = P->message;
     break;
 
+  case PDC_CMD_GR_DOWN:
+    if (p->cf->gr_mode != BGP_GR_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
index 5e3b1e3f1d32497c9d4d5b4e165cbd6523b92bfb..b1b9abedeedf343519c65f85a3f5e51ddf8b08b6 100644 (file)
@@ -453,7 +453,7 @@ void bgp_graceful_restart_done(struct bgp_channel *c);
 void bgp_refresh_begin(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_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);
index 253127a7f1189bf1625ec8eee25b20eb87cd6708..44e6f34bb46d4cf2512f4f8d5c1a5bd0ceb7e59a 100644 (file)
@@ -130,6 +130,10 @@ CF_CLI(CONFIGURE CHECK, cfg_name, [\"<file>\"], [[Parse configuration and check
 CF_CLI(DOWN,,, [[Shut the daemon down]])
 { cmd_shutdown(); } ;
 
+CF_CLI(GRACEFUL DOWN,,, [[Shut the daemon down for graceful restart]])
+{ cmd_graceful_restart(); } ;
+
+
 cfg_name:
    /* empty */ { $$ = NULL; }
  | TEXT
index 13c1601407bb6ee02cd89088470e8e6033a636d6..1a49542827698fe401e5bd133042a5e3c7db6940 100644 (file)
@@ -1146,7 +1146,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;
index 2251d3fb7a1f6d23c32935909e2f76e32ade45d3..a898a19a803d225755f14a1d4fbdac69d4c00cc7 100644 (file)
@@ -549,14 +549,14 @@ 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
@@ -568,6 +568,17 @@ sysdep_shutdown_done(void)
   exit(0);
 }
 
+void
+cmd_graceful_restart(void)
+{
+  if (cli_access_restricted())
+    return;
+
+  cli_msg(25, "Graceful restart requested");
+  order_shutdown(1);
+}
+
+
 /*
  *     Signals
  */
index 1230616704a7f17a1ae4d346b1d5c7de6714d929..7e3a9fede072601f3f25865b0a40ffe87833e71c 100644 (file)
@@ -27,6 +27,7 @@ void cmd_reconfig(char *name, int type, uint 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