summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO2
-rw-r--r--conf/conf.c34
-rw-r--r--conf/conf.h6
-rw-r--r--doc/reply_codes5
-rw-r--r--nest/bird.h4
-rw-r--r--nest/proto.c30
-rw-r--r--nest/protocol.h7
-rw-r--r--nest/rt-table.c4
-rw-r--r--sysdep/unix/config.Y3
-rw-r--r--sysdep/unix/main.c10
10 files changed, 57 insertions, 48 deletions
diff --git a/TODO b/TODO
index c2a6fc88..e932761a 100644
--- a/TODO
+++ b/TODO
@@ -30,8 +30,6 @@ Core
- 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?
diff --git a/conf/conf.c b/conf/conf.c
index 1c5401bc..c3f52344 100644
--- a/conf/conf.c
+++ b/conf/conf.c
@@ -25,6 +25,7 @@ static jmp_buf conf_jmpbuf;
struct config *config, *new_config, *old_config, *future_config;
static event *config_event;
+int shutting_down;
struct config *
config_alloc(byte *name)
@@ -100,11 +101,13 @@ config_del_obstacle(struct config *c)
}
static int
-global_commit(struct config *c, struct config *old)
+global_commit(struct config *new, struct config *old)
{
if (!old)
return 0;
- if (c->router_id != old->router_id)
+ if (!new->router_id)
+ new->router_id = old->router_id;
+ if (new->router_id != old->router_id)
return 1;
return 0;
}
@@ -116,7 +119,7 @@ config_do_commit(struct config *c)
DBG("do_commit\n");
old_config = config;
- config = c;
+ config = new_config = c;
if (old_config)
old_config->obstacle_count++;
DBG("sysdep_commit\n");
@@ -144,6 +147,8 @@ config_done(void *unused)
DBG("config_done\n");
for(;;)
{
+ if (config->shutdown)
+ sysdep_shutdown_done();
log(L_INFO "Reconfigured");
if (old_config)
{
@@ -171,6 +176,12 @@ config_commit(struct config *c)
}
if (old_config) /* Reconfiguration already in progress */
{
+ if (shutting_down)
+ {
+ log(L_INFO "New configuration discarded due to shutdown");
+ config_free(c);
+ return CONF_SHUTDOWN;
+ }
if (future_config)
{
log(L_INFO "Queueing new configuration, ignoring the one already queued");
@@ -195,6 +206,23 @@ config_commit(struct config *c)
}
void
+order_shutdown(void)
+{
+ struct config *c;
+
+ if (shutting_down)
+ return;
+ log(L_INFO "Shutting down");
+ c = lp_alloc(config->mem, sizeof(struct config));
+ memcpy(c, config, sizeof(struct config));
+ init_list(&c->protos);
+ init_list(&c->tables);
+ c->shutdown = 1;
+ config_commit(c);
+ shutting_down = 1;
+}
+
+void
cf_error(char *msg, ...)
{
char buf[1024];
diff --git a/conf/conf.h b/conf/conf.h
index 7d13ae9c..9fe133ee 100644
--- a/conf/conf.h
+++ b/conf/conf.h
@@ -27,6 +27,7 @@ struct config {
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 */
+ int shutdown; /* This is a pseudo-config for daemon shutdown */
};
/* Please don't use these variables in protocols. Use proto_config->global instead. */
@@ -35,6 +36,8 @@ 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 */
+extern int shutting_down;
+
struct config *config_alloc(byte *name);
int config_parse(struct config *);
int cli_parse(struct config *);
@@ -43,10 +46,12 @@ int config_commit(struct config *);
void cf_error(char *msg, ...) NORET;
void config_add_obstacle(struct config *);
void config_del_obstacle(struct config *);
+void order_shutdown(void);
#define CONF_DONE 0
#define CONF_PROGRESS 1
#define CONF_QUEUED 2
+#define CONF_SHUTDOWN 3
/* Pools */
@@ -98,5 +103,6 @@ int cf_parse(void);
void sysdep_preconfig(struct config *);
int sysdep_commit(struct config *, struct config *);
+void sysdep_shutdown_done(void);
#endif
diff --git a/doc/reply_codes b/doc/reply_codes
index 9b74c5b1..93c3d515 100644
--- a/doc/reply_codes
+++ b/doc/reply_codes
@@ -11,6 +11,11 @@ Reply codes of BIRD command-line interface
0000 OK
0001 Welcome
0002 Reading configuration
+0003 Reconfigured
+0004 Reconfiguration in progress
+0005 Reconfiguration already in progress, queueing
+0006 Reconfiguration ignored, shutting down
+0007 Shutdown ordered
1000 BIRD version
1001 Interface list
diff --git a/nest/bird.h b/nest/bird.h
index b35cd31a..3c7d749b 100644
--- a/nest/bird.h
+++ b/nest/bird.h
@@ -1,7 +1,7 @@
/*
* BIRD Internet Routing Daemon -- Basic Declarations
*
- * (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.
*/
@@ -13,6 +13,4 @@
#include "lib/birdlib.h"
#include "lib/ip.h"
-extern int shutting_down; /* The daemon is shutting down */
-
#endif
diff --git a/nest/proto.c b/nest/proto.c
index ecf0d906..36829bfd 100644
--- a/nest/proto.c
+++ b/nest/proto.c
@@ -30,8 +30,6 @@ static list inactive_proto_list;
static list initial_proto_list;
static list flush_proto_list;
-static int proto_shutdown_counter;
-
static event *proto_flush_event;
static char *p_states[] = { "DOWN", "START", "UP", "STOP" };
@@ -221,7 +219,7 @@ protos_commit(struct config *new, struct config *old, int force_reconfig)
{
struct proto *p = oc->proto;
struct symbol *sym = cf_find_symbol(oc->name);
- if (sym && sym->class == SYM_PROTO)
+ if (sym && sym->class == SYM_PROTO && !new->shutdown)
{
/* Found match, let's check if we can smoothly switch to new configuration */
nc = sym->def;
@@ -236,7 +234,7 @@ protos_commit(struct config *new, struct config *old, int force_reconfig)
{
/* Generic attributes match, try converting them and then ask the protocol */
p->debug = nc->debug;
- if (p->proto->reconfigure(p, nc))
+ if (p->proto->reconfigure && p->proto->reconfigure(p, nc))
{
DBG("\t%s: same\n", oc->name);
p->cf = nc;
@@ -247,6 +245,7 @@ protos_commit(struct config *new, struct config *old, int force_reconfig)
/* Unsuccessful, force reconfig */
DBG("\t%s: power cycling\n", oc->name);
p->cf_new = nc;
+ nc->proto = p;
}
else
{
@@ -290,7 +289,7 @@ proto_rethink_goal(struct proto *p)
}
/* Determine what state we want to reach */
- if (p->disabled || shutting_down || p->reconfiguring)
+ if (p->disabled || p->reconfiguring)
p->core_goal = FS_HUNGRY;
else
p->core_goal = FS_HAPPY;
@@ -321,25 +320,6 @@ proto_rethink_goal(struct proto *p)
}
void
-protos_shutdown(void)
-{
- struct proto *p, *n;
-
- debug("Protocol shutdown\n");
- WALK_LIST_BACKWARDS_DELSAFE(p, n, inactive_proto_list)
- if (p->core_state != FS_HUNGRY || p->proto_state != PS_DOWN)
- {
- proto_shutdown_counter++;
- proto_rethink_goal(p);
- }
- WALK_LIST_BACKWARDS_DELSAFE(p, n, proto_list)
- {
- proto_shutdown_counter++;
- proto_rethink_goal(p);
- }
-}
-
-void
protos_dump_all(void)
{
struct proto *p;
@@ -389,8 +369,6 @@ 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);
}
diff --git a/nest/protocol.h b/nest/protocol.h
index 72f88b6b..7c14f972 100644
--- a/nest/protocol.h
+++ b/nest/protocol.h
@@ -56,7 +56,6 @@ void protos_preconfig(struct config *);
void protos_postconfig(struct config *);
void protos_commit(struct config *new, struct config *old, int force_restart);
void protos_dump_all(void);
-void protos_shutdown(void);
extern list protocol_list;
@@ -251,10 +250,4 @@ struct announce_hook {
struct announce_hook *proto_add_announce_hook(struct proto *, struct rtable *);
-/*
- * Callback to sysdep code when shutdown is finished
- */
-
-void protos_shutdown_notify(void);
-
#endif
diff --git a/nest/rt-table.c b/nest/rt-table.c
index b0d1e291..dcde0af8 100644
--- a/nest/rt-table.c
+++ b/nest/rt-table.c
@@ -513,7 +513,7 @@ rt_commit(struct config *new, struct config *old)
if (!ot->deleted)
{
struct symbol *sym = cf_find_symbol(o->name);
- if (sym && sym->class == SYM_TABLE)
+ if (sym && sym->class == SYM_TABLE && !new->shutdown)
{
DBG("\t%s: same\n", o->name);
r = sym->def;
@@ -522,7 +522,7 @@ rt_commit(struct config *new, struct config *old)
}
else
{
- DBG("\t%s: deleted", o->name);
+ DBG("\t%s: deleted\n", o->name);
ot->deleted = old;
config_add_obstacle(old);
rt_lock_table(ot);
diff --git a/sysdep/unix/config.Y b/sysdep/unix/config.Y
index 299cc41d..cd553f8e 100644
--- a/sysdep/unix/config.Y
+++ b/sysdep/unix/config.Y
@@ -67,6 +67,9 @@ log_cat:
CF_CLI(CONFIGURE, cfg_name, [<file>], [[Reload configuration]])
{ cmd_reconfig($2); } ;
+CF_CLI(SHUTDOWN,,, [[Shut the daemon down]])
+{ cli_msg(7, "Shutdown ordered"); order_shutdown(); } ;
+
cfg_name:
/* empty */ { $$ = NULL; }
| TEXT
diff --git a/sysdep/unix/main.c b/sysdep/unix/main.c
index 97b9dc60..5019a3d5 100644
--- a/sysdep/unix/main.c
+++ b/sysdep/unix/main.c
@@ -29,8 +29,6 @@
#include "unix.h"
#include "krt.h"
-int shutting_down;
-
/*
* Debugging
*/
@@ -153,6 +151,9 @@ cmd_reconfig(char *name)
case CONF_PROGRESS:
cli_msg(4, "Reconfiguration in progress.");
break;
+ case CONF_SHUTDOWN:
+ cli_msg(6, "Reconfiguration ignored, shutting down.");
+ break;
default:
cli_msg(5, "Reconfiguration already in progress, queueing new config");
}
@@ -275,12 +276,11 @@ void
async_shutdown(void)
{
debug("Shutting down...\n");
- shutting_down = 1;
- protos_shutdown();
+ order_shutdown();
}
void
-protos_shutdown_notify(void)
+sysdep_shutdown_done(void)
{
unlink(PATH_CONTROL_SOCKET);
die("System shutdown completed");