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:
parent
394aec8fdd
commit
50fe90edf3
13 changed files with 434 additions and 90 deletions
17
TODO
17
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
|
||||
~~~~~~
|
||||
|
|
121
conf/conf.c
121
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_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 = c;
|
||||
sysdep_commit(c);
|
||||
rt_commit(c);
|
||||
protos_commit(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
|
||||
|
|
18
conf/conf.h
18
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
|
||||
|
|
|
@ -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
|
||||
|
|
133
nest/proto.c
133
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,19 +187,12 @@ protos_postconfig(struct config *c)
|
|||
debug("\n");
|
||||
}
|
||||
|
||||
void
|
||||
protos_commit(struct config *c)
|
||||
static struct proto *
|
||||
proto_init(struct proto_config *c)
|
||||
{
|
||||
struct proto_config *x;
|
||||
struct protocol *p;
|
||||
struct proto *q;
|
||||
struct protocol *p = c->protocol;
|
||||
struct proto *q = p->init(c);
|
||||
|
||||
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->core_state = FS_HUNGRY;
|
||||
proto_enqueue(&initial_proto_list, q);
|
||||
|
@ -210,17 +205,100 @@ protos_commit(struct config *c)
|
|||
*/
|
||||
if (!q->disabled)
|
||||
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
|
||||
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);
|
||||
return; /* The protocol might have ceased to exist */
|
||||
}
|
||||
else if (cs == FS_FLUSHING) /* Still flushing... */
|
||||
;
|
||||
else /* Need to start flushing */
|
||||
|
|
|
@ -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 */
|
||||
|
||||
/*
|
||||
|
|
11
nest/route.h
11
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); }
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
|
||||
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));
|
||||
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");
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 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
|
||||
read_config(void)
|
||||
{
|
||||
struct config *conf = config_alloc(config_name);
|
||||
struct config *conf;
|
||||
|
||||
conf_fd = open(config_name, O_RDONLY);
|
||||
if (conf_fd < 0)
|
||||
die("Unable to open configuration file %s: %m", config_name);
|
||||
cf_read_hook = cf_read;
|
||||
if (!config_parse(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();
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
Loading…
Reference in a new issue