0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-22 09:41:54 +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;
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 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 */
@ -77,28 +77,15 @@ static timer *config_timer; /* Timer for scheduled configuration rollback */
/* 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 configuring; /* Reconfiguration is running */
struct config *old_config_pending; /* Just for debug convenience */
int undo_available; /* Undo was not requested from last reconfiguration */
/* Note that both shutting_down and undo_available are related to requests, not processing */
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));
if (c == old_config_pending)
{
old_config_pending = NULL;
if (!shutting_down)
OBSREF_SET(old_config, c);
if (configuring)
config_done();
}
else
config_free(c);
ASSERT_DIE(configuring);
config_done();
}
/**
@ -235,9 +222,11 @@ config_free(struct config *c)
void
config_free_old(void)
{
OBSREF_CLEAR(old_config);
tm_stop(config_timer);
undo_available = 0;
config_free(old_config);
old_config = NULL;
}
struct global_runtime global_runtime_internal[2] = {{
@ -302,17 +291,17 @@ config_do_commit(config_ref *cr, int type)
{
if (type == RECONFIG_UNDO)
{
OBSREF_SET(*cr, OBSREF_GET(old_config));
OBSREF_SET(*cr, old_config);
type = old_cftype;
}
else
config_free(old_config);
OBSREF_CLEAR(old_config);
old_config = NULL;
old_cftype = type;
struct config *c = OBSREF_GET(*cr);
struct config *oc = OBSREF_GET(config);
old_config_pending = oc;
old_config = OBSREF_GET(config);
OBSREF_CLEAR(config);
OBSREF_SET(config, OBSREF_GET(*cr));
@ -326,23 +315,30 @@ config_do_commit(config_ref *cr, int type)
}
configuring = 1;
if (oc && !c->shutdown)
if (old_config && !c->shutdown)
log(L_INFO "Reconfiguring");
DBG("filter_commit\n");
filter_commit(c, oc);
filter_commit(c, old_config);
DBG("sysdep_commit\n");
sysdep_commit(c, oc);
sysdep_commit(c, old_config);
DBG("global_commit\n");
global_commit(c, oc);
mpls_commit(c, oc);
global_commit(c, old_config);
mpls_commit(c, old_config);
DBG("rt_commit\n");
rt_commit(c, oc);
rt_commit(c, old_config);
DBG("protos_commit\n");
protos_commit(c, oc, type);
protos_commit(c, old_config, type);
/* 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
@ -355,7 +351,8 @@ config_done(void)
sysdep_shutdown_done();
configuring = 0;
if (OBSREF_GET(old_config))
if (old_config)
log(L_INFO "Reconfigured");
if (future_cftype)
@ -486,7 +483,7 @@ config_undo(void)
if (shutting_down)
return CONF_SHUTDOWN;
if (!undo_available || !OBSREF_GET(old_config))
if (!undo_available || !old_config)
return CONF_NOTHING;
undo_available = 0;