[ovs-dev] [PATCH] timeval: Use monotonic time where appropriate.

Jesse Gross jesse at nicira.com
Mon Jun 7 20:22:54 UTC 2010


Most of the timekeeping needs of OVS are simply to measure intervals,
which means that it is sensitive to changes in the clock.  This commit
replaces the existing clocks with monotonic timers.  An additional set
of wall clock timers are added and used in locations that need absolute
time.
---
 lib/dpif-netdev.c       |    8 ++--
 lib/dynamic-string.c    |    2 +-
 lib/odp-util.c          |    2 +-
 lib/timeval.c           |  108 +++++++++++++++++++++++++++++++++++++----------
 lib/timeval.h           |   13 ++++--
 lib/vlog.c              |    2 +-
 ofproto/netflow.c       |    6 +-
 ofproto/ofproto-sflow.c |    4 +-
 ofproto/ofproto.c       |   12 +++---
 ovsdb/automake.mk       |    6 +-
 ovsdb/file.c            |    2 +-
 tests/automake.mk       |   34 +++++++-------
 tests/test-timeval.c    |    4 +-
 utilities/automake.mk   |   19 ++++----
 vswitchd/automake.mk    |    5 +-
 xenserver/automake.mk   |    2 +-
 16 files changed, 150 insertions(+), 79 deletions(-)

diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index 7b1bb5d..5021874 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -99,7 +99,7 @@ struct dp_netdev_flow {
     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. */
@@ -680,7 +680,7 @@ answer_flow_query(struct dp_netdev_flow *flow, uint32_t query_flags,
         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;
@@ -826,7 +826,7 @@ static void
 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;
@@ -1003,7 +1003,7 @@ static void
 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)) {
diff --git a/lib/dynamic-string.c b/lib/dynamic-string.c
index 79a7d8e..180a430 100644
--- a/lib/dynamic-string.c
+++ b/lib/dynamic-string.c
@@ -179,7 +179,7 @@ void
 ds_put_strftime(struct ds *ds, const char *template, const struct tm *tm)
 {
     if (!tm) {
-        time_t now = time_now();
+        time_t now = time_wall();
         tm = localtime(&now);
     }
     for (;;) {
diff --git a/lib/odp-util.c b/lib/odp-util.c
index 67d1b3e..1671a25 100644
--- a/lib/odp-util.c
+++ b/lib/odp-util.c
@@ -122,7 +122,7 @@ format_odp_flow_stats(struct ds *ds, const struct odp_flow_stats *s)
                   (unsigned long long int) s->n_bytes);
     if (s->used_sec) {
         long long int used = s->used_sec * 1000 + s->used_nsec / 1000000;
-        ds_put_format(ds, "%.3fs", (time_msec() - used) / 1000.0);
+        ds_put_format(ds, "%.3fs", (time_wall_msec() - used) / 1000.0);
     } else {
         ds_put_format(ds, "never");
     }
diff --git a/lib/timeval.c b/lib/timeval.c
index ab564a1..2dd881d 100644
--- a/lib/timeval.c
+++ b/lib/timeval.c
@@ -35,10 +35,12 @@
 static bool inited;
 
 /* 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;
@@ -46,7 +48,8 @@ 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 *);
@@ -64,8 +67,7 @@ time_init(void)
     coverage_init();
 
     inited = true;
-    gettimeofday(&now, NULL);
-    tick = false;
+    time_refresh();
 
     set_up_signal(SA_RESTART);
     set_up_timer();
@@ -136,39 +138,85 @@ time_postfork(void)
     set_up_timer();
 }
 
+static void
+refresh_wall(void)
+{
+    clock_gettime(CLOCK_REALTIME, &wall_time);
+    wall_tick = false;
+}
+
+static void
+refresh_monotonic(void)
+{
+    static bool have_monotonic = true;
+
+    if (have_monotonic) {
+        int err;
+
+        err = clock_gettime(CLOCK_MONOTONIC, &monotonic_time);
+        if (err) {
+            have_monotonic = false;
+            VLOG_DBG("monotonic timer not available");
+        }
+    }
+
+    if (!have_monotonic) {
+        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;
+    refresh_wall();
+    refresh_monotonic();
 }
 
-/* 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). */
+/* 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 the current time, accurate within TIME_UPDATE_INTERVAL ms, into
- * '*tv'. */
+ * '*ts'. */
 void
-time_timeval(struct timeval *tv)
+time_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
@@ -252,18 +300,28 @@ time_add(time_t a, time_t b)
 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() > 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();
     }
 }
 
