Timers: Parse and format functions for microsecond times

Date/time output (e.g. in logs, show commands) can use %f to specify
subsecond time. By default, millisecond precision is used in output.
This commit is contained in:
Ondrej Zajicek (work) 2017-06-06 16:47:30 +02:00
parent 025525266f
commit f047271cb9
21 changed files with 244 additions and 193 deletions

View file

@ -102,9 +102,9 @@ config_alloc(const char *name)
c->pool = p; c->pool = p;
c->mem = l; c->mem = l;
c->file_name = ndup; c->file_name = ndup;
c->load_time = now; c->load_time = current_time();
c->tf_route = c->tf_proto = (struct timeformat){"%T", "%F", 20*3600}; c->tf_route = c->tf_proto = TM_ISO_SHORT_MS;
c->tf_base = c->tf_log = (struct timeformat){"%F %T", NULL, 0}; c->tf_base = c->tf_log = TM_ISO_LONG_MS;
c->gr_wait = DEFAULT_GR_WAIT; c->gr_wait = DEFAULT_GR_WAIT;
return c; return c;

View file

@ -57,7 +57,7 @@ struct config {
struct config *fallback; /* Link to regular config for CLI parsing */ struct config *fallback; /* Link to regular config for CLI parsing */
int obstacle_count; /* Number of items blocking freeing of this config */ int obstacle_count; /* Number of items blocking freeing of this config */
int shutdown; /* This is a pseudo-config for daemon shutdown */ int shutdown; /* This is a pseudo-config for daemon shutdown */
bird_clock_t load_time; /* When we've got this configuration */ btime load_time; /* When we've got this configuration */
}; };
/* Please don't use these variables in protocols. Use proto_config->global instead. */ /* Please don't use these variables in protocols. Use proto_config->global instead. */

View file

@ -14,7 +14,7 @@ CF_HDR
#include "conf/conf.h" #include "conf/conf.h"
#include "lib/resource.h" #include "lib/resource.h"
#include "lib/socket.h" #include "lib/socket.h"
#include "sysdep/unix/timer.h" #include "lib/timer.h"
#include "lib/string.h" #include "lib/string.h"
#include "nest/protocol.h" #include "nest/protocol.h"
#include "nest/iface.h" #include "nest/iface.h"
@ -60,7 +60,7 @@ CF_DECLS
struct lsadb_show_data *ld; struct lsadb_show_data *ld;
struct iface *iface; struct iface *iface;
void *g; void *g;
bird_clock_t time; btime time;
struct f_prefix px; struct f_prefix px;
struct proto_spec ps; struct proto_spec ps;
struct channel_limit cl; struct channel_limit cl;
@ -81,7 +81,7 @@ CF_DECLS
%type <i> expr bool pxlen4 %type <i> expr bool pxlen4
%type <i32> expr_us %type <i32> expr_us
%type <time> datetime %type <time> time
%type <a> ipa %type <a> ipa
%type <net> net_ip4_ net_ip6_ net_ip6 net_ip_ net_ip net_or_ipa %type <net> net_ip4_ net_ip6_ net_ip6 net_ip_ net_ip net_or_ipa
%type <net_ptr> net_ net_any net_vpn4_ net_vpn6_ net_vpn_ net_roa4_ net_roa6_ net_roa_ %type <net_ptr> net_ net_any net_vpn4_ net_vpn6_ net_vpn_ net_roa4_ net_roa6_ net_roa_
@ -308,11 +308,11 @@ label_stack:
} }
; ;
datetime: time:
TEXT { TEXT {
$$ = tm_parse_datetime($1); $$ = tm_parse_time($1);
if (!$$) if (!$$)
cf_error("Invalid date and time"); cf_error("Invalid date/time");
} }
; ;

View file

