mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-11-09 12:48:43 +00:00
Global runtime values separated from config
This commit is contained in:
parent
73ad0e2dcb
commit
61dcbb1d83
54
conf/conf.c
54
conf/conf.c
@ -105,7 +105,6 @@ config_alloc(const char *name)
|
||||
c->pool = p;
|
||||
c->mem = l;
|
||||
c->file_name = ndup;
|
||||
c->load_time = current_time();
|
||||
c->tf_route = c->tf_proto = TM_ISO_SHORT_MS;
|
||||
c->tf_base = c->tf_log = TM_ISO_LONG_MS;
|
||||
c->gr_wait = DEFAULT_GR_WAIT;
|
||||
@ -150,11 +149,6 @@ config_parse(struct config *c)
|
||||
if (EMPTY_LIST(c->protos))
|
||||
cf_error("No protocol is specified in the config file");
|
||||
|
||||
/*
|
||||
if (!c->router_id)
|
||||
cf_error("Router ID must be configured manually");
|
||||
*/
|
||||
|
||||
done = 1;
|
||||
|
||||
cleanup:
|
||||
@ -244,25 +238,61 @@ config_del_obstacle(struct config *c)
|
||||
ev_send_loop(&main_birdloop, &c->done_event);
|
||||
}
|
||||
|
||||
struct global_runtime global_runtime_internal[2] = {{
|
||||
.tf_log = {
|
||||
.fmt1 = "%F %T.%3f",
|
||||
},
|
||||
}};
|
||||
struct global_runtime * _Atomic global_runtime = &global_runtime_internal[0];
|
||||
|
||||
static void
|
||||
global_commit(struct config *new, struct config *old)
|
||||
{
|
||||
if (!old)
|
||||
return;
|
||||
/* Updating the global runtime. */
|
||||
struct global_runtime *og = atomic_load_explicit(&global_runtime, memory_order_relaxed);
|
||||
struct global_runtime *ng = &global_runtime_internal[og == &global_runtime_internal[0]];
|
||||
ASSERT_DIE(ng != og);
|
||||
|
||||
if (!new->router_id)
|
||||
#define COPY(x) ng->x = new->x;
|
||||
MACRO_FOREACH(COPY,
|
||||
tf_route,
|
||||
tf_proto,
|
||||
tf_log,
|
||||
tf_base,
|
||||
cli_debug,
|
||||
latency_debug,
|
||||
latency_limit,
|
||||
watchdog_warning,
|
||||
watchdog_timeout,
|
||||
gr_wait,
|
||||
hostname
|
||||
);
|
||||
#undef COPY
|
||||
|
||||
ng->load_time = current_time();
|
||||
|
||||
if (new->router_id)
|
||||
ng->router_id = new->router_id;
|
||||
else if (old)
|
||||
{
|
||||
new->router_id = old->router_id;
|
||||
/* The startup router ID must be determined after start of device protocol,
|
||||
* thus if old == NULL then we do nothing */
|
||||
ng->router_id = og->router_id;
|
||||
|
||||
if (new->router_id_from)
|
||||
{
|
||||
u32 id = if_choose_router_id(new->router_id_from, old->router_id);
|
||||
u32 id = if_choose_router_id(new->router_id_from, og->router_id);
|
||||
if (!id)
|
||||
log(L_WARN "Cannot determine router ID, using old one");
|
||||
else
|
||||
new->router_id = id;
|
||||
ng->router_id = id;
|
||||
}
|
||||
}
|
||||
|
||||
atomic_store_explicit(&global_runtime, ng, memory_order_release);
|
||||
|
||||
/* We have to wait until every reader surely doesn't read the old values */
|
||||
synchronize_rcu();
|
||||
}
|
||||
|
||||
static int
|
||||
|
22
conf/conf.h
22
conf/conf.h
@ -72,9 +72,29 @@ struct config {
|
||||
event done_event; /* Called when obstacle_count reaches zero */
|
||||
int shutdown; /* This is a pseudo-config for daemon shutdown */
|
||||
int gr_down; /* This is a pseudo-config for graceful restart */
|
||||
btime load_time; /* When we've got this configuration */
|
||||
};
|
||||
|
||||
struct global_runtime {
|
||||
struct timeformat tf_route; /* Time format for 'show route' */
|
||||
struct timeformat tf_proto; /* Time format for 'show protocol' */
|
||||
struct timeformat tf_log; /* Time format for the logfile */
|
||||
struct timeformat tf_base; /* Time format for other purposes */
|
||||
|
||||
u32 gr_wait; /* Graceful restart wait timeout (sec) */
|
||||
|
||||
u32 router_id; /* Our Router ID */
|
||||
const char *hostname; /* Hostname */
|
||||
|
||||
btime load_time; /* When we reconfigured last time */
|
||||
int cli_debug; /* Tracing of CLI connections and commands */
|
||||
enum latency_debug_flags latency_debug;
|
||||
u32 latency_limit; /* Events with longer duration are logged (us) */
|
||||
u32 watchdog_warning; /* I/O loop watchdog limit for warning (us) */
|
||||
u32 watchdog_timeout; /* Watchdog timeout (in seconds, 0 = disabled) */
|
||||
};
|
||||
|
||||
extern struct global_runtime * _Atomic global_runtime;
|
||||
|
||||
/* Please don't use these variables in protocols. Use proto_config->global instead. */
|
||||
extern struct config *config; /* Currently active configuration */
|
||||
extern _Thread_local struct config *new_config; /* Configuration being parsed */
|
||||
|
@ -25,7 +25,7 @@ _Bool task_before_halftime(void);
|
||||
|
||||
#define MAYBE_DEFER_TASK(target, event, fmt, args...) do { \
|
||||
if (!task_still_in_limit()) { \
|
||||
if (config && (config->latency_debug & DL_SCHEDULING)) \
|
||||
if (atomic_load_explicit(&global_runtime, memory_order_relaxed)->latency_debug & DL_SCHEDULING) \
|
||||
log(L_TRACE "Deferring " fmt, ##args); \
|
||||
return ev_send(target, event); \
|
||||
} } while (0)
|
||||
|
16
nest/cmds.c
16
nest/cmds.c
@ -24,14 +24,18 @@ cmd_show_status(void)
|
||||
{
|
||||
byte tim[TM_DATETIME_BUFFER_SIZE];
|
||||
|
||||
rcu_read_lock();
|
||||
struct global_runtime *gr = atomic_load_explicit(&global_runtime, memory_order_acquire);
|
||||
struct timeformat *tf = &gr->tf_base;
|
||||
|
||||
cli_msg(-1000, "BIRD " BIRD_VERSION);
|
||||
tm_format_time(tim, &config->tf_base, current_time());
|
||||
cli_msg(-1011, "Router ID is %R", config->router_id);
|
||||
cli_msg(-1011, "Hostname is %s", config->hostname);
|
||||
tm_format_time(tim, tf, current_time());
|
||||
cli_msg(-1011, "Router ID is %R", gr->router_id);
|
||||
cli_msg(-1011, "Hostname is %s", gr->hostname);
|
||||
cli_msg(-1011, "Current server time is %s", tim);
|
||||
tm_format_time(tim, &config->tf_base, boot_time);
|
||||
tm_format_time(tim, tf, boot_time);
|
||||
cli_msg(-1011, "Last reboot on %s", tim);
|
||||
tm_format_time(tim, &config->tf_base, config->load_time);
|
||||
tm_format_time(tim, tf, gr->load_time);
|
||||
cli_msg(-1011, "Last reconfiguration on %s", tim);
|
||||
|
||||
graceful_restart_show_status();
|
||||
@ -42,6 +46,8 @@ cmd_show_status(void)
|
||||
cli_msg(13, "Reconfiguration in progress");
|
||||
else
|
||||
cli_msg(13, "Daemon is up and running");
|
||||
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -164,7 +164,9 @@ if_dump_all(void)
|
||||
debug("Known network interfaces:\n");
|
||||
IFACE_WALK(i)
|
||||
if_dump(i);
|
||||
debug("Router ID: %08x\n", config->router_id);
|
||||
rcu_read_lock();
|
||||
debug("Router ID: %08x\n", atomic_load_explicit(&global_runtime, memory_order_relaxed)->router_id);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
void
|
||||
|
25
nest/proto.c
25
nest/proto.c
@ -1624,12 +1624,16 @@ protos_do_commit(struct config *new, struct config *old, int type)
|
||||
|
||||
/* Determine router ID for the first time - it has to be here and not in
|
||||
global_commit() because it is postponed after start of device protocol */
|
||||
if (!config->router_id)
|
||||
if ((phase == PROTOCOL_STARTUP_NECESSARY) && !old)
|
||||
{
|
||||
config->router_id = if_choose_router_id(config->router_id_from, 0);
|
||||
if (!config->router_id)
|
||||
struct global_runtime *gr = atomic_load_explicit(&global_runtime, memory_order_relaxed);
|
||||
if (!gr->router_id)
|
||||
{
|
||||
gr->router_id = if_choose_router_id(new->router_id_from, 0);
|
||||
if (!gr->router_id)
|
||||
die("Cannot determine router ID, please configure it manually");
|
||||
}
|
||||
}
|
||||
|
||||
/* Commit next round of protocols */
|
||||
if (new->shutdown && !new->gr_down)
|
||||
@ -1781,7 +1785,8 @@ graceful_restart_init(void)
|
||||
|
||||
graceful_restart_state = GRS_ACTIVE;
|
||||
gr_wait_timer = tm_new_init(proto_pool, graceful_restart_done, NULL, 0, 0);
|
||||
tm_start(gr_wait_timer, config->gr_wait S);
|
||||
u32 gr_wait = atomic_load_explicit(&global_runtime, memory_order_relaxed)->gr_wait;
|
||||
tm_start(gr_wait_timer, gr_wait S);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1795,7 +1800,7 @@ graceful_restart_init(void)
|
||||
* restart wait timer fires (but there are still some locks).
|
||||
*/
|
||||
static void
|
||||
graceful_restart_done(timer *t UNUSED)
|
||||
graceful_restart_done(timer *t)
|
||||
{
|
||||
log(L_INFO "Graceful restart done");
|
||||
graceful_restart_state = GRS_DONE;
|
||||
@ -1821,6 +1826,8 @@ graceful_restart_done(timer *t UNUSED)
|
||||
}
|
||||
|
||||
graceful_restart_locks = 0;
|
||||
|
||||
rfree(t);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1831,7 +1838,8 @@ graceful_restart_show_status(void)
|
||||
|
||||
cli_msg(-24, "Graceful restart recovery in progress");
|
||||
cli_msg(-24, " Waiting for %d channels to recover", graceful_restart_locks);
|
||||
cli_msg(-24, " Wait timer is %t/%u", tm_remains(gr_wait_timer), config->gr_wait);
|
||||
cli_msg(-24, " Wait timer is %t/%u", tm_remains(gr_wait_timer),
|
||||
atomic_load_explicit(&global_runtime, memory_order_relaxed)->gr_wait);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2422,7 +2430,10 @@ proto_cmd_show(struct proto *p, uintptr_t verbose, int cnt)
|
||||
buf[0] = 0;
|
||||
if (p->proto->get_status)
|
||||
p->proto->get_status(p, buf);
|
||||
tm_format_time(tbuf, &config->tf_proto, p->last_state_change);
|
||||
|
||||
rcu_read_lock();
|
||||
tm_format_time(tbuf, &atomic_load_explicit(&global_runtime, memory_order_acquire)->tf_proto, p->last_state_change);
|
||||
rcu_read_unlock();
|
||||
cli_msg(-1002, "%-10s %-10s %-10s %-6s %-12s %s",
|
||||
p->name,
|
||||
p->proto->name,
|
||||
|
@ -302,7 +302,7 @@ static inline struct domain_generic *proto_domain(struct proto *p)
|
||||
static inline u32
|
||||
proto_get_router_id(struct proto_config *pc)
|
||||
{
|
||||
return pc->router_id ? pc->router_id : pc->global->router_id;
|
||||
return pc->router_id ?: atomic_load_explicit(&global_runtime, memory_order_relaxed)->router_id;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1237,7 +1237,11 @@ bfd_show_session(struct bfd_session *s, int details)
|
||||
|
||||
byte dbuf[BFD_DIAG_BUFFER_SIZE];
|
||||
byte tbuf[TM_DATETIME_BUFFER_SIZE];
|
||||
tm_format_time(tbuf, &config->tf_proto, s->last_state_change);
|
||||
|
||||
rcu_read_lock();
|
||||
struct global_runtime *gr = atomic_load_explicit(&global_runtime, memory_order_relaxed);
|
||||
tm_format_time(tbuf, &gr->tf_proto, s->last_state_change);
|
||||
rcu_read_unlock();
|
||||
|
||||
if (!details)
|
||||
{
|
||||
|
@ -283,13 +283,16 @@ bgp_prepare_capabilities(struct bgp_conn *conn)
|
||||
if (p->cf->llgr_mode)
|
||||
caps->llgr_aware = 1;
|
||||
|
||||
if (p->cf->enable_hostname && config->hostname)
|
||||
rcu_read_lock();
|
||||
struct global_runtime *gr = atomic_load_explicit(&global_runtime, memory_order_relaxed);
|
||||
if (p->cf->enable_hostname && gr->hostname)
|
||||
{
|
||||
size_t length = strlen(config->hostname);
|
||||
size_t length = strlen(gr->hostname);
|
||||
char *hostname = mb_allocz(p->p.pool, length+1);
|
||||
memcpy(hostname, config->hostname, length+1);
|
||||
memcpy(hostname, gr->hostname, length+1);
|
||||
caps->hostname = hostname;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
/* Allocate and fill per-AF fields */
|
||||
BGP_WALK_CHANNELS(p, c)
|
||||
|
@ -123,7 +123,8 @@ void do_lock(struct domain_generic *dg, struct domain_generic **lsp)
|
||||
btime lock_begin = current_time();
|
||||
pthread_mutex_lock(&dg->mutex);
|
||||
btime duration = current_time() - lock_begin;
|
||||
if (config && (duration > config->watchdog_warning))
|
||||
btime wdw = atomic_load_explicit(&global_runtime, memory_order_relaxed)->watchdog_warning;
|
||||
if (wdw && (duration > wdw))
|
||||
log(L_WARN "Locking of %s took %d ms", dg->name, (int) (duration TO_MS));
|
||||
|
||||
if (dg->prev || dg->locked_by)
|
||||
|
@ -152,9 +152,10 @@ static _Thread_local struct birdloop *birdloop_wakeup_masked;
|
||||
static _Thread_local uint birdloop_wakeup_masked_count;
|
||||
|
||||
#define LOOP_NAME(loop) domain_name((loop)->time.domain)
|
||||
#define LATENCY_DEBUG(flags) (atomic_load_explicit(&global_runtime, memory_order_relaxed)->latency_debug & (flags))
|
||||
|
||||
#define LOOP_TRACE(loop, flags, fmt, args...) do { if (config && (config->latency_debug & (flags))) log(L_TRACE "%s (%p): " fmt, LOOP_NAME(loop), (loop), ##args); } while (0)
|
||||
#define THREAD_TRACE(flags, ...) do { if (config && (config->latency_debug & (flags))) log(L_TRACE "Thread: " __VA_ARGS__); } while (0)
|
||||
#define LOOP_TRACE(loop, flags, fmt, args...) do { if (LATENCY_DEBUG(flags)) log(L_TRACE "%s (%p): " fmt, LOOP_NAME(loop), (loop), ##args); } while (0)
|
||||
#define THREAD_TRACE(flags, ...) do { if (LATENCY_DEBUG(flags)) log(L_TRACE "Thread: " __VA_ARGS__); } while (0)
|
||||
|
||||
#define LOOP_WARN(loop, fmt, args...) log(L_WARN "%s (%p): " fmt, LOOP_NAME(loop), (loop), ##args)
|
||||
|
||||
@ -1506,7 +1507,8 @@ birdloop_run(void *_loop)
|
||||
/* Now we can actually do some work */
|
||||
u64 dif = account_to(&loop->working);
|
||||
|
||||
if (dif > this_thread->max_loop_time_ns + config->latency_limit TO_NS)
|
||||
struct global_runtime *gr = atomic_load_explicit(&global_runtime, memory_order_relaxed);
|
||||
if (dif > this_thread->max_loop_time_ns + gr->latency_limit TO_NS)
|
||||
LOOP_WARN(loop, "locked %lu us after its scheduled end time", dif NS TO_US);
|
||||
|
||||
uint repeat, loop_runs = 0;
|
||||
|
@ -2247,7 +2247,8 @@ io_update_time(void)
|
||||
{
|
||||
event_open->duration = last_io_time - event_open->timestamp;
|
||||
|
||||
if (event_open->duration > config->latency_limit)
|
||||
struct global_runtime *gr = atomic_load_explicit(&global_runtime, memory_order_relaxed);
|
||||
if (event_open->duration > gr->latency_limit)
|
||||
log(L_WARN "Event 0x%p 0x%p took %u.%03u ms",
|
||||
event_open->hook, event_open->data, (uint) (event_open->duration TO_MS), (uint) (event_open->duration % 1000));
|
||||
|
||||
@ -2267,7 +2268,8 @@ io_update_time(void)
|
||||
void
|
||||
io_log_event(void *hook, void *data, uint flag)
|
||||
{
|
||||
if (config->latency_debug & flag)
|
||||
struct global_runtime *gr = atomic_load_explicit(&global_runtime, memory_order_relaxed);
|
||||
if (gr->latency_debug & flag)
|
||||
io_update_time();
|
||||
|
||||
struct event_log_entry *en = event_log + event_log_pos;
|
||||
@ -2281,7 +2283,7 @@ io_log_event(void *hook, void *data, uint flag)
|
||||
event_log_pos++;
|
||||
event_log_pos %= EVENT_LOG_LENGTH;
|
||||
|
||||
event_open = (config->latency_debug & flag) ? en : NULL;
|
||||
event_open = (gr->latency_debug & flag) ? en : NULL;
|
||||
}
|
||||
|
||||
static inline void
|
||||
@ -2310,7 +2312,8 @@ void
|
||||
watchdog_sigalrm(int sig UNUSED)
|
||||
{
|
||||
/* Update last_io_time and duration, but skip latency check */
|
||||
config->latency_limit = 0xffffffff;
|
||||
struct global_runtime *gr = atomic_load_explicit(&global_runtime, memory_order_relaxed);
|
||||
gr->latency_limit = 0xffffffff;
|
||||
io_update_time();
|
||||
|
||||
debug_safe("Watchdog timer timed out\n");
|
||||
@ -2335,9 +2338,10 @@ watchdog_start(void)
|
||||
loop_time = last_io_time;
|
||||
event_log_num = 0;
|
||||
|
||||
if (config->watchdog_timeout)
|
||||
struct global_runtime *gr = atomic_load_explicit(&global_runtime, memory_order_relaxed);
|
||||
if (gr->watchdog_timeout)
|
||||
{
|
||||
alarm(config->watchdog_timeout);
|
||||
alarm(gr->watchdog_timeout);
|
||||
watchdog_active = 1;
|
||||
}
|
||||
}
|
||||
@ -2354,7 +2358,8 @@ watchdog_stop(void)
|
||||
}
|
||||
|
||||
btime duration = last_io_time - loop_time;
|
||||
if (duration > config->watchdog_warning)
|
||||
struct global_runtime *gr = atomic_load_explicit(&global_runtime, memory_order_relaxed);
|
||||
if (duration > gr->watchdog_warning)
|
||||
log(L_WARN "I/O loop cycle took %u.%03u ms for %d events",
|
||||
(uint) (duration TO_MS), (uint) (duration % 1000), event_log_num);
|
||||
}
|
||||
|
@ -284,8 +284,10 @@ log_prepare(log_buffer *buf, int class)
|
||||
buf->pos[LBP_TIMESTAMP] = buf->buf.pos;
|
||||
if (BIT32_TEST(&lf, LBP_TIMESTAMP))
|
||||
{
|
||||
const char *fmt = config ? config->tf_log.fmt1 : "%F %T.%3f";
|
||||
rcu_read_lock();
|
||||
const char *fmt = atomic_load_explicit(&global_runtime, memory_order_acquire)->tf_log.fmt1;
|
||||
int t = tm_format_real_time(buf->buf.pos, buf->buf.end - buf->buf.pos, fmt, current_real_time());
|
||||
rcu_read_unlock();
|
||||
if (t)
|
||||
buf->buf.pos += t;
|
||||
else
|
||||
@ -307,8 +309,10 @@ log_prepare(log_buffer *buf, int class)
|
||||
else
|
||||
buffer_puts(&buf->buf, "<time format error>");
|
||||
|
||||
const char *hostname = (config && config->hostname) ? config->hostname : "<none>";
|
||||
rcu_read_lock();
|
||||
const char *hostname = atomic_load_explicit(&global_runtime, memory_order_acquire)->hostname ?: "<none>";
|
||||
buffer_print(&buf->buf, " %s %s: ", hostname, bird_name);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
buf->pos[LBP_THREAD_ID] = buf->buf.pos;
|
||||
|
@ -487,10 +487,12 @@ cli_rx(sock *s, uint size UNUSED)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define GLOBAL_CLI_DEBUG (atomic_load_explicit(&global_runtime, memory_order_relaxed)->cli_debug)
|
||||
|
||||
static void
|
||||
cli_err(sock *s, int err)
|
||||
{
|
||||
if (config->cli_debug)
|
||||
if (GLOBAL_CLI_DEBUG)
|
||||
{
|
||||
if (err)
|
||||
log(L_INFO "CLI connection dropped: %s", strerror(err));
|
||||
@ -505,7 +507,7 @@ static void
|
||||
cli_connect_err(sock *s UNUSED, int err)
|
||||
{
|
||||
ASSERT_DIE(err);
|
||||
if (config->cli_debug)
|
||||
if (GLOBAL_CLI_DEBUG)
|
||||
log(L_INFO "Failed to accept CLI connection: %s", strerror(err));
|
||||
}
|
||||
|
||||
@ -514,7 +516,7 @@ cli_connect(sock *s, uint size UNUSED)
|
||||
{
|
||||
cli *c;
|
||||
|
||||
if (config->cli_debug)
|
||||
if (GLOBAL_CLI_DEBUG)
|
||||
log(L_INFO "CLI connect");
|
||||
s->rx_hook = cli_rx;
|
||||
s->tx_hook = cli_tx;
|
||||
|
Loading…
Reference in New Issue
Block a user