ofp-util: Work on decoding OF1.1 flow_mods.
[openvswitch] / lib / timeval.c
index 35819edd35e938ebd49e02eda2e70dd7180131b6..d29b66187c79789441e8879e2565b23c74014c4d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira Networks.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -54,8 +54,9 @@ static struct timespec monotonic_time;
 /* The monotonic time at which the time module was initialized. */
 static long long int boot_time;
 
-/* Fixed monotonic time offset, for use by unit tests. */
-static struct timespec warp_offset;
+/* features for use by unit tests. */
+static struct timespec warp_offset; /* Offset added to monotonic_time. */
+static bool time_stopped;           /* Disables real-time updates, if true. */
 
 /* Time at which to die with SIGALRM (if not TIME_MIN). */
 static time_t deadline = TIME_MIN;
@@ -183,15 +184,17 @@ refresh_monotonic(void)
 {
     time_init();
 
-    if (monotonic_clock == CLOCK_MONOTONIC) {
-        clock_gettime(monotonic_clock, &monotonic_time);
-    } else {
-        refresh_wall_if_ticked();
-        monotonic_time = wall_time;
-    }
-    timespec_add(&monotonic_time, &monotonic_time, &warp_offset);
+    if (!time_stopped) {
+        if (monotonic_clock == CLOCK_MONOTONIC) {
+            clock_gettime(monotonic_clock, &monotonic_time);
+        } else {
+            refresh_wall_if_ticked();
+            monotonic_time = wall_time;
+        }
+        timespec_add(&monotonic_time, &monotonic_time, &warp_offset);
 
-    monotonic_tick = false;
+        monotonic_tick = false;
+    }
 }
 
 /* Forces a refresh of the current time from the kernel.  It is not usually
@@ -460,42 +463,43 @@ log_poll_interval(long long int last_wakeup)
     /* Warn if we took too much time between polls: at least 50 ms and at least
      * 8X the mean interval. */
     if (n_samples > 10 && interval > mean_interval * 8 && interval > 50 * 16) {
-        const struct rusage *last_rusage = get_recent_rusage();
-        struct rusage rusage;
-
-        getrusage(RUSAGE_SELF, &rusage);
-        VLOG_WARN("%lld ms poll interval (%lld ms user, %lld ms system) "
-                  "is over %u times the weighted mean interval %u ms "
-                  "(%u samples)",
-                  now - last_wakeup,
-                  timeval_diff_msec(&rusage.ru_utime, &last_rusage->ru_utime),
-                  timeval_diff_msec(&rusage.ru_stime, &last_rusage->ru_stime),
-                  interval / mean_interval,
-                  (mean_interval + 8) / 16, n_samples);
-        if (rusage.ru_minflt > last_rusage->ru_minflt
-            || rusage.ru_majflt > last_rusage->ru_majflt) {
-            VLOG_WARN("faults: %ld minor, %ld major",
-                      rusage.ru_minflt - last_rusage->ru_minflt,
-                      rusage.ru_majflt - last_rusage->ru_majflt);
-        }
-        if (rusage.ru_inblock > last_rusage->ru_inblock
-            || rusage.ru_oublock > last_rusage->ru_oublock) {
-            VLOG_WARN("disk: %ld reads, %ld writes",
-                      rusage.ru_inblock - last_rusage->ru_inblock,
-                      rusage.ru_oublock - last_rusage->ru_oublock);
-        }
-        if (rusage.ru_nvcsw > last_rusage->ru_nvcsw
-            || rusage.ru_nivcsw > last_rusage->ru_nivcsw) {
-            VLOG_WARN("context switches: %ld voluntary, %ld involuntary",
-                      rusage.ru_nvcsw - last_rusage->ru_nvcsw,
-                      rusage.ru_nivcsw - last_rusage->ru_nivcsw);
+        static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 3);
+
+        if (!VLOG_DROP_WARN(&rl)) {
+            const struct rusage *last_rusage = get_recent_rusage();
+            struct rusage rusage;
+
+            getrusage(RUSAGE_SELF, &rusage);
+            VLOG_WARN("%lld ms poll interval (%lld ms user, %lld ms system) "
+                      "is over %u times the weighted mean interval %u ms "
+                      "(%u samples)",
+                      now - last_wakeup,
+                      timeval_diff_msec(&rusage.ru_utime,
+                                        &last_rusage->ru_utime),
+                      timeval_diff_msec(&rusage.ru_stime,
+                                        &last_rusage->ru_stime),
+                      interval / mean_interval,
+                      (mean_interval + 8) / 16, n_samples);
+            if (rusage.ru_minflt > last_rusage->ru_minflt
+                || rusage.ru_majflt > last_rusage->ru_majflt) {
+                VLOG_WARN("faults: %ld minor, %ld major",
+                          rusage.ru_minflt - last_rusage->ru_minflt,
+                          rusage.ru_majflt - last_rusage->ru_majflt);
+            }
+            if (rusage.ru_inblock > last_rusage->ru_inblock
+                || rusage.ru_oublock > last_rusage->ru_oublock) {
+                VLOG_WARN("disk: %ld reads, %ld writes",
+                          rusage.ru_inblock - last_rusage->ru_inblock,
+                          rusage.ru_oublock - last_rusage->ru_oublock);
+            }
+            if (rusage.ru_nvcsw > last_rusage->ru_nvcsw
+                || rusage.ru_nivcsw > last_rusage->ru_nivcsw) {
+                VLOG_WARN("context switches: %ld voluntary, %ld involuntary",
+                          rusage.ru_nvcsw - last_rusage->ru_nvcsw,
+                          rusage.ru_nivcsw - last_rusage->ru_nivcsw);
+            }
         }
-
-        /* Care should be taken in the value chosen for logging.  Depending
-         * on the configuration, syslog can write changes synchronously,
-         * which can cause the coverage messages to take longer to log
-         * than the processing delay that triggered it. */
-        coverage_log(VLL_INFO, true);
+        coverage_log();
     }
 
     /* Update exponentially weighted moving average.  With these parameters, a
@@ -561,6 +565,22 @@ get_cpu_usage(void)
 \f
 /* Unixctl interface. */
 