@ -456,24 +456,26 @@ protocol rip {
used for other commands and <cf/log/ is used in a log file. used for other commands and <cf/log/ is used in a log file.
"<m/format1/" is a format string using <it/strftime(3)/ notation (see "<m/format1/" is a format string using <it/strftime(3)/ notation (see
<it/man strftime/ for details). <m/limit> and "<m/format2/" allow to <it/man strftime/ for details). It is extended to support sub-second
specify the second format string for times in past deeper than <m/limit/ time part with variable precision (up to microseconds) using "%f"
seconds. There are few shorthands: <cf/iso long/ is a ISO 8601 date/time conversion code (e.g., "%T.%3f" is hh:mm:ss.sss time). <m/limit/ and
format (YYYY-MM-DD hh:mm:ss) that can be also specified using <cf/"%F %T"/. "<m/format2/" allow to specify the second format string for times in
past deeper than <m/limit/ seconds.
There are several shorthands: <cf/iso long/ is a ISO 8601 date/time
format (YYYY-MM-DD hh:mm:ss) that can be also specified using <cf/"%F
%T"/. Similarly, <cf/iso long ms/ and <cf/iso long us/ are ISO 8601
date/time formats with millisecond or microsecond precision.
<cf/iso short/ is a variant of ISO 8601 that uses just the time format <cf/iso short/ is a variant of ISO 8601 that uses just the time format
(hh:mm:ss) for near times (up to 20 hours in the past) and the date (hh:mm:ss) for near times (up to 20 hours in the past) and the date
format (YYYY-MM-DD) for far times. This is a shorthand for format (YYYY-MM-DD) for far times. This is a shorthand for <cf/"%T"
<cf/"%T" 72000 "%F"/. 72000 "%F"/. And there are also <cf/iso short ms/ and <cf/iso short us/
high-precision variants of that.
By default, BIRD uses the <cf/iso short/ format for <cf/route/ and By default, BIRD uses the <cf/iso short ms/ format for <cf/route/ and
<cf/protocol/ times, and the <cf/iso long/ format for <cf/base/ and <cf/protocol/ times, and the <cf/iso long ms/ format for <cf/base/ and
<cf/log/ times. <cf/log/ times.
In pre-1.4.0 versions, BIRD used an short, ad-hoc format for <cf/route/
and <cf/protocol/ times, and a <cf/iso long/ similar format (DD-MM-YYYY
hh:mm:ss) for <cf/base/ and <cf/log/. These timeformats could be set by
<cf/old short/ and <cf/old long/ compatibility shorthands.
<tag><label id="opt-table">table <m/name/ [sorted]</tag> <tag><label id="opt-table">table <m/name/ [sorted]</tag>
Create a new routing table. The default routing table is created Create a new routing table. The default routing table is created
implicitly, other routing tables have to be added by this command. implicitly, other routing tables have to be added by this command.

View file

@ -8,6 +8,7 @@
*/ */
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "nest/bird.h" #include "nest/bird.h"
@ -222,3 +223,137 @@ timer_init(void)
timers_init(&main_timeloop, &root_pool); timers_init(&main_timeloop, &root_pool);
timeloop_init_current(); timeloop_init_current();
} }
/**
* tm_parse_time - parse a date and time
* @x: time string
*
* tm_parse_time() takes a textual representation of a date and time
* (yyyy-mm-dd[ hh:mm:ss[.sss]]) and converts it to the corresponding value of
* type &btime.
*/
btime
tm_parse_time(char *x)
{
struct tm tm;
int usec, n1, n2, n3, r;
r = sscanf(x, "%d-%d-%d%n %d:%d:%d%n.%d%n",
&tm.tm_year, &tm.tm_mon, &tm.tm_mday, &n1,
&tm.tm_hour, &tm.tm_min, &tm.tm_sec, &n2,
&usec, &n3);
if ((r == 3) && !x[n1])
tm.tm_hour = tm.tm_min = tm.tm_sec = usec = 0;
else if ((r == 6) && !x[n2])
usec = 0;
else if ((r == 7) && !x[n3])
{
/* Convert subsecond digits to proper precision */
int digits = n3 - n2 - 1;
if ((usec < 0) || (usec > 999999) || (digits < 1) || (digits > 6))
return 0;
while (digits++ < 6)
usec *= 10;
}
else
return 0;
tm.tm_mon--;
tm.tm_year -= 1900;
s64 ts = mktime(&tm);
if ((ts == (s64) (time_t) -1) || (ts < 0) || (ts > ((s64) 1 << 40)))
return 0;
return ts S + usec;
}
/**
* tm_format_time - convert date and time to textual representation
* @x: destination buffer of size %TM_DATETIME_BUFFER_SIZE
* @fmt: specification of resulting textual representation of the time
* @t: time
*
* This function formats the given relative time value @t to a textual
* date/time representation (dd-mm-yyyy hh:mm:ss) in real time.
*/
void
tm_format_time(char *x, struct timeformat *fmt, btime t)
{
btime dt = current_time() - t;
btime rt = current_real_time() - dt;
int v1 = !fmt->limit || (dt < fmt->limit);
tm_format_real_time(x, v1 ? fmt->fmt1 : fmt->fmt2, rt);
}
/* Replace %f in format string with usec scaled to requested precision */
static int
strfusec(char *buf, int size, const char *fmt, uint usec)
{
char *str = buf;
int parity = 0;
while (*fmt)
{
if (!size)
return 0;
if ((fmt[0] == '%') && (!parity) &&
((fmt[1] == 'f') || (fmt[1] >= '1') && (fmt[1] <= '6') && (fmt[2] == 'f')))
{
int digits = (fmt[1] == 'f') ? 6 : (fmt[1] - '0');
uint d = digits, u = usec;
/* Convert microseconds to requested precision */
while (d++ < 6)
u /= 10;
int num = bsnprintf(str, size, "%0*u", digits, u);
if (num < 0)
return 0;
fmt += (fmt[1] == 'f') ? 2 : 3;
ADVANCE(str, size, num);
}
else
{
/* Handle '%%' expression */
parity = (*fmt == '%') ? !parity : 0;
*str++ = *fmt++;
size--;
}
}
if (!size)
return 0;
*str = 0;
return str - buf;
}
void
tm_format_real_time(char *x, const char *fmt, btime t)
{
s64 t1 = t TO_S;
s64 t2 = t - t1 S;
time_t ts = t1;
struct tm tm;
if (!localtime_r(&ts, &tm))
goto err;
byte tbuf[TM_DATETIME_BUFFER_SIZE];
if (!strfusec(tbuf, TM_DATETIME_BUFFER_SIZE, fmt, t2))
goto err;
if (!strftime(x, TM_DATETIME_BUFFER_SIZE, tbuf, &tm))
goto err;
return;
err:
strcpy(x, "<error>");
}

