]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
First attempt on dynamic reconfiguration. There are still lots of bugs
authorMartin Mares <mj@ucw.cz>
Sun, 16 Jan 2000 16:44:50 +0000 (16:44 +0000)
committerMartin Mares <mj@ucw.cz>
Sun, 16 Jan 2000 16:44:50 +0000 (16:44 +0000)
and problems to solve, but the hardest part works.

13 files changed:
TODO
conf/conf.c
conf/conf.h
doc/reply_codes
nest/proto.c
nest/protocol.h
nest/route.h
nest/rt-table.c
proto/pipe/pipe.c
sysdep/unix/config.Y
sysdep/unix/krt.c
sysdep/unix/main.c
sysdep/unix/unix.h

diff --git a/TODO b/TODO
index 79efcb0d852af4f8b4a9414b242abb1545a6d03f..c2a6fc880f6c9fbed6598a5a61c131d97fa855a5 100644 (file)
--- a/TODO
+++ b/TODO
@@ -26,19 +26,21 @@ Core
 - config: executable config files
 - config: when parsing prefix, check zero bits
 - config: reconfiguration
+- config: reconfiguration of filters
 - config: useless rules when protocols disabled
 - config: remove protocol startup priority hacks?
 - config: better datetime format
+- config: treat shutdown as reconfiguration to null config? (what about config of logging etc. ?)
+- config: fix auto_router_id
 
 - krt: rescan interfaces when route addition fails?
 - krt: does PERSIST mode have any sense if kernel syncer is shut down as last?
+- krt: check behaviour wrt. reconfiguration of routing tables
 
 - tagging of external routes?
 
 - io: use poll if available
 
-- port to FreeBSD
-
 Commands
 ~~~~~~~~
 shutdown                       # order system shutdown
@@ -50,6 +52,17 @@ show <name>                  # show everything you know about symbol <name>
        symbols
 (disable|enable|restart) <protocol>    # or ALL?
 - showing of routing table as seen by given protocol
+- showing of deleted routing tables and filters
+
+Roadmap
+~~~~~~~
+- Dynamic reconfiguration
+- Allocators and data structures
+- Client
+- Remaining bits of IPv6 support (radvd)
+- RIPv6
+- BGP?
+- Logging and debugging messages
 
 Client
 ~~~~~~
index ea65183b8075ac692403cf755101334813378646..1c5401bc44a20a4e23694a5f1db22f12fb13ff27 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     BIRD Internet Routing Daemon -- Configuration File Handling
  *
- *     (c) 1999 Martin Mares <mj@ucw.cz>
+ *     (c) 1998--2000 Martin Mares <mj@ucw.cz>
  *
  *     Can be freely distributed and used under the terms of the GNU GPL.
  */
@@ -9,18 +9,22 @@
 #include <setjmp.h>
 #include <stdarg.h>
 
+#define LOCAL_DEBUG
+
 #include "nest/bird.h"
 #include "nest/route.h"
 #include "nest/protocol.h"
 #include "nest/iface.h"
 #include "lib/resource.h"
 #include "lib/string.h"
+#include "lib/event.h"
 #include "conf/conf.h"
 #include "filter/filter.h"
 
 static jmp_buf conf_jmpbuf;
 
-struct config *config, *new_config;
+struct config *config, *new_config, *old_config, *future_config;
+static event *config_event;
 
 struct config *
 config_alloc(byte *name)
@@ -77,12 +81,117 @@ config_free(struct config *c)
 }
 
 void