+/* "time/stop" stops the monotonic time returned by e.g. time_msec() from
+ * advancing, except due to later calls to "time/warp". */
+static void
+timeval_stop_cb(struct unixctl_conn *conn,
+                 int argc OVS_UNUSED, const char *argv[] OVS_UNUSED,
+                 void *aux OVS_UNUSED)
+{
+    time_stopped = true;
+    unixctl_command_reply(conn, NULL);
+}
+
+/* "time/warp MSECS" advances the current monotonic time by the specified
+ * number of milliseconds.  Unless "time/stop" has also been executed, the
+ * monotonic clock continues to tick forward at the normal rate afterward.
+ *
+ * Does not affect wall clock readings. */
 static void
 timeval_warp_cb(struct unixctl_conn *conn,
                 int argc OVS_UNUSED, const char *argv[], void *aux OVS_UNUSED)
@@ -577,12 +597,14 @@ timeval_warp_cb(struct unixctl_conn *conn,
     ts.tv_sec = msecs / 1000;
     ts.tv_nsec = (msecs % 1000) * 1000 * 1000;
     timespec_add(&warp_offset, &warp_offset, &ts);
+    timespec_add(&monotonic_time, &monotonic_time, &ts);
     unixctl_command_reply(conn, "warped");
 }
 
 void
 timeval_dummy_register(void)
 {
+    unixctl_command_register("time/stop", "", 0, 0, timeval_stop_cb, NULL);
     unixctl_command_register("time/warp", "MSECS", 1, 1,
                              timeval_warp_cb, NULL);
 }