]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Fix problem with local time changes.
authorOndrej Zajicek <santiago@crfreenet.org>
Wed, 5 Nov 2008 21:36:49 +0000 (22:36 +0100)
committerOndrej Zajicek <santiago@crfreenet.org>
Wed, 5 Nov 2008 21:36:49 +0000 (22:36 +0100)
configure.in
nest/password.c
proto/ospf/packet.c
proto/rip/auth.c
sysdep/unix/io.c
sysdep/unix/timer.h

index 44d55c904330aea1772d4884b306df0ff6ffce54..438273257f71bf4b6c38e4efaeaeafff503f13a6 100644 (file)
@@ -49,6 +49,8 @@ else
        fi
 fi
 
+LIBS=" -lrt"
+
 AC_CANONICAL_HOST
 
 AC_PROG_CC
index 7f1c8dce19858506b322be6275cfe4f8122cf09b..80c4c7b473c0af7c15ac5f55f0d9333a4d33b9d6 100644 (file)
@@ -22,7 +22,7 @@ password_find(list *l)
   {
     WALK_LIST(pi, *l)
     {
-      if ((pi->genfrom < now) && (pi->gento > now))
+      if ((pi->genfrom < now_real) && (pi->gento > now_real))
         return pi;
     }
   }
index ead4b86f9b2abeaa9e82e86253b0c06590afc1a6..4e8dcaf04e924cb20e4dce8f650bd00254bd83d7 100644 (file)
@@ -165,7 +165,7 @@ ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_
       WALK_LIST(ptmp, *(ifa->passwords))
       {
         if (pkt->u.md5.keyid != ptmp->id) continue;
-        if ((ptmp->accfrom > now) || (ptmp->accto < now)) continue;
+        if ((ptmp->accfrom > now_real) || (ptmp->accto < now_real)) continue;
         pass = ptmp;
         break;
       }
