2005-10-21 Paul Jakma <paul.jakma@sun.com>

	* (general) SPF millisecond resolution timer with adaptive,
	  linear back-off holdtime. Prettification of ospf_timer_dump.
	* ospf_dump.c: (ospf_timeval_dump) new function. The guts of
	  ospf_timer_dump, but made to be more dynamic in printing out
	  the relative timeval, sliding the precision printed out
	  according to the value.
	  (ospf_timer_dump) guts moved to ospf_timeval_dump.
	* ospf_dump.h: export ospf_timeval_dump.
	* ospf_flood.c: (ospf_flood) remove gettimeofday, use
	  the libzebra exported recent_time instead, as it's not
	  terribly critical to have time exactly right - the dropped
	  LSA will be retransmited to us if we don't ACK it.
	* ospf_packet.c: (ospf_ls_upd_timer) Ditto, but here we're
	  not transmitting, just putting LSA back on update transmit list.
	* ospfd.h: delay and holdtimes should be unsigned.
	  Add spf_max_holdtime and spf_hold_multiplier.
	  Update default defines for delay and hold time to be in msec.
	  (struct ospf) change the SPF timestamp to a struct timeval.
	  Remove ospf_timers_spf_(un)?set.
	* ospfd.c: (ospf_timers_spf_{set,unset}) removed.
	  (ospf_new) initialise spf_max_holdtime and spf_hold_multiplier
	* ospf_spf.c: (ospf_spf_calculate) SPF timestamp is a timeval
	  now, update with gettimeofday.
	  (ospf_spf_calculate_schedule) Change SPF timers to millisecond
	  resolution.
	  Make the holdtime be adaptive, with a linear increase in
	  holdtime ever consecutive SPF run which occurs within holdtime
	  of previous SPF, bounded by spf_max_holdtime.
	* ospf_vty.c: Update spf timers commands.
	  (ospf_timers_spf_set) trivial helper.
	  (ospf_timers_throttle_spf_cmd) new command to set SPF delay,
	  initial hold and max hold times with millisecond resolution.
	  (ospf_timers_spf_cmd) Deprecated. Accept the old values,
	  convert to msec, truncate to new limits.
	  (no_ospf_timers_throttle_spf_cmd) set timers to defaults.
	  (no_ospf_timers_spf_cmd) deprecated form, same as previous.
	  (show_ip_ospf_cmd) Display SPF parameters and times.
	  (show_ip_ospf_neighbour_header) Centralise the 'sh ip os ne'
	  header.
	  (show_ip_ospf_neighbor_sub) Fix the field widths. Get rid of
	  the multiple spaces which were making the lines even longer.
	  (show_ip_ospf_neighbor_cmd) Use show_ip_ospf_neighbour_header
	  (show_ip_ospf_neighbor_all_cmd) ditto and fix the field
	  widths for NBMA neighbours.
	  (show_ip_ospf_neighbor_int) Use header function.
	  (show_ip_ospf_nbr_nbma_detail_sub) use sizeof for timebuf,
	  local array - safer.
	  (show_ip_ospf_neighbor_detail_sub) ditto
	  (ospf_vty_init) install the new SPF throttle timer commands.
diff --git a/ospfd/ospf_dump.c b/ospfd/ospf_dump.c
index 829c00f..9ae87a6 100644
--- a/ospfd/ospf_dump.c
+++ b/ospfd/ospf_dump.c
@@ -230,45 +230,82 @@
 }
 
 const char *
-ospf_timer_dump (struct thread *t, char *buf, size_t size)
+ospf_timeval_dump (struct timeval *t, char *buf, size_t size)
 {
-  struct timeval now, result;
-  unsigned long h, m, s, ms;
-
+  /* Making formatted timer strings. */
+#define MINUTE_IN_SECONDS	60
+#define HOUR_IN_SECONDS		(60*MINUTE_IN_SECONDS)
+#define DAY_IN_SECONDS		(24*HOUR_IN_SECONDS)
+#define WEEK_IN_SECONDS		(7*DAY_IN_SECONDS)
+  unsigned long w, d, h, m, s, ms;
+  
   if (!t)
     return "inactive";
-
-  h = m = s = ms = 0;
+  
+  w = d = h = m = s = ms = 0;
   memset (buf, 0, size);
-
-  gettimeofday (&now, NULL);
   
-  timersub (&t->u.sands, &now, &result);
-  
-  ms = result.tv_usec / 1000;
+  ms = t->tv_usec / 1000;
   
   if (ms >= 1000)
     {
-      result.tv_sec = ms / 1000;
-      ms =- result.tv_sec * 1000;
+      t->tv_sec = ms / 1000;
+      ms =- t->tv_sec * 1000;
     }
-  if (result.tv_sec >= 3600)
+  
+  if (t->tv_sec > WEEK_IN_SECONDS)
     {
-      h = result.tv_sec / 3600;
-      result.tv_sec -= h * 3600;
+      w = t->tv_sec / WEEK_IN_SECONDS;
+      t->tv_sec -= w * WEEK_IN_SECONDS;
     }
-
-  if (result.tv_sec >= 60)
+  
+  if (t->tv_sec > DAY_IN_SECONDS)
     {
-      m = result.tv_sec / 60;
-      result.tv_sec -= m * 60;
+      d = t->tv_sec / DAY_IN_SECONDS;
+      t->tv_sec -= d * DAY_IN_SECONDS;
     }
-
-  snprintf (buf, size, "%02ld:%02ld:%02ld.%03ld", h, m, result.tv_sec, ms);
-
+  
+  if (t->tv_sec >= HOUR_IN_SECONDS)
+    {
+      h = t->tv_sec / HOUR_IN_SECONDS;
+      t->tv_sec -= h * HOUR_IN_SECONDS;
+    }
+  
+  if (t->tv_sec >= MINUTE_IN_SECONDS)
+    {
+      m = t->tv_sec / MINUTE_IN_SECONDS;
+      t->tv_sec -= m * MINUTE_IN_SECONDS;
+    }
+  
+  if (w > 99)
+    snprintf (buf, size, "%ldw%1ldd", w, d);
+  else if (w)
+    snprintf (buf, size, "%ldw%1ldd%02ldh", w, d, h);
+  else if (d)
+    snprintf (buf, size, "%1ldd%02ldh%02ldm", d, h, m);
+  else if (h)
+    snprintf (buf, size, "%ldh%02ldm%02lds", h, m, t->tv_sec);
+  else if (m)
+    snprintf (buf, size, "%ldm%02lds", m, t->tv_sec);
+  else
+    snprintf (buf, size, "%ld.%03lds", t->tv_sec, ms);
+  
   return buf;
 }
 
+const char *
+ospf_timer_dump (struct thread *t, char *buf, size_t size)
+{
+  struct timeval result;
+  
+  if (!t)
+    return "inactive";
+  
+  timersub (&t->u.sands, &recent_time, &result);
+    
+  return ospf_timeval_dump (&result, buf, size);
+}
+
 #define OSPF_OPTION_STR_MAXLEN		24
 
 char *