Converted shutdown to a kind of reconfiguration, it's no more handled
as a exception in protocol state machines. Introduced a `shutdown' CLI command. Killed few reconfiguration bugs.
This commit is contained in:
parent
ebc793a5f5
commit
bf8558bc9c
10 changed files with 57 additions and 48 deletions
2
TODO
2
TODO
|
@ -30,8 +30,6 @@ Core
|
||||||
- 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?
|
||||||
|
|
34
conf/conf.c
34
conf/conf.c
|
@ -25,6 +25,7 @@ static jmp_buf conf_jmpbuf;
|
||||||
|
|
||||||
struct config *config, *new_config, *old_config, *future_config;
|
struct config *config, *new_config, *old_config, *future_config;
|
||||||
static event *config_event;
|
static event *config_event;
|
||||||
|
int shutting_down;
|
||||||
|
|
||||||
struct config *
|
struct config *
|
||||||
config_alloc(byte *name)
|
config_alloc(byte *name)
|
||||||
|
@ -100,11 +101,13 @@ config_del_obstacle(struct config *c)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
global_commit(struct config *c, struct config *old)
|
global_commit(struct config *new, struct config *old)
|
||||||
{
|
{
|
||||||
if (!old)
|
if (!old)
|
||||||
return 0;
|
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 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -116,7 +119,7 @@ config_do_commit(struct config *c)
|
||||||
|
|
||||||
DBG("do_commit\n");
|
DBG("do_commit\n");
|
||||||
old_config = config;
|
old_config = config;
|
||||||
config = c;
|
config = new_config = c;
|
||||||
if (old_config)
|
if (old_config)
|
||||||
old_config->obstacle_count++;
|
old_config->obstacle_count++;
|
||||||
DBG("sysdep_commit\n");
|
DBG("sysdep_commit\n");
|
||||||
|
@ -144,6 +147,8 @@ config_done(void *unused)
|
||||||
DBG("config_done\n");
|
DBG("config_done\n");
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
|
if (config->shutdown)
|
||||||
|
sysdep_shutdown_done();
|
||||||
log(L_INFO "Reconfigured");
|
log(L_INFO "Reconfigured");
|
||||||
if (old_config)
|
if (old_config)
|
||||||
{
|
{
|
||||||
|
@ -171,6 +176,12 @@ config_commit(struct config *c)
|
||||||
}
|
}
|
||||||
if (old_config) /* Reconfiguration already in progress */
|
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)
|
if (future_config)
|
||||||
{
|
{
|
||||||
log(L_INFO "Queueing new configuration, ignoring the one already queued");
|
log(L_INFO "Queueing new configuration, ignoring the one already queued");
|
||||||
|
@ -194,6 +205,23 @@ config_commit(struct config *c)
|
||||||
return CONF_PROGRESS;
|
return CONF_PROGRESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
void
|
||||||
cf_error(char *msg, ...)
|
cf_error(char *msg, ...)
|
||||||
{
|
{
|
||||||
|
|
|
@ -27,6 +27,7 @@ struct config {
|
||||||
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 */
|
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. */
|
/* 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 *old_config; /* Old configuration when reconfiguration is in progress */
|
||||||
extern struct config *future_config; /* New config held here if recon requested during recon */
|
extern struct config *future_config; /* New config held here if recon requested during recon */
|
||||||
|
|
||||||
|
extern int shutting_down;
|
||||||
|
|
||||||
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 *);
|
||||||
|
@ -43,10 +46,12 @@ 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_add_obstacle(struct config *);
|
||||||
void config_del_obstacle(struct config *);
|
void config_del_obstacle(struct config *);
|
||||||
|
void order_shutdown(void);
|
||||||
|
|
||||||
#define CONF_DONE 0
|
#define CONF_DONE 0
|
||||||
#define CONF_PROGRESS 1
|
#define CONF_PROGRESS 1
|
||||||
#define CONF_QUEUED 2
|
#define CONF_QUEUED 2
|
||||||
|
#define CONF_SHUTDOWN 3
|
||||||
|
|
||||||
/* Pools */
|
/* Pools */
|
||||||
|
|
||||||
|
@ -98,5 +103,6 @@ int cf_parse(void);
|
||||||
|
|
||||||
void sysdep_preconfig(struct config *);
|
void sysdep_preconfig(struct config *);
|
||||||
int sysdep_commit(struct config *, struct config *);
|
int sysdep_commit(struct config *, struct config *);
|
||||||
|
void sysdep_shutdown_done(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -11,6 +11,11 @@ Reply codes of BIRD command-line interface
|
||||||
0000 OK
|
0000 OK
|
||||||
0001 Welcome
|
0001 Welcome
|
||||||
0002 Reading configuration
|
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
|
1000 BIRD version
|
||||||
1001 Interface list
|
1001 Interface list
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* BIRD Internet Routing Daemon -- Basic Declarations
|
* 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.
|
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||||
*/
|
*/
|
||||||
|
@ -13,6 +13,4 @@
|
||||||
#include "lib/birdlib.h"
|
#include "lib/birdlib.h"
|
||||||
#include "lib/ip.h"
|
#include "lib/ip.h"
|
||||||
|
|
||||||
extern int shutting_down; /* The daemon is shutting down */
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
30
nest/proto.c
30
nest/proto.c
|
@ -30,8 +30,6 @@ static list inactive_proto_list;
|
||||||
static list initial_proto_list;
|
static list initial_proto_list;
|
||||||
static list flush_proto_list;
|
static list flush_proto_list;
|
||||||
|
|
||||||
static int proto_shutdown_counter;
|
|
||||||
|
|
||||||
static event *proto_flush_event;
|
static event *proto_flush_event;
|
||||||
|
|
||||||
static char *p_states[] = { "DOWN", "START", "UP", "STOP" };
|
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 proto *p = oc->proto;
|
||||||
struct symbol *sym = cf_find_symbol(oc->name);
|
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 */
|
/* Found match, let's check if we can smoothly switch to new configuration */
|
||||||
nc = sym->def;
|
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 */
|
/* Generic attributes match, try converting them and then ask the protocol */
|
||||||
p->debug = nc->debug;
|
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);
|
DBG("\t%s: same\n", oc->name);
|
||||||
p->cf = nc;
|
p->cf = nc;
|
||||||
|
@ -247,6 +245,7 @@ protos_commit(struct config *new, struct config *old, int force_reconfig)
|
||||||
/* Unsuccessful, force reconfig */
|
/* Unsuccessful, force reconfig */
|
||||||
DBG("\t%s: power cycling\n", oc->name);
|
DBG("\t%s: power cycling\n", oc->name);
|
||||||
p->cf_new = nc;
|
p->cf_new = nc;
|
||||||
|
nc->proto = p;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -290,7 +289,7 @@ proto_rethink_goal(struct proto *p)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Determine what state we want to reach */
|
/* Determine what state we want to reach */
|
||||||
if (p->disabled || shutting_down || p->reconfiguring)
|
if (p->disabled || p->reconfiguring)
|
||||||
p->core_goal = FS_HUNGRY;
|
p->core_goal = FS_HUNGRY;
|
||||||
else
|
else
|
||||||
p->core_goal = FS_HAPPY;
|
p->core_goal = FS_HAPPY;
|
||||||
|
@ -320,25 +319,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
|
void
|
||||||
protos_dump_all(void)
|
protos_dump_all(void)
|
||||||
{
|
{
|
||||||
|
@ -389,8 +369,6 @@ 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);
|
rt_unlock_table(p->table);
|
||||||
if (!--proto_shutdown_counter)
|
|
||||||
protos_shutdown_notify();
|
|
||||||
proto_rethink_goal(p);
|
proto_rethink_goal(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,6 @@ void protos_preconfig(struct config *);
|
||||||
void protos_postconfig(struct config *);
|
void protos_postconfig(struct config *);
|
||||||
void protos_commit(struct config *new, struct config *old, int force_restart);
|
void protos_commit(struct config *new, struct config *old, int force_restart);
|
||||||
void protos_dump_all(void);
|
void protos_dump_all(void);
|
||||||
void protos_shutdown(void);
|
|
||||||
|
|
||||||
extern list protocol_list;
|
extern list protocol_list;
|
||||||
|
|
||||||
|
@ -251,10 +250,4 @@ struct announce_hook {
|
||||||
|
|
||||||
struct announce_hook *proto_add_announce_hook(struct proto *, struct rtable *);
|
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
|
#endif
|
||||||
|
|
|
@ -513,7 +513,7 @@ rt_commit(struct config *new, struct config *old)
|
||||||
if (!ot->deleted)
|
if (!ot->deleted)
|
||||||
{
|
{
|
||||||
struct symbol *sym = cf_find_symbol(o->name);
|
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);
|
DBG("\t%s: same\n", o->name);
|
||||||
r = sym->def;
|
r = sym->def;
|
||||||
|
@ -522,7 +522,7 @@ rt_commit(struct config *new, struct config *old)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DBG("\t%s: deleted", o->name);
|
DBG("\t%s: deleted\n", o->name);
|
||||||
ot->deleted = old;
|
ot->deleted = old;
|
||||||
config_add_obstacle(old);
|
config_add_obstacle(old);
|
||||||
rt_lock_table(ot);
|
rt_lock_table(ot);
|
||||||
|
|
|
@ -67,6 +67,9 @@ log_cat:
|
||||||
CF_CLI(CONFIGURE, cfg_name, [<file>], [[Reload configuration]])
|
CF_CLI(CONFIGURE, cfg_name, [<file>], [[Reload configuration]])
|
||||||
{ cmd_reconfig($2); } ;
|
{ cmd_reconfig($2); } ;
|
||||||
|
|
||||||
|
CF_CLI(SHUTDOWN,,, [[Shut the daemon down]])
|
||||||
|
{ cli_msg(7, "Shutdown ordered"); order_shutdown(); } ;
|
||||||
|
|
||||||
cfg_name:
|
cfg_name:
|
||||||
/* empty */ { $$ = NULL; }
|
/* empty */ { $$ = NULL; }
|
||||||
| TEXT
|
| TEXT
|
||||||
|
|
|
@ -29,8 +29,6 @@
|
||||||
#include "unix.h"
|
#include "unix.h"
|
||||||
#include "krt.h"
|
#include "krt.h"
|
||||||
|
|
||||||
int shutting_down;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Debugging
|
* Debugging
|
||||||
*/
|
*/
|
||||||
|
@ -153,6 +151,9 @@ cmd_reconfig(char *name)
|
||||||
case CONF_PROGRESS:
|
case CONF_PROGRESS:
|
||||||
cli_msg(4, "Reconfiguration in progress.");
|
cli_msg(4, "Reconfiguration in progress.");
|
||||||
break;
|
break;
|
||||||
|
case CONF_SHUTDOWN:
|
||||||
|
cli_msg(6, "Reconfiguration ignored, shutting down.");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
cli_msg(5, "Reconfiguration already in progress, queueing new config");
|
cli_msg(5, "Reconfiguration already in progress, queueing new config");
|
||||||
}
|
}
|
||||||
|
@ -275,12 +276,11 @@ void
|
||||||
async_shutdown(void)
|
async_shutdown(void)
|
||||||
{
|
{
|
||||||
debug("Shutting down...\n");
|
debug("Shutting down...\n");
|
||||||
shutting_down = 1;
|
order_shutdown();
|
||||||
protos_shutdown();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
protos_shutdown_notify(void)
|
sysdep_shutdown_done(void)
|
||||||
{
|
{
|
||||||
unlink(PATH_CONTROL_SOCKET);
|
unlink(PATH_CONTROL_SOCKET);
|
||||||
die("System shutdown completed");
|
die("System shutdown completed");
|
||||||
|
|
Loading…
Reference in a new issue