View file

@ -105,4 +105,23 @@ void timers_fire(struct timeloop *loop);
void timer_init(void); void timer_init(void);
struct timeformat {
char *fmt1, *fmt2;
btime limit;
};
#define TM_ISO_SHORT_S (struct timeformat){"%T", "%F", (s64) (20*3600) S_}
#define TM_ISO_SHORT_MS (struct timeformat){"%T.%3f", "%F", (s64) (20*3600) S_}
#define TM_ISO_SHORT_US (struct timeformat){"%T.%6f", "%F", (s64) (20*3600) S_}
#define TM_ISO_LONG_S (struct timeformat){"%F %T", NULL, 0}
#define TM_ISO_LONG_MS (struct timeformat){"%F %T.%3f", NULL, 0}
#define TM_ISO_LONG_US (struct timeformat){"%F %T.%6f", NULL, 0}
#define TM_DATETIME_BUFFER_SIZE 32 /* Buffer size required by tm_format_time() */
btime tm_parse_time(char *x);
void tm_format_time(char *x, struct timeformat *fmt, btime t);
void tm_format_real_time(char *x, const char *fmt, btime t);
#endif #endif

View file

@ -25,12 +25,12 @@ cmd_show_status(void)
byte tim[TM_DATETIME_BUFFER_SIZE]; byte tim[TM_DATETIME_BUFFER_SIZE];
cli_msg(-1000, "BIRD " BIRD_VERSION); cli_msg(-1000, "BIRD " BIRD_VERSION);
tm_format_datetime(tim, &config->tf_base, now); tm_format_time(tim, &config->tf_base, current_time());
cli_msg(-1011, "Router ID is %R", config->router_id); cli_msg(-1011, "Router ID is %R", config->router_id);
cli_msg(-1011, "Current server time is %s", tim); cli_msg(-1011, "Current server time is %s", tim);
tm_format_datetime(tim, &config->tf_base, boot_time TO_S); tm_format_time(tim, &config->tf_base, boot_time);
cli_msg(-1011, "Last reboot on %s", tim); cli_msg(-1011, "Last reboot on %s", tim);
tm_format_datetime(tim, &config->tf_base, config->load_time); tm_format_time(tim, &config->tf_base, config->load_time);
cli_msg(-1011, "Last reconfiguration on %s", tim); cli_msg(-1011, "Last reconfiguration on %s", tim);
graceful_restart_show_status(); graceful_restart_show_status();

View file

