diff --git a/conf/conf.c b/conf/conf.c index 71e81b5c..710d5c20 100644 --- a/conf/conf.c +++ b/conf/conf.c @@ -189,7 +189,7 @@ global_commit(struct config *new, struct config *old) } static int -config_do_commit(struct config *c) +config_do_commit(struct config *c, int type) { int force_restart, nobs; @@ -205,7 +205,7 @@ config_do_commit(struct config *c) DBG("rt_commit\n"); rt_commit(c, old_config); DBG("protos_commit\n"); - protos_commit(c, old_config, force_restart); + protos_commit(c, old_config, force_restart, type); new_config = NULL; /* Just to be sure nobody uses that now */ if (old_config) nobs = --old_config->obstacle_count; @@ -236,7 +236,7 @@ config_done(void *unused UNUSED) c = future_config; future_config = NULL; log(L_INFO "Switching to queued configuration..."); - if (!config_do_commit(c)) + if (!config_do_commit(c, RECONFIG_HARD)) break; } } @@ -244,6 +244,7 @@ config_done(void *unused UNUSED) /** * config_commit - commit a configuration * @c: new configuration + * @type: type of reconfiguration (RECONFIG_SOFT or RECONFIG_HARD) * * When a configuration is parsed and prepared for use, the * config_commit() function starts the process of reconfiguration. @@ -263,11 +264,11 @@ config_done(void *unused UNUSED) * are accepted. */ int -config_commit(struct config *c) +config_commit(struct config *c, int type) { if (!config) /* First-time configuration */ { - config_do_commit(c); + config_do_commit(c, RECONFIG_HARD); return CONF_DONE; } if (old_config) /* Reconfiguration already in progress */ @@ -288,7 +289,7 @@ config_commit(struct config *c) future_config = c; return CONF_QUEUED; } - if (config_do_commit(c)) + if (config_do_commit(c, type)) { config_done(NULL); return CONF_DONE; @@ -321,7 +322,7 @@ order_shutdown(void) init_list(&c->tables); c->shutdown = 1; shutting_down = 1; - config_commit(c); + config_commit(c, RECONFIG_HARD); shutting_down = 2; } diff --git a/conf/conf.h b/conf/conf.h index ef27f3f4..8c2d5491 100644 --- a/conf/conf.h +++ b/conf/conf.h @@ -50,7 +50,9 @@ struct config *config_alloc(byte *name); int config_parse(struct config *); int cli_parse(struct config *); void config_free(struct config *); -int config_commit(struct config *); +int config_commit(struct config *, int type); +#define RECONFIG_HARD 0 +#define RECONFIG_SOFT 1 void cf_error(char *msg, ...) NORET; void config_add_obstacle(struct config *); void config_del_obstacle(struct config *); diff --git a/nest/proto.c b/nest/proto.c index ef0587b2..2af077b8 100644 --- a/nest/proto.c +++ b/nest/proto.c @@ -269,6 +269,7 @@ proto_init(struct proto_config *c) * @old: old configuration or %NULL if it's boot time config * @force_reconfig: force restart of all protocols (used for example * when the router ID changes) + * @type: type of reconfiguration (RECONFIG_SOFT or RECONFIG_HARD) * * Scan differences between @old and @new configuration and adjust all * protocol instances to conform to the new configuration. @@ -281,15 +282,17 @@ proto_init(struct proto_config *c) * When a protocol exists in the old configuration, but it doesn't in the * new one, it's shut down and deleted after the shutdown completes. * - * When a protocol exists in both configurations, the core decides whether - * it's possible to reconfigure it dynamically (it checks all the core properties - * of the protocol and if they match, it asks the reconfigure() hook of the - * protocol to see if the protocol is able to switch to the new configuration). - * If it isn't possible, the protocol is shut down and a new instance is started - * with the new configuration after the shutdown is completed. + * When a protocol exists in both configurations, the core decides + * whether it's possible to reconfigure it dynamically - it checks all + * the core properties of the protocol (changes in filters are ignored + * if type is RECONFIG_SOFT) and if they match, it asks the + * reconfigure() hook of the protocol to see if the protocol is able + * to switch to the new configuration. If it isn't possible, the + * protocol is shut down and a new instance is started with the new + * configuration after the shutdown is completed. */ void -protos_commit(struct config *new, struct config *old, int force_reconfig) +protos_commit(struct config *new, struct config *old, int force_reconfig, int type) { struct proto_config *oc, *nc; struct proto *p, *n; @@ -310,8 +313,8 @@ protos_commit(struct config *new, struct config *old, int force_reconfig) && nc->preference == oc->preference && nc->disabled == oc->disabled && nc->table->table == oc->table->table - && filter_same(nc->in_filter, oc->in_filter) - && filter_same(nc->out_filter, oc->out_filter) + && ((type == RECONFIG_SOFT) || filter_same(nc->in_filter, oc->in_filter)) + && ((type == RECONFIG_SOFT) || filter_same(nc->out_filter, oc->out_filter)) && p->proto_state != PS_DOWN) { /* Generic attributes match, try converting them and then ask the protocol */ diff --git a/nest/protocol.h b/nest/protocol.h index eee3a746..0f9d59d8 100644 --- a/nest/protocol.h +++ b/nest/protocol.h @@ -55,7 +55,7 @@ void protos_build(void); void proto_build(struct protocol *); void protos_preconfig(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, int type); void protos_dump_all(void); #define GA_UNKNOWN 0 /* Attribute not recognized */ diff --git a/sysdep/unix/config.Y b/sysdep/unix/config.Y index 5176be62..1917fe68 100644 --- a/sysdep/unix/config.Y +++ b/sysdep/unix/config.Y @@ -13,7 +13,7 @@ CF_HDR CF_DECLS -CF_KEYWORDS(LOG, SYSLOG, ALL, DEBUG, TRACE, INFO, REMOTE, WARNING, ERROR, AUTH, FATAL, BUG, STDERR) +CF_KEYWORDS(LOG, SYSLOG, ALL, DEBUG, TRACE, INFO, REMOTE, WARNING, ERROR, AUTH, FATAL, BUG, STDERR, SOFT) %type log_mask log_mask_list log_cat %type log_file @@ -65,8 +65,13 @@ log_cat: /* Unix specific commands */ +CF_CLI_HELP(CONFIGURE, [soft] [\"\"], [[Reload configuration]]) + CF_CLI(CONFIGURE, cfg_name, [\"\"], [[Reload configuration]]) -{ cmd_reconfig($2); } ; +{ cmd_reconfig($2, RECONFIG_HARD); } ; + +CF_CLI(CONFIGURE SOFT, cfg_name, [\"\"], [[Reload configuration and ignore changes in filters]]) +{ cmd_reconfig($3, RECONFIG_SOFT); } ; CF_CLI(DOWN,,, [[Shut the daemon down]]) { cli_msg(7, "Shutdown requested"); order_shutdown(); } ; diff --git a/sysdep/unix/main.c b/sysdep/unix/main.c index 4df4e9fe..5f5b165f 100644 --- a/sysdep/unix/main.c +++ b/sysdep/unix/main.c @@ -115,7 +115,7 @@ read_config(void) else die("Unable to open configuration file %s: %m", config_name); } - config_commit(conf); + config_commit(conf, RECONFIG_HARD); } void @@ -133,11 +133,11 @@ async_config(void) config_free(conf); } else - config_commit(conf); + config_commit(conf, RECONFIG_HARD); } void -cmd_reconfig(char *name) +cmd_reconfig(char *name, int type) { struct config *conf; @@ -154,7 +154,7 @@ cmd_reconfig(char *name) } else { - switch (config_commit(conf)) + switch (config_commit(conf, type)) { case CONF_DONE: cli_msg(3, "Reconfigured."); diff --git a/sysdep/unix/unix.h b/sysdep/unix/unix.h index 997a4088..83f61af9 100644 --- a/sysdep/unix/unix.h +++ b/sysdep/unix/unix.h @@ -16,7 +16,7 @@ struct pool; void async_config(void); void async_dump(void); void async_shutdown(void); -void cmd_reconfig(char *name); +void cmd_reconfig(char *name, int type); /* io.c */