First attempt on dynamic reconfiguration. There are still lots of bugs

and problems to solve, but the hardest part works.
This commit is contained in:
Martin Mares 2000-01-16 16:44:50 +00:00
parent 394aec8fdd
commit 50fe90edf3
13 changed files with 434 additions and 90 deletions

17
TODO
View file

@ -26,19 +26,21 @@ Core
- config: executable config files - config: executable config files
- config: when parsing prefix, check zero bits - config: when parsing prefix, check zero bits
- config: reconfiguration - config: reconfiguration
- config: reconfiguration of filters
- config: useless rules when protocols disabled - config: useless rules when protocols disabled
- config: remove protocol startup priority hacks? - config: remove protocol startup priority hacks?
- config: better datetime format - 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: rescan interfaces when route addition fails?
- krt: does PERSIST mode have any sense if kernel syncer is shut down as last? - 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? - tagging of external routes?
- io: use poll if available - io: use poll if available
- port to FreeBSD
Commands Commands
~~~~~~~~ ~~~~~~~~
shutdown # order system shutdown shutdown # order system shutdown
@ -50,6 +52,17 @@ show <name> # show everything you know about symbol <name>
symbols symbols
(disable|enable|restart) <protocol> # or ALL? (disable|enable|restart) <protocol> # or ALL?
- showing of routing table as seen by given protocol - 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 Client
~~~~~~ ~~~~~~

View file