-config_commit(struct config *c)
+config_add_obstacle(struct config *c)
+{
+  DBG("+++ adding obstacle %d\n", c->obstacle_count);
+  c->obstacle_count++;
+}
+
+void
+config_del_obstacle(struct config *c)
 {
+  DBG("+++ deleting obstacle %d\n", c->obstacle_count);
+  c->obstacle_count--;
+  if (!c->obstacle_count)
+    {
+      ASSERT(config_event);
+      ev_schedule(config_event);
+    }
+}
+
+static int
+global_commit(struct config *c, struct config *old)
+{
+  if (!old)
+    return 0;
+  if (c->router_id != old->router_id)
+    return 1;
+  return 0;
+}
+
+static int
+config_do_commit(struct config *c)
+{
+  int force_restart, nobs;
+
+  DBG("do_commit\n");
+  old_config = config;
   config = c;
-  sysdep_commit(c);
-  rt_commit(c);
-  protos_commit(c);
+  if (old_config)
+    old_config->obstacle_count++;
+  DBG("sysdep_commit\n");
+  force_restart = sysdep_commit(c, old_config);
+  DBG("global_commit\n");
+  force_restart |= global_commit(c, old_config);
+  DBG("rt_commit\n");
+  rt_commit(c, old_config);
+  DBG("protos_commit\n");
+  protos_commit(c, old_config, force_restart);
+  new_config = NULL;                   /* Just to be sure nobody uses that now */
+  if (old_config)
+    nobs = --old_config->obstacle_count;
+  else
+    nobs = 0;
+  DBG("do_commit finished with %d obstacles remaining\n", nobs);
+  return !nobs;
+}
+
+static int
+config_done(void *unused)
+{
+  struct config *c;
+
+  DBG("config_done\n");
+  for(;;)
+    {
+      log(L_INFO "Reconfigured");
+      if (old_config)
+       {
+         config_free(old_config);
+         old_config = NULL;
+       }
+      if (!future_config)
+       break;
+      c = future_config;
+      future_config = NULL;
+      log(L_INFO "Switching to queued configuration...");
+      if (!config_do_commit(c))
+       break;
+    }
+  return 0;
+}
+
+int
+config_commit(struct config *c)
+{
+  if (!config)                         /* First-time configuration */
+    {
+      config_do_commit(c);
+      return CONF_DONE;
+    }
+  if (old_config)                      /* Reconfiguration already in progress */
+    {
+      if (future_config)
+       {
+         log(L_INFO "Queueing new configuration, ignoring the one already queued");
+         config_free(future_config);
+       }
+      else
+       log(L_INFO "Queued new configuration");
+      future_config = c;
+      return CONF_QUEUED;
+    }
+  if (config_do_commit(c))
+    {
+      config_done(NULL);
+      return CONF_DONE;
+    }
+  if (!config_event)
+    {
+      config_event = ev_new(&root_pool);
+      config_event->hook = config_done;
+    }
+  return CONF_PROGRESS;
 }
 
 void
index b0a3811826a121e34d0c95d6953da93fc8a8d12c..7d13ae9ce4a923543a42c1dd126eb7f420329e73 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     BIRD Internet Routing Daemon -- Configuration File Handling
  *
- *     (c) 1998--1999 Martin Mares <mj@ucw.cz>
+ *     (c) 1998--2000 Martin Mares <mj@ucw.cz>
  *
  *     Can be freely distributed and used under the terms of the GNU GPL.
  */
@@ -26,17 +26,27 @@ struct config {
   char *file_name;                     /* Name of configuration file */
   struct symbol **sym_hash;            /* Lexer: symbol hash table */
   struct symbol **sym_fallback;                /* Lexer: fallback symbol hash table */
+  int obstacle_count;                  /* Number of items blocking freeing of this config */
 };
 
-extern struct config *config, *new_config;
 /* Please don't use these variables in protocols. Use proto_config->global instead. */
+extern struct config *config;          /* Currently active configuration */
+extern struct config *new_config;      /* Configuration being parsed */
+extern struct config *old_config;      /* Old configuration when reconfiguration is in progress */
+extern struct config *future_config;   /* New config held here if recon requested during recon */
 
 struct config *config_alloc(byte *name);
 int config_parse(struct config *);
 int cli_parse(struct config *);
 void config_free(struct config *);
