summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Mares <mj@ucw.cz>2000-01-16 16:44:50 +0000
committerMartin Mares <mj@ucw.cz>2000-01-16 16:44:50 +0000
commit50fe90edf3deab409ea7887c131bfe6ce89fa556 (patch)
treed9aad4ed34285a59cfcc0286a22ca5ccdb63a82f
parent394aec8fdd112a81da1e2f6f0e09ee74256dc24e (diff)
First attempt on dynamic reconfiguration. There are still lots of bugs
and problems to solve, but the hardest part works.
-rw-r--r--TODO17
-rw-r--r--conf/conf.c121
-rw-r--r--conf/conf.h18
-rw-r--r--doc/reply_codes2
-rw-r--r--nest/proto.c155
-rw-r--r--nest/protocol.h7
-rw-r--r--nest/route.h11
-rw-r--r--nest/rt-table.c67
-rw-r--r--proto/pipe/pipe.c13
-rw-r--r--sysdep/unix/config.Y13
-rw-r--r--sysdep/unix/krt.c10
-rw-r--r--sysdep/unix/main.c85
-rw-r--r--sysdep/unix/unix.h3
13 files changed, 433 insertions, 89 deletions
diff --git a/TODO b/TODO
index 79efcb0d..c2a6fc88 100644
--- 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
~~~~~~
diff --git a/conf/conf.c b/conf/conf.c
index ea65183b..1c5401bc 100644
--- a/conf/conf.c
+++ b/conf/conf.c
@@ -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
diff --git a/conf/conf.h b/conf/conf.h
index b0a38118..7d13ae9c 100644
--- a/conf/conf.h
+++ b/conf/conf.h
@@ -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
diff --git a/doc/reply_codes b/doc/reply_codes
index 844ed435..9b74c5b1 100644
--- a/doc/reply_codes
+++ b/doc/reply_codes
@@ -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
diff --git a/nest/proto.c b/nest/proto.c
index a58c3f71..ecf0d906 100644
--- a/nest/proto.c
+++ b/nest/proto.c
@@ -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 */
diff --git a/nest/protocol.h b/nest/protocol.h
index 39d1cf5d..72f88b6b 100644
--- a/nest/protocol.h
+++ b/nest/protocol.h
@@ -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 */
/*
diff --git a/nest/route.h b/nest/route.h
index 903e9b93..da793d6c 100644
--- a/nest/route.h
+++ b/nest/route.h
@@ -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); }
diff --git a/nest/rt-table.c b/nest/rt-table.c
index 401c5f85..b0d1e291 100644
--- a/nest/rt-table.c
+++ b/nest/rt-table.c
@@ -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");
}
/*
diff --git a/proto/pipe/pipe.c b/proto/pipe/pipe.c
index 0612f5f4..c6a8317d 100644
--- a/proto/pipe/pipe.c
+++ b/proto/pipe/pipe.c
@@ -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,
};
diff --git a/sysdep/unix/config.Y b/sysdep/unix/config.Y
index f0a517e9..299cc41d 100644
--- a/sysdep/unix/config.Y
+++ b/sysdep/unix/config.Y
@@ -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
diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c
index aa9a9c43..7c92c551 100644
--- a/sysdep/unix/krt.c
+++ b/sysdep/unix/krt.c
@@ -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.
*/
@@ -68,6 +68,12 @@ 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)
{
struct kif_proto *p = t->data;
@@ -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);
}
diff --git a/sysdep/unix/main.c b/sysdep/unix/main.c
index 4b9ab615..97b9dc60 100644
--- a/sysdep/unix/main.c
+++ b/sysdep/unix/main.c
@@ -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();
diff --git a/sysdep/unix/unix.h b/sysdep/unix/unix.h
index 8dd72496..68850bcc 100644
--- a/sysdep/unix/unix.h
+++ b/sysdep/unix/unix.h
@@ -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 */