@ -73,6 +73,7 @@ CF_KEYWORDS(ALGORITHM, KEYED, HMAC, MD5, SHA1, SHA256, SHA384, SHA512)
CF_KEYWORDS(PRIMARY, STATS, COUNT, BY, FOR, COMMANDS, PREEXPORT, NOEXPORT, GENERATE) CF_KEYWORDS(PRIMARY, STATS, COUNT, BY, FOR, COMMANDS, PREEXPORT, NOEXPORT, GENERATE)
CF_KEYWORDS(LISTEN, BGP, V6ONLY, DUAL, ADDRESS, PORT, PASSWORDS, DESCRIPTION, SORTED) CF_KEYWORDS(LISTEN, BGP, V6ONLY, DUAL, ADDRESS, PORT, PASSWORDS, DESCRIPTION, SORTED)
CF_KEYWORDS(RELOAD, IN, OUT, MRTDUMP, MESSAGES, RESTRICT, MEMORY, IGP_METRIC, CLASS, DSCP) CF_KEYWORDS(RELOAD, IN, OUT, MRTDUMP, MESSAGES, RESTRICT, MEMORY, IGP_METRIC, CLASS, DSCP)
CF_KEYWORDS(TIMEFORMAT, ISO, SHORT, LONG, ROUTE, PROTOCOL, BASE, LOG, S, MS, US)
CF_KEYWORDS(GRACEFUL, RESTART, WAIT, MAX, FLUSH, AS) CF_KEYWORDS(GRACEFUL, RESTART, WAIT, MAX, FLUSH, AS)
/* For r_args_channel */ /* For r_args_channel */
@ -295,6 +296,7 @@ limit_spec:
| OFF { $$ = (struct channel_limit){}; } | OFF { $$ = (struct channel_limit){}; }
; ;
CF_ADDTO(conf, debug_default) CF_ADDTO(conf, debug_default)
debug_default: debug_default:
@ -304,6 +306,31 @@ debug_default:
/* MRTDUMP PROTOCOLS is in systep/unix/config.Y */ /* MRTDUMP PROTOCOLS is in systep/unix/config.Y */
CF_ADDTO(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; }
;
timeformat_spec:
timeformat_which TEXT { *$1 = (struct timeformat){$2, NULL, 0}; }
| timeformat_which TEXT expr TEXT { *$1 = (struct timeformat){$2, $4, (s64) $3 S_}; }
| timeformat_which ISO SHORT { *$1 = TM_ISO_SHORT_S; }
| timeformat_which ISO SHORT MS { *$1 = TM_ISO_SHORT_MS; }
| timeformat_which ISO SHORT US { *$1 = TM_ISO_SHORT_US; }
| timeformat_which ISO LONG { *$1 = TM_ISO_LONG_S; }
| timeformat_which ISO LONG MS { *$1 = TM_ISO_LONG_MS; }
| timeformat_which ISO LONG US { *$1 = TM_ISO_LONG_US; }
;
timeformat_base:
TIMEFORMAT timeformat_spec ';'
;
/* Interface patterns */ /* Interface patterns */
iface_patt_node_init: iface_patt_node_init:
@ -462,12 +489,12 @@ password_item_begin:
password_item_params: password_item_params:
/* empty */ { } /* empty */ { }
| GENERATE FROM datetime ';' password_item_params { this_p_item->genfrom = $3; } | GENERATE FROM time ';' password_item_params { this_p_item->genfrom = $3; }
| GENERATE TO datetime ';' password_item_params { this_p_item->gento = $3; } | GENERATE TO time ';' password_item_params { this_p_item->gento = $3; }
| ACCEPT FROM datetime ';' password_item_params { this_p_item->accfrom = $3; } | ACCEPT FROM time ';' password_item_params { this_p_item->accfrom = $3; }
| ACCEPT TO datetime ';' password_item_params { this_p_item->accto = $3; } | ACCEPT TO time ';' password_item_params { this_p_item->accto = $3; }
| FROM datetime ';' password_item_params { this_p_item->genfrom = this_p_item->accfrom = $2; } | FROM time ';' password_item_params { this_p_item->genfrom = this_p_item->accfrom = $2; }
| TO datetime ';' password_item_params { this_p_item->gento = this_p_item->accto = $2; } | TO time ';' password_item_params { this_p_item->gento = this_p_item->accto = $2; }
| ID expr ';' password_item_params { this_p_item->id = $2; if ($2 <= 0) cf_error("Password ID has to be greated than zero."); } | ID expr ';' password_item_params { this_p_item->id = $2; if ($2 <= 0) cf_error("Password ID has to be greated than zero."); }
| ALGORITHM password_algorithm ';' password_item_params { this_p_item->alg = $2; } | ALGORITHM password_algorithm ';' password_item_params { this_p_item->alg = $2; }
; ;

View file

