mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-11-08 12:18:42 +00:00
Global runtime splitout to BIRD specific and lib things
This commit is contained in:
parent
d6cb22f246
commit
1b998e846c
52
conf/conf.c
52
conf/conf.c
@ -113,9 +113,9 @@ config_alloc(const char *name)
|
||||
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");
|
||||
@ -229,42 +229,15 @@ config_free_old(void)
|
||||
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);
|
||||
union bird_global_runtime *ng = &new->runtime;
|
||||
SKIP_BACK_DECLARE(union bird_global_runtime, og, generic,
|
||||
atomic_load_explicit(&global_runtime, memory_order_relaxed));
|
||||
|
||||
#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)
|
||||
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 */
|
||||
@ -280,10 +253,7 @@ global_commit(struct config *new, struct config *old)
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
@ -306,11 +276,11 @@ config_do_commit(config_ref *cr, int type)
|
||||
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");
|
||||
}
|
||||
|
||||
|
60
conf/conf.h
60
conf/conf.h
@ -13,6 +13,7 @@
|
||||
#include "lib/ip.h"
|
||||
#include "lib/hash.h"
|
||||
#include "lib/resource.h"
|
||||
#include "lib/runtime.h"
|
||||
#include "lib/obstacle.h"
|
||||
#include "lib/timer.h"
|
||||
|
||||
@ -32,33 +33,30 @@ struct config {
|
||||
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 */
|
||||
@ -76,26 +74,8 @@ struct config {
|
||||
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;
|
||||
|
@ -1,4 +1,4 @@
|
||||
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)
|
||||
|
||||
|
32
lib/runtime.c
Normal file
32
lib/runtime.c
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
|
35
lib/runtime.h
Normal file
35
lib/runtime.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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 *);
|
@ -221,7 +221,7 @@ cli_command(struct cli *c)
|
||||
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;
|
||||
|
@ -25,7 +25,7 @@ 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);
|
||||
union bird_global_runtime *gr = BIRD_GLOBAL_RUNTIME;
|
||||
struct timeformat *tf = &gr->tf_base;
|
||||
|
||||
cli_msg(-1000, "BIRD " BIRD_VERSION);
|
||||
|
@ -202,7 +202,7 @@ CF_GRAMMAR
|
||||
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; }
|
||||
;
|
||||
|
||||
@ -222,11 +222,11 @@ idval:
|
||||
|
||||
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) */
|
||||
@ -443,7 +443,7 @@ debug_default:
|
||||
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; }
|
||||
;
|
||||
|
||||
@ -452,10 +452,10 @@ debug_default:
|
||||
conf: timeformat_base ;
|
||||
|
||||
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:
|
||||
@ -736,7 +736,7 @@ r_args:
|
||||
$$->filter = FILTER_ACCEPT;
|
||||
OBSREF_SET($$->running_on_config, this_cli->main_config);
|
||||
$$->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;
|
||||
|
@ -165,7 +165,7 @@ if_dump_all(void)
|
||||
IFACE_WALK(i)
|
||||
if_dump(i);
|
||||
rcu_read_lock();
|
||||
debug("Router ID: %08x\n", atomic_load_explicit(&global_runtime, memory_order_relaxed)->router_id);
|
||||
debug("Router ID: %08x\n", BIRD_GLOBAL_RUNTIME->router_id);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
|
@ -1671,7 +1671,7 @@ protos_do_commit(struct config *new, struct config *old, int type)
|
||||
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);
|
||||
@ -1830,7 +1830,7 @@ graceful_restart_init(void)
|
||||
|
||||
graceful_restart_state = GRS_ACTIVE;
|
||||
gr_wait_timer = tm_new_init(proto_pool, graceful_restart_done, NULL, 0, 0);
|
||||
u32 gr_wait = atomic_load_explicit(&global_runtime, memory_order_relaxed)->gr_wait;
|
||||
u32 gr_wait = BIRD_GLOBAL_RUNTIME->gr_wait;
|
||||
tm_start(gr_wait_timer, gr_wait S);
|
||||
}
|
||||
|
||||
@ -1884,7 +1884,7 @@ 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),
|
||||
atomic_load_explicit(&global_runtime, memory_order_relaxed)->gr_wait);
|
||||
BIRD_GLOBAL_RUNTIME->gr_wait);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2472,7 +2472,7 @@ proto_cmd_show(struct proto *p, uintptr_t verbose, int cnt)
|
||||
p->proto->get_status(p, buf);
|
||||
|
||||
rcu_read_lock();
|
||||
tm_format_time(tbuf, &atomic_load_explicit(&global_runtime, memory_order_acquire)->tf_proto, p->last_state_change);
|
||||
tm_format_time(tbuf, &BIRD_GLOBAL_RUNTIME->tf_proto, p->last_state_change);
|
||||
rcu_read_unlock();
|
||||
cli_msg(-1002, "%-10s %-10s %-10s %-6s %-12s %s",
|
||||
p->name,
|
||||
|
@ -303,7 +303,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 ?: atomic_load_explicit(&global_runtime, memory_order_relaxed)->router_id;
|
||||
return pc->router_id ?: BIRD_GLOBAL_RUNTIME->router_id;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1239,7 +1239,7 @@ bfd_show_session(struct bfd_session *s, int details)
|
||||
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, &gr->tf_proto, s->last_state_change);
|
||||
rcu_read_unlock();
|
||||
|
||||
|
@ -284,7 +284,7 @@ bgp_prepare_capabilities(struct bgp_conn *conn)
|
||||
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);
|
||||
|
@ -132,10 +132,10 @@ conf: THREADS expr {
|
||||
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:
|
||||
|
@ -464,7 +464,7 @@ watchdog_start(void)
|
||||
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);
|
||||
@ -484,7 +484,7 @@ watchdog_stop(void)
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -191,8 +191,8 @@ sysdep_preconfig(struct config *c)
|
||||
{
|
||||
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);
|
||||
@ -489,7 +489,7 @@ cli_rx(sock *s, uint size UNUSED)
|
||||
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)
|
||||
|
Loading…
Reference in New Issue
Block a user