@ -1,7 +1,7 @@
/* /*
* BIRD Internet Routing Daemon -- Configuration File Handling * 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. * Can be freely distributed and used under the terms of the GNU GPL.
*/ */
@ -9,18 +9,22 @@
#include <setjmp.h> #include <setjmp.h>
#include <stdarg.h> #include <stdarg.h>
#define LOCAL_DEBUG
#include "nest/bird.h" #include "nest/bird.h"
#include "nest/route.h" #include "nest/route.h"
#include "nest/protocol.h" #include "nest/protocol.h"
#include "nest/iface.h" #include "nest/iface.h"
#include "lib/resource.h" #include "lib/resource.h"
#include "lib/string.h" #include "lib/string.h"
#include "lib/event.h"
#include "conf/conf.h" #include "conf/conf.h"
#include "filter/filter.h" #include "filter/filter.h"
static jmp_buf conf_jmpbuf; 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 * struct config *
config_alloc(byte *name) config_alloc(byte *name)
@ -77,12 +81,117 @@ config_free(struct config *c)
} }
void void
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;
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) config_commit(struct config *c)
{ {
config = c; if (!config) /* First-time configuration */
sysdep_commit(c); {
rt_commit(c); config_do_commit(c);
protos_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 void

View file

@ -1,7 +1,7 @@
/* /*
* BIRD Internet Routing Daemon -- Configuration File Handling * 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. * 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 */ char *file_name; /* Name of configuration file */
struct symbol **sym_hash; /* Lexer: symbol hash table */ struct symbol **sym_hash; /* Lexer: symbol hash table */
struct symbol **sym_fallback; /* Lexer: fallback 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. */ /* 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); struct config *config_alloc(byte *name);
int config_parse(struct config *); int config_parse(struct config *);
int cli_parse(struct config *); int cli_parse(struct config *);
void config_free(struct config *); void config_free(struct config *);
void config_commit(struct config *); int config_commit(struct config *);
void cf_error(char *msg, ...) NORET; 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 */ /* Pools */
@ -87,6 +97,6 @@ int cf_parse(void);
/* Sysdep hooks */ /* Sysdep hooks */
void sysdep_preconfig(struct config *); void sysdep_preconfig(struct config *);
void sysdep_commit(struct config *); int sysdep_commit(struct config *, struct config *);
#endif #endif

View file

@ -10,6 +10,7 @@ Reply codes of BIRD command-line interface
0000 OK 0000 OK
0001 Welcome 0001 Welcome
0002 Reading configuration
1000 BIRD version 1000 BIRD version
1001 Interface list 1001 Interface list
@ -24,6 +25,7 @@ Reply codes of BIRD command-line interface
8000 Reply too long 8000 Reply too long
8001 Route not found 8001 Route not found
8002 Configuration file error
9000 Command too long 9000 Command too long
9001 Parse error 9001 Parse error

View file

@ -1,7 +1,7 @@
/* /*
* BIRD -- Protocols * 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. * 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 char *c_states[] = { "HUNGRY", "FEEDING", "HAPPY", "FLUSHING" };
static int proto_flush_all(void *); static int proto_flush_all(void *);
static void proto_rethink_goal(struct proto *p);
static void static void
proto_enqueue(list *l, struct proto *p) 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->pool = rp_new(proto_pool, p->proto->name);
p->attn = ev_new(p->pool); p->attn = ev_new(p->pool);
p->attn->data = p; p->attn->data = p;
rt_lock_table(p->table);
} }
struct announce_hook * struct announce_hook *
@ -185,19 +187,12 @@ protos_postconfig(struct config *c)
debug("\n"); debug("\n");
} }
void static struct proto *
protos_commit(struct config *c) proto_init(struct proto_config *c)
{ {
struct proto_config *x; struct protocol *p = c->protocol;
struct protocol *p; struct proto *q = p->init(c);
struct proto *q;
debug("Protocol commit:");
WALK_LIST(x, c->protos)
{
debug(" %s", x->name);
p = x->protocol;
q = p->init(x);
q->proto_state = PS_DOWN; q->proto_state = PS_DOWN;
q->core_state = FS_HUNGRY; q->core_state = FS_HUNGRY;
proto_enqueue(&initial_proto_list, q); proto_enqueue(&initial_proto_list, q);
@ -210,17 +205,100 @@ protos_commit(struct config *c)
*/ */
if (!q->disabled) if (!q->disabled)
p->startup_counter++; p->startup_counter++;
return q;
} }
debug("\n");
void
protos_commit(struct config *new, struct config *old, int force_reconfig)
{
struct proto_config *oc, *nc;
struct proto *p, *n;
DBG("protos_commit:\n");
if (old)
{
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);
}
}
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 static void
proto_rethink_goal(struct proto *p) 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) if (p->core_state == p->core_goal)
return; return;
q = p->proto;
if (p->core_goal == FS_HAPPY) /* Going up */ if (p->core_goal == FS_HAPPY) /* Going up */
{ {
if (p->core_state == FS_HUNGRY && p->proto_state == PS_DOWN) 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 void
protos_shutdown(void) protos_shutdown(void)
{ {
@ -271,12 +330,12 @@ protos_shutdown(void)
if (p->core_state != FS_HUNGRY || p->proto_state != PS_DOWN) if (p->core_state != FS_HUNGRY || p->proto_state != PS_DOWN)
{ {
proto_shutdown_counter++; proto_shutdown_counter++;
proto_set_goal(p, FS_HUNGRY); proto_rethink_goal(p);
} }
WALK_LIST_BACKWARDS_DELSAFE(p, n, proto_list) WALK_LIST_BACKWARDS_DELSAFE(p, n, proto_list)
{ {
proto_shutdown_counter++; 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) proto_fell_down(struct proto *p)
{ {
DBG("Protocol %s down\n", p->name); DBG("Protocol %s down\n", p->name);
rt_unlock_table(p->table);
if (!--proto_shutdown_counter) if (!--proto_shutdown_counter)
protos_shutdown_notify(); protos_shutdown_notify();
proto_rethink_goal(p); proto_rethink_goal(p);
@ -363,7 +423,10 @@ proto_notify_state(struct proto *p, unsigned ps)
{ {
case PS_DOWN: case PS_DOWN:
if (cs == FS_HUNGRY) /* Shutdown finished */ 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 if (cs == FS_FLUSHING) /* Still flushing... */
; ;
else /* Need to start flushing */ else /* Need to start flushing */

View file

@ -41,7 +41,7 @@ struct protocol {
void (*preconfig)(struct protocol *, struct config *); /* Just before configuring */ void (*preconfig)(struct protocol *, struct config *); /* Just before configuring */
void (*postconfig)(struct proto_config *); /* After configuring each instance */ void (*postconfig)(struct proto_config *); /* After configuring each instance */
struct proto * (*init)(struct proto_config *); /* Create new 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)(struct proto *); /* Debugging dump */
void (*dump_attrs)(struct rte *); /* Dump protocol-dependent attributes */ void (*dump_attrs)(struct rte *); /* Dump protocol-dependent attributes */
int (*start)(struct proto *); /* Start the instance */ int (*start)(struct proto *); /* Start the instance */
@ -54,8 +54,7 @@ struct protocol {
void protos_build(void); void protos_build(void);
void protos_preconfig(struct config *); void protos_preconfig(struct config *);
void protos_postconfig(struct config *); void protos_postconfig(struct config *);
void protos_commit(struct config *); void protos_commit(struct config *new, struct config *old, int force_restart);
void protos_start(void);
void protos_dump_all(void); void protos_dump_all(void);
void protos_shutdown(void); void protos_shutdown(void);
@ -92,6 +91,7 @@ struct proto {
node n; node n;
struct protocol *proto; /* Protocol */ struct protocol *proto; /* Protocol */
struct proto_config *cf; /* Configuration data */ 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 */ pool *pool; /* Pool containing local objects */
struct event *attn; /* "Pay attention" event */ struct event *attn; /* "Pay attention" event */
@ -103,6 +103,7 @@ struct proto {
unsigned proto_state; /* Protocol state machine (see below) */ unsigned proto_state; /* Protocol state machine (see below) */
unsigned core_state; /* Core state machine (see below) */ unsigned core_state; /* Core state machine (see below) */
unsigned core_goal; /* State we want to reach (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 */ bird_clock_t last_state_change; /* Time of last state transition */
/* /*

View file

@ -1,7 +1,7 @@
/* /*
* BIRD Internet Routing Daemon -- Routing Table * 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. * 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 */ char *name; /* Name of this table */
list hooks; /* List of announcement hooks */ list hooks; /* List of announcement hooks */
int pipe_busy; /* Pipe loop detection */ 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; } rtable;
typedef struct network { typedef struct network {
@ -171,7 +176,9 @@ struct config;
void rt_init(void); void rt_init(void);
void rt_preconfig(struct config *); 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 *); 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_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); } static inline net *net_get(rtable *tab, ip_addr addr, unsigned len) { return (net *) fib_get(&tab->fib, &addr, len); }

View file

@ -1,7 +1,7 @@
/* /*
* BIRD -- Routing Table * 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. * Can be freely distributed and used under the terms of the GNU GPL.
*/ */
@ -480,17 +480,68 @@ rt_preconfig(struct config *c)
} }
void void
rt_commit(struct config *c) rt_lock_table(rtable *r)
{ {
struct rtable_config *r; r->use_count++;
}
WALK_LIST(r, c->tables) 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;
DBG("rt_commit:\n");
if (old)
{
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)); 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); rt_setup(rt_table_pool, t, r->name);
add_tail(&routing_tables, &t->n); add_tail(&routing_tables, &t->n);
r->table = t; r->table = t;
} }
DBG("\tdone\n");
} }
/* /*

View file

@ -1,7 +1,7 @@
/* /*
* BIRD -- Table-to-Table Routing Protocol a.k.a Pipe * 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. * 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_add_announce_hook(P, p->peer);
a->proto = &ph->p; a->proto = &ph->p;
rt_lock_table(p->peer);
return PS_UP; 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 * static struct proto *
pipe_init(struct proto_config *C) pipe_init(struct proto_config *C)
{ {
@ -147,5 +157,6 @@ struct protocol proto_pipe = {
postconfig: pipe_postconfig, postconfig: pipe_postconfig,
init: pipe_init, init: pipe_init,
start: pipe_start, start: pipe_start,
shutdown: pipe_shutdown,
get_status: pipe_get_status, get_status: pipe_get_status,
}; };

View file

@ -1,7 +1,7 @@
/* /*
* BIRD -- UNIX Configuration * 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. * 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 <i> log_mask log_mask_list log_cat
%type <g> log_file %type <g> log_file
%type <t> cfg_name
CF_GRAMMAR CF_GRAMMAR
@ -61,6 +62,16 @@ log_cat:
| BUG { $$ = L_BUG[0]; } | 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_CODE
CF_END CF_END

View file

@ -1,7 +1,7 @@
/* /*
* BIRD -- UNIX Kernel Synchronization * 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. * 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 timer *kif_scan_timer;
static bird_clock_t kif_last_shot; static bird_clock_t kif_last_shot;
static void
kif_preconfig(struct protocol *P, struct config *c)
{
cf_kif = NULL;
}
static void static void
kif_scan(timer *t) kif_scan(timer *t)
{ {
@ -137,6 +143,7 @@ kif_shutdown(struct proto *P)
struct protocol proto_unix_iface = { struct protocol proto_unix_iface = {
name: "Device", name: "Device",
priority: 100, priority: 100,
preconfig: kif_preconfig,
init: kif_init, init: kif_init,
start: kif_start, start: kif_start,
shutdown: kif_shutdown, shutdown: kif_shutdown,
@ -646,6 +653,7 @@ struct proto_config *cf_krt;
static void static void
krt_preconfig(struct protocol *P, struct config *c) krt_preconfig(struct protocol *P, struct config *c)
{ {
cf_krt = NULL;
krt_scan_preconfig(c); krt_scan_preconfig(c);
} }

View file

@ -1,7 +1,7 @@
/* /*
* BIRD Internet Routing Daemon -- Unix Entry Point * 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. * 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); init_list(&c->logfiles);
} }
void int
sysdep_commit(struct config *c) sysdep_commit(struct config *new, struct config *old)
{ {
log_switch(&c->logfiles); log_switch(&new->logfiles);
return 0;
}
static int
unix_read_config(struct config **cp, char *name)
{
struct config *conf = config_alloc(name);
*cp = conf;
conf_fd = open(name, O_RDONLY);
if (conf_fd < 0)
return 0;
cf_read_hook = cf_read;
return config_parse(conf);
} }
static void static void
read_config(void) read_config(void)
{ {
struct config *conf = config_alloc(config_name); struct config *conf;
conf_fd = open(config_name, O_RDONLY); if (!unix_read_config(&conf, config_name))
if (conf_fd < 0) {
die("Unable to open configuration file %s: %m", config_name); if (conf->err_msg)
cf_read_hook = cf_read;
if (!config_parse(conf))
die("%s, line %d: %s", config_name, conf->err_lino, 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); config_commit(conf);
} }
void void
async_config(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(); cli_init_unix();
protos_start();
ev_run_list(&global_event_list); ev_run_list(&global_event_list);
async_dump(); async_dump();

View file

@ -1,7 +1,7 @@
/* /*
* BIRD -- Declarations Common to Unix Port * 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. * 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_config(void);
void async_dump(void); void async_dump(void);
void async_shutdown(void); void async_shutdown(void);
void cmd_reconfig(char *name);
/* io.c */ /* io.c */