diff --git a/conf/conf.c b/conf/conf.c index e8c0dc67..c4933122 100644 --- a/conf/conf.c +++ b/conf/conf.c @@ -452,7 +452,7 @@ config_undo(void) extern void cmd_reconfig_undo_notify(void); static void -config_timeout(struct timer *t UNUSED) +config_timeout(timer *t UNUSED) { log(L_INFO "Config timeout expired, starting undo"); cmd_reconfig_undo_notify(); diff --git a/lib/birdlib.h b/lib/birdlib.h index 317b5202..a0826aab 100644 --- a/lib/birdlib.h +++ b/lib/birdlib.h @@ -9,7 +9,6 @@ #ifndef _BIRD_BIRDLIB_H_ #define _BIRD_BIRDLIB_H_ -#include "sysdep/unix/timer.h" #include "lib/alloca.h" /* Ugly structure offset handling macros */ @@ -70,6 +69,7 @@ static inline int u64_cmp(u64 i1, u64 i2) /* Microsecond time */ typedef s64 btime; +typedef s64 bird_clock_t; #define S_ *1000000 #define MS_ *1000 diff --git a/lib/tbf.c b/lib/tbf.c index 39e18e57..c1dafee8 100644 --- a/lib/tbf.c +++ b/lib/tbf.c @@ -8,6 +8,7 @@ */ #include "nest/bird.h" +#include "lib/timer.h" void tbf_update(struct tbf *f) diff --git a/lib/timer.c b/lib/timer.c index 7ca0bdaa..2c08b353 100644 --- a/lib/timer.c +++ b/lib/timer.c @@ -56,6 +56,17 @@ current_time(void) return timeloop_current()->last_time; } +btime +current_real_time(void) +{ + struct timeloop *loop = timeloop_current(); + + if (!loop->real_time) + times_update_real_time(loop); + + return loop->real_time; +} + #define TIMER_LESS(a,b) ((a)->expires < (b)->expires) #define TIMER_SWAP(heap,a,b,t) (t = heap[a], heap[a] = heap[b], heap[b] = t, \ diff --git a/lib/timer.h b/lib/timer.h index 88c53547..b70ac48d 100644 --- a/lib/timer.h +++ b/lib/timer.h @@ -44,6 +44,11 @@ static inline timer2 *timers_first(struct timeloop *loop) extern struct timeloop main_timeloop; btime current_time(void); +btime current_real_time(void); + +#define now (current_time() TO_S) +#define now_real (current_real_time() TO_S) +extern btime boot_time; timer2 *tm2_new(pool *p); void tm2_set(timer2 *t, btime when); @@ -59,8 +64,8 @@ tm2_active(timer2 *t) static inline btime tm2_remains(timer2 *t) { - btime now = current_time(); - return (t->expires > now) ? (t->expires - now) : 0; + btime now_ = current_time(); + return (t->expires > now_) ? (t->expires - now_) : 0; } static inline timer2 * @@ -81,18 +86,17 @@ tm2_set_max(timer2 *t, btime when) tm2_set(t, when); } -/* static inline void tm2_start_max(timer2 *t, btime after) { btime rem = tm2_remains(t); tm2_start(t, MAX_(rem, after)); } -*/ /* In sysdep code */ void times_init(struct timeloop *loop); void times_update(struct timeloop *loop); +void times_update_real_time(struct timeloop *loop); /* For I/O loop */ void timers_init(struct timeloop *loop, pool *p); diff --git a/nest/cmds.c b/nest/cmds.c index 2bc672ea..371e8877 100644 --- a/nest/cmds.c +++ b/nest/cmds.c @@ -28,7 +28,7 @@ cmd_show_status(void) tm_format_datetime(tim, &config->tf_base, now); cli_msg(-1011, "Router ID is %R", config->router_id); cli_msg(-1011, "Current server time is %s", tim); - tm_format_datetime(tim, &config->tf_base, boot_time); + tm_format_datetime(tim, &config->tf_base, boot_time TO_S); cli_msg(-1011, "Last reboot on %s", tim); tm_format_datetime(tim, &config->tf_base, config->load_time); cli_msg(-1011, "Last reconfiguration on %s", tim); diff --git a/nest/proto.c b/nest/proto.c index 361bb225..65375c35 100644 --- a/nest/proto.c +++ b/nest/proto.c @@ -43,7 +43,7 @@ static char *c_states[] = { "DOWN", "START", "UP", "FLUSHING" }; extern struct protocol proto_unix_iface; -static void proto_shutdown_loop(struct timer *); +static void proto_shutdown_loop(timer *); static void proto_rethink_goal(struct proto *p); static char *proto_state_name(struct proto *p); static void channel_verify_limits(struct channel *c); @@ -1046,7 +1046,7 @@ proto_rethink_goal(struct proto *p) * */ -static void graceful_restart_done(struct timer *t); +static void graceful_restart_done(timer *t); /** * graceful_restart_recovery - request initial graceful restart recovery @@ -1099,7 +1099,7 @@ graceful_restart_init(void) * restart wait timer fires (but there are still some locks). */ static void -graceful_restart_done(struct timer *t UNUSED) +graceful_restart_done(timer *t UNUSED) { log(L_INFO "Graceful restart done"); graceful_restart_state = GRS_DONE; @@ -1298,7 +1298,7 @@ protos_build(void) int proto_restart; static void -proto_shutdown_loop(struct timer *t UNUSED) +proto_shutdown_loop(timer *t UNUSED) { struct proto *p, *p_next; diff --git a/proto/babel/babel.c b/proto/babel/babel.c index 23746155..bab2e8b3 100644 --- a/proto/babel/babel.c +++ b/proto/babel/babel.c @@ -1367,7 +1367,7 @@ babel_iface_timer(timer *t) static inline void babel_iface_kick_timer(struct babel_iface *ifa) { - if (ifa->timer->expires > (now + 1)) + if (ifa->timer->expires TO_S > (now + 1)) tm_start(ifa->timer, 1); } @@ -1948,7 +1948,7 @@ babel_timer(timer *t) static inline void babel_kick_timer(struct babel_proto *p) { - if (p->timer->expires > (now + 1)) + if (p->timer->expires TO_S > (now + 1)) tm_start(p->timer, 1); } diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index a8d5cf9d..dba7c875 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -103,6 +103,8 @@ #undef LOCAL_DEBUG +#include + #include "nest/bird.h" #include "nest/iface.h" #include "nest/protocol.h" @@ -324,8 +326,8 @@ bgp_start_timer(timer *t, int value) if (value) { /* The randomization procedure is specified in RFC 1771: 9.2.3.3 */ - t->randomize = value / 4; - tm_start(t, value - t->randomize); + int randomize = random() % ((value / 4) + 1); + tm_start(t, value - randomize); } else tm_stop(t); @@ -2006,17 +2008,18 @@ bgp_show_proto_info(struct proto *P) struct bgp_conn *oc = &p->outgoing_conn; if ((p->start_state < BSS_CONNECT) && - (p->startup_timer->expires)) + (tm_active(p->startup_timer))) cli_msg(-1006, " Error wait: %d/%d", - p->startup_timer->expires - now, p->startup_delay); + (int) tm_remains(p->startup_timer), p->startup_delay); if ((oc->state == BS_ACTIVE) && - (oc->connect_timer->expires)) + (tm_active(oc->connect_timer))) cli_msg(-1006, " Connect delay: %d/%d", - oc->connect_timer->expires - now, p->cf->connect_delay_time); + (int) tm_remains(oc->connect_timer), p->cf->connect_delay_time); - if (p->gr_active_num && p->gr_timer->expires) - cli_msg(-1006, " Restart timer: %d/-", p->gr_timer->expires - now); + if (p->gr_active_num && tm_active(p->gr_timer)) + cli_msg(-1006, " Restart timer: %d/-", + (int) tm_remains(p->gr_timer)); } else if (P->proto_state == PS_UP) { diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h index 7ffcb68a..3b38c05f 100644 --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@ -210,10 +210,10 @@ struct bgp_conn { struct bgp_caps *local_caps; struct bgp_caps *remote_caps; - struct timer *connect_timer; - struct timer *hold_timer; - struct timer *keepalive_timer; - struct event *tx_ev; + timer *connect_timer; + timer *hold_timer; + timer *keepalive_timer; + event *tx_ev; u32 packets_to_send; /* Bitmap of packet types to be sent */ u32 channels_to_send; /* Bitmap of channels with packets to be sent */ u8 last_channel; /* Channel used last time for TX */ @@ -254,9 +254,9 @@ struct bgp_proto { struct bfd_request *bfd_req; /* BFD request, if BFD is used */ ip_addr source_addr; /* Local address used as an advertised next hop */ ip_addr link_addr; /* Link-local version of source_addr */ - struct event *event; /* Event for respawning and shutting process */ - struct timer *startup_timer; /* Timer used to delay protocol startup due to previous errors (startup_delay) */ - struct timer *gr_timer; /* Timer waiting for reestablishment after graceful restart */ + event *event; /* Event for respawning and shutting process */ + timer *startup_timer; /* Timer used to delay protocol startup due to previous errors (startup_delay) */ + timer *gr_timer; /* Timer waiting for reestablishment after graceful restart */ unsigned startup_delay; /* Time to delay protocol startup by due to errors */ bird_clock_t last_proto_error; /* Time of last error that leads to protocol stop */ u8 last_error_class; /* Error class of last error */ @@ -422,7 +422,7 @@ extern struct linpool *bgp_linpool; extern struct linpool *bgp_linpool2; -void bgp_start_timer(struct timer *t, int value); +void bgp_start_timer(timer *t, int value); void bgp_check_config(struct bgp_config *c); void bgp_error(struct bgp_conn *c, unsigned code, unsigned subcode, byte *data, int len); void bgp_close_conn(struct bgp_conn *c); diff --git a/proto/ospf/iface.c b/proto/ospf/iface.c index 98d48aa1..d1f9365e 100644 --- a/proto/ospf/iface.c +++ b/proto/ospf/iface.c @@ -715,9 +715,9 @@ ospf_iface_change_timer(timer *tm, uint val) if (!tm) return; - tm->recurrent = val; + tm->recurrent = val S; - if (tm->expires) + if (tm_active(tm)) tm_start(tm, val); } diff --git a/proto/ospf/neighbor.c b/proto/ospf/neighbor.c index b68ba6f4..64165e46 100644 --- a/proto/ospf/neighbor.c +++ b/proto/ospf/neighbor.c @@ -654,7 +654,7 @@ ospf_sh_neigh_info(struct ospf_neighbor *n) char etime[6]; int exp, sec, min; - exp = n->inactim->expires - now; + exp = tm_remains(n->inactim); sec = exp % 60; min = exp / 60; if (min > 59) diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c index 7ce6698e..a9081ed0 100644 --- a/proto/ospf/ospf.c +++ b/proto/ospf/ospf.c @@ -676,7 +676,7 @@ ospf_reconfigure(struct proto *P, struct proto_config *CF) p->asbr = new->asbr; p->ecmp = new->ecmp; p->tick = new->tick; - p->disp_timer->recurrent = p->tick; + p->disp_timer->recurrent = p->tick S; tm_start(p->disp_timer, 1); /* Mark all areas and ifaces */ diff --git a/proto/radv/radv.c b/proto/radv/radv.c index 2c0a23ad..34a3f473 100644 --- a/proto/radv/radv.c +++ b/proto/radv/radv.c @@ -154,12 +154,7 @@ radv_iface_new(struct radv_proto *p, struct iface *iface, struct radv_iface_conf add_tail(&p->iface_list, NODE ifa); - timer *tm = tm_new(pool); - tm->hook = radv_timer; - tm->data = ifa; - tm->randomize = 0; - tm->recurrent = 0; - ifa->timer = tm; + ifa->timer = tm_new_set(pool, radv_timer, ifa, 0, 0); struct object_lock *lock = olock_new(pool); lock->addr = IPA_NONE; diff --git a/proto/rip/rip.c b/proto/rip/rip.c index 820c5117..2583b49b 100644 --- a/proto/rip/rip.c +++ b/proto/rip/rip.c @@ -902,7 +902,7 @@ rip_timer(timer *t) static inline void rip_kick_timer(struct rip_proto *p) { - if (p->timer->expires > (now + 1)) + if (p->timer->expires TO_S > (now + 1)) tm_start(p->timer, 1); /* Or 100 ms */ } @@ -962,7 +962,7 @@ rip_iface_timer(timer *t) static inline void rip_iface_kick_timer(struct rip_iface *ifa) { - if (ifa->timer->expires > (now + 1)) + if (ifa->timer->expires TO_S > (now + 1)) tm_start(ifa->timer, 1); /* Or 100 ms */ } diff --git a/proto/rpki/rpki.c b/proto/rpki/rpki.c index 349d2f70..a331e45e 100644 --- a/proto/rpki/rpki.c +++ b/proto/rpki/rpki.c @@ -382,7 +382,7 @@ rpki_do_we_recv_prefix_pdu_in_last_seconds(struct rpki_cache *cache) * |End of Data| PDU and has run by some &ERROR is occurred. */ static void -rpki_refresh_hook(struct timer *tm) +rpki_refresh_hook(timer *tm) { struct rpki_cache *cache = tm->data; @@ -428,7 +428,7 @@ rpki_refresh_hook(struct timer *tm) * ends by reaching of &ESTABLISHED state again. */ static void -rpki_retry_hook(struct timer *tm) +rpki_retry_hook(timer *tm) { struct rpki_cache *cache = tm->data; @@ -473,7 +473,7 @@ rpki_retry_hook(struct timer *tm) * of the protocol. */ static void -rpki_expire_hook(struct timer *tm) +rpki_expire_hook(timer *tm) { struct rpki_cache *cache = tm->data; @@ -789,8 +789,8 @@ rpki_get_status(struct proto *P, byte *buf) static void rpki_show_proto_info_timer(const char *name, uint num, timer *t) { - if (t->expires) - cli_msg(-1006, " %-17s %us (remains %us)", name, num, tm_remains(t)); + if (tm_active(t)) + cli_msg(-1006, " %-17s %us (remains %ds)", name, num, (int) tm_remains(t)); else cli_msg(-1006, " %-17s ---", name); } diff --git a/sysdep/unix/io.c b/sysdep/unix/io.c index 13635586..d3506d75 100644 --- a/sysdep/unix/io.c +++ b/sysdep/unix/io.c @@ -122,11 +122,13 @@ tracked_fopen(pool *p, char *name, char *mode) * for the other fields see |timer.h|. */ +#if 0 #define NEAR_TIMER_LIMIT 4 static list near_timers, far_timers; static bird_clock_t first_far_timer = TIME_INFINITY; + /* now must be different from 0, because 0 is a special value in timer->expires */ bird_clock_t now = 1, now_real, boot_time; @@ -183,7 +185,6 @@ init_times(void) log(L_WARN "Monotonic timer is missing"); } - static void tm_free(resource *r) { @@ -382,6 +383,7 @@ tm_shot(void) t->hook(t); } } +#endif /** * tm_parse_datetime - parse a date and time @@ -484,6 +486,8 @@ tm_format_datetime(char *x, struct timeformat *fmt_spec, bird_clock_t t) * Time clock */ +btime boot_time; + void times_init(struct timeloop *loop) { @@ -520,6 +524,19 @@ times_update(struct timeloop *loop) loop->real_time = 0; } +void +times_update_real_time(struct timeloop *loop) +{ + struct timespec ts; + int rv; + + rv = clock_gettime(CLOCK_REALTIME, &ts); + if (rv < 0) + die("clock_gettime: %m"); + + loop->real_time = ((s64) ts.tv_sec S) + (ts.tv_nsec / 1000); +} + /** * DOC: Sockets @@ -2349,9 +2366,6 @@ io_update_time(void) struct timespec ts; int rv; - if (!clock_monotonic_available) - return; - /* * This is third time-tracking procedure (after update_times() above and * times_update() in BFD), dedicated to internal event log and latency @@ -2490,14 +2504,12 @@ volatile int async_shutdown_flag; void io_init(void) { - init_list(&near_timers); - init_list(&far_timers); init_list(&sock_list); init_list(&global_event_list); krt_io_init(); - init_times(); - update_times(); - boot_time = now; + // XXX init_times(); + // XXX update_times(); + boot_time = current_time(); srandom((int) now_real); } @@ -2508,7 +2520,6 @@ void io_loop(void) { int poll_tout, timeout; - time_t tout; int nfds, events, pout; timer2 *t; sock *s; @@ -2522,17 +2533,10 @@ io_loop(void) times_update(&main_timeloop); events = ev_run_list(&global_event_list); timers_fire(&main_timeloop); - timers: - update_times(); - tout = tm_first_shot(); - if (tout <= now) - { - tm_shot(); - goto timers; - } io_close_event(); - poll_tout = (events ? 0 : MIN(tout - now, 3)) * 1000; /* Time in milliseconds */ + // FIXME + poll_tout = (events ? 0 : 3000); /* Time in milliseconds */ if (t = timers_first(&main_timeloop)) { times_update(&main_timeloop); diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c index 0349a09f..a5ec8a39 100644 --- a/sysdep/unix/krt.c +++ b/sysdep/unix/krt.c @@ -122,7 +122,7 @@ kif_force_scan(void) void kif_request_scan(void) { - if (kif_proto && kif_scan_timer->expires > now) + if (kif_proto && (kif_scan_timer->expires TO_S > (now + 1))) tm_start(kif_scan_timer, 1); } @@ -147,7 +147,7 @@ kif_start(struct proto *P) kif_scan_timer = tm_new(P->pool); kif_scan_timer->hook = kif_scan; kif_scan_timer->data = p; - kif_scan_timer->recurrent = KIF_CF->scan_time; + kif_scan_timer->recurrent = KIF_CF->scan_time S; kif_scan(kif_scan_timer); tm_start(kif_scan_timer, KIF_CF->scan_time); @@ -178,7 +178,7 @@ kif_reconfigure(struct proto *p, struct proto_config *new) if (o->scan_time != n->scan_time) { tm_stop(kif_scan_timer); - kif_scan_timer->recurrent = n->scan_time; + kif_scan_timer->recurrent = n->scan_time S; kif_scan(kif_scan_timer); tm_start(kif_scan_timer, n->scan_time); } diff --git a/sysdep/unix/main.c b/sysdep/unix/main.c index 396310fd..6cab21ac 100644 --- a/sysdep/unix/main.c +++ b/sysdep/unix/main.c @@ -57,7 +57,7 @@ async_dump(void) rdump(&root_pool); sk_dump_all(); - tm_dump_all(); + // XXXX tm_dump_all(); if_dump_all(); neigh_dump_all(); rta_dump_all(); diff --git a/sysdep/unix/timer.h b/sysdep/unix/timer.h index aa3ed143..1c4f6e3b 100644 --- a/sysdep/unix/timer.h +++ b/sysdep/unix/timer.h @@ -11,58 +11,38 @@ #include -#include "lib/resource.h" +#include "lib/birdlib.h" +#include "lib/timer.h" -typedef time_t bird_clock_t; /* Use instead of time_t */ -typedef struct timer { - resource r; - void (*hook)(struct timer *); - void *data; - uint randomize; /* Amount of randomization */ - uint recurrent; /* Timer recurrence */ - node n; /* Internal link */ - bird_clock_t expires; /* 0=inactive */ -} timer; +typedef struct timer2 timer; -timer *tm_new(pool *); -void tm_start(timer *, uint after); -void tm_stop(timer *); -void tm_dump_all(void); +static inline timer *tm_new(pool *p) +{ return (void *) tm2_new(p); } -extern bird_clock_t now; /* Relative, monotonic time in seconds */ -extern bird_clock_t now_real; /* Time in seconds since fixed known epoch */ -extern bird_clock_t boot_time; +static inline void tm_start(timer *t, bird_clock_t after) +{ tm2_start(t, after S_); } -static inline int -tm_active(timer *t) -{ - return t->expires != 0; -} +static inline void tm_stop(timer *t) +{ tm2_stop(t); } -static inline bird_clock_t -tm_remains(timer *t) -{ - return t->expires ? t->expires - now : 0; -} +// void tm_dump_all(void); -static inline void -tm_start_max(timer *t, bird_clock_t after) -{ - bird_clock_t rem = tm_remains(t); - tm_start(t, (rem > after) ? rem : after); -} +//extern bird_clock_t now; /* Relative, monotonic time in seconds */ +//extern bird_clock_t now_real; /* Time in seconds since fixed known epoch */ +//extern bird_clock_t boot_time; -static inline timer * -tm_new_set(pool *p, void (*hook)(struct timer *), void *data, uint rand, uint rec) -{ - timer *t = tm_new(p); - t->hook = hook; - t->data = data; - t->randomize = rand; - t->recurrent = rec; - return t; -} +static inline int tm_active(timer *t) +{ return tm2_active(t); } + +static inline bird_clock_t tm_remains(timer *t) +{ return tm2_remains(t) TO_S; } + +static inline void tm_start_max(timer *t, bird_clock_t after) +{ tm2_start_max(t, after S_); } + +static inline timer * tm_new_set(pool *p, void (*hook)(timer *), void *data, uint rand, uint rec) +{ return tm2_new_init(p, hook, data, rec S_, rand S_); } struct timeformat { @@ -77,12 +57,7 @@ bird_clock_t tm_parse_datetime(char *); /* Convert date to bird_clock_t */ void tm_format_datetime(char *x, struct timeformat *fmt_spec, bird_clock_t t); -#define TIME_T_IS_64BIT (sizeof(time_t) == 8) -#define TIME_T_IS_SIGNED ((time_t) -1 < 0) +#define TIME_INFINITY ((s64) 0x7fffffffffffffff) -#define TIME_INFINITY \ - ((time_t) (TIME_T_IS_SIGNED ? \ - (TIME_T_IS_64BIT ? 0x7fffffffffffffff : 0x7fffffff): \ - (TIME_T_IS_64BIT ? 0xffffffffffffffff : 0xffffffff))) #endif