-void config_commit(struct config *);
+int config_commit(struct config *);
 void cf_error(char *msg, ...) NORET;
+void config_add_obstacle(struct config *);
+void config_del_obstacle(struct config *);
+
+#define CONF_DONE 0
+#define CONF_PROGRESS 1
+#define CONF_QUEUED 2
 
 /* Pools */
 
@@ -87,6 +97,6 @@ int cf_parse(void);
 /* Sysdep hooks */
 
 void sysdep_preconfig(struct config *);
-void sysdep_commit(struct config *);
+int sysdep_commit(struct config *, struct config *);
 
 #endif
index 844ed435f7f36bea92c04485edf593a48c8338b0..9b74c5b15bb18a912c7ca3b92344725269ae6b19 100644 (file)
@@ -10,6 +10,7 @@ Reply codes of BIRD command-line interface
 
 0000   OK
 0001   Welcome
+0002   Reading configuration
 
 1000   BIRD version
 1001   Interface list
@@ -24,6 +25,7 @@ Reply codes of BIRD command-line interface
 
 8000   Reply too long
 8001   Route not found
+8002   Configuration file error
 
 9000   Command too long
 9001   Parse error
index a58c3f71d60422bad966cb64cc985592d6f5dc88..ecf0d906ee1dcc8fa359fe8c94e79bbfc6ea2246 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     BIRD -- Protocols
  *
- *     (c) 1998--1999 Martin Mares <mj@ucw.cz>
+ *     (c) 1998--2000 Martin Mares <mj@ucw.cz>
  *
  *     Can be freely distributed and used under the terms of the GNU GPL.
  */
@@ -38,6 +38,7 @@ static char *p_states[] = { "DOWN", "START", "UP", "STOP" };
 static char *c_states[] = { "HUNGRY", "FEEDING", "HAPPY", "FLUSHING" };
 
 static int proto_flush_all(void *);
+static void proto_rethink_goal(struct proto *p);
 
 static void
 proto_enqueue(list *l, struct proto *p)
@@ -103,6 +104,7 @@ proto_init_instance(struct proto *p)
   p->pool = rp_new(proto_pool, p->proto->name);
   p->attn = ev_new(p->pool);
   p->attn->data = p;
+  rt_lock_table(p->table);
 }
 
 struct announce_hook *
@@ -185,42 +187,118 @@ protos_postconfig(struct config *c)
   debug("\n");
 }
 
+static struct proto *
+proto_init(struct proto_config *c)
+{
+  struct protocol *p = c->protocol;
+  struct proto *q = p->init(c);
+
+  q->proto_state = PS_DOWN;
+  q->core_state = FS_HUNGRY;
+  proto_enqueue(&initial_proto_list, q);
+  /*
+   *  HACK ALERT!  In case of multiple kernel routing tables,
+   *  the kernel syncer acts as multiple protocols which cooperate
+   *  with each other.  In order to speed up their initialization,
+   *  we need to know when we're initializing the last one, hence
+   *  the startup counter.
+   */
+  if (!q->disabled)
+    p->startup_counter++;
+  return q;
+}
+
 void