@ -19,12 +19,13 @@ password_find(list *l, int first_fit)
{ {
struct password_item *pi; struct password_item *pi;
struct password_item *pf = NULL; struct password_item *pf = NULL;
btime now_ = current_real_time();
if (l) if (l)
{ {
WALK_LIST(pi, *l) WALK_LIST(pi, *l)
{ {
if ((pi->genfrom < now_real) && (pi->gento > now_real)) if ((pi->genfrom < now_) && (pi->gento > now_))
{ {
if (first_fit) if (first_fit)
return pi; return pi;
@ -41,12 +42,13 @@ struct password_item *
password_find_by_id(list *l, uint id) password_find_by_id(list *l, uint id)
{ {
struct password_item *pi; struct password_item *pi;
btime now_ = current_real_time();
if (!l) if (!l)
return NULL; return NULL;
WALK_LIST(pi, *l) WALK_LIST(pi, *l)
if ((pi->id == id) && (pi->accfrom <= now_real) && (now_real < pi->accto)) if ((pi->id == id) && (pi->accfrom <= now_) && (now_ < pi->accto))
return pi; return pi;
return NULL; return NULL;
@ -56,12 +58,13 @@ struct password_item *
password_find_by_value(list *l, char *pass, uint size) password_find_by_value(list *l, char *pass, uint size)
{ {
struct password_item *pi; struct password_item *pi;
btime now_ = current_real_time();
if (!l) if (!l)
return NULL; return NULL;
WALK_LIST(pi, *l) WALK_LIST(pi, *l)
if (password_verify(pi, pass, size) && (pi->accfrom <= now_real) && (now_real < pi->accto)) if (password_verify(pi, pass, size) && (pi->accfrom <= now_) && (now_ < pi->accto))
return pi; return pi;
return NULL; return NULL;

View file

@ -10,15 +10,13 @@
#ifndef PASSWORD_H #ifndef PASSWORD_H
#define PASSWORD_H #define PASSWORD_H
#include "sysdep/unix/timer.h"
struct password_item { struct password_item {
node n; node n;
char *password; /* Key data, null terminated */ char *password; /* Key data, null terminated */
uint length; /* Key length, without null */ uint length; /* Key length, without null */
uint id; /* Key ID */ uint id; /* Key ID */
uint alg; /* MAC algorithm */ uint alg; /* MAC algorithm */
bird_clock_t accfrom, accto, genfrom, gento; btime accfrom, accto, genfrom, gento;
}; };
extern struct password_item *last_password_item; extern struct password_item *last_password_item;

View file

@ -162,7 +162,7 @@ proto_add_channel(struct proto *p, struct channel_config *cf)
c->channel_state = CS_DOWN; c->channel_state = CS_DOWN;
c->export_state = ES_DOWN; c->export_state = ES_DOWN;
c->last_state_change = now; c->last_state_change = current_time();
c->reloadable = 1; c->reloadable = 1;
CALL(c->channel->init, c, cf); CALL(c->channel->init, c, cf);
@ -341,7 +341,7 @@ channel_set_state(struct channel *c, uint state)
return; return;
c->channel_state = state; c->channel_state = state;
c->last_state_change = now; c->last_state_change = current_time();
switch (state) switch (state)
{ {
@ -672,7 +672,7 @@ proto_init(struct proto_config *c, node *n)
struct proto *p = pr->init(c); struct proto *p = pr->init(c);
p->proto_state = PS_DOWN; p->proto_state = PS_DOWN;
p->last_state_change = now; p->last_state_change = current_time();
insert_node(&p->n, n); insert_node(&p->n, n);
p->event = ev_new(proto_pool); p->event = ev_new(proto_pool);
@ -1500,7 +1500,7 @@ proto_notify_state(struct proto *p, uint state)
return; return;
p->proto_state = state; p->proto_state = state;
p->last_state_change = now; p->last_state_change = current_time();
switch (state) switch (state)
{ {
@ -1631,7 +1631,7 @@ proto_cmd_show(struct proto *p, uint verbose, int cnt)
buf[0] = 0; buf[0] = 0;
if (p->proto->get_status) if (p->proto->get_status)
p->proto->get_status(p, buf); p->proto->get_status(p, buf);
tm_format_datetime(tbuf, &config->tf_proto, p->last_state_change); tm_format_time(tbuf, &config->tf_proto, p->last_state_change);
cli_msg(-1002, "%-8s %-8s %-8s %-5s %-10s %s", cli_msg(-1002, "%-8s %-8s %-8s %-5s %-10s %s",
p->name, p->name,
p->proto->name, p->proto->name,

View file

@ -159,7 +159,7 @@ struct proto {
byte down_sched; /* Shutdown is scheduled for later (PDS_*) */ byte down_sched; /* Shutdown is scheduled for later (PDS_*) */
byte down_code; /* Reason for shutdown (PDC_* codes) */ byte down_code; /* Reason for shutdown (PDC_* codes) */
u32 hash_key; /* Random key used for hashing of neighbors */ u32 hash_key; /* Random key used for hashing of neighbors */
bird_clock_t last_state_change; /* Time of last state transition */ btime last_state_change; /* Time of last state transition */
char *last_state_name_announced; /* Last state name we've announced to the user */ char *last_state_name_announced; /* Last state name we've announced to the user */
/* /*
@ -508,7 +508,7 @@ struct channel {
u8 gr_lock; /* Graceful restart mechanism should wait for this channel */ u8 gr_lock; /* Graceful restart mechanism should wait for this channel */
u8 gr_wait; /* Route export to channel is postponed until graceful restart */ u8 gr_wait; /* Route export to channel is postponed until graceful restart */
bird_clock_t last_state_change; /* Time of last state transition */ btime last_state_change; /* Time of last state transition */
}; };

View file

@ -159,8 +159,8 @@ typedef struct rtable {
* obstacle from this routing table. * obstacle from this routing table.
*/ */
struct event *rt_event; /* Routing table event */ struct event *rt_event; /* Routing table event */
btime gc_time; /* Time of last GC */
int gc_counter; /* Number of operations since last GC */ int gc_counter; /* Number of operations since last GC */
bird_clock_t gc_time; /* Time of last GC */
byte prune_state; /* Table prune state, 1 -> scheduled, 2-> running */ byte prune_state; /* Table prune state, 1 -> scheduled, 2-> running */
byte hcu_scheduled; /* Hostcache update is scheduled */ byte hcu_scheduled; /* Hostcache update is scheduled */
byte nhu_state; /* Next Hop Update state */ byte nhu_state; /* Next Hop Update state */
@ -213,7 +213,7 @@ typedef struct rte {
byte flags; /* Flags (REF_...) */ byte flags; /* Flags (REF_...) */
byte pflags; /* Protocol-specific flags */ byte pflags; /* Protocol-specific flags */
word pref; /* Route preference */ word pref; /* Route preference */
bird_clock_t lastmod; /* Last modified */ btime lastmod; /* Last modified */
union { /* Protocol-dependent data (metrics etc.) */ union { /* Protocol-dependent data (metrics etc.) */
#ifdef CONFIG_RIP #ifdef CONFIG_RIP
struct { struct {

View file

@ -39,7 +39,7 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, ea_list *tm
void (*get_route_info)(struct rte *, byte *buf, struct ea_list *attrs); void (*get_route_info)(struct rte *, byte *buf, struct ea_list *attrs);
struct nexthop *nh; struct nexthop *nh;
tm_format_datetime(tm, &config->tf_route, e->lastmod); tm_format_time(tm, &config->tf_route, e->lastmod);
if (ipa_nonzero(a->from) && !ipa_equal(a->from, a->nh.gw)) if (ipa_nonzero(a->from) && !ipa_equal(a->from, a->nh.gw))
bsprintf(from, " from %I", a->from); bsprintf(from, " from %I", a->from);
else else

View file

@ -1173,7 +1173,7 @@ rte_recalculate(struct channel *c, net *net, rte *new, struct rte_src *src)
} }
if (new) if (new)
new->lastmod = now; new->lastmod = current_time();
/* Log the route change */ /* Log the route change */
if (p->debug & D_ROUTES) if (p->debug & D_ROUTES)
@ -1201,7 +1201,7 @@ rte_recalculate(struct channel *c, net *net, rte *new, struct rte_src *src)
if (!net->routes && if (!net->routes &&
(table->gc_counter++ >= table->config->gc_max_ops) && (table->gc_counter++ >= table->config->gc_max_ops) &&
(table->gc_time + table->config->gc_min_time <= now)) (table->gc_time + table->config->gc_min_time <= current_time()))
rt_schedule_prune(table); rt_schedule_prune(table);
if (old_ok && p->rte_remove) if (old_ok && p->rte_remove)
@ -1497,7 +1497,7 @@ rte_dump(rte *e)
{ {
net *n = e->net; net *n = e->net;
debug("%-1N ", n->n.addr); debug("%-1N ", n->n.addr);
debug("KF=%02x PF=%02x pref=%d lm=%d ", n->n.flags, e->pflags, e->pref, now-e->lastmod); debug("KF=%02x PF=%02x pref=%d ", n->n.flags, e->pflags, e->pref);
rta_dump(e->attrs); rta_dump(e->attrs);
if (e->attrs->src->proto->proto->dump_attrs) if (e->attrs->src->proto->proto->dump_attrs)
e->attrs->src->proto->proto->dump_attrs(e); e->attrs->src->proto->proto->dump_attrs(e);
@ -1609,7 +1609,7 @@ rt_setup(pool *p, rtable *t, char *name, struct rtable_config *cf)
t->rt_event = ev_new(p); t->rt_event = ev_new(p);
t->rt_event->hook = rt_event; t->rt_event->hook = rt_event;
t->rt_event->data = t; t->rt_event->data = t;
t->gc_time = now; t->gc_time = current_time();
} }
} }
@ -1708,7 +1708,7 @@ again:
#endif #endif
tab->gc_counter = 0; tab->gc_counter = 0;
tab->gc_time = now; tab->gc_time = current_time();
/* state change 2->0, 3->1 */ /* state change 2->0, 3->1 */
tab->prune_state &= 1; tab->prune_state &= 1;

View file

@ -145,6 +145,7 @@ bfd_session_update_state(struct bfd_session *s, uint state, uint diag)
bfd_lock_sessions(p); bfd_lock_sessions(p);
s->loc_state = state; s->loc_state = state;
s->loc_diag = diag; s->loc_diag = diag;
s->last_state_change = current_time();
notify = !NODE_VALID(&s->n); notify = !NODE_VALID(&s->n);
if (notify) if (notify)
@ -438,7 +439,7 @@ bfd_add_session(struct bfd_proto *p, ip_addr addr, ip_addr local, struct iface *
bfd_session_control_tx_timer(s, 1); bfd_session_control_tx_timer(s, 1);
init_list(&s->request_list); init_list(&s->request_list);
s->last_state_change = now; s->last_state_change = current_time();
TRACE(D_EVENTS, "Session to %I added", s->addr); TRACE(D_EVENTS, "Session to %I added", s->addr);
@ -879,9 +880,6 @@ bfd_notify_hook(sock *sk, uint len UNUSED)
diag = s->loc_diag; diag = s->loc_diag;
bfd_unlock_sessions(p); bfd_unlock_sessions(p);
/* FIXME: convert to btime and move to bfd_session_update_state() */
s->last_state_change = now;
s->notify_running = 1; s->notify_running = 1;
WALK_LIST_DELSAFE(n, nn, s->request_list) WALK_LIST_DELSAFE(n, nn, s->request_list)
bfd_request_notify(SKIP_BACK(struct bfd_request, n, n), state, diag); bfd_request_notify(SKIP_BACK(struct bfd_request, n, n), state, diag);
@ -1105,7 +1103,7 @@ bfd_show_sessions(struct proto *P)
timeout = (MAX(s->req_min_rx_int, s->rem_min_tx_int) TO_MS) * s->rem_detect_mult; timeout = (MAX(s->req_min_rx_int, s->rem_min_tx_int) TO_MS) * s->rem_detect_mult;
state = (state < 4) ? state : 0; state = (state < 4) ? state : 0;
tm_format_datetime(tbuf, &config->tf_proto, s->last_state_change); tm_format_time(tbuf, &config->tf_proto, s->last_state_change);
cli_msg(-1020, "%-25I %-10s %-10s %-10s %3u.%03u %3u.%03u", cli_msg(-1020, "%-25I %-10s %-10s %-10s %3u.%03u %3u.%03u",
s->addr, ifname, bfd_state_names[state], tbuf, s->addr, ifname, bfd_state_names[state], tbuf,

View file

@ -144,7 +144,7 @@ struct bfd_session
timer2 *hold_timer; /* Timer for session down detection time */ timer2 *hold_timer; /* Timer for session down detection time */
list request_list; /* List of client requests (struct bfd_request) */ list request_list; /* List of client requests (struct bfd_request) */
bird_clock_t last_state_change; /* Time of last state change */ btime last_state_change; /* Time of last state change */
u8 notify_running; /* 1 if notify hooks are running */ u8 notify_running; /* 1 if notify hooks are running */
u8 rx_csn_known; /* Received crypto sequence number is known */ u8 rx_csn_known; /* Received crypto sequence number is known */

View file

@ -14,8 +14,7 @@ CF_HDR
CF_DECLS CF_DECLS
CF_KEYWORDS(LOG, SYSLOG, ALL, DEBUG, TRACE, INFO, REMOTE, WARNING, ERROR, AUTH, FATAL, BUG, STDERR, SOFT) CF_KEYWORDS(LOG, SYSLOG, ALL, DEBUG, TRACE, INFO, REMOTE, WARNING, ERROR, AUTH, FATAL, BUG, STDERR, SOFT)
CF_KEYWORDS(TIMEFORMAT, ISO, OLD, SHORT, LONG, BASE, NAME, CONFIRM, UNDO, CHECK, TIMEOUT) CF_KEYWORDS(NAME, CONFIRM, UNDO, CHECK, TIMEOUT, DEBUG, LATENCY, LIMIT, WATCHDOG, WARNING)
CF_KEYWORDS(DEBUG, LATENCY, LIMIT, WATCHDOG, WARNING, TIMEOUT)
%type <i> log_mask log_mask_list log_cat cfg_timeout %type <i> log_mask log_mask_list log_cat cfg_timeout
%type <g> log_file %type <g> log_file
@ -85,29 +84,6 @@ mrtdump_base:
; ;
CF_ADDTO(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; }
;
timeformat_spec:
timeformat_which TEXT { *$1 = (struct timeformat){$2, NULL, 0}; }
| timeformat_which TEXT expr TEXT { *$1 = (struct timeformat){$2, $4, $3}; }
| timeformat_which ISO SHORT { *$1 = (struct timeformat){"%T", "%F", 20*3600}; }
| timeformat_which ISO LONG { *$1 = (struct timeformat){"%F %T", NULL, 0}; }
| timeformat_which OLD SHORT { *$1 = (struct timeformat){NULL, NULL, 0}; }
| timeformat_which OLD LONG { *$1 = (struct timeformat){"%d-%m-%Y %T", NULL, 0}; }
;
timeformat_base:
TIMEFORMAT timeformat_spec ';'
;
CF_ADDTO(conf, debug_unix) CF_ADDTO(conf, debug_unix)
debug_unix: debug_unix:

View file

@ -40,6 +40,7 @@
#include "lib/timer.h" #include "lib/timer.h"
#include "lib/string.h" #include "lib/string.h"
#include "nest/iface.h" #include "nest/iface.h"
#include "conf/conf.h"
#include "sysdep/unix/unix.h" #include "sysdep/unix/unix.h"
#include CONFIG_INCLUDE_SYSIO_H #include CONFIG_INCLUDE_SYSIO_H
@ -385,102 +386,6 @@ tm_shot(void)
} }
#endif #endif
/**
* tm_parse_datetime - parse a date and time
* @x: datetime string
*
* tm_parse_datetime() takes a textual representation of
* a date and time (dd-mm-yyyy hh:mm:ss)
* and converts it to the corresponding value of type &bird_clock_t.
*/
bird_clock_t
tm_parse_datetime(char *x)
{
struct tm tm;
int n;
time_t t;
if (sscanf(x, "%d-%d-%d %d:%d:%d%n", &tm.tm_mday, &tm.tm_mon, &tm.tm_year, &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &n) != 6 || x[n])
return tm_parse_date(x);
tm.tm_mon--;
tm.tm_year -= 1900;
t = mktime(&tm);
if (t == (time_t) -1)
return 0;
return t;
}
/**
* tm_parse_date - parse a date
* @x: date string
*
* tm_parse_date() takes a textual representation of a date (dd-mm-yyyy)
* and converts it to the corresponding value of type &bird_clock_t.
*/
bird_clock_t
tm_parse_date(char *x)
{
struct tm tm;
int n;
time_t t;
if (sscanf(x, "%d-%d-%d%n", &tm.tm_mday, &tm.tm_mon, &tm.tm_year, &n) != 3 || x[n])
return 0;
tm.tm_mon--;
tm.tm_year -= 1900;
tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
t = mktime(&tm);
if (t == (time_t) -1)
return 0;
return t;
}
static void
tm_format_reltime(char *x, struct tm *tm, bird_clock_t delta)
{
static char *month_names[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
if (delta < 20*3600)
bsprintf(x, "%02d:%02d", tm->tm_hour, tm->tm_min);
else if (delta < 360*86400)
bsprintf(x, "%s%02d", month_names[tm->tm_mon], tm->tm_mday);
else
bsprintf(x, "%d", tm->tm_year+1900);
}
#include "conf/conf.h"
/**
* tm_format_datetime - convert date and time to textual representation
* @x: destination buffer of size %TM_DATETIME_BUFFER_SIZE
* @fmt_spec: specification of resulting textual representation of the time
* @t: time
*
* This function formats the given relative time value @t to a textual
* date/time representation (dd-mm-yyyy hh:mm:ss) in real time.
*/
void
tm_format_datetime(char *x, struct timeformat *fmt_spec, bird_clock_t t)
{
const char *fmt_used;
struct tm *tm;
bird_clock_t delta = now - t;
t = now_real - delta;
tm = localtime(&t);
if (fmt_spec->fmt1 == NULL)
return tm_format_reltime(x, tm, delta);
if ((fmt_spec->limit == 0) || (delta < fmt_spec->limit))
fmt_used = fmt_spec->fmt1;
else
fmt_used = fmt_spec->fmt2;
int rv = strftime(x, TM_DATETIME_BUFFER_SIZE, fmt_used, tm);
if (((rv == 0) && fmt_used[0]) || (rv == TM_DATETIME_BUFFER_SIZE))
strcpy(x, "<too-long>");
}
/* /*
* Time clock * Time clock

View file

@ -120,7 +120,7 @@ log_commit(int class, buffer *buf)
else else
{ {
byte tbuf[TM_DATETIME_BUFFER_SIZE]; byte tbuf[TM_DATETIME_BUFFER_SIZE];
tm_format_datetime(tbuf, &config->tf_log, now); tm_format_real_time(tbuf, config->tf_log.fmt1, current_real_time());
fprintf(l->fh, "%s <%s> ", tbuf, class_names[class]); fprintf(l->fh, "%s <%s> ", tbuf, class_names[class]);
} }
fputs(buf->start, l->fh); fputs(buf->start, l->fh);

View file

@ -45,18 +45,6 @@ static inline timer * tm_new_set(pool *p, void (*hook)(timer *), void *data, uin
{ return tm2_new_init(p, hook, data, rec S_, rand S_); } { return tm2_new_init(p, hook, data, rec S_, rand S_); }
struct timeformat {
char *fmt1, *fmt2;
bird_clock_t limit;
};
bird_clock_t tm_parse_date(char *); /* Convert date to bird_clock_t */
bird_clock_t tm_parse_datetime(char *); /* Convert date to bird_clock_t */
#define TM_DATETIME_BUFFER_SIZE 32 /* Buffer size required by tm_format_datetime */
void
tm_format_datetime(char *x, struct timeformat *fmt_spec, bird_clock_t t);
#define TIME_INFINITY ((s64) 0x7fffffffffffffff) #define TIME_INFINITY ((s64) 0x7fffffffffffffff)