@@ -287,6 +345,12 @@ unblock_sigalrm(const sigset_t *oldsigs)
 }
 
 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)
 {
     return (long long int) tv->tv_sec * 1000 + tv->tv_usec / 1000;
diff --git a/lib/timeval.h b/lib/timeval.h
index 89abe80..ee6af81 100644
--- a/lib/timeval.h
+++ b/lib/timeval.h
@@ -26,6 +26,7 @@ extern "C" {
 #endif
 
 struct pollfd;
+struct timespec;
 struct timeval;
 
 /* POSIX allows floating-point time_t, but we don't support it. */
@@ -38,10 +39,9 @@ BUILD_ASSERT_DECL(TYPE_IS_SIGNED(time_t));
 #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);
@@ -50,11 +50,14 @@ void time_enable_restart(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_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
diff --git a/lib/vlog.c b/lib/vlog.c
index b534d19..e086e79 100644
--- a/lib/vlog.c
+++ b/lib/vlog.c
@@ -428,7 +428,7 @@ vlog_init(void)
     vlog_set_levels(VLM_ANY_MODULE, VLF_ANY_FACILITY, VLL_INFO);
 
     boot_time = time_msec();
-    now = time_now();
+    now = time_wall();
     if (now < 0) {
         struct tm tm;
         char s[128];
diff --git a/ofproto/netflow.c b/ofproto/netflow.c
index 34d571f..495dc0e 100644
--- a/ofproto/netflow.c
+++ b/ofproto/netflow.c
@@ -109,7 +109,7 @@ netflow_expire(struct netflow *nf, struct netflow_flow *nf_flow,
 {
     struct netflow_v5_header *nf_hdr;
     struct netflow_v5_record *nf_rec;
-    struct timeval now;
+    struct timespec now;
 
     nf_flow->last_expired += nf->active_timeout;
 
@@ -120,7 +120,7 @@ netflow_expire(struct netflow *nf, struct netflow_flow *nf_flow,
         return;
     }
 
-    time_timeval(&now);
+    time_timespec(&now);
 
     if (!nf->packet.size) {
         nf_hdr = ofpbuf_put_zeros(&nf->packet, sizeof *nf_hdr);
@@ -128,7 +128,7 @@ netflow_expire(struct netflow *nf, struct netflow_flow *nf_flow,
         nf_hdr->count = htons(0);
         nf_hdr->sysuptime = htonl(time_msec() - nf->boot_time);
         nf_hdr->unix_secs = htonl(now.tv_sec);
-        nf_hdr->unix_nsecs = htonl(now.tv_usec * 1000);
+        nf_hdr->unix_nsecs = htonl(now.tv_nsec);
         nf_hdr->flow_seq = htonl(nf->netflow_cnt++);
         nf_hdr->engine_type = nf->engine_type;
         nf_hdr->engine_id = nf->engine_id;
diff --git a/ofproto/ofproto-sflow.c b/ofproto/ofproto-sflow.c
index 37c1bb7..a96d8b4 100644
--- a/ofproto/ofproto-sflow.c
+++ b/ofproto/ofproto-sflow.c
@@ -415,7 +415,7 @@ ofproto_sflow_set_options(struct ofproto_sflow *os,
         sfl_agent_release(os->sflow_agent);
     }
     os->sflow_agent = xcalloc(1, sizeof *os->sflow_agent);
-    now = time_now();
+    now = time_wall();
     sfl_agent_init(os->sflow_agent,
                    &agentIP,
                    options->sub_id,
@@ -597,7 +597,7 @@ ofproto_sflow_run(struct ofproto_sflow *os)
     if (ofproto_sflow_is_enabled(os)) {
         time_t now = time_now();
         if (now >= os->next_tick) {
-            sfl_agent_tick(os->sflow_agent, now);
+            sfl_agent_tick(os->sflow_agent, time_wall());
             os->next_tick = now + 1;
         }
     }
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index 0fd2fdf..6ab4d0c 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -1710,7 +1710,7 @@ rule_create(struct ofproto *ofproto, struct rule *super,
     rule->idle_timeout = idle_timeout;
     rule->hard_timeout = hard_timeout;
     rule->flow_cookie = flow_cookie;
-    rule->used = rule->created = time_msec();
+    rule->used = rule->created = time_wall_msec();
     rule->send_flow_removed = send_flow_removed;
     rule->super = super;
     if (super) {
@@ -1827,7 +1827,7 @@ rule_execute(struct ofproto *ofproto, struct rule *rule,
         struct odp_flow_stats stats;
         flow_extract_stats(flow, packet, &stats);
         update_stats(ofproto, rule, &stats);
-        rule->used = time_msec();
+        rule->used = time_wall_msec();
         netflow_flow_update_time(ofproto->netflow, &rule->nf_flow, rule->used);
     }
 }
@@ -2936,7 +2936,7 @@ flow_stats_cb(struct cls_rule *rule_, void *cbdata_)
     struct ofp_flow_stats *ofs;
     uint64_t packet_count, byte_count;
     size_t act_len, len;
-    long long int tdiff = time_msec() - rule->created;
+    long long int tdiff = time_wall_msec() - rule->created;
     uint32_t sec = tdiff / 1000;
     uint32_t msec = tdiff - (sec * 1000);
 
@@ -3028,7 +3028,7 @@ flow_stats_ds_cb(struct cls_rule *rule_, void *cbdata_)
                   cbdata->ofproto->tun_id_from_cookie, &match);
 
     ds_put_format(results, "duration=%llds, ",
-                  (time_msec() - rule->created) / 1000);
+                  (time_wall_msec() - rule->created) / 1000);
     ds_put_format(results, "priority=%u, ", rule->cr.priority);
     ds_put_format(results, "n_packets=%"PRIu64", ", packet_count);
     ds_put_format(results, "n_bytes=%"PRIu64", ", byte_count);
@@ -3459,7 +3459,7 @@ delete_flow(struct ofproto *p, struct rule *rule, uint16_t out_port)
         return;
     }
 
-    send_flow_removed(p, rule, time_msec(), OFPRR_DELETE);
+    send_flow_removed(p, rule, time_wall_msec(), OFPRR_DELETE);
     rule_remove(p, rule);
 }
 
@@ -3941,7 +3941,7 @@ expire_rule(struct cls_rule *cls_rule, void *p_)
                    : LLONG_MAX);
     expire = MIN(hard_expire, idle_expire);
 
-    now = time_msec();
+    now = time_wall_msec();
     if (now < expire) {
         if (rule->installed && now >= rule->used + 5000) {
             uninstall_idle_flow(p, rule);
diff --git a/ovsdb/automake.mk b/ovsdb/automake.mk
index 37d669b..593f5cf 100644
--- a/ovsdb/automake.mk
+++ b/ovsdb/automake.mk
@@ -34,7 +34,7 @@ EXTRA_DIST += \
 # ovsdb-tool
 bin_PROGRAMS += ovsdb/ovsdb-tool
 ovsdb_ovsdb_tool_SOURCES = ovsdb/ovsdb-tool.c
-ovsdb_ovsdb_tool_LDADD = ovsdb/libovsdb.a lib/libopenvswitch.a
+ovsdb_ovsdb_tool_LDADD = ovsdb/libovsdb.a lib/libopenvswitch.a -lrt
 # ovsdb-tool.1
 man_MANS += ovsdb/ovsdb-tool.1
 DISTCLEANFILES += ovsdb/ovsdb-tool.1
@@ -43,7 +43,7 @@ EXTRA_DIST += ovsdb/ovsdb-tool.1.in
 # ovsdb-client
 bin_PROGRAMS += ovsdb/ovsdb-client
 ovsdb_ovsdb_client_SOURCES = ovsdb/ovsdb-client.c
-ovsdb_ovsdb_client_LDADD = ovsdb/libovsdb.a lib/libopenvswitch.a $(SSL_LIBS)
+ovsdb_ovsdb_client_LDADD = ovsdb/libovsdb.a lib/libopenvswitch.a $(SSL_LIBS) -lrt
 # ovsdb-client.1
 man_MANS += ovsdb/ovsdb-client.1
 DISTCLEANFILES += ovsdb/ovsdb-client.1
@@ -52,7 +52,7 @@ EXTRA_DIST += ovsdb/ovsdb-client.1.in
 # ovsdb-server
 sbin_PROGRAMS += ovsdb/ovsdb-server
 ovsdb_ovsdb_server_SOURCES = ovsdb/ovsdb-server.c
-ovsdb_ovsdb_server_LDADD = ovsdb/libovsdb.a lib/libopenvswitch.a $(SSL_LIBS)
+ovsdb_ovsdb_server_LDADD = ovsdb/libovsdb.a lib/libopenvswitch.a $(SSL_LIBS) -lrt
 # ovsdb-server.1
 man_MANS += ovsdb/ovsdb-server.1
 DISTCLEANFILES += ovsdb/ovsdb-server.1
diff --git a/ovsdb/file.c b/ovsdb/file.c
index cf5bb41..f0913e9 100644
--- a/ovsdb/file.c
+++ b/ovsdb/file.c
@@ -737,7 +737,7 @@ ovsdb_file_txn_commit(struct json *json, const char *comment,
     if (comment) {
         json_object_put_string(json, "_comment", comment);
     }
-    json_object_put(json, "_date", json_integer_create(time_now()));
+    json_object_put(json, "_date", json_integer_create(time_wall()));
 
     error = ovsdb_log_write(log, json);
     json_destroy(json);
diff --git a/tests/automake.mk b/tests/automake.mk
index 51205d9..b6266f2 100644
--- a/tests/automake.mk
+++ b/tests/automake.mk
@@ -168,23 +168,23 @@ $(srcdir)/package.m4: $(top_srcdir)/configure.ac
 
 noinst_PROGRAMS += tests/test-aes128
 tests_test_aes128_SOURCES = tests/test-aes128.c
-tests_test_aes128_LDADD = lib/libopenvswitch.a
+tests_test_aes128_LDADD = lib/libopenvswitch.a -lrt
 
 noinst_PROGRAMS += tests/test-classifier
 tests_test_classifier_SOURCES = tests/test-classifier.c
-tests_test_classifier_LDADD = lib/libopenvswitch.a
+tests_test_classifier_LDADD = lib/libopenvswitch.a -lrt
 
 noinst_PROGRAMS += tests/test-csum
 tests_test_csum_SOURCES = tests/test-csum.c
-tests_test_csum_LDADD = lib/libopenvswitch.a
+tests_test_csum_LDADD = lib/libopenvswitch.a -lrt
 
 noinst_PROGRAMS += tests/test-dir_name
 tests_test_dir_name_SOURCES = tests/test-dir_name.c
-tests_test_dir_name_LDADD = lib/libopenvswitch.a
+tests_test_dir_name_LDADD = lib/libopenvswitch.a -lrt
 
 noinst_PROGRAMS += tests/test-flows
 tests_test_flows_SOURCES = tests/test-flows.c
-tests_test_flows_LDADD = lib/libopenvswitch.a
+tests_test_flows_LDADD = lib/libopenvswitch.a -lrt
 dist_check_SCRIPTS = tests/flowgen.pl
 
 noinst_PROGRAMS += tests/test-hash
@@ -193,15 +193,15 @@ tests_test_hash_LDADD = lib/libopenvswitch.a
 
 noinst_PROGRAMS += tests/test-hmap
 tests_test_hmap_SOURCES = tests/test-hmap.c
-tests_test_hmap_LDADD = lib/libopenvswitch.a
+tests_test_hmap_LDADD = lib/libopenvswitch.a -lrt
 
 noinst_PROGRAMS += tests/test-json
 tests_test_json_SOURCES = tests/test-json.c
-tests_test_json_LDADD = lib/libopenvswitch.a
+tests_test_json_LDADD = lib/libopenvswitch.a -lrt
 
 noinst_PROGRAMS += tests/test-jsonrpc
 tests_test_jsonrpc_SOURCES = tests/test-jsonrpc.c
-tests_test_jsonrpc_LDADD = lib/libopenvswitch.a $(SSL_LIBS)
+tests_test_jsonrpc_LDADD = lib/libopenvswitch.a $(SSL_LIBS) -lrt
 
 noinst_PROGRAMS += tests/test-list
 tests_test_list_SOURCES = tests/test-list.c
@@ -209,7 +209,7 @@ tests_test_list_LDADD = lib/libopenvswitch.a
 
 noinst_PROGRAMS += tests/test-lockfile
 tests_test_lockfile_SOURCES = tests/test-lockfile.c
-tests_test_lockfile_LDADD = lib/libopenvswitch.a
+tests_test_lockfile_LDADD = lib/libopenvswitch.a -lrt
 
 noinst_PROGRAMS += tests/test-ovsdb
 tests_test_ovsdb_SOURCES = \
@@ -217,7 +217,7 @@ tests_test_ovsdb_SOURCES = \
 	tests/idltest.c \
 	tests/idltest.h
 EXTRA_DIST += tests/uuidfilt.pl tests/ovsdb-monitor-sort.pl
-tests_test_ovsdb_LDADD = ovsdb/libovsdb.a lib/libopenvswitch.a $(SSL_LIBS)
+tests_test_ovsdb_LDADD = ovsdb/libovsdb.a lib/libopenvswitch.a $(SSL_LIBS) -lrt
 
 # idltest schema and IDL
 OVSIDL_BUILT +=	tests/idltest.c tests/idltest.h tests/idltest.ovsidl
@@ -231,15 +231,15 @@ tests/idltest.c: tests/idltest.h
 
 noinst_PROGRAMS += tests/test-reconnect
 tests_test_reconnect_SOURCES = tests/test-reconnect.c
-tests_test_reconnect_LDADD = lib/libopenvswitch.a
+tests_test_reconnect_LDADD = lib/libopenvswitch.a -lrt
 
 noinst_PROGRAMS += tests/test-sha1
 tests_test_sha1_SOURCES = tests/test-sha1.c
-tests_test_sha1_LDADD = lib/libopenvswitch.a
+tests_test_sha1_LDADD = lib/libopenvswitch.a -lrt
 
 noinst_PROGRAMS += tests/test-timeval
 tests_test_timeval_SOURCES = tests/test-timeval.c
-tests_test_timeval_LDADD = lib/libopenvswitch.a
+tests_test_timeval_LDADD = lib/libopenvswitch.a -lrt
 
 noinst_PROGRAMS += tests/test-strtok_r
 tests_test_strtok_r_SOURCES = tests/test-strtok_r.c
@@ -249,19 +249,19 @@ tests_test_type_props_SOURCES = tests/test-type-props.c
 
 noinst_PROGRAMS += tests/test-dhcp-client
 tests_test_dhcp_client_SOURCES = tests/test-dhcp-client.c
-tests_test_dhcp_client_LDADD = lib/libopenvswitch.a
+tests_test_dhcp_client_LDADD = lib/libopenvswitch.a -lrt
 
 noinst_PROGRAMS += tests/test-stp
 tests_test_stp_SOURCES = tests/test-stp.c
-tests_test_stp_LDADD = lib/libopenvswitch.a
+tests_test_stp_LDADD = lib/libopenvswitch.a -lrt
 
 noinst_PROGRAMS += tests/test-uuid
 tests_test_uuid_SOURCES = tests/test-uuid.c
-tests_test_uuid_LDADD = lib/libopenvswitch.a
+tests_test_uuid_LDADD = lib/libopenvswitch.a -lrt
 
 noinst_PROGRAMS += tests/test-vconn
 tests_test_vconn_SOURCES = tests/test-vconn.c
-tests_test_vconn_LDADD = lib/libopenvswitch.a $(SSL_LIBS)
+tests_test_vconn_LDADD = lib/libopenvswitch.a $(SSL_LIBS) -lrt
 EXTRA_DIST += \
 	tests/testpki-cacert.pem \
 	tests/testpki-cert.pem \
diff --git a/tests/test-timeval.c b/tests/test-timeval.c
index 533f81a..f0552f8 100644
--- a/tests/test-timeval.c
+++ b/tests/test-timeval.c
@@ -48,10 +48,11 @@ do_test(void)
      * setitimer()).  Then ensure that, if time has really advanced by
      * TIME_UPDATE_INTERVAL, then time_msec() reports that it advanced.
      */
-    long long int start_time_msec;
+    long long int start_time_msec, start_time_wall;
     long long int start_gtod;
 
     start_time_msec = time_msec();
+    start_time_wall = time_wall_msec();
     start_gtod = gettimeofday_in_msec();
     for (;;) {
         /* Wait up to 1 second.  Using select() to do the timeout avoids
@@ -70,6 +71,7 @@ do_test(void)
 
         if (gettimeofday_in_msec() - start_gtod >= TIME_UPDATE_INTERVAL) {
             assert(time_msec() - start_time_msec >= TIME_UPDATE_INTERVAL);
+            assert(time_wall_msec() - start_time_wall >= TIME_UPDATE_INTERVAL);
             break;
         }
     }
diff --git a/utilities/automake.mk b/utilities/automake.mk
index c5bf98f..4998eee 100644
--- a/utilities/automake.mk
+++ b/utilities/automake.mk
@@ -50,32 +50,33 @@ man_MANS += \
 	utilities/ovs-vsctl.8
 
 utilities_ovs_appctl_SOURCES = utilities/ovs-appctl.c
-utilities_ovs_appctl_LDADD = lib/libopenvswitch.a
+utilities_ovs_appctl_LDADD = lib/libopenvswitch.a -lrt
 
 utilities_ovs_controller_SOURCES = utilities/ovs-controller.c
-utilities_ovs_controller_LDADD = lib/libopenvswitch.a $(SSL_LIBS)
+utilities_ovs_controller_LDADD = lib/libopenvswitch.a $(SSL_LIBS) -lrt
 
 utilities_ovs_discover_SOURCES = utilities/ovs-discover.c
-utilities_ovs_discover_LDADD = lib/libopenvswitch.a
+utilities_ovs_discover_LDADD = lib/libopenvswitch.a -lrt
 
 utilities_ovs_dpctl_SOURCES = utilities/ovs-dpctl.c
-utilities_ovs_dpctl_LDADD = lib/libopenvswitch.a
+utilities_ovs_dpctl_LDADD = lib/libopenvswitch.a -lrt
 
 utilities_ovs_kill_SOURCES = utilities/ovs-kill.c
-utilities_ovs_kill_LDADD = lib/libopenvswitch.a
+utilities_ovs_kill_LDADD = lib/libopenvswitch.a -lrt
 
 utilities_ovs_ofctl_SOURCES = utilities/ovs-ofctl.c
-utilities_ovs_ofctl_LDADD = lib/libopenvswitch.a $(SSL_LIBS)
+utilities_ovs_ofctl_LDADD = lib/libopenvswitch.a $(SSL_LIBS) -lrt
 
 utilities_ovs_openflowd_SOURCES = utilities/ovs-openflowd.c
 utilities_ovs_openflowd_LDADD = \
 	ofproto/libofproto.a \
 	lib/libsflow.a \
 	lib/libopenvswitch.a \
-	$(SSL_LIBS)
+	$(SSL_LIBS) \
+	-lrt
 
 utilities_ovs_vsctl_SOURCES = utilities/ovs-vsctl.c vswitchd/vswitch-idl.c
-utilities_ovs_vsctl_LDADD = lib/libopenvswitch.a $(SSL_LIBS)
+utilities_ovs_vsctl_LDADD = lib/libopenvswitch.a $(SSL_LIBS) -lrt
 
 if HAVE_NETLINK
 bin_PROGRAMS += utilities/ovs-wdt
@@ -83,5 +84,5 @@ utilities_ovs_wdt_SOURCES = utilities/ovs-wdt.c
 
 noinst_PROGRAMS += utilities/nlmon
 utilities_nlmon_SOURCES = utilities/nlmon.c
-utilities_nlmon_LDADD = lib/libopenvswitch.a
+utilities_nlmon_LDADD = lib/libopenvswitch.a -lrt
 endif
diff --git a/vswitchd/automake.mk b/vswitchd/automake.mk
index 6c20191..4aee768 100644
--- a/vswitchd/automake.mk
+++ b/vswitchd/automake.mk
@@ -20,7 +20,8 @@ vswitchd_ovs_vswitchd_LDADD = \
 	ofproto/libofproto.a \
 	lib/libsflow.a \
 	lib/libopenvswitch.a \
-	$(SSL_LIBS)
+	$(SSL_LIBS) \
+	-lrt
 EXTRA_DIST += \
 	vswitchd/ovs-vswitchd.8.in \
 	vswitchd/INTERNALS
@@ -31,7 +32,7 @@ vswitchd_ovs_brcompatd_SOURCES = \
 	vswitchd/ovs-brcompatd.c \
 	vswitchd/vswitch-idl.c \
 	vswitchd/vswitch-idl.h
-vswitchd_ovs_brcompatd_LDADD = lib/libopenvswitch.a $(SSL_LIBS)
+vswitchd_ovs_brcompatd_LDADD = lib/libopenvswitch.a $(SSL_LIBS) -lrt
 endif
 EXTRA_DIST += vswitchd/ovs-brcompatd.8.in
 
diff --git a/xenserver/automake.mk b/xenserver/automake.mk
index 1340b0d..f03adca 100644
--- a/xenserver/automake.mk
+++ b/xenserver/automake.mk
@@ -28,7 +28,7 @@ EXTRA_DIST += \
 
 noinst_PROGRAMS += xenserver/ovs-xenserverd
 xenserver_ovs_xenserverd_SOURCES = xenserver/ovs-xenserverd.c
-xenserver_ovs_xenserverd_LDADD = lib/libopenvswitch.a
+xenserver_ovs_xenserverd_LDADD = lib/libopenvswitch.a -lrt
 
 man_MANS += xenserver/ovs-xenserverd.8
 DISTCLEANFILES += xenserver/ovs-xenserverd.8
-- 
1.7.0.4





More information about the dev mailing list