-protos_commit(struct config *c)
+protos_commit(struct config *new, struct config *old, int force_reconfig)
 {
-  struct proto_config *x;
-  struct protocol *p;
-  struct proto *q;
+  struct proto_config *oc, *nc;
+  struct proto *p, *n;
 
-  debug("Protocol commit:");
-  WALK_LIST(x, c->protos)
+  DBG("protos_commit:\n");
+  if (old)
     {
-      debug(" %s", x->name);
-      p = x->protocol;
-      q = p->init(x);
-      q->proto_state = PS_DOWN;
-      q->core_state = FS_HUNGRY;
-      proto_enqueue(&initial_proto_list, q);
-      /*
-       *  HACK ALERT!  In case of multiple kernel routing tables,
-       *  the kernel syncer acts as multiple protocols which cooperate
-       *  with each other.  In order to speed up their initialization,
-       *  we need to know when we're initializing the last one, hence
-       *  the startup counter.
-       */
-      if (!q->disabled)
-       p->startup_counter++;
+      WALK_LIST(oc, old->protos)
+       {
+         struct proto *p = oc->proto;
+         struct symbol *sym = cf_find_symbol(oc->name);
+         if (sym && sym->class == SYM_PROTO)
+           {
+             /* Found match, let's check if we can smoothly switch to new configuration */
+             nc = sym->def;
+             if (!force_reconfig
+                 && nc->protocol == oc->protocol
+                 && nc->preference == oc->preference
+                 && nc->disabled == oc->disabled
+                 && nc->table->table == oc->table->table
+                 && nc->in_filter == oc->in_filter
+                 && nc->out_filter == oc->out_filter
+                 && p->proto_state != PS_DOWN)
+               {
+                 /* Generic attributes match, try converting them and then ask the protocol */
+                 p->debug = nc->debug;
+                 if (p->proto->reconfigure(p, nc))
+                   {
+                     DBG("\t%s: same\n", oc->name);
+                     p->cf = nc;
+                     nc->proto = p;
+                     continue;
+                   }
+               }
+             /* Unsuccessful, force reconfig */
+             DBG("\t%s: power cycling\n", oc->name);
+             p->cf_new = nc;
+           }
+         else
+           {
+             DBG("\t%s: deleting\n", oc->name);
+             p->cf_new = NULL;
+           }
+         p->reconfiguring = 1;
+         config_add_obstacle(old);
+         proto_rethink_goal(p);
+       }
     }
-  debug("\n");
+
+  WALK_LIST(nc, new->protos)
+    if (!nc->proto)
+      {
+       DBG("\t%s: adding\n", nc->name);
+       proto_init(nc);
+      }
+  DBG("\tdone\n");
+
+  DBG("Protocol start\n");
+  WALK_LIST_DELSAFE(p, n, initial_proto_list)
+    proto_rethink_goal(p);
 }
 
 static void
 proto_rethink_goal(struct proto *p)
 {
-  struct protocol *q = p->proto;
+  struct protocol *q;
+
+  if (p->reconfiguring && p->core_state == FS_HUNGRY && p->proto_state == PS_DOWN)
+    {
+      struct proto_config *nc = p->cf_new;
+      DBG("%s has shut down for reconfiguration\n", p->name);
+      config_del_obstacle(p->cf->global);
+      rem_node(&p->n);
+      mb_free(p);
+      if (!nc)
+       return;
+      p = proto_init(nc);              /* FIXME: What about protocol priorities??? */
+    }
+
+  /* Determine what state we want to reach */
+  if (p->disabled || shutting_down || p->reconfiguring)
+    p->core_goal = FS_HUNGRY;
+  else
+    p->core_goal = FS_HAPPY;
 
   if (p->core_state == p->core_goal)
     return;
+
+  q = p->proto;
   if (p->core_goal == FS_HAPPY)                /* Going up */
     {
       if (p->core_state == FS_HUNGRY && p->proto_state == PS_DOWN)
@@ -242,25 +320,6 @@ proto_rethink_goal(struct proto *p)
     }
 }
 
-static void
-proto_set_goal(struct proto *p, unsigned goal)
-{
-  if (p->disabled || shutting_down)
-    goal = FS_HUNGRY;
-  p->core_goal = goal;
-  proto_rethink_goal(p);
-}
-
-void
-protos_start(void)
-{
-  struct proto *p, *n;
-
-  debug("Protocol start\n");
-  WALK_LIST_DELSAFE(p, n, initial_proto_list)
-    proto_set_goal(p, FS_HAPPY);
-}
-
 void
 protos_shutdown(void)
 {
@@ -271,12 +330,12 @@ protos_shutdown(void)
     if (p->core_state != FS_HUNGRY || p->proto_state != PS_DOWN)
     {
       proto_shutdown_counter++;
-      proto_set_goal(p, FS_HUNGRY);
+      proto_rethink_goal(p);
     }
   WALK_LIST_BACKWARDS_DELSAFE(p, n, proto_list)
     {
       proto_shutdown_counter++;
-      proto_set_goal(p, FS_HUNGRY);
+      proto_rethink_goal(p);
     }
 }
 
