0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-22 17:51:53 +00:00

Fixed fast subsequent reconfigurations bug

This commit is contained in:
Maria Matejka 2024-06-25 15:53:13 +02:00
parent 7d455d64ca
commit a9534186f1

View File

@ -64,7 +64,7 @@ config_ref config;
_Thread_local struct config *new_config; _Thread_local struct config *new_config;
pool *config_pool; pool *config_pool;
static config_ref old_config; /* Old configuration */ struct config *old_config; /* Old configuration */
static config_ref future_config; /* New config held here if recon requested during recon */ static config_ref future_config; /* New config held here if recon requested during recon */
static int old_cftype; /* Type of transition old_config -> config (RECONFIG_SOFT/HARD) */ static int old_cftype; /* Type of transition old_config -> config (RECONFIG_SOFT/HARD) */
static int future_cftype; /* Type of scheduled transition, may also be RECONFIG_UNDO */ static int future_cftype; /* Type of scheduled transition, may also be RECONFIG_UNDO */
@ -77,29 +77,16 @@ static timer *config_timer; /* Timer for scheduled configuration rollback */
/* These are public just for cmd_show_status(), should not be accessed elsewhere */ /* These are public just for cmd_show_status(), should not be accessed elsewhere */
int shutting_down; /* Shutdown requested, do not accept new config changes */ int shutting_down; /* Shutdown requested, do not accept new config changes */
int configuring; /* Reconfiguration is running */ int configuring; /* Reconfiguration is running */
struct config *old_config_pending; /* Just for debug convenience */
int undo_available; /* Undo was not requested from last reconfiguration */ int undo_available; /* Undo was not requested from last reconfiguration */
/* Note that both shutting_down and undo_available are related to requests, not processing */ /* Note that both shutting_down and undo_available are related to requests, not processing */
static void static void
config_obstacles_cleared(struct callback *cb) config_obstacles_cleared(struct callback *_ UNUSED)
{ {
SKIP_BACK_DECLARE(struct config, c, obstacles_cleared, cb);
ASSERT_DIE(birdloop_inside(&main_birdloop)); ASSERT_DIE(birdloop_inside(&main_birdloop));
ASSERT_DIE(configuring);
if (c == old_config_pending)
{
old_config_pending = NULL;
if (!shutting_down)
OBSREF_SET(old_config, c);
if (configuring)
config_done(); config_done();
} }
else
config_free(c);
}
/** /**
* config_alloc - allocate a new configuration * config_alloc - allocate a new configuration
@ -235,9 +222,11 @@ config_free(struct config *c)
void void
config_free_old(void) config_free_old(void)
{ {
OBSREF_CLEAR(old_config);
tm_stop(config_timer); tm_stop(config_timer);
undo_available = 0; undo_available = 0;
config_free(old_config);
old_config = NULL;
} }
struct global_runtime global_runtime_internal[2] = {{ struct global_runtime global_runtime_internal[2] = {{
@ -302,17 +291,17 @@ config_do_commit(config_ref *cr, int type)
{ {
if (type == RECONFIG_UNDO) if (type == RECONFIG_UNDO)
{ {
OBSREF_SET(*cr, OBSREF_GET(old_config)); OBSREF_SET(*cr, old_config);
type = old_cftype; type = old_cftype;
} }
else
config_free(old_config);
OBSREF_CLEAR(old_config); old_config = NULL;
old_cftype = type; old_cftype = type;
struct config *c = OBSREF_GET(*cr); struct config *c = OBSREF_GET(*cr);
struct config *oc = OBSREF_GET(config); old_config = OBSREF_GET(config);
old_config_pending = oc;
OBSREF_CLEAR(config); OBSREF_CLEAR(config);
OBSREF_SET(config, OBSREF_GET(*cr)); OBSREF_SET(config, OBSREF_GET(*cr));
@ -326,23 +315,30 @@ config_do_commit(config_ref *cr, int type)
} }
configuring = 1; configuring = 1;
if (oc && !c->shutdown) if (old_config && !c->shutdown)
log(L_INFO "Reconfiguring"); log(L_INFO "Reconfiguring");
DBG("filter_commit\n"); DBG("filter_commit\n");
filter_commit(c, oc); filter_commit(c, old_config);
DBG("sysdep_commit\n"); DBG("sysdep_commit\n");
sysdep_commit(c, oc); sysdep_commit(c, old_config);
DBG("global_commit\n"); DBG("global_commit\n");
global_commit(c, oc); global_commit(c, old_config);
mpls_commit(c, oc); mpls_commit(c, old_config);
DBG("rt_commit\n"); DBG("rt_commit\n");
rt_commit(c, oc); rt_commit(c, old_config);
DBG("protos_commit\n"); DBG("protos_commit\n");
protos_commit(c, oc, type); protos_commit(c, old_config, type);
/* Can be cleared directly? */ /* Can be cleared directly? */
return !oc || callback_is_active(&oc->obstacles_cleared); if (!old_config)
return 1;
if (!callback_is_active(&old_config->obstacles_cleared))
return 0;
callback_cancel(&old_config->obstacles_cleared);
return 1;
} }
static void static void
@ -355,7 +351,8 @@ config_done(void)
sysdep_shutdown_done(); sysdep_shutdown_done();
configuring = 0; configuring = 0;
if (OBSREF_GET(old_config))
if (old_config)
log(L_INFO "Reconfigured"); log(L_INFO "Reconfigured");
if (future_cftype) if (future_cftype)
@ -486,7 +483,7 @@ config_undo(void)
if (shutting_down) if (shutting_down)
return CONF_SHUTDOWN; return CONF_SHUTDOWN;
if (!undo_available || !OBSREF_GET(old_config)) if (!undo_available || !old_config)
return CONF_NOTHING; return CONF_NOTHING;
undo_available = 0; undo_available = 0;