flow_t key;
 
     /* Statistics. */
-       struct timeval used;        /* Last used time, in milliseconds. */
+       struct timespec used;       /* Last used time. */
        long long int packet_count; /* Number of packets matched. */
        long long int byte_count;   /* Number of bytes matched. */
        uint8_t ip_tos;             /* IP TOS value. */
         odp_flow->stats.n_packets = flow->packet_count;
         odp_flow->stats.n_bytes = flow->byte_count;
         odp_flow->stats.used_sec = flow->used.tv_sec;
-        odp_flow->stats.used_nsec = flow->used.tv_usec * 1000;
+        odp_flow->stats.used_nsec = flow->used.tv_nsec;
         odp_flow->stats.tcp_flags = TCP_FLAGS(flow->tcp_ctl);
         odp_flow->stats.ip_tos = flow->ip_tos;
         odp_flow->stats.error = 0;
 clear_stats(struct dp_netdev_flow *flow)
 {
     flow->used.tv_sec = 0;
-    flow->used.tv_usec = 0;
+    flow->used.tv_nsec = 0;
     flow->packet_count = 0;
     flow->byte_count = 0;
     flow->ip_tos = 0;
 dp_netdev_flow_used(struct dp_netdev_flow *flow, const flow_t *key,
                     const struct ofpbuf *packet)
 {
-    time_timeval(&flow->used);
+    time_timespec(&flow->used);
     flow->packet_count++;
     flow->byte_count += packet->size;
     if (key->dl_type == htons(ETH_TYPE_IP)) {
 
 /* Initialized? */
 static bool inited;
 
+/* Does this system have monotonic timers? */
+static bool monotonic_inited;
+static clockid_t monotonic_clock;
+
 /* Has a timer tick occurred? */
-static volatile sig_atomic_t tick;
+static volatile sig_atomic_t wall_tick;
+static volatile sig_atomic_t monotonic_tick;
 
 /* The current time, as of the last refresh. */
-static struct timeval now;
+static struct timespec wall_time;
+static struct timespec monotonic_time;
 
 /* Time at which to die with SIGALRM (if not TIME_MIN). */
 static time_t deadline = TIME_MIN;
 static void set_up_timer(void);
 static void set_up_signal(int flags);
 static void sigalrm_handler(int);
-static void refresh_if_ticked(void);
+static void refresh_wall_if_ticked(void);
+static void refresh_monotonic_if_ticked(void);
 static time_t time_add(time_t, time_t);
 static void block_sigalrm(sigset_t *);
 static void unblock_sigalrm(const sigset_t *);
     coverage_init();
 
     inited = true;
-    gettimeofday(&now, NULL);
-    tick = false;
+    time_refresh();
 
     set_up_signal(SA_RESTART);
     set_up_timer();
 }
 
+static void
+set_up_monotonic(void)
+{
+    int err;
+
+    if (monotonic_inited) {
+        return;
+    }
+
+    err = clock_gettime(CLOCK_MONOTONIC, &monotonic_time);
+    if (!err) {
+        monotonic_clock = CLOCK_MONOTONIC;
+    } else {
+        monotonic_clock = CLOCK_REALTIME;
+        VLOG_DBG("monotonic timer not available");
+    }
+
+    monotonic_inited = true;
+}
+
 static void
 set_up_signal(int flags)
 {
 static void
 set_up_timer(void)
 {
-    struct itimerval itimer;
+    timer_t timer_id;
+    struct itimerspec itimer;
+
+    set_up_monotonic();
+
+    if (timer_create(monotonic_clock, NULL, &timer_id)) {
+        ovs_fatal(errno, "timer_create failed");
+    }
 
     itimer.it_interval.tv_sec = 0;
-    itimer.it_interval.tv_usec = TIME_UPDATE_INTERVAL * 1000;
+    itimer.it_interval.tv_nsec = TIME_UPDATE_INTERVAL * 1000 * 1000;
     itimer.it_value = itimer.it_interval;
-    if (setitimer(ITIMER_REAL, &itimer, NULL)) {
-        ovs_fatal(errno, "setitimer failed");
+
+    if (timer_settime(timer_id, 0, &itimer, NULL)) {
+        ovs_fatal(errno, "timer_settime failed");
     }
 }
 
     set_up_timer();
 }
 
+static void
+refresh_wall(void)
+{
+    clock_gettime(CLOCK_REALTIME, &wall_time);
+    wall_tick = false;
+}
+
+static void
+refresh_monotonic(void)
+{
+    set_up_monotonic();
+
+    if (monotonic_clock == CLOCK_MONOTONIC) {
+        clock_gettime(monotonic_clock, &monotonic_time);
+    } else {
+        refresh_wall_if_ticked();
+        monotonic_time = wall_time;
+    }
+
+    monotonic_tick = false;
+}
+
 /* Forces a refresh of the current time from the kernel.  It is not usually
  * necessary to call this function, since the time will be refreshed
  * automatically at least every TIME_UPDATE_INTERVAL milliseconds. */
 void
 time_refresh(void)
 {
-    gettimeofday(&now, NULL);
-    tick = false;
+    wall_tick = monotonic_tick = true;
 }
 
-/* Returns the current time, in seconds. */
+/* Returns a monotonic timer, in seconds. */
 time_t
 time_now(void)
 {
-    refresh_if_ticked();
-    return now.tv_sec;
+    refresh_monotonic_if_ticked();
+    return monotonic_time.tv_sec;
 }
 
-/* Returns the current time, in ms (within TIME_UPDATE_INTERVAL ms). */
+/* Same as time_now() except does not write to static variables, for use in
+ * signal handlers. set_up_monotonic() must have already been called. */
+static time_t
+time_now_sig(void)
+{
+    struct timespec cur_time;
+
+    clock_gettime(monotonic_clock, &cur_time);
+    return cur_time.tv_sec;
+}
+
+/* Returns the current time, in seconds. */
+time_t
+time_wall(void)
+{
+    refresh_wall_if_ticked();
+    return wall_time.tv_sec;
+}
+
+/* Returns a monotonic timer, in ms (within TIME_UPDATE_INTERVAL ms). */
 long long int
 time_msec(void)
 {
-    refresh_if_ticked();
-    return timeval_to_msec(&now);
+    refresh_monotonic_if_ticked();
+    return timespec_to_msec(&monotonic_time);
+}
+
+/* Returns the current time, in ms (within TIME_UPDATE_INTERVAL ms). */
+long long int
+time_wall_msec(void)
+{
+    refresh_wall_if_ticked();
+    return timespec_to_msec(&wall_time);
+}
+
+/* Stores a monotonic timer, accurate within TIME_UPDATE_INTERVAL ms, into
+ * '*ts'. */
+void
+time_timespec(struct timespec *ts)
+{
+    refresh_monotonic_if_ticked();
+    *ts = monotonic_time;
 }
 
 /* Stores the current time, accurate within TIME_UPDATE_INTERVAL ms, into
- * '*tv'. */
+ * '*ts'. */
 void
-time_timeval(struct timeval *tv)
+time_wall_timespec(struct timespec *ts)
 {
-    refresh_if_ticked();
-    *tv = now;
+    refresh_wall_if_ticked();
+    *ts = wall_time;
 }
 
 /* Configures the program to die with SIGALRM 'secs' seconds from now, if
 static void
 sigalrm_handler(int sig_nr)
 {
-    tick = true;
-    if (deadline != TIME_MIN && time(0) > deadline) {
+    wall_tick = true;
+    monotonic_tick = true;
+    if (deadline != TIME_MIN && time_now_sig() > deadline) {
         fatal_signal_handler(sig_nr);
     }
 }
 
 static void
-refresh_if_ticked(void)
+refresh_wall_if_ticked(void)
 {
     assert(inited);
-    if (tick) {
-        time_refresh();
+    if (wall_tick) {
+        refresh_wall();
+    }
+}
+
+static void
+refresh_monotonic_if_ticked(void)
+{
+    assert(inited);
+    if (monotonic_tick) {
+        refresh_monotonic();
     }
 }
 
     }
 }
 
+long long int
+timespec_to_msec(const struct timespec *ts)
+{
+    return (long long int) ts->tv_sec * 1000 + ts->tv_nsec / (1000 * 1000);
+}
+
 long long int
 timeval_to_msec(const struct timeval *tv)
 {
 
 #endif
 
 struct pollfd;
+struct timespec;
 struct timeval;
 
 /* POSIX allows floating-point time_t, but we don't support it. */
 #define TIME_MAX TYPE_MAXIMUM(time_t)
 #define TIME_MIN TYPE_MINIMUM(time_t)
 
-/* Interval between updates to the time reported by time_gettimeofday(), in ms.
- * This should not be adjusted much below 10 ms or so with the current
- * implementation, or too much time will be wasted in signal handlers and calls
- * to time(0). */
+/* Interval between updates to the reported time, in ms.  This should not be
+ * adjusted much below 10 ms or so with the current implementation, or too
+ * much time will be wasted in signal handlers and calls to clock_gettime(). */
 #define TIME_UPDATE_INTERVAL 100
 
 void time_init(void);
 void time_postfork(void);
 void time_refresh(void);
 time_t time_now(void);
+time_t time_wall(void);
 long long int time_msec(void);
-void time_timeval(struct timeval *);
+long long int time_wall_msec(void);
+void time_timespec(struct timespec *);
+void time_wall_timespec(struct timespec *);
 void time_alarm(unsigned int secs);
 int time_poll(struct pollfd *, int n_pollfds, int timeout);
 
+long long int timespec_to_msec(const struct timespec *);
 long long int timeval_to_msec(const struct timeval *);
 
 #ifdef  __cplusplus