Add portable time abstraction (#738).  Fixes #253.

From author's notes (@ben-foxmore):

The current usage of gettimeofday causes issues for us when performing
tests shortly after restarting a system. In our setup, this occurs
often as we restart the system before each test to ensure reliable
results. We already maintain our own version of iperf for some subtle
changes, but this change feels like it might be useful to upstream.
(It's also a reasonable size change, so we'd prefer not maintain it
with each new version of iperf.)

It uses clock_gettime on systems that have it available, and falls
back to gettimeofday when it's not. These two options use different
structures for storing time - clock_gettime uses timespec, and
gettimeofday uses timeval. To provide abstraction to which one is
available, a separate iperf_time struct is defined to store time.

timespec has nanosecond accuracy, while timeval only has microseconds.
For the purposes of iperf, I don't think nanosecond accuracy is
neccesary, so iperf_time only uses microseconds, throwing away any
additional accuracy. Currently I have used the MONOTONIC clock, as I
think we only need a consistent time interval measure.
diff --git a/configure b/configure
index 0fadd03..9f9023e 100755
--- a/configure
+++ b/configure
@@ -13111,6 +13111,75 @@
 
 fi
 
+# Check if we need -lrt for clock_gettime
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing clock_gettime" >&5
+$as_echo_n "checking for library containing clock_gettime... " >&6; }
+if ${ac_cv_search_clock_gettime+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char clock_gettime ();
+int
+main ()
+{
+return clock_gettime ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' rt posix4; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_clock_gettime=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if ${ac_cv_search_clock_gettime+:} false; then :
+  break
+fi
+done
+if ${ac_cv_search_clock_gettime+:} false; then :
+
+else
+  ac_cv_search_clock_gettime=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_clock_gettime" >&5
+$as_echo "$ac_cv_search_clock_gettime" >&6; }
+ac_res=$ac_cv_search_clock_gettime
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+# Check for clock_gettime support
+for ac_func in clock_gettime
+do :
+  ac_fn_c_check_func "$LINENO" "clock_gettime" "ac_cv_func_clock_gettime"
+if test "x$ac_cv_func_clock_gettime" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_CLOCK_GETTIME 1
+_ACEOF
+
+fi
+done
+
 
 ac_config_files="$ac_config_files Makefile src/Makefile src/version.h examples/Makefile iperf3.spec"
 
diff --git a/configure.ac b/configure.ac
index c00aabc..7e36a1d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -189,5 +189,9 @@
     AC_DEFINE([HAVE_SO_MAX_PACING_RATE], [1], [Have SO_MAX_PACING_RATE sockopt.])
 fi
 
+# Check if we need -lrt for clock_gettime
+AC_SEARCH_LIBS(clock_gettime, [rt posix4])
+# Check for clock_gettime support
+AC_CHECK_FUNCS([clock_gettime])
 
 AC_OUTPUT([Makefile src/Makefile src/version.h examples/Makefile iperf3.spec])
diff --git a/src/Makefile.am b/src/Makefile.am
index e95722d..5be8562 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -31,7 +31,9 @@
                         iperf_sctp.h \
                         iperf_util.c \
                         iperf_util.h \
-                        dscp.c \
+                        iperf_time.c \
+                        iperf_time.h \
+			dscp.c \
                         net.c \
                         net.h \
                         portable_endian.h \
diff --git a/src/Makefile.in b/src/Makefile.in
index a584c59..619cd45 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -147,7 +147,8 @@
 am_libiperf_la_OBJECTS = cjson.lo iperf_api.lo iperf_error.lo \
 	iperf_auth.lo iperf_client_api.lo iperf_locale.lo \
 	iperf_server_api.lo iperf_tcp.lo iperf_udp.lo iperf_sctp.lo \
-	iperf_util.lo dscp.lo net.lo tcp_info.lo timer.lo units.lo
+	iperf_util.lo iperf_time.lo dscp.lo net.lo tcp_info.lo \
+	timer.lo units.lo
 libiperf_la_OBJECTS = $(am_libiperf_la_OBJECTS)
 AM_V_lt = $(am__v_lt_@AM_V@)
 am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
@@ -164,8 +165,9 @@
 	iperf_auth.c iperf_client_api.c iperf_locale.c iperf_locale.h \
 	iperf_server_api.c iperf_tcp.c iperf_tcp.h iperf_udp.c \
 	iperf_udp.h iperf_sctp.c iperf_sctp.h iperf_util.c \
-	iperf_util.h dscp.c net.c net.h portable_endian.h queue.h \
-	tcp_info.c timer.c timer.h units.c units.h version.h
+	iperf_util.h iperf_time.c iperf_time.h dscp.c net.c net.h \
+	portable_endian.h queue.h tcp_info.c timer.c timer.h units.c \
+	units.h version.h
 am__objects_1 = iperf3_profile-cjson.$(OBJEXT) \
 	iperf3_profile-iperf_api.$(OBJEXT) \
 	iperf3_profile-iperf_error.$(OBJEXT) \
@@ -177,6 +179,7 @@
 	iperf3_profile-iperf_udp.$(OBJEXT) \
 	iperf3_profile-iperf_sctp.$(OBJEXT) \
 	iperf3_profile-iperf_util.$(OBJEXT) \
+	iperf3_profile-iperf_time.$(OBJEXT) \
 	iperf3_profile-dscp.$(OBJEXT) iperf3_profile-net.$(OBJEXT) \
 	iperf3_profile-tcp_info.$(OBJEXT) \
 	iperf3_profile-timer.$(OBJEXT) iperf3_profile-units.$(OBJEXT)
@@ -239,6 +242,7 @@
 	./$(DEPDIR)/iperf3_profile-iperf_sctp.Po \
 	./$(DEPDIR)/iperf3_profile-iperf_server_api.Po \
 	./$(DEPDIR)/iperf3_profile-iperf_tcp.Po \
+	./$(DEPDIR)/iperf3_profile-iperf_time.Po \
 	./$(DEPDIR)/iperf3_profile-iperf_udp.Po \
 	./$(DEPDIR)/iperf3_profile-iperf_util.Po \
 	./$(DEPDIR)/iperf3_profile-main.Po \
@@ -249,12 +253,12 @@
 	./$(DEPDIR)/iperf_auth.Plo ./$(DEPDIR)/iperf_client_api.Plo \
 	./$(DEPDIR)/iperf_error.Plo ./$(DEPDIR)/iperf_locale.Plo \
 	./$(DEPDIR)/iperf_sctp.Plo ./$(DEPDIR)/iperf_server_api.Plo \
-	./$(DEPDIR)/iperf_tcp.Plo ./$(DEPDIR)/iperf_udp.Plo \
-	./$(DEPDIR)/iperf_util.Plo ./$(DEPDIR)/net.Plo \
-	./$(DEPDIR)/t_api-t_api.Po ./$(DEPDIR)/t_timer-t_timer.Po \
-	./$(DEPDIR)/t_units-t_units.Po ./$(DEPDIR)/t_uuid-t_uuid.Po \
-	./$(DEPDIR)/tcp_info.Plo ./$(DEPDIR)/timer.Plo \
-	./$(DEPDIR)/units.Plo
+	./$(DEPDIR)/iperf_tcp.Plo ./$(DEPDIR)/iperf_time.Plo \
+	./$(DEPDIR)/iperf_udp.Plo ./$(DEPDIR)/iperf_util.Plo \
+	./$(DEPDIR)/net.Plo ./$(DEPDIR)/t_api-t_api.Po \
+	./$(DEPDIR)/t_timer-t_timer.Po ./$(DEPDIR)/t_units-t_units.Po \
+	./$(DEPDIR)/t_uuid-t_uuid.Po ./$(DEPDIR)/tcp_info.Plo \
+	./$(DEPDIR)/timer.Plo ./$(DEPDIR)/units.Plo
 am__mv = mv -f
 COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
 	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
@@ -639,7 +643,9 @@
                         iperf_sctp.h \
                         iperf_util.c \
                         iperf_util.h \
-                        dscp.c \
+                        iperf_time.c \
+                        iperf_time.h \
+			dscp.c \
                         net.c \
                         net.h \
                         portable_endian.h \
@@ -877,6 +883,7 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf3_profile-iperf_sctp.Po@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf3_profile-iperf_server_api.Po@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf3_profile-iperf_tcp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf3_profile-iperf_time.Po@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf3_profile-iperf_udp.Po@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf3_profile-iperf_util.Po@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf3_profile-main.Po@am__quote@ # am--include-marker
@@ -892,6 +899,7 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf_sctp.Plo@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf_server_api.Plo@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf_tcp.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf_time.Plo@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf_udp.Plo@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf_util.Plo@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net.Plo@am__quote@ # am--include-marker
@@ -1112,6 +1120,20 @@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(iperf3_profile_CFLAGS) $(CFLAGS) -c -o iperf3_profile-iperf_util.obj `if test -f 'iperf_util.c'; then $(CYGPATH_W) 'iperf_util.c'; else $(CYGPATH_W) '$(srcdir)/iperf_util.c'; fi`
 
+iperf3_profile-iperf_time.o: iperf_time.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(iperf3_profile_CFLAGS) $(CFLAGS) -MT iperf3_profile-iperf_time.o -MD -MP -MF $(DEPDIR)/iperf3_profile-iperf_time.Tpo -c -o iperf3_profile-iperf_time.o `test -f 'iperf_time.c' || echo '$(srcdir)/'`iperf_time.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/iperf3_profile-iperf_time.Tpo $(DEPDIR)/iperf3_profile-iperf_time.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='iperf_time.c' object='iperf3_profile-iperf_time.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(iperf3_profile_CFLAGS) $(CFLAGS) -c -o iperf3_profile-iperf_time.o `test -f 'iperf_time.c' || echo '$(srcdir)/'`iperf_time.c
+
+iperf3_profile-iperf_time.obj: iperf_time.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(iperf3_profile_CFLAGS) $(CFLAGS) -MT iperf3_profile-iperf_time.obj -MD -MP -MF $(DEPDIR)/iperf3_profile-iperf_time.Tpo -c -o iperf3_profile-iperf_time.obj `if test -f 'iperf_time.c'; then $(CYGPATH_W) 'iperf_time.c'; else $(CYGPATH_W) '$(srcdir)/iperf_time.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/iperf3_profile-iperf_time.Tpo $(DEPDIR)/iperf3_profile-iperf_time.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='iperf_time.c' object='iperf3_profile-iperf_time.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(iperf3_profile_CFLAGS) $(CFLAGS) -c -o iperf3_profile-iperf_time.obj `if test -f 'iperf_time.c'; then $(CYGPATH_W) 'iperf_time.c'; else $(CYGPATH_W) '$(srcdir)/iperf_time.c'; fi`
+
 iperf3_profile-dscp.o: dscp.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(iperf3_profile_CFLAGS) $(CFLAGS) -MT iperf3_profile-dscp.o -MD -MP -MF $(DEPDIR)/iperf3_profile-dscp.Tpo -c -o iperf3_profile-dscp.o `test -f 'dscp.c' || echo '$(srcdir)/'`dscp.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/iperf3_profile-dscp.Tpo $(DEPDIR)/iperf3_profile-dscp.Po
@@ -1683,6 +1705,7 @@
 	-rm -f ./$(DEPDIR)/iperf3_profile-iperf_sctp.Po
 	-rm -f ./$(DEPDIR)/iperf3_profile-iperf_server_api.Po
 	-rm -f ./$(DEPDIR)/iperf3_profile-iperf_tcp.Po
+	-rm -f ./$(DEPDIR)/iperf3_profile-iperf_time.Po
 	-rm -f ./$(DEPDIR)/iperf3_profile-iperf_udp.Po
 	-rm -f ./$(DEPDIR)/iperf3_profile-iperf_util.Po
 	-rm -f ./$(DEPDIR)/iperf3_profile-main.Po
@@ -1698,6 +1721,7 @@
 	-rm -f ./$(DEPDIR)/iperf_sctp.Plo
 	-rm -f ./$(DEPDIR)/iperf_server_api.Plo
 	-rm -f ./$(DEPDIR)/iperf_tcp.Plo
+	-rm -f ./$(DEPDIR)/iperf_time.Plo
 	-rm -f ./$(DEPDIR)/iperf_udp.Plo
 	-rm -f ./$(DEPDIR)/iperf_util.Plo
 	-rm -f ./$(DEPDIR)/net.Plo
@@ -1766,6 +1790,7 @@
 	-rm -f ./$(DEPDIR)/iperf3_profile-iperf_sctp.Po
 	-rm -f ./$(DEPDIR)/iperf3_profile-iperf_server_api.Po
 	-rm -f ./$(DEPDIR)/iperf3_profile-iperf_tcp.Po
+	-rm -f ./$(DEPDIR)/iperf3_profile-iperf_time.Po
 	-rm -f ./$(DEPDIR)/iperf3_profile-iperf_udp.Po
 	-rm -f ./$(DEPDIR)/iperf3_profile-iperf_util.Po
 	-rm -f ./$(DEPDIR)/iperf3_profile-main.Po
@@ -1781,6 +1806,7 @@
 	-rm -f ./$(DEPDIR)/iperf_sctp.Plo
 	-rm -f ./$(DEPDIR)/iperf_server_api.Plo
 	-rm -f ./$(DEPDIR)/iperf_tcp.Plo
+	-rm -f ./$(DEPDIR)/iperf_time.Plo
 	-rm -f ./$(DEPDIR)/iperf_udp.Plo
 	-rm -f ./$(DEPDIR)/iperf_util.Plo
 	-rm -f ./$(DEPDIR)/net.Plo
diff --git a/src/iperf.h b/src/iperf.h
index 5c36123..26e4f4f 100755
--- a/src/iperf.h
+++ b/src/iperf.h
@@ -61,6 +61,7 @@
 #include "timer.h"
 #include "queue.h"
 #include "cjson.h"
+#include "iperf_time.h"
 
 #if defined(HAVE_SSL)
 #include <openssl/bio.h>
@@ -72,8 +73,8 @@
 struct iperf_interval_results
 {
     iperf_size_t bytes_transferred; /* bytes transfered in this interval */
-    struct timeval interval_start_time;
-    struct timeval interval_end_time;
+    struct iperf_time interval_start_time;
+    struct iperf_time interval_end_time;
     float     interval_duration;
 
     /* for UDP */
@@ -119,9 +120,9 @@
     int stream_sum_rtt;
     int stream_count_rtt;
     int stream_max_snd_cwnd;
-    struct timeval start_time;
-    struct timeval end_time;
-    struct timeval start_time_fixed;
+    struct iperf_time start_time;
+    struct iperf_time end_time;
+    struct iperf_time start_time_fixed;
     double sender_time;
     double receiver_time;
     TAILQ_HEAD(irlisthead, iperf_interval_results) interval_results;
diff --git a/src/iperf_api.c b/src/iperf_api.c
index 18fde62..d6c4717 100755
--- a/src/iperf_api.c
+++ b/src/iperf_api.c
@@ -1304,14 +1304,16 @@
 }
 
 void
-iperf_check_throttle(struct iperf_stream *sp, struct timeval *nowP)
+iperf_check_throttle(struct iperf_stream *sp, struct iperf_time *nowP)
 {
+    struct iperf_time temp_time;
     double seconds;
     uint64_t bits_per_second;
 
     if (sp->test->done)
         return;
-    seconds = timeval_diff(&sp->result->start_time_fixed, nowP);
+    iperf_time_diff(&sp->result->start_time_fixed, nowP, &temp_time);
+    seconds = iperf_time_in_secs(&temp_time);
     bits_per_second = sp->result->bytes_sent * 8 / seconds;
     if (bits_per_second < sp->test->settings->rate) {
         sp->green_light = 1;
@@ -1327,7 +1329,7 @@
 {
     register int multisend, r, streams_active;
     register struct iperf_stream *sp;
-    struct timeval now;
+    struct iperf_time now;
 
     /* Can we do multisend mode? */
     if (test->settings->burst != 0)
@@ -1339,7 +1341,7 @@
 
     for (; multisend > 0; --multisend) {
 	if (test->settings->rate != 0 && test->settings->burst == 0)
-	    gettimeofday(&now, NULL);
+	    iperf_time_now(&now);
 	streams_active = 0;
 	SLIST_FOREACH(sp, &test->streams, streams) {
 	    if ((sp->green_light &&
@@ -1365,7 +1367,7 @@
 	    break;
     }
     if (test->settings->burst != 0) {
-	gettimeofday(&now, NULL);
+	iperf_time_now(&now);
 	SLIST_FOREACH(sp, &test->streams, streams)
 	    iperf_check_throttle(sp, &now);
     }
@@ -1401,7 +1403,7 @@
 int
 iperf_init_test(struct iperf_test *test)
 {
-    struct timeval now;
+    struct iperf_time now;
     struct iperf_stream *sp;
 
     if (test->protocol->init) {
@@ -1410,7 +1412,7 @@
     }
 
     /* Init each stream. */
-    if (gettimeofday(&now, NULL) < 0) {
+    if (iperf_time_now(&now) < 0) {
 	i_errno = IEINITTEST;
 	return -1;
     }
@@ -1425,7 +1427,7 @@
 }
 
 static void
-send_timer_proc(TimerClientData client_data, struct timeval *nowP)
+send_timer_proc(TimerClientData client_data, struct iperf_time *nowP)
 {
     struct iperf_stream *sp = client_data.p;
 
@@ -1439,11 +1441,11 @@
 int
 iperf_create_send_timers(struct iperf_test * test)
 {
-    struct timeval now;
+    struct iperf_time now;
     struct iperf_stream *sp;
     TimerClientData cd;
 
-    if (gettimeofday(&now, NULL) < 0) {
+    if (iperf_time_now(&now) < 0) {
 	i_errno = IEINITTEST;
 	return -1;
     }
@@ -1451,7 +1453,7 @@
         sp->green_light = 1;
 	if (test->settings->rate != 0) {
 	    cd.p = sp;
-	    sp->send_timer = tmr_create((struct timeval*) 0, send_timer_proc, cd, test->settings->pacing_timer, 1);
+	    sp->send_timer = tmr_create(NULL, send_timer_proc, cd, test->settings->pacing_timer, 1);
 	    if (sp->send_timer == NULL) {
 		i_errno = IEINITTEST;
 		return -1;
@@ -1749,6 +1751,7 @@
     int sender_has_retransmits;
     iperf_size_t bytes_transferred;
     int retransmits;
+    struct iperf_time temp_time;
     double start_time, end_time;
 
     j = cJSON_CreateObject();
@@ -1818,8 +1821,10 @@
 		    cJSON_AddNumberToObject(j_stream, "errors", sp->cnt_error);
 		    cJSON_AddNumberToObject(j_stream, "packets", sp->packet_count);
 
-		    start_time = timeval_diff(&sp->result->start_time, &sp->result->start_time);
-		    end_time = timeval_diff(&sp->result->start_time, &sp->result->end_time);
+		    iperf_time_diff(&sp->result->start_time, &sp->result->start_time, &temp_time);
+		    start_time = iperf_time_in_secs(&temp_time);
+		    iperf_time_diff(&sp->result->start_time, &sp->result->end_time, &temp_time);
+		    end_time = iperf_time_in_secs(&temp_time);
 		    cJSON_AddNumberToObject(j_stream, "start_time", start_time);
 		    cJSON_AddNumberToObject(j_stream, "end_time", end_time);
 
@@ -2490,13 +2495,13 @@
 void
 iperf_reset_stats(struct iperf_test *test)
 {
-    struct timeval now;
+    struct iperf_time now;
     struct iperf_stream *sp;
     struct iperf_stream_result *rp;
 
     test->bytes_sent = 0;
     test->blocks_sent = 0;
-    gettimeofday(&now, NULL);
+    iperf_time_now(&now);
     SLIST_FOREACH(sp, &test->streams, streams) {
 	sp->omitted_packet_count = sp->packet_count;
         sp->omitted_cnt_error = sp->cnt_error;
@@ -2529,6 +2534,7 @@
     struct iperf_stream *sp;
     struct iperf_stream_result *rp = NULL;
     struct iperf_interval_results *irp, temp;
+    struct iperf_time temp_time;
 
     temp.omitted = test->omitting;
     SLIST_FOREACH(sp, &test->streams, streams) {
@@ -2539,14 +2545,14 @@
 	irp = TAILQ_LAST(&rp->interval_results, irlisthead);
         /* result->end_time contains timestamp of previous interval */
         if ( irp != NULL ) /* not the 1st interval */
-            memcpy(&temp.interval_start_time, &rp->end_time, sizeof(struct timeval));
+            memcpy(&temp.interval_start_time, &rp->end_time, sizeof(struct iperf_time));
         else /* or use timestamp from beginning */
-            memcpy(&temp.interval_start_time, &rp->start_time, sizeof(struct timeval));
+            memcpy(&temp.interval_start_time, &rp->start_time, sizeof(struct iperf_time));
         /* now save time of end of this interval */
-        gettimeofday(&rp->end_time, NULL);
-        memcpy(&temp.interval_end_time, &rp->end_time, sizeof(struct timeval));
-        temp.interval_duration = timeval_diff(&temp.interval_start_time, &temp.interval_end_time);
-        //temp.interval_duration = timeval_diff(&temp.interval_start_time, &temp.interval_end_time);
+        iperf_time_now(&rp->end_time);
+        memcpy(&temp.interval_end_time, &rp->end_time, sizeof(struct iperf_time));
+        iperf_time_diff(&temp.interval_start_time, &temp.interval_end_time, &temp_time);
+        temp.interval_duration = iperf_time_in_secs(&temp_time);
 	if (test->protocol->id == Ptcp) {
 	    if ( has_tcpinfo()) {
 		save_tcpinfo(sp, &temp);
@@ -2613,6 +2619,7 @@
     double bandwidth;
     int retransmits = 0;
     double start_time, end_time;
+    struct iperf_time temp_time;
     cJSON *json_interval;
     cJSON *json_interval_streams;
     int total_packets = 0, lost_packets = 0;
@@ -2635,8 +2642,8 @@
     SLIST_FOREACH(sp, &test->streams, streams) {
 	irp = TAILQ_LAST(&sp->result->interval_results, irlisthead);
 	if (irp) {
-	    double interval_len = timeval_diff(&irp->interval_start_time,
-					       &irp->interval_end_time);
+	    iperf_time_diff(&irp->interval_start_time, &irp->interval_end_time, &temp_time);
+	    double interval_len = iperf_time_in_secs(&temp_time);
 	    if (test->debug) {
 		printf("interval_len %f bytes_transferred %" PRIu64 "\n", interval_len, irp->bytes_transferred);
 	    }
@@ -2701,14 +2708,16 @@
         sp = SLIST_FIRST(&test->streams); /* reset back to 1st stream */
 	/* Only do this of course if there was a first stream */
 	if (sp) {
-        irp = TAILQ_LAST(&sp->result->interval_results, irlisthead);    /* use 1st stream for timing info */
+	    irp = TAILQ_LAST(&sp->result->interval_results, irlisthead);    /* use 1st stream for timing info */
 
-        unit_snprintf(ubuf, UNIT_LEN, (double) bytes, 'A');
-	bandwidth = (double) bytes / (double) irp->interval_duration;
-        unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
+	    unit_snprintf(ubuf, UNIT_LEN, (double) bytes, 'A');
+	    bandwidth = (double) bytes / (double) irp->interval_duration;
+	    unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
 
-        start_time = timeval_diff(&sp->result->start_time,&irp->interval_start_time);
-        end_time = timeval_diff(&sp->result->start_time,&irp->interval_end_time);
+	    iperf_time_diff(&sp->result->start_time,&irp->interval_start_time, &temp_time);
+	    start_time = iperf_time_in_secs(&temp_time);
+	    iperf_time_diff(&sp->result->start_time,&irp->interval_end_time, &temp_time);
+	    end_time = iperf_time_in_secs(&temp_time);
 	if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
 	    if (test->sender_has_retransmits == 1) {
 		/* Interval sum, TCP with retransmits. */
@@ -2770,6 +2779,7 @@
     iperf_size_t bytes_received, total_received = 0;
     double start_time, end_time = 0.0, avg_jitter = 0.0, lost_percent = 0.0;
     double sender_time = 0.0, receiver_time = 0.0;
+    struct iperf_time temp_time;
     double bandwidth;
 
     /* print final summary for all intervals */
@@ -2807,7 +2817,8 @@
      * basically emulating what iperf 3.1 did.
      */
     if (sp) {
-    end_time = timeval_diff(&sp->result->start_time, &sp->result->end_time);
+    iperf_time_diff(&sp->result->start_time, &sp->result->end_time, &temp_time);
+    end_time = iperf_time_in_secs(&temp_time);
     if (test->sender) {
 	sp->result->sender_time = end_time;
 	if (sp->result->receiver_time == 0.0) {
@@ -3202,6 +3213,7 @@
     char nbuf[UNIT_LEN];
     char cbuf[UNIT_LEN];
     double st = 0., et = 0.;
+    struct iperf_time temp_time;
     struct iperf_interval_results *irp = NULL;
     double bandwidth, lost_percent;
 
@@ -3217,7 +3229,7 @@
 	    ** else if there's more than one stream, print the separator;
 	    ** else nothing.
 	    */
-	    if (timeval_equals(&sp->result->start_time, &irp->interval_start_time)) {
+	    if (iperf_time_compare(&sp->result->start_time, &irp->interval_start_time) == 0) {
 		if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
 		    if (test->sender_has_retransmits == 1)
 			iperf_printf(test, "%s", report_bw_retrans_cwnd_header);
@@ -3243,8 +3255,10 @@
     }
     unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
     
-    st = timeval_diff(&sp->result->start_time, &irp->interval_start_time);
-    et = timeval_diff(&sp->result->start_time, &irp->interval_end_time);
+    iperf_time_diff(&sp->result->start_time, &irp->interval_start_time, &temp_time);
+    st = iperf_time_in_secs(&temp_time);
+    iperf_time_diff(&sp->result->start_time, &irp->interval_end_time, &temp_time);
+    et = iperf_time_in_secs(&temp_time);
     
     if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
 	if (test->sender_has_retransmits == 1) {
diff --git a/src/iperf_api.h b/src/iperf_api.h
index 82322ef..54936ab 100755
--- a/src/iperf_api.h
+++ b/src/iperf_api.h
@@ -42,6 +42,7 @@
 struct iperf_stream_result;
 struct iperf_interval_results;
 struct iperf_stream;
+struct iperf_time;
 
 /* default settings */
 #define Ptcp SOCK_STREAM
@@ -247,7 +248,7 @@
 void build_tcpinfo_message(struct iperf_interval_results *r, char *message);
 
 int iperf_set_send_state(struct iperf_test *test, signed char state);
-void iperf_check_throttle(struct iperf_stream *sp, struct timeval *nowP);
+void iperf_check_throttle(struct iperf_stream *sp, struct iperf_time *nowP);
 int iperf_send(struct iperf_test *, fd_set *) /* __attribute__((hot)) */;
 int iperf_recv(struct iperf_test *, fd_set *);
 void iperf_catch_sigend(void (*handler)(int));
diff --git a/src/iperf_client_api.c b/src/iperf_client_api.c
index 3ca6b06..aca6826 100644
--- a/src/iperf_client_api.c
+++ b/src/iperf_client_api.c
@@ -41,6 +41,7 @@
 #include "iperf_api.h"
 #include "iperf_util.h"
 #include "iperf_locale.h"
+#include "iperf_time.h"
 #include "net.h"
 #include "timer.h"
 
@@ -116,7 +117,7 @@
 }
 
 static void
-test_timer_proc(TimerClientData client_data, struct timeval *nowP)
+test_timer_proc(TimerClientData client_data, struct iperf_time *nowP)
 {
     struct iperf_test *test = client_data.p;
 
@@ -125,7 +126,7 @@
 }
 
 static void
-client_stats_timer_proc(TimerClientData client_data, struct timeval *nowP)
+client_stats_timer_proc(TimerClientData client_data, struct iperf_time *nowP)
 {
     struct iperf_test *test = client_data.p;
 
@@ -136,7 +137,7 @@
 }
 
 static void
-client_reporter_timer_proc(TimerClientData client_data, struct timeval *nowP)
+client_reporter_timer_proc(TimerClientData client_data, struct iperf_time *nowP)
 {
     struct iperf_test *test = client_data.p;
 
@@ -149,10 +150,10 @@
 static int
 create_client_timers(struct iperf_test * test)
 {
-    struct timeval now;
+    struct iperf_time now;
     TimerClientData cd;
 
-    if (gettimeofday(&now, NULL) < 0) {
+    if (iperf_time_now(&now) < 0) {
 	i_errno = IEINITTEST;
 	return -1;
     }
@@ -184,7 +185,7 @@
 }
 
 static void
-client_omit_timer_proc(TimerClientData client_data, struct timeval *nowP)
+client_omit_timer_proc(TimerClientData client_data, struct iperf_time *nowP)
 {
     struct iperf_test *test = client_data.p;
 
@@ -204,14 +205,14 @@
 static int
 create_client_omit_timer(struct iperf_test * test)
 {
-    struct timeval now;
+    struct iperf_time now;
     TimerClientData cd;
 
     if (test->omit == 0) {
 	test->omit_timer = NULL;
         test->omitting = 0;
     } else {
-	if (gettimeofday(&now, NULL) < 0) {
+	if (iperf_time_now(&now) < 0) {
 	    i_errno = IEINITTEST;
 	    return -1;
 	}
@@ -442,7 +443,7 @@
     int startup;
     int result = 0;
     fd_set read_set, write_set;
-    struct timeval now;
+    struct iperf_time now;
     struct timeval* timeout = NULL;
     struct iperf_stream *sp;
 
@@ -475,7 +476,7 @@
     while (test->state != IPERF_DONE) {
 	memcpy(&read_set, &test->read_set, sizeof(fd_set));
 	memcpy(&write_set, &test->write_set, sizeof(fd_set));
-	(void) gettimeofday(&now, NULL);
+	iperf_time_now(&now);
 	timeout = tmr_timeout(&now);
 	result = select(test->max_fd + 1, &read_set, &write_set, NULL, timeout);
 	if (result < 0 && errno != EINTR) {
@@ -516,7 +517,7 @@
 	    }
 
             /* Run the timers. */
-            (void) gettimeofday(&now, NULL);
+            iperf_time_now(&now);
             tmr_run(&now);
 
 	    /* Is the test done yet? */
diff --git a/src/iperf_config.h.in b/src/iperf_config.h.in
index 2d13f98..e543cbd 100644
--- a/src/iperf_config.h.in
+++ b/src/iperf_config.h.in
@@ -1,5 +1,8 @@
 /* src/iperf_config.h.in.  Generated from configure.ac by autoheader.  */
 
+/* Define to 1 if you have the `clock_gettime' function. */
+#undef HAVE_CLOCK_GETTIME
+
 /* Define to 1 if you have the `cpuset_setaffinity' function. */
 #undef HAVE_CPUSET_SETAFFINITY
 
diff --git a/src/iperf_server_api.c b/src/iperf_server_api.c
index fabee60..78c7099 100644
--- a/src/iperf_server_api.c
+++ b/src/iperf_server_api.c
@@ -54,6 +54,7 @@
 #include "iperf_tcp.h"
 #include "iperf_util.h"
 #include "timer.h"
+#include "iperf_time.h"
 #include "net.h"
 #include "units.h"
 #include "iperf_util.h"
@@ -223,7 +224,7 @@
 }
 
 static void
