diff --git a/client/util.c b/client/util.c index 1d83e518..3a78a7c4 100644 --- a/client/util.c +++ b/client/util.c @@ -17,7 +17,7 @@ /* Client versions of logging functions */ static void -vlog(const char *msg, va_list args) +vlog_cli(const char *msg, va_list args) { char buf[1024]; @@ -38,7 +38,7 @@ bug(const char *msg, ...) va_start(args, msg); cleanup(); fputs("Internal error: ", stderr); - vlog(msg, args); + vlog_cli(msg, args); vfprintf(stderr, msg, args); va_end(args); exit(1); @@ -51,7 +51,7 @@ die(const char *msg, ...) va_start(args, msg); cleanup(); - vlog(msg, args); + vlog_cli(msg, args); va_end(args); exit(1); } diff --git a/lib/birdlib.h b/lib/birdlib.h index 57149cc9..41aa8b3f 100644 --- a/lib/birdlib.h +++ b/lib/birdlib.h @@ -16,6 +16,8 @@ #include "lib/alloca.h" #include "lib/macro.h" +#include + /* Ugly structure offset handling macros */ #define SAME_TYPE(a, b) ({ int _ = ((a) != (b)); !_; }) @@ -211,6 +213,7 @@ void log_msg(const char *msg, ...); void log_rl(struct tbf *rl, const char *msg, ...); void die(const char *msg, ...) NORET; void bug(const char *msg, ...) NORET; +void vlog(int class, const char *msg, va_list args); #define L_DEBUG "\001" /* Debugging messages */ #define L_TRACE "\002" /* Protocol tracing */ diff --git a/lib/mempool.c b/lib/mempool.c index 5940e571..6de44b6b 100644 --- a/lib/mempool.c +++ b/lib/mempool.c @@ -29,6 +29,7 @@ struct lp_chunk { struct lp_chunk *next; struct linpool *lp; uintptr_t data_align[0]; + _Atomic u64 data_align_atomic[0]; byte data[0]; }; diff --git a/lib/printf.c b/lib/printf.c index 318e683c..0d2f95e8 100644 --- a/lib/printf.c +++ b/lib/printf.c @@ -169,9 +169,9 @@ int bvsnprintf(char *buf, int size, const char *fmt, va_list args) int qualifier; /* 'h' or 'l' for integer fields */ for (start=str=buf ; *fmt ; ++fmt, size-=(str-start), start=str) { + if (!size) + return -1; if (*fmt != '%') { - if (!size) - return -1; *str++ = *fmt; continue; } @@ -272,7 +272,7 @@ int bvsnprintf(char *buf, int size, const char *fmt, va_list args) len = strlen(s); if (precision >= 0 && len > precision) len = precision; - if (len > size) + if ((len > size) || (field_width > size)) return -1; if (!(flags & LEFT)) diff --git a/lib/resource.c b/lib/resource.c index b89f772c..17af79d7 100644 --- a/lib/resource.c +++ b/lib/resource.c @@ -373,7 +373,10 @@ tmp_flush(void) struct mblock { resource r; unsigned size; - uintptr_t data_align[0]; + union { + uintptr_t bigint; + _Atomic u64 atom; + } _align[0]; byte data[0]; }; diff --git a/lib/slab.c b/lib/slab.c index ab913f0c..276ea8d0 100644 --- a/lib/slab.c +++ b/lib/slab.c @@ -171,6 +171,8 @@ struct sl_head { struct sl_alignment { /* Magic structure for testing of alignment */ byte data; int x[0]; + _Atomic u64 y[0]; + void *z[0]; }; #define TLIST_PREFIX sl_head diff --git a/nest/cli.c b/nest/cli.c index 37f310b0..934451b1 100644 --- a/nest/cli.c +++ b/nest/cli.c @@ -117,9 +117,8 @@ cli_alloc_out(cli *c, int size) * macro instead. */ void -cli_printf(cli *c, int code, char *msg, ...) +cli_vprintf(cli *c, int code, const char *msg, va_list args) { - va_list args; byte buf[CLI_LINE_SIZE]; int cd = code; int errcode; @@ -147,9 +146,7 @@ cli_printf(cli *c, int code, char *msg, ...) } c->last_reply = cd; - va_start(args, msg); cnt = bvsnprintf(buf+size, sizeof(buf)-size-1, msg, args); - va_end(args); if (cnt < 0) { cli_printf(c, errcode, ""); diff --git a/nest/cli.h b/nest/cli.h index e9b59c51..54fc2964 100644 --- a/nest/cli.h +++ b/nest/cli.h @@ -73,7 +73,15 @@ extern struct cli *this_cli; /* Used during parsing */ /* Functions to be called by command handlers */ -void cli_printf(cli *, int, char *, ...); +void cli_vprintf(cli *, int, const char *, va_list); +static inline void cli_printf(cli *cli, int code, const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + cli_vprintf(cli, code, fmt, args); + va_end(args); +} + #define cli_msg(x...) cli_printf(this_cli, x) void cli_set_timeformat(cli *c, const struct timeformat tf); diff --git a/nest/proto.c b/nest/proto.c index 5a46514b..1029957a 100644 --- a/nest/proto.c +++ b/nest/proto.c @@ -1334,6 +1334,7 @@ proto_new(struct proto_config *cf) p->proto = cf->protocol; p->proto_state = PS_DOWN_XX; p->last_state_change = current_time(); + p->last_reconfiguration = current_time(); p->net_type = cf->net_type; p->disabled = cf->disabled; @@ -2183,14 +2184,17 @@ proto_restart_event_hook(void *_p) proto_rethink_goal(p); if (proto_restart) - if (current_time_now() - p->last_restart < p->restart_limit) - log(L_ERR "%s: too frequent restarts, disabling", p->name); - else - p->disabled = 0; + { + /* Store the last restart time */ + p->last_restart = current_time(); + + /* Allow the protocol back again */ + p->disabled = 0; /* No need to call proto_rethink_goal() here again as the proto_cleanup() routine will * call it after the protocol stops ... and both these routines are fixed to main_birdloop. */ + } } static inline void @@ -2306,8 +2310,16 @@ channel_limit_down(struct limit *l, void *data) channel_activate_limit(c, l, dir); + bool restart = (c->limit_actions[dir] == PLA_RESTART); + + if (restart && (current_time_now() - p->last_restart < p->restart_limit)) + { + log(L_ERR "%s: too frequent restarts, disabling", p->name); + restart = false; + } + if (p->proto_state == PS_UP) - proto_schedule_down(p, c->limit_actions[dir] == PLA_RESTART, chl_dir_down[dir]); + proto_schedule_down(p, restart, chl_dir_down[dir]); return 1; } @@ -2619,8 +2631,10 @@ proto_cmd_show(struct proto *p, uintptr_t verbose, int cnt) p->proto->get_status(p, buf); rcu_read_lock(); - tm_format_time(tbuf, this_cli->tf ?: &atomic_load_explicit(&global_runtime, memory_order_acquire)->tf_proto, p->last_state_change); + struct timeformat *tf = this_cli->tf ?: &atomic_load_explicit(&global_runtime, memory_order_acquire)->tf_proto; 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, @@ -2632,13 +2646,20 @@ proto_cmd_show(struct proto *p, uintptr_t verbose, int cnt) if (verbose) { if (p->cf->dsc) - cli_msg(-1006, " Description: %s", p->cf->dsc); + cli_msg(-1006, " Description: %s", p->cf->dsc); if (p->message) - cli_msg(-1006, " Message: %s", p->message); + cli_msg(-1006, " Message: %s", p->message); + tm_format_time(tbuf, tf, p->last_reconfiguration); + cli_msg(-1006, " Created: %s", tbuf); + if (p->last_restart > p->last_reconfiguration) + { + tm_format_time(tbuf, tf, p->last_restart); + cli_msg(-1006, " Last autorestart: %s", tbuf); + } if (p->cf->router_id) - cli_msg(-1006, " Router ID: %R", p->cf->router_id); + cli_msg(-1006, " Router ID: %R", p->cf->router_id); if (p->vrf) - cli_msg(-1006, " VRF: %s", p->vrf->name); + cli_msg(-1006, " VRF: %s", p->vrf->name); if (p->proto->show_proto_info) p->proto->show_proto_info(p); diff --git a/nest/protocol.h b/nest/protocol.h index 171a0a5b..5e1098c2 100644 --- a/nest/protocol.h +++ b/nest/protocol.h @@ -170,6 +170,7 @@ struct proto { u32 hash_key; /* Random key used for hashing of neighbors */ btime last_state_change; /* Time of last state transition */ btime last_restart; /* Time of last restart */ + btime last_reconfiguration; /* Time of last hard reconfiguration */ btime restart_limit; /* Minimum allowed time between limit restarts */ char *last_state_name_announced; /* Last state name we've announced to the user */ char *message; /* State-change message, allocated from proto_pool */ diff --git a/proto/mrt/mrt.c b/proto/mrt/mrt.c index ff3b0227..cc5ad06a 100644 --- a/proto/mrt/mrt.c +++ b/proto/mrt/mrt.c @@ -632,7 +632,10 @@ static void mrt_table_dump_step(void *_s) { struct mrt_table_dump_state *s = _s; - struct bgp_write_state bws = { .as4_session = 1 }; + struct bgp_write_state bws = { + .as4_session = 1, + .ignore_non_bgp_attrs = 1, + }; s->max = 2048; s->bws = &bws; diff --git a/sysdep/unix/log.c b/sysdep/unix/log.c index 9d77211b..384da303 100644 --- a/sysdep/unix/log.c +++ b/sysdep/unix/log.c @@ -337,7 +337,7 @@ log_prepare(log_buffer *buf, int class) buf->pos[LBP_MSG] = buf->buf.pos; } -static void +void vlog(int class, const char *msg, va_list args) { static _Thread_local log_buffer buf;