c->pool = p;
c->mem = l;
c->file_name = ndup;
- 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;
+ c->runtime.tf_route = c->runtime.tf_proto = TM_ISO_SHORT_MS;
+ c->runtime.tf_base = c->runtime.tf_log = TM_ISO_LONG_MS;
+ c->runtime.gr_wait = DEFAULT_GR_WAIT;
callback_init(&c->obstacles_cleared, config_obstacles_cleared, &main_birdloop);
obstacle_target_init(&c->obstacles, &c->obstacles_cleared, p, "Config");
old_config = NULL;
}
-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)
{
/* 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);
-
-#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)
+ union bird_global_runtime *ng = &new->runtime;
+ SKIP_BACK_DECLARE(union bird_global_runtime, og, generic,
+ atomic_load_explicit(&global_runtime, memory_order_relaxed));
+
+ if (!ng->router_id && old)
{
/* The startup router ID must be determined after start of device protocol,
* thus if old == NULL then we do nothing */
}
}
- 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();
+ switch_runtime(&ng->generic);
}
static int
OBSREF_CLEAR(config);
OBSREF_SET(config, OBSREF_GET(*cr));
- if (!c->hostname)
+ if (!c->runtime.hostname)
{
- c->hostname = get_hostname(c->mem);
+ c->runtime.hostname = get_hostname(c->mem);
- if (!c->hostname)
+ if (!c->runtime.hostname)
log(L_WARN "Cannot determine hostname");
}
#include "lib/ip.h"
#include "lib/hash.h"
#include "lib/resource.h"
+#include "lib/runtime.h"
#include "lib/obstacle.h"
#include "lib/timer.h"
#include "lib/tlists.h"
struct symbol *def_tables[NET_MAX]; /* Default routing tables for each network */
struct iface_patt *router_id_from; /* Configured list of router ID iface patterns */
- u32 router_id; /* Our Router ID */
u32 proto_default_debug; /* Default protocol debug mask */
u32 proto_default_mrtdump; /* Default protocol mrtdump mask */
u32 channel_default_debug; /* Default channel debug mask */
u32 table_default_debug; /* Default table debug mask */
u32 show_route_debug; /* Exports to CLI debug mask */
u16 filter_vstk, filter_estk; /* Filter stack depth */
- 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) */
- const char *hostname; /* Hostname */
-
- int cli_debug; /* Tracing of CLI connections and commands */
- enum latency_debug_flags {
- DL_PING = 1,
- DL_WAKEUP = 2,
- DL_SCHEDULING = 4,
- DL_ALLOCATOR = 8,
- DL_SOCKETS = 0x10,
- DL_EVENTS = 0x20,
- DL_TIMERS = 0x40,
- } latency_debug; /* I/O loops log information about task scheduling */
- 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) */
+
+ union bird_global_runtime {
+ struct global_runtime generic;
+ struct {
+ GLOBAL_RUNTIME_CONTENTS;
+
+ struct timeformat tf_route; /* Time format for 'show route' */
+ struct timeformat tf_proto; /* Time format for 'show protocol' */
+
+ u32 gr_wait; /* Graceful restart wait timeout (sec) */
+
+ u32 router_id; /* Our Router ID */
+
+ int cli_debug; /* Tracing of CLI connections and commands */
+ u32 watchdog_timeout; /* Watchdog timeout (in seconds, 0 = disabled) */
+ };
+ } runtime;
+
char *err_msg; /* Parser error message */
int err_lino; /* Line containing error */
int err_chno; /* Character where the parser stopped */
int gr_down; /* This is a pseudo-config for graceful restart */
};
-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;
+/* BIRD's global runtime accessor */
+#define BIRD_GLOBAL_RUNTIME SKIP_BACK(union bird_global_runtime, generic, atomic_load_explicit(&global_runtime, memory_order_relaxed))
/* Please don't use these variables in protocols. Use proto_config->global instead. */
typedef OBSREF(struct config) config_ref;
-src := a-path.c a-set.c bitmap.c bitops.c blake2s.c blake2b.c checksum.c defer.c event.c flowspec.c idm.c ip.c lists.c lockfree.c mac.c md5.c mempool.c net.c netindex.c patmatch.c printf.c rcu.c resource.c sha1.c sha256.c sha512.c slab.c slists.c strtoul.c tbf.c timer.c xmalloc.c
+src := a-path.c a-set.c bitmap.c bitops.c blake2s.c blake2b.c checksum.c defer.c event.c flowspec.c idm.c ip.c lists.c lockfree.c mac.c md5.c mempool.c net.c netindex.c patmatch.c printf.c rcu.c resource.c runtime.c sha1.c sha256.c sha512.c slab.c slists.c strtoul.c tbf.c timer.c xmalloc.c
obj := $(src-o-files)
$(all-daemon)
--- /dev/null
+/*
+ * BIRD Internet Routing Daemon -- Global runtime context
+ *
+ * (c) 2024 Maria Matejka <mq@jmq.cz>
+ * (c) 2024 CZ.NIC, z.s.p.o.
+ *
+ * Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+#include "lib/runtime.h"
+
+struct global_runtime global_runtime_initial = {
+ .tf_log = {
+ .fmt1 = "%F %T.%3f",
+ },
+ .tf_base = {
+ .fmt1 = "%F %T.%3f",
+ },
+};
+
+struct global_runtime * _Atomic global_runtime = &global_runtime_initial;
+
+void
+switch_runtime(struct global_runtime *new)
+{
+ new->load_time = current_time();
+ atomic_store_explicit(&global_runtime, new, memory_order_release);
+
+ /* We have to wait until every reader surely doesn't read the old values */
+ synchronize_rcu();
+}
+
--- /dev/null
+/*
+ * BIRD Internet Routing Daemon -- Global runtime context
+ *
+ * (c) 2024 Maria Matejka <mq@jmq.cz>
+ * (c) 2024 CZ.NIC, z.s.p.o.
+ *
+ * Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+#include "lib/timer.h"
+
+/* I/O loops log information about task scheduling */
+enum latency_debug_flags {
+ DL_PING = 1,
+ DL_WAKEUP = 2,
+ DL_SCHEDULING = 4,
+ DL_ALLOCATOR = 8,
+ DL_SOCKETS = 0x10,
+ DL_EVENTS = 0x20,
+ DL_TIMERS = 0x40,
+};
+
+#define GLOBAL_RUNTIME_CONTENTS \
+ struct timeformat tf_log; /* Time format for the logfile */ \
+ struct timeformat tf_base; /* Time format for other purposes */ \
+ btime load_time; /* When we reconfigured last time */ \
+ enum latency_debug_flags latency_debug; /* What to log about IO loop */ \
+ u32 latency_limit; /* Events with longer duration are logged (us) */ \
+ u32 watchdog_warning; /* I/O loop watchdog limit for warning (us) */ \
+ const char *hostname; /* Hostname */ \
+
+struct global_runtime { GLOBAL_RUNTIME_CONTENTS };
+extern struct global_runtime * _Atomic global_runtime;
+
+void switch_runtime(struct global_runtime *);
struct config f;
int res;
- if (OBSREF_GET(config)->cli_debug > 1)
+ if (BIRD_GLOBAL_RUNTIME->cli_debug > 1)
log(L_TRACE "CLI: %s", c->rx_buf);
bzero(&f, sizeof(f));
f.mem = c->parser_pool;
cmd_show_status(void)
{
rcu_read_lock();
- struct global_runtime *gr = atomic_load_explicit(&global_runtime, memory_order_acquire);
+ union bird_global_runtime *gr = BIRD_GLOBAL_RUNTIME;
struct timeformat *tf = this_cli->tf ?: &gr->tf_base;
byte tim[TM_DATETIME_BUFFER_SIZE];
conf: rtrid ;
rtrid:
- ROUTER ID idval ';' { new_config->router_id = $3; }
+ ROUTER ID idval ';' { new_config->runtime.router_id = $3; }
| ROUTER ID FROM iface_patt ';' { new_config->router_id_from = this_ipatt; }
;
conf: hostname_override ;
-hostname_override: HOSTNAME text ';' { new_config->hostname = $2; } ;
+hostname_override: HOSTNAME text ';' { new_config->runtime.hostname = $2; } ;
conf: gr_opts ;
-gr_opts: GRACEFUL RESTART WAIT expr ';' { new_config->gr_wait = $4; } ;
+gr_opts: GRACEFUL RESTART WAIT expr ';' { new_config->runtime.gr_wait = $4; } ;
/* Network types (for tables, channels) */
DEBUG PROTOCOLS debug_mask { new_config->proto_default_debug = $3; }
| DEBUG CHANNELS debug_mask { new_config->channel_default_debug = $3; }
| DEBUG TABLES debug_mask { new_config->table_default_debug = $3; }
- | DEBUG COMMANDS expr { new_config->cli_debug = $3; }
+ | DEBUG COMMANDS expr { new_config->runtime.cli_debug = $3; }
| DEBUG SHOW ROUTE debug_mask { new_config->show_route_debug = $4; }
;
;
timeformat_which:
- ROUTE { $$ = &new_config->tf_route; }
- | PROTOCOL { $$ = &new_config->tf_proto; }
- | BASE { $$ = &new_config->tf_base; }
- | LOG { $$ = &new_config->tf_log; }
+ ROUTE { $$ = &new_config->runtime.tf_route; }
+ | PROTOCOL { $$ = &new_config->runtime.tf_proto; }
+ | BASE { $$ = &new_config->runtime.tf_base; }
+ | LOG { $$ = &new_config->runtime.tf_log; }
;
timeformat_spec:
init_list(&($$->tables));
$$->filter = FILTER_ACCEPT;
$$->cli = this_cli;
- $$->tf_route = this_cli->main_config->tf_route;
+ $$->tf_route = this_cli->main_config->runtime.tf_route;
}
| r_args net_any {
$$ = $1;
IFACE_WALK(i)
if_dump_locked(dreq, i);
rcu_read_lock();
- RDUMP("Router ID: %08x\n", atomic_load_explicit(&global_runtime, memory_order_relaxed)->router_id);
+ RDUMP("Router ID: %08x\n", BIRD_GLOBAL_RUNTIME->router_id);
rcu_read_unlock();
}
global_commit() because it is postponed after start of device protocol */
if ((phase == PROTOCOL_STARTUP_NECESSARY) && !old)
{
- struct global_runtime *gr = atomic_load_explicit(&global_runtime, memory_order_relaxed);
+ union bird_global_runtime *gr = BIRD_GLOBAL_RUNTIME;
if (!gr->router_id)
{
gr->router_id = if_choose_router_id(new->router_id_from, 0);
_graceful_recovery_context.grc_state = GRS_ACTIVE;
_graceful_recovery_context.wait_timer = (timer) { .hook = graceful_recovery_timeout };
- u32 gr_wait = atomic_load_explicit(&global_runtime, memory_order_relaxed)->gr_wait;
+ u32 gr_wait = BIRD_GLOBAL_RUNTIME->gr_wait;
tm_start(&_graceful_recovery_context.wait_timer, gr_wait S);
callback_init(&_graceful_recovery_context.obstacles_cleared, graceful_recovery_done, &main_birdloop);
obstacle_target_count(&_graceful_recovery_context.obstacles));
cli_msg(-24, " Wait timer is %t/%u",
tm_remains(&_graceful_recovery_context.wait_timer),
- atomic_load_explicit(&global_runtime, memory_order_relaxed)->gr_wait);
+ BIRD_GLOBAL_RUNTIME->gr_wait);
}
/**
if (p->proto->get_status)
p->proto->get_status(p, buf);
- rcu_read_lock();
- struct timeformat *tf = this_cli->tf ?: &atomic_load_explicit(&global_runtime, memory_order_acquire)->tf_proto;
- rcu_read_unlock();
+ struct timeformat *tf = this_cli->tf;
+ if (this_cli->tf)
+ tm_format_time(tbuf, this_cli->tf, p->last_state_change);
+ else
+ {
+ rcu_read_lock();
+ tm_format_time(tbuf, &BIRD_GLOBAL_RUNTIME->tf_proto, p->last_state_change);
+ rcu_read_unlock();
+ }
- tm_format_time(tbuf, tf, p->last_state_change);
cli_msg(-1002, "%-10s %-10s %-10s %-6s %-12s %s",
p->name,
p->proto->name,
static inline u32
proto_get_router_id(struct proto_config *pc)
{
- return pc->router_id ?: atomic_load_explicit(&global_runtime, memory_order_relaxed)->router_id;
+ return pc->router_id ?: BIRD_GLOBAL_RUNTIME->router_id;
}
byte tbuf[TM_DATETIME_BUFFER_SIZE];
rcu_read_lock();
- struct global_runtime *gr = atomic_load_explicit(&global_runtime, memory_order_relaxed);
+ union bird_global_runtime *gr = BIRD_GLOBAL_RUNTIME;
tm_format_time(tbuf, this_cli->tf ?: &gr->tf_proto, s->last_state_change);
rcu_read_unlock();
caps->llgr_aware = 1;
rcu_read_lock();
- struct global_runtime *gr = atomic_load_explicit(&global_runtime, memory_order_relaxed);
+ union bird_global_runtime *gr = BIRD_GLOBAL_RUNTIME;
if (p->cf->enable_hostname && gr->hostname)
{
size_t length = strlen(gr->hostname);
mrt_peer_table_dump(struct mrt_table_dump_state *s)
{
mrt_init_message(&s->buf, MRT_TABLE_DUMP_V2, MRT_PEER_INDEX_TABLE);
- mrt_peer_table_header(s, OBSREF_GET(config)->router_id, s->table_open->name);
+
+ rcu_read_lock();
+ mrt_peer_table_header(s, BIRD_GLOBAL_RUNTIME->router_id, s->table_open->name);
+ rcu_read_unlock();
/* 0 is fake peer for non-BGP routes */
mrt_peer_table_entry(s, 0, 0, IPA_NONE);
conf: debug_unix ;
debug_unix:
- DEBUG LATENCY latency_debug_mask { new_config->latency_debug = $3; }
- | DEBUG LATENCY LIMIT expr_us { new_config->latency_limit = $4; }
- | WATCHDOG WARNING expr_us { new_config->watchdog_warning = $3; }
- | WATCHDOG TIMEOUT expr_us { new_config->watchdog_timeout = ($3 + 999999) TO_S; }
+ DEBUG LATENCY latency_debug_mask { new_config->runtime.latency_debug = $3; }
+ | DEBUG LATENCY LIMIT expr_us { new_config->runtime.latency_limit = $4; }
+ | WATCHDOG WARNING expr_us { new_config->runtime.watchdog_warning = $3; }
+ | WATCHDOG TIMEOUT expr_us { new_config->runtime.watchdog_timeout = ($3 + 999999) TO_S; }
;
latency_debug_mask:
loop_time = last_io_time;
event_log_num = 0;
- struct global_runtime *gr = atomic_load_explicit(&global_runtime, memory_order_relaxed);
+ union bird_global_runtime *gr = BIRD_GLOBAL_RUNTIME;
if (gr->watchdog_timeout)
{
alarm(gr->watchdog_timeout);
}
btime duration = last_io_time - loop_time;
- struct global_runtime *gr = atomic_load_explicit(&global_runtime, memory_order_relaxed);
+ union bird_global_runtime *gr = BIRD_GLOBAL_RUNTIME;
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);
{
init_list(&c->logfiles);
- c->latency_limit = UNIX_DEFAULT_LATENCY_LIMIT;
- c->watchdog_warning = UNIX_DEFAULT_WATCHDOG_WARNING;
+ c->runtime.latency_limit = UNIX_DEFAULT_LATENCY_LIMIT;
+ c->runtime.watchdog_warning = UNIX_DEFAULT_WATCHDOG_WARNING;
#ifdef PATH_IPROUTE_DIR
read_iproute_table(c, PATH_IPROUTE_DIR "/rt_protos", "ipp_", 255);
return 0;
}
-#define GLOBAL_CLI_DEBUG (atomic_load_explicit(&global_runtime, memory_order_relaxed)->cli_debug)
+#define GLOBAL_CLI_DEBUG (BIRD_GLOBAL_RUNTIME->cli_debug)
static void
cli_err(sock *s, int err)