-server_timer_proc(TimerClientData client_data, struct timeval *nowP)
+server_timer_proc(TimerClientData client_data, struct iperf_time *nowP)
 {
     struct iperf_test *test = client_data.p;
     struct iperf_stream *sp;
@@ -243,7 +244,7 @@
 }
 
 static void
-server_stats_timer_proc(TimerClientData client_data, struct timeval *nowP)
+server_stats_timer_proc(TimerClientData client_data, struct iperf_time *nowP)
 {
     struct iperf_test *test = client_data.p;
 
@@ -254,7 +255,7 @@
 }
 
 static void
-server_reporter_timer_proc(TimerClientData client_data, struct timeval *nowP)
+server_reporter_timer_proc(TimerClientData client_data, struct iperf_time *nowP)
 {
     struct iperf_test *test = client_data.p;
 
@@ -267,10 +268,10 @@
 static int
 create_server_timers(struct iperf_test * test)
 {
-    struct timeval now;
+    struct iperf_time now;
     TimerClientData cd;
 
-    if (gettimeofday(&now, NULL) < 0) {
+    if (iperf_time_now(&now) < 0) {
 	i_errno = IEINITTEST;
 	return -1;
     }
@@ -304,7 +305,7 @@
 }
 
 static void
-server_omit_timer_proc(TimerClientData client_data, struct timeval *nowP)
+server_omit_timer_proc(TimerClientData client_data, struct iperf_time *nowP)
 {   
     struct iperf_test *test = client_data.p;
 
@@ -324,14 +325,14 @@
 static int
 create_server_omit_timer(struct iperf_test * test)
 {
-    struct timeval now;
+    struct iperf_time now;
     TimerClientData cd; 
 
     if (test->omit == 0) {
 	test->omit_timer = NULL;
 	test->omitting = 0;
     } else {
-	if (gettimeofday(&now, NULL) < 0) {
+	if (iperf_time_now(&now) < 0) {
 	    i_errno = IEINITTEST;
 	    return -1; 
 	}
@@ -391,7 +392,7 @@
 #endif /* HAVE_TCP_CONGESTION */
     fd_set read_set, write_set;
     struct iperf_stream *sp;
-    struct timeval now;
+    struct iperf_time now;
     struct timeval* timeout;
 
     if (test->affinity != -1) 
@@ -428,7 +429,7 @@
         memcpy(&read_set, &test->read_set, sizeof(fd_set));
         memcpy(&write_set, &test->write_set, sizeof(fd_set));
 
-	(void) gettimeofday(&now, NULL);
+	iperf_time_now(&now);
 	timeout = tmr_timeout(&now);
         result = select(test->max_fd + 1, &read_set, &write_set, NULL, timeout);
         if (result < 0 && errno != EINTR) {
@@ -606,7 +607,7 @@
 	if (result == 0 ||
 	    (timeout != NULL && timeout->tv_sec == 0 && timeout->tv_usec == 0)) {
 	    /* Run the timers. */
-	    (void) gettimeofday(&now, NULL);
+	    iperf_time_now(&now);
 	    tmr_run(&now);
 	}
     }
diff --git a/src/iperf_time.c b/src/iperf_time.c
new file mode 100644
index 0000000..0ca3790
--- /dev/null
+++ b/src/iperf_time.c
@@ -0,0 +1,156 @@
+/*
+ * iperf, Copyright (c) 2014-2018, The Regents of the University of
+ * California, through Lawrence Berkeley National Laboratory (subject
+ * to receipt of any required approvals from the U.S. Dept. of
+ * Energy).  All rights reserved.
+ *
+ * If you have questions about your rights to use or distribute this
+ * software, please contact Berkeley Lab's Technology Transfer
+ * Department at TTD@lbl.gov.
+ *
+ * NOTICE.  This software is owned by the U.S. Department of Energy.
+ * As such, the U.S. Government has been granted for itself and others
+ * acting on its behalf a paid-up, nonexclusive, irrevocable,
+ * worldwide license in the Software to reproduce, prepare derivative
+ * works, and perform publicly and display publicly.  Beginning five
+ * (5) years after the date permission to assert copyright is obtained
+ * from the U.S. Department of Energy, and subject to any subsequent
+ * five (5) year renewals, the U.S. Government is granted for itself
+ * and others acting on its behalf a paid-up, nonexclusive,
+ * irrevocable, worldwide license in the Software to reproduce,
+ * prepare derivative works, distribute copies to the public, perform
+ * publicly and display publicly, and to permit others to do so.
+ *
+ * This code is distributed under a BSD style license, see the LICENSE
+ * file for complete information.
+ */
+
+
+#include <stddef.h>
+
+#include "iperf_config.h"
+#include "iperf_time.h"
+
+#ifdef HAVE_CLOCK_GETTIME
+
+#include <time.h>
+
+int
+iperf_time_now(struct iperf_time *time1)
+{
+    struct timespec ts;
+    int result;
+    result = clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
+    if (result == 0) {
+        time1->secs = (uint32_t) ts.tv_sec;
+        time1->usecs = (uint32_t) ts.tv_nsec / 1000;
+    }
+    return result;
+}
+
+#else
+
+#include <sys/time.h>
+
+int
+iperf_time_now(struct iperf_time *time1)
+{
+    struct timeval tv;
+    int result;
+    result = gettimeofday(&tv, NULL);
+    time1->secs = tv.tv_sec;
+    time1->usecs = tv.tv_usec;
+    return result;
+}
+
+#endif
+
+/* iperf_time_add_usecs
+ *
+ * Add a number of microseconds to a iperf_time.
+ */
+void
+iperf_time_add_usecs(struct iperf_time *time1, uint64_t usecs)
+{
+    time1->secs += usecs / 1000000L;
+    time1->usecs += usecs % 1000000L;
+    if ( time1->usecs >= 1000000L ) {
+        time1->secs += time1->usecs / 1000000L;
+        time1->usecs %= 1000000L;
+    }
+}
+
+uint64_t
+iperf_time_in_usecs(struct iperf_time *time)
+{
+    return time->secs * 1000000LL + time->usecs;
+}
+
+double
+iperf_time_in_secs(struct iperf_time *time)
+{
+    return time->secs + time->usecs / 1000000.0; 
+}
+
+/* iperf_time_compare
+ *
+ * Compare two timestamps
+ * 
+ * Returns -1 if time1 is earlier, 1 if time1 is later,
+ * or 0 if the timestamps are equal.
+ */
+int
+iperf_time_compare(struct iperf_time *time1, struct iperf_time *time2)
+{
+    if (time1->secs < time2->secs)
+        return -1;
+    if (time1->secs > time2->secs)
+        return 1;
+    if (time1->usecs < time2->usecs)
+        return -1;
+    if (time1->usecs > time2->usecs)
+        return 1;
+    return 0;
+}
+
+/* iperf_time_diff
+ *
+ * Calculates the time from time2 to time1, assuming time1 is later than time2.
+ * The diff will always be positive, so the return value should be checked
+ * to determine if time1 was earlier than time2.
+ *
+ * Returns 1 if the time1 is less than or equal to time2, otherwise 0.
+ */
+int 
+iperf_time_diff(struct iperf_time *time1, struct iperf_time *time2, struct iperf_time *diff)
+{
+    int past = 0;
+    int cmp = 0;
+
+    cmp = iperf_time_compare(time1, time2);
+    if (cmp == 0) {
+        diff->secs = 0;
+        diff->usecs = 0;
+        past = 1;
+    } 
+    else if (cmp == 1) {
+        diff->secs = time1->secs - time2->secs;
+        diff->usecs = time1->usecs;
+        if (diff->usecs < time2->usecs) {
+            diff->secs -= 1;
+            diff->usecs += 1000000;
+        }
+        diff->usecs = diff->usecs - time2->usecs;
+    } else {
+        diff->secs = time2->secs - time1->secs;
+        diff->usecs = time2->usecs;
+        if (diff->usecs < time1->usecs) {
+            diff->secs -= 1;
+            diff->usecs += 1000000;
+        }
+        diff->usecs = diff->usecs - time1->usecs;
+        past = 1;
+    }
+
+    return past;
+}
diff --git a/src/iperf_time.h b/src/iperf_time.h
new file mode 100644
index 0000000..588ee26
--- /dev/null
+++ b/src/iperf_time.h
@@ -0,0 +1,49 @@
+/*
+ * iperf, Copyright (c) 2014-2018, The Regents of the University of
+ * California, through Lawrence Berkeley National Laboratory (subject
+ * to receipt of any required approvals from the U.S. Dept. of
+ * Energy).  All rights reserved.
+ *
+ * If you have questions about your rights to use or distribute this
+ * software, please contact Berkeley Lab's Technology Transfer
+ * Department at TTD@lbl.gov.
+ *
+ * NOTICE.  This software is owned by the U.S. Department of Energy.
+ * As such, the U.S. Government has been granted for itself and others
+ * acting on its behalf a paid-up, nonexclusive, irrevocable,
+ * worldwide license in the Software to reproduce, prepare derivative
+ * works, and perform publicly and display publicly.  Beginning five
+ * (5) years after the date permission to assert copyright is obtained
+ * from the U.S. Department of Energy, and subject to any subsequent
+ * five (5) year renewals, the U.S. Government is granted for itself
+ * and others acting on its behalf a paid-up, nonexclusive,
+ * irrevocable, worldwide license in the Software to reproduce,
+ * prepare derivative works, distribute copies to the public, perform
+ * publicly and display publicly, and to permit others to do so.
+ *
+ * This code is distributed under a BSD style license, see the LICENSE
+ * file for complete information.
+ */
+#ifndef __IPERF_TIME_H
+#define __IPERF_TIME_H
+
+#include <stdint.h>
+
+struct iperf_time {
+    uint32_t secs;
+    uint32_t usecs;
+};
+
+int iperf_time_now(struct iperf_time *time1);
+
+void iperf_time_add_usecs(struct iperf_time *time1, uint64_t usecs);
+
+int iperf_time_compare(struct iperf_time *time1, struct iperf_time *time2);
+
+int iperf_time_diff(struct iperf_time *time1, struct iperf_time *time2, struct iperf_time *diff);
+
+uint64_t iperf_time_in_usecs(struct iperf_time *time);
+
+double iperf_time_in_secs(struct iperf_time *time);
+
+#endif
diff --git a/src/iperf_udp.c b/src/iperf_udp.c
index 33f367f..3d37dab 100644
--- a/src/iperf_udp.c
+++ b/src/iperf_udp.c
@@ -66,7 +66,7 @@
     int       r;
     int       size = sp->settings->blksize;
     double    transit = 0, d = 0;
-    struct timeval sent_time, arrival_time;
+    struct iperf_time sent_time, arrival_time, temp_time;
 
     r = Nread(sp->socket, sp->buffer, size, Pudp);
 
@@ -90,8 +90,8 @@
 	    sec = ntohl(sec);
 	    usec = ntohl(usec);
 	    pcount = be64toh(pcount);
-	    sent_time.tv_sec = sec;
-	    sent_time.tv_usec = usec;
+	    sent_time.secs = sec;
+	    sent_time.usecs = usec;
 	}
 	else {
 	    uint32_t pc;
@@ -101,8 +101,8 @@
 	    sec = ntohl(sec);
 	    usec = ntohl(usec);
 	    pcount = ntohl(pc);
-	    sent_time.tv_sec = sec;
-	    sent_time.tv_usec = usec;
+	    sent_time.secs = sec;
+	    sent_time.usecs = usec;
 	}
 
 	if (sp->test->debug)
@@ -163,9 +163,10 @@
 	 * computation does not require knowing the round-trip
 	 * time.
 	 */
-	gettimeofday(&arrival_time, NULL);
+	iperf_time_now(&arrival_time);
 
-	transit = timeval_diff(&sent_time, &arrival_time);
+	iperf_time_diff(&arrival_time, &sent_time, &temp_time);
+	transit = iperf_time_in_secs(&temp_time);
 	d = transit - sp->prev_transit;
 	if (d < 0)
 	    d = -d;
@@ -190,9 +191,9 @@
 {
     int r;
     int       size = sp->settings->blksize;
-    struct timeval before;
+    struct iperf_time before;
 
-    gettimeofday(&before, 0);
+    iperf_time_now(&before);
 
     ++sp->packet_count;
 
@@ -201,8 +202,8 @@
 	uint32_t  sec, usec;
 	uint64_t  pcount;
 
-	sec = htonl(before.tv_sec);
-	usec = htonl(before.tv_usec);
+	sec = htonl(before.secs);
+	usec = htonl(before.usecs);
 	pcount = htobe64(sp->packet_count);
 	
 	memcpy(sp->buffer, &sec, sizeof(sec));
@@ -214,8 +215,8 @@
 
 	uint32_t  sec, usec, pcount;
 
-	sec = htonl(before.tv_sec);
-	usec = htonl(before.tv_usec);
+	sec = htonl(before.secs);
+	usec = htonl(before.usecs);
 	pcount = htonl(sp->packet_count);
 	
 	memcpy(sp->buffer, &sec, sizeof(sec));
diff --git a/src/iperf_util.c b/src/iperf_util.c
index 3922def..c5af476 100644
--- a/src/iperf_util.c
+++ b/src/iperf_util.c
@@ -189,10 +189,10 @@
 void
 cpu_util(double pcpu[3])
 {
-    static struct timeval last;
+    static struct iperf_time last;
     static clock_t clast;
     static struct rusage rlast;
-    struct timeval temp;
+    struct iperf_time now, temp_time;
     clock_t ctemp;
     struct rusage rtemp;
     double timediff;
@@ -200,18 +200,19 @@
     double systemdiff;
 
     if (pcpu == NULL) {
-        gettimeofday(&last, NULL);
+        iperf_time_now(&last);
         clast = clock();
 	getrusage(RUSAGE_SELF, &rlast);
         return;
     }
 
-    gettimeofday(&temp, NULL);
+    iperf_time_now(&now);
     ctemp = clock();
     getrusage(RUSAGE_SELF, &rtemp);
 
-    timediff = ((temp.tv_sec * 1000000.0 + temp.tv_usec) -
-                (last.tv_sec * 1000000.0 + last.tv_usec));
+    iperf_time_diff(&now, &last, &temp_time);
+    timediff = iperf_time_in_secs(&temp_time);
+
     userdiff = ((rtemp.ru_utime.tv_sec * 1000000.0 + rtemp.ru_utime.tv_usec) -
                 (rlast.ru_utime.tv_sec * 1000000.0 + rlast.ru_utime.tv_usec));
     systemdiff = ((rtemp.ru_stime.tv_sec * 1000000.0 + rtemp.ru_stime.tv_usec) -
diff --git a/src/t_timer.c b/src/t_timer.c
index ed74672..9598594 100644
--- a/src/t_timer.c
+++ b/src/t_timer.c
@@ -35,13 +35,14 @@
 #include <sys/time.h>
 
 #include "timer.h"
+#include "iperf_time.h"
 
 
 static int flag;
 
 
 static void
-timer_proc( TimerClientData client_data, struct timeval* nowP )
+timer_proc( TimerClientData client_data, struct iperf_time* nowP )
 {
     flag = 1;
 }
@@ -53,7 +54,7 @@
     Timer *tp;
 
     flag = 0;
-    tp = tmr_create((struct timeval*) 0, timer_proc, JunkClientData, 3000000, 0);
+    tp = tmr_create(NULL, timer_proc, JunkClientData, 3000000, 0);
     if (!tp)
     {
 	printf("failed to create timer\n");
@@ -62,7 +63,7 @@
 
     sleep(2);
 
-    tmr_run((struct timeval*) 0);
+    tmr_run(NULL);
     if (flag)
     {
 	printf("timer should not have expired\n");
@@ -70,7 +71,7 @@
     }
     sleep(1);
 
-    tmr_run((struct timeval*) 0);
+    tmr_run(NULL);
     if (!flag)
     {
 	printf("timer should have expired\n");
diff --git a/src/timer.c b/src/timer.c
index bfc52e4..33923c7 100644
--- a/src/timer.c
+++ b/src/timer.c
@@ -31,7 +31,7 @@
 #include <stdlib.h>
 
 #include "timer.h"
-
+#include "iperf_time.h"
 
 static Timer* timers = NULL;
 static Timer* free_timers = NULL;
@@ -41,19 +41,19 @@
 
 
 /* This is an efficiency tweak.  All the routines that need to know the
-** current time get passed a pointer to a struct timeval.  If it's non-NULL
-** it gets used, otherwise we do our own gettimeofday() to fill it in.
-** This lets the caller avoid extraneous gettimeofday()s when efficiency
+** current time get passed a pointer to a struct iperf_time.  If it's non-NULL
+** it gets used, otherwise we do our own iperf_time_now() to fill it in.
+** This lets the caller avoid extraneous iperf_time_now()s when efficiency
 ** is needed, and not bother with the extra code when efficiency doesn't
 ** matter too much.
 */
 static void
-getnow( struct timeval* nowP, struct timeval* nowP2 )
+getnow( struct iperf_time* nowP, struct iperf_time* nowP2 )
 {
     if ( nowP != NULL )
 	*nowP2 = *nowP;
     else
-	(void) gettimeofday( nowP2, NULL );
+	iperf_time_now(nowP2);
 }
 
 
@@ -68,9 +68,7 @@
 	timers = t;
 	t->prev = t->next = NULL;
     } else {
-	if ( t->time.tv_sec < timers->time.tv_sec ||
-	     ( t->time.tv_sec == timers->time.tv_sec &&
-	       t->time.tv_usec < timers->time.tv_usec ) ) {
+	if (iperf_time_compare(&t->time, &timers->time) < 0) {
 	    /* The new timer goes at the head of the list. */
 	    t->prev = NULL;
 	    t->next = timers;
@@ -80,9 +78,7 @@
 	    /* Walk the list to find the insertion point. */
 	    for ( t2prev = timers, t2 = timers->next; t2 != NULL;
 		  t2prev = t2, t2 = t2->next ) {
-		if ( t->time.tv_sec < t2->time.tv_sec ||
-		     ( t->time.tv_sec == t2->time.tv_sec &&
-		       t->time.tv_usec < t2->time.tv_usec ) ) {
+		if (iperf_time_compare(&t->time, &t2->time) < 0) {
 		    /* Found it. */
 		    t2prev->next = t;
 		    t->prev = t2prev;
@@ -122,24 +118,12 @@
 }
 
 
-static void
-add_usecs( struct timeval* t, int64_t usecs )
-{
-    t->tv_sec += usecs / 1000000L;
-    t->tv_usec += usecs % 1000000L;
-    if ( t->tv_usec >= 1000000L ) {
-	t->tv_sec += t->tv_usec / 1000000L;
-	t->tv_usec %= 1000000L;
-    }
-}
-
-
 Timer*
 tmr_create(
-    struct timeval* nowP, TimerProc* timer_proc, TimerClientData client_data,
+    struct iperf_time* nowP, TimerProc* timer_proc, TimerClientData client_data,
     int64_t usecs, int periodic )
 {
-    struct timeval now;
+    struct iperf_time now;
     Timer* t;
 
     getnow( nowP, &now );
@@ -158,7 +142,7 @@
     t->usecs = usecs;
     t->periodic = periodic;
     t->time = now;
-    add_usecs( &t->time, usecs );
+    iperf_time_add_usecs(&t->time, usecs);
     /* Add the new timer to the active list. */
     list_add( t );
 
@@ -167,20 +151,22 @@
 
 
 struct timeval*
-tmr_timeout( struct timeval* nowP )
+tmr_timeout( struct iperf_time* nowP )
 {
-    struct timeval now;
+    struct iperf_time now, diff;
     int64_t usecs;
+    int past;
     static struct timeval timeout;
 
     getnow( nowP, &now );
     /* Since the list is sorted, we only need to look at the first timer. */
     if ( timers == NULL )
 	return NULL;
-    usecs = ( timers->time.tv_sec - now.tv_sec ) * 1000000LL +
-	    ( timers->time.tv_usec - now.tv_usec );
-    if ( usecs <= 0 )
-	usecs = 0;
+    past = iperf_time_diff(&timers->time, &now, &diff);
+    if (past)
+        usecs = 0;
+    else
+        usecs = iperf_time_in_usecs(&diff);
     timeout.tv_sec = usecs / 1000000LL;
     timeout.tv_usec = usecs % 1000000LL;
     return &timeout;
@@ -188,9 +174,9 @@
 
 
 void
-tmr_run( struct timeval* nowP )
+tmr_run( struct iperf_time* nowP )
 {
-    struct timeval now;
+    struct iperf_time now;
     Timer* t;
     Timer* next;
 
@@ -200,14 +186,12 @@
 	/* Since the list is sorted, as soon as we find a timer
 	** that isn't ready yet, we are done.
 	*/
-	if ( t->time.tv_sec > now.tv_sec ||
-	     ( t->time.tv_sec == now.tv_sec &&
-	       t->time.tv_usec > now.tv_usec ) )
+	if (iperf_time_compare(&t->time, &now) > 0)
 	    break;
 	(t->timer_proc)( t->client_data, &now );
 	if ( t->periodic ) {
 	    /* Reschedule. */
-	    add_usecs( &t->time, t->usecs );
+	    iperf_time_add_usecs(&t->time, t->usecs);
 	    list_resort( t );
 	} else
 	    tmr_cancel( t );
@@ -216,13 +200,13 @@
 
 
 void
-tmr_reset( struct timeval* nowP, Timer* t )
+tmr_reset( struct iperf_time* nowP, Timer* t )
 {
-    struct timeval now;
+    struct iperf_time now;
     
     getnow( nowP, &now );
     t->time = now;
-    add_usecs( &t->time, t->usecs );
+    iperf_time_add_usecs( &t->time, t->usecs );
     list_resort( t );
 }
 
diff --git a/src/timer.h b/src/timer.h
index 0f9c5eb..301cdf3 100644
--- a/src/timer.h
+++ b/src/timer.h
@@ -30,7 +30,8 @@
 #ifndef __TIMER_H
 #define __TIMER_H
 
-#include <sys/time.h>
+#include <time.h>
+#include "iperf_time.h"
 
 /* TimerClientData is an opaque value that tags along with a timer.  The
 ** client can use it for whatever, and it gets passed to the callback when
@@ -46,10 +47,10 @@
 extern TimerClientData JunkClientData;	/* for use when you don't care */
 
 /* The TimerProc gets called when the timer expires.  It gets passed
-** the TimerClientData associated with the timer, and a timeval in case
+** the TimerClientData associated with the timer, and a iperf_time in case
 ** it wants to schedule another timer.
 */
-typedef void TimerProc( TimerClientData client_data, struct timeval* nowP );
+typedef void TimerProc( TimerClientData client_data, struct iperf_time* nowP );
 
 /* The Timer struct. */
 typedef struct TimerStruct
@@ -58,7 +59,7 @@
     TimerClientData client_data;
     int64_t usecs;
     int periodic;
-    struct timeval time;
+    struct iperf_time time;
     struct TimerStruct* prev;
     struct TimerStruct* next;
     int hash;
@@ -66,22 +67,22 @@
 
 /* Set up a timer, either periodic or one-shot. Returns (Timer*) 0 on errors. */
 extern Timer* tmr_create(
-    struct timeval* nowP, TimerProc* timer_proc, TimerClientData client_data,
+    struct iperf_time* nowP, TimerProc* timer_proc, TimerClientData client_data,
     int64_t usecs, int periodic );
 
 /* Returns a timeout indicating how long until the next timer triggers.  You
 ** can just put the call to this routine right in your select().  Returns
 ** (struct timeval*) 0 if no timers are pending.
 */
-extern struct timeval* tmr_timeout( struct timeval* nowP ) /* __attribute__((hot)) */;
+extern struct timeval* tmr_timeout( struct iperf_time* nowP ) /* __attribute__((hot)) */;
 
 /* Run the list of timers. Your main program needs to call this every so often,
 ** or as indicated by tmr_timeout().
 */
-extern void tmr_run( struct timeval* nowP ) /* __attribute__((hot)) */;
+extern void tmr_run( struct iperf_time* nowP ) /* __attribute__((hot)) */;
 
 /* Reset the clock on a timer, to current time plus the original timeout. */
-extern void tmr_reset( struct timeval* nowP, Timer* timer );
+extern void tmr_reset( struct iperf_time* nowP, Timer* timer );
 
 /* Deschedule a timer.  Note that non-periodic timers are automatically
 ** descheduled when they run, so you don't have to call this on them.