index 8669e166801b9427df5d27a59a5359b85d4b888b..1f7050f0599121246edd423e40949ec0cd2055e3 100644 (file)
@@ -77,7 +77,7 @@ rip_incoming_authentication( struct proto *p, struct rip_block_auth *block, stru
       WALK_LIST(ptmp, *l)
       {
         if (block->keyid != ptmp->id) continue;
-        if ((ptmp->genfrom > now) || (ptmp->gento < now)) continue;
+        if ((ptmp->genfrom > now_real) || (ptmp->gento < now_real)) continue;
         pass = ptmp;
         break;
       }
index ddb3c4d956c6f38c8c25b97b1db8d99d4475ea13..5aed1b22bf7055c92306e890783293f517cf0d25 100644 (file)
@@ -83,10 +83,11 @@ tracked_fopen(pool *p, char *name, char *mode)
  * doesn't guarantee exact timing, only that a timer function
  * won't be called before the requested time.
  *
- * In BIRD, real time is represented by values of the &bird_clock_t type
- * which are integral numbers interpreted as a number of seconds since
- * a fixed (but platform dependent) epoch. The current time can be read
- * from a variable @now with reasonable accuracy.
+ * In BIRD, time is represented by values of the &bird_clock_t type
+ * which are integral numbers interpreted as a relative number of seconds since
+ * some fixed time point in past. The current time can be read
+ * from variable @now with reasonable accuracy and is monotonic. There is also
+ * a current 'absolute' time in variable @now_real reported by OS.
  *
  * Each timer is described by a &timer structure containing a pointer
  * to the handler function (@hook), data private to this function (@data),
@@ -99,7 +100,61 @@ tracked_fopen(pool *p, char *name, char *mode)
 static list near_timers, far_timers;
 static bird_clock_t first_far_timer = TIME_INFINITY;
 
-bird_clock_t now;
+bird_clock_t now, now_real;
+
+static void
+update_times_plain(void)
+{
+  bird_clock_t new_time = time(NULL);
+  int delta = new_time - now_real;
+
+  if ((delta >= 0) && (delta < 60))
+    now += delta;
+  else if (now_real != 0)
+   log(L_WARN "Time jump, delta %d s", delta);
+
+  now_real = new_time;
+}
+
+static void
+update_times_gettime(void)
+{
+  struct timespec ts;
+  int rv;
+
+  rv = clock_gettime(CLOCK_MONOTONIC, &ts);
+  if (rv != 0)
+    die("clock_gettime: %m");
+
+  if (ts.tv_sec != now) {
+    if (ts.tv_sec < now)
+      log(L_ERR "Monotonic timer is broken");
+
+    now = ts.tv_sec;
+    now_real = time(NULL);
+  }
+}
+
+static int clock_monotonic_available;
+
+static inline void
+update_times(void)
+{
+  if (clock_monotonic_available)
+    update_times_gettime();
+  else
+    update_times_plain();
+}
+
+static inline void
+init_times(void)
+{
+ struct timespec ts;
+ clock_monotonic_available = (clock_gettime(CLOCK_MONOTONIC, &ts) == 0);
+ if (!clock_monotonic_available)
+   log(L_WARN "Monotonic timer is missing");
+}
+
 
 static void
 tm_free(resource *r)
@@ -353,8 +408,8 @@ tm_parse_date(char *x)
  * @x: destination buffer of size %TM_DATE_BUFFER_SIZE
  * @t: time
  *
- * This function formats the given time value @t to a textual
- * date representation (dd-mm-yyyy).
+ * This function formats the given relative time value @t to a textual
+ * date representation (dd-mm-yyyy) in real time..
  */
 void
 tm_format_date(char *x, bird_clock_t t)
@@ -370,14 +425,15 @@ tm_format_date(char *x, bird_clock_t t)
  * @x: destination buffer of size %TM_DATETIME_BUFFER_SIZE
  * @t: time
  *
- * This function formats the given time value @t to a textual
- * date/time representation (dd-mm-yyyy hh:mm:ss).
+ * 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, bird_clock_t t)
 {
   struct tm *tm;
-
+  bird_clock_t delta = now - t;
+  t = now_real - delta;
   tm = localtime(&t);
   if (strftime(x, TM_DATETIME_BUFFER_SIZE, "%d-%m-%Y %H:%M:%S", tm) == TM_DATETIME_BUFFER_SIZE)
     strcpy(x, "<too-long>");
@@ -388,16 +444,17 @@ tm_format_datetime(char *x, bird_clock_t t)
  * @x: destination buffer of size %TM_RELTIME_BUFFER_SIZE
  * @t: time
  *
- * This function formats the given time value @t to a short
- * textual representation relative to the current time.
+ * This function formats the given relative time value @t to a short
+ * textual representation in real time, relative to the current time.
  */
 void
 tm_format_reltime(char *x, bird_clock_t t)
 {
   struct tm *tm;
-  bird_clock_t delta = (t < now) ? (now - t) : (t - now);
   static char *month_names[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
 
+  bird_clock_t delta = now - t;
+  t = now_real - delta;
   tm = localtime(&t);
   if (delta < 20*3600)
     bsprintf(x, "%02d:%02d", tm->tm_hour, tm->tm_min);
@@ -1217,8 +1274,9 @@ io_init(void)
   init_list(&sock_list);
   init_list(&global_event_list);
   krt_io_init();
-  now = time(NULL);
-  srandom((int) now);
+  init_times();
+  update_times();
+  srandom((int) now_real);
 }
 
 void
@@ -1235,7 +1293,7 @@ io_loop(void)
   for(;;)
     {
       events = ev_run_list(&global_event_list);
-      now = time(NULL);
+      update_times();
       tout = tm_first_shot();
       if (tout <= now)
        {
index 608dabb82a4b6494210116e75b194c4193f1850f..761cb42b0c158321982057334b889058c80a977b 100644 (file)
@@ -30,7 +30,8 @@ void tm_start(timer *, unsigned after);
 void tm_stop(timer *);
 void tm_dump_all(void);
 
-extern bird_clock_t now;               /* Time in seconds since unknown epoch */
+extern bird_clock_t now;               /* Relative, monotonic time in seconds */
+extern bird_clock_t now_real;          /* Time in seconds since fixed known epoch */
 
 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 */