@@ -329,6 +388,7 @@ static void
 proto_fell_down(struct proto *p)
 {
   DBG("Protocol %s down\n", p->name);
+  rt_unlock_table(p->table);
   if (!--proto_shutdown_counter)
     protos_shutdown_notify();
   proto_rethink_goal(p);
@@ -363,7 +423,10 @@ proto_notify_state(struct proto *p, unsigned ps)
     {
     case PS_DOWN:
       if (cs == FS_HUNGRY)             /* Shutdown finished */
-       proto_fell_down(p);
+       {
+         proto_fell_down(p);
+         return;                       /* The protocol might have ceased to exist */
+       }
       else if (cs == FS_FLUSHING)      /* Still flushing... */
        ;
       else                             /* Need to start flushing */
index 39d1cf5d01cac5d09c6f9eb38abebd765cc9f644..72f88b6b6f7b869cfd57af8b618e03c33957cc3c 100644 (file)
@@ -41,7 +41,7 @@ struct protocol {
   void (*preconfig)(struct protocol *, struct config *);       /* Just before configuring */
   void (*postconfig)(struct proto_config *);                   /* After configuring each instance */
   struct proto * (*init)(struct proto_config *);               /* Create new instance */
-  int (*reconfigure)(struct proto *, struct proto_config *);   /* Try to reconfigure instance */
+  int (*reconfigure)(struct proto *, struct proto_config *);   /* Try to reconfigure instance, returns success */
   void (*dump)(struct proto *);                        /* Debugging dump */
   void (*dump_attrs)(struct rte *);            /* Dump protocol-dependent attributes */
   int (*start)(struct proto *);                        /* Start the instance */
@@ -54,8 +54,7 @@ struct protocol {
 void protos_build(void);
 void protos_preconfig(struct config *);
 void protos_postconfig(struct config *);
-void protos_commit(struct config *);
-void protos_start(void);
+void protos_commit(struct config *new, struct config *old, int force_restart);
 void protos_dump_all(void);
 void protos_shutdown(void);
 
@@ -92,6 +91,7 @@ struct proto {
   node n;
   struct protocol *proto;              /* Protocol */
   struct proto_config *cf;             /* Configuration data */
+  struct proto_config *cf_new;         /* Configuration we want to switch to after shutdown (NULL=delete) */
   pool *pool;                          /* Pool containing local objects */
   struct event *attn;                  /* "Pay attention" event */
 
@@ -103,6 +103,7 @@ struct proto {
   unsigned proto_state;                        /* Protocol state machine (see below) */
   unsigned core_state;                 /* Core state machine (see below) */
   unsigned core_goal;                  /* State we want to reach (see below) */
+  unsigned reconfiguring;              /* We're shutting down due to reconfiguration */
   bird_clock_t last_state_change;      /* Time of last state transition */
 
   /*
index 903e9b930fdce7164db038f42734e601bda0bef5..da793d6c406950087126997c0d7d917f373b55a2 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     BIRD Internet Routing Daemon -- Routing Table
  *
- *     (c) 1998--1999 Martin Mares <mj@ucw.cz>
+ *     (c) 1998--2000 Martin Mares <mj@ucw.cz>
  *
  *     Can be freely distributed and used under the terms of the GNU GPL.
  */
@@ -121,6 +121,11 @@ typedef struct rtable {
   char *name;                          /* Name of this table */
   list hooks;                          /* List of announcement hooks */
   int pipe_busy;                       /* Pipe loop detection */
+  int use_count;                       /* Number of protocols using this table */
+  struct config *deleted;              /* Table doesn't exist in current configuration,
+                                        * delete as soon as use_count becomes 0 and remove
+                                        * obstacle from this routing table.
+                                        */
 } rtable;
 
 typedef struct network {
@@ -171,7 +176,9 @@ struct config;
 
 void rt_init(void);
 void rt_preconfig(struct config *);
-void rt_commit(struct config *);
+void rt_commit(struct config *new, struct config *old);
+void rt_lock_table(rtable *);
+void rt_unlock_table(rtable *);
 void rt_setup(pool *, rtable *, char *);
 static inline net *net_find(rtable *tab, ip_addr addr, unsigned len) { return (net *) fib_find(&tab->fib, &addr, len); }
 static inline net *net_get(rtable *tab, ip_addr addr, unsigned len) { return (net *) fib_get(&tab->fib, &addr, len); }
index 401c5f85d8114ee54c28cf9a955b56a00a036dff..b0d1e2911ab081efcc2b5add66fb31b1ea6948c1 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     BIRD -- Routing Table
  *
- *     (c) 1998--1999 Martin Mares <mj@ucw.cz>
+ *     (c) 1998--2000 Martin Mares <mj@ucw.cz>
  *
  *     Can be freely distributed and used under the terms of the GNU GPL.
  */
@@ -480,17 +480,68 @@ rt_preconfig(struct config *c)
 }
 
 void
-rt_commit(struct config *c)
+rt_lock_table(rtable *r)
 {
-  struct rtable_config *r;
+  r->use_count++;
+}
+
+void
+rt_unlock_table(rtable *r)
+{
+  if (!--r->use_count && r->deleted)
+    {
+      struct config *conf = r->deleted;
+      DBG("Deleting routing table %s\n", r->name);
+      rem_node(&r->n);
+      fib_free(&r->fib);
+      mb_free(r);
+      config_del_obstacle(conf);
+    }
+}
+
+void
+rt_commit(struct config *new, struct config *old)
+{
+  struct rtable_config *o, *r;
 
-  WALK_LIST(r, c->tables)
+  DBG("rt_commit:\n");
+  if (old)
     {
-      rtable *t = mb_alloc(rt_table_pool, sizeof(struct rtable));
-      rt_setup(rt_table_pool, t, r->name);
-      add_tail(&routing_tables, &t->n);
-      r->table = t;
+      WALK_LIST(o, old->tables)
+       {
+         rtable *ot = o->table;
+         if (!ot->deleted)
+           {
+             struct symbol *sym = cf_find_symbol(o->name);
+             if (sym && sym->class == SYM_TABLE)
+               {
+                 DBG("\t%s: same\n", o->name);
+                 r = sym->def;
+                 r->table = ot;
+                 ot->name = r->name;
+               }
+             else
+               {
+                 DBG("\t%s: deleted", o->name);
+                 ot->deleted = old;
+                 config_add_obstacle(old);
+                 rt_lock_table(ot);
+                 rt_unlock_table(ot);
+               }
+           }
+       }
     }
+
+  WALK_LIST(r, new->tables)
+    if (!r->table)
+      {
+       rtable *t = mb_alloc(rt_table_pool, sizeof(struct rtable));
+       DBG("\t%s: created\n", r->name);
+       rt_setup(rt_table_pool, t, r->name);
+       add_tail(&routing_tables, &t->n);
+       r->table = t;
+      }
+  DBG("\tdone\n");
 }
 
 /*
index 0612f5f47b3df24e5c8a5ecd6dd2a42d9a481317..c6a8317d7dee5b6d8ee4bc1fd7730583c078001b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     BIRD -- Table-to-Table Routing Protocol a.k.a Pipe
  *
- *     (c) 1999 Martin Mares <mj@ucw.cz>
+ *     (c) 1999--2000 Martin Mares <mj@ucw.cz>
  *
  *     Can be freely distributed and used under the terms of the GNU GPL.
  */
@@ -106,10 +106,20 @@ pipe_start(struct proto *P)
    */
   a = proto_add_announce_hook(P, p->peer);
   a->proto = &ph->p;
+  rt_lock_table(p->peer);
 
   return PS_UP;
 }
 
+static int
+pipe_shutdown(struct proto *P)
+{
+  struct pipe_proto *p = (struct pipe_proto *) P;
+
+  rt_unlock_table(p->peer);
+  return PS_DOWN;
+}
+
 static struct proto *
 pipe_init(struct proto_config *C)
 {
@@ -147,5 +157,6 @@ struct protocol proto_pipe = {
   postconfig:  pipe_postconfig,
   init:                pipe_init,
   start:       pipe_start,
+  shutdown:    pipe_shutdown,
   get_status:  pipe_get_status,
 };
index f0a517e9c962e697a62b852e71432f1b4929f65e..299cc41d94d28e511d1ba27ba2f853bcd92a3db8 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     BIRD -- UNIX Configuration
  *
- *     (c) 1999 Martin Mares <mj@ucw.cz>
+ *     (c) 1999--2000 Martin Mares <mj@ucw.cz>
  *
  *     Can be freely distributed and used under the terms of the GNU GPL.
  */
@@ -16,6 +16,7 @@ CF_KEYWORDS(LOG, SYSLOG, ALL, DEBUG, TRACE, INFO, REMOTE, WARNING, ERROR, AUTH,
 
 %type <i> log_mask log_mask_list log_cat
 %type <g> log_file
+%type <t> cfg_name
 
 CF_GRAMMAR
 
@@ -61,6 +62,16 @@ log_cat:
  | BUG { $$ = L_BUG[0]; }
  ;
 
+/* Unix specific commands */
+
+CF_CLI(CONFIGURE, cfg_name, [<file>], [[Reload configuration]])
+{ cmd_reconfig($2); } ;
+
+cfg_name:
+   /* empty */ { $$ = NULL; }
+ | TEXT
+ ;
+
 CF_CODE
 
 CF_END
index aa9a9c43618ca37ebf9e61e95ea42dc3a7790faf..7c92c551b7e6e0fe2a251c3492db0586d2860d70 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     BIRD -- UNIX Kernel Synchronization
  *
- *     (c) 1998--1999 Martin Mares <mj@ucw.cz>
+ *     (c) 1998--2000 Martin Mares <mj@ucw.cz>
  *
  *     Can be freely distributed and used under the terms of the GNU GPL.
  */
@@ -67,6 +67,12 @@ static struct kif_proto *kif_proto;
 static timer *kif_scan_timer;
 static bird_clock_t kif_last_shot;
 
+static void
+kif_preconfig(struct protocol *P, struct config *c)
+{
+  cf_kif = NULL;
+}
+
 static void
 kif_scan(timer *t)
 {
@@ -137,6 +143,7 @@ kif_shutdown(struct proto *P)
 struct protocol proto_unix_iface = {
   name:                "Device",
   priority:    100,
+  preconfig:   kif_preconfig,
   init:                kif_init,
   start:       kif_start,
   shutdown:    kif_shutdown,
@@ -646,6 +653,7 @@ struct proto_config *cf_krt;
 static void
 krt_preconfig(struct protocol *P, struct config *c)
 {
+  cf_krt = NULL;
   krt_scan_preconfig(c);
 }
 
index 4b9ab615eb8596da2ac07351f1e0845b9e747ea7..97b9dc608a172d2a05cdcd91be975bbb5034836a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     BIRD Internet Routing Daemon -- Unix Entry Point
  *
- *     (c) 1998--1999 Martin Mares <mj@ucw.cz>
+ *     (c) 1998--2000 Martin Mares <mj@ucw.cz>
  *
  *     Can be freely distributed and used under the terms of the GNU GPL.
  */
@@ -74,30 +74,89 @@ sysdep_preconfig(struct config *c)
   init_list(&c->logfiles);
 }
 
-void
-sysdep_commit(struct config *c)
+int
+sysdep_commit(struct config *new, struct config *old)
 {
-  log_switch(&c->logfiles);
+  log_switch(&new->logfiles);
+  return 0;
 }
 
-static void
-read_config(void)
+static int
+unix_read_config(struct config **cp, char *name)
 {
-  struct config *conf = config_alloc(config_name);
+  struct config *conf = config_alloc(name);
 
-  conf_fd = open(config_name, O_RDONLY);
+  *cp = conf;
+  conf_fd = open(name, O_RDONLY);
   if (conf_fd < 0)
-    die("Unable to open configuration file %s: %m", config_name);
+    return 0;
   cf_read_hook = cf_read;
-  if (!config_parse(conf))
-    die("%s, line %d: %s", config_name, conf->err_lino, conf->err_msg);
+  return config_parse(conf);
+}
+
+static void
+read_config(void)
+{
+  struct config *conf;
+
+  if (!unix_read_config(&conf, config_name))
+    {
+      if (conf->err_msg)
+       die("%s, line %d: %s", config_name, conf->err_lino, conf->err_msg);
+      else
+       die("Unable to open configuration file %s: %m", config_name);
+    }
   config_commit(conf);
 }
 
 void
 async_config(void)
 {
-  debug("Asynchronous reconfigurations are not supported in demo version\n");
+  struct config *conf;
+
+  log(L_INFO "Reconfiguration requested by SIGHUP");
+  if (!unix_read_config(&conf, config_name))
+    {
+      if (conf->err_msg)
+       log(L_ERR "%s, line %d: %s", config_name, conf->err_lino, conf->err_msg);
+      else
+       log(L_ERR "Unable to open configuration file %s: %m", config_name);
+      config_free(conf);
+    }
+  else
+    config_commit(conf);
+}
+
+void
+cmd_reconfig(char *name)
+{
+  struct config *conf;
+
+  if (!name)
+    name = config_name;
+  cli_msg(-2, "Reading configuration from %s", name);
+  if (!unix_read_config(&conf, name))
+    {
+      if (conf->err_msg)
+       cli_msg(8002, "%s, line %d: %s", name, conf->err_lino, conf->err_msg);
+      else
+       cli_msg(8002, "%s: %m", name);
+      config_free(conf);
+    }
+  else
+    {
+      switch (config_commit(conf))
+       {
+       case CONF_DONE:
+         cli_msg(3, "Reconfigured.");
+         break;
+       case CONF_PROGRESS:
+         cli_msg(4, "Reconfiguration in progress.");
+         break;
+       default:
+         cli_msg(5, "Reconfiguration already in progress, queueing new config");
+       }
+    }
 }
 
 /*
@@ -350,8 +409,6 @@ main(int argc, char **argv)
 
   cli_init_unix();
 
-  protos_start();
-
   ev_run_list(&global_event_list);
   async_dump();
 
index 8dd7249610415d779e3eb3daa7ab781a336edabd..68850bcc68eac371a51c34fb54c6f95446472a00 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     BIRD -- Declarations Common to Unix Port
  *
- *     (c) 1998 Martin Mares <mj@ucw.cz>
+ *     (c) 1998--2000 Martin Mares <mj@ucw.cz>
  *
  *     Can be freely distributed and used under the terms of the GNU GPL.
  */
@@ -16,6 +16,7 @@ struct pool;
 void async_config(void);
 void async_dump(void);
 void async_shutdown(void);
+void cmd_reconfig(char *name);
 
 /* io.c */