Mark Android R (rvc-dev-plus-aosp-without-vendor@6692709) as merged

Bug: 166295507
Merged-In: I278f6a7f0cb1bf0cdb54df470162ea518a816a7a
Change-Id: Ie2000c7cc15c09e5444d9effd5a23953941bd188
diff --git a/METADATA b/METADATA
index 51a13c1..8199d28 100644
--- a/METADATA
+++ b/METADATA
@@ -9,11 +9,11 @@
     type: GIT
     value: "https://github.com/esnet/iperf.git"
   }
-  version: "3.8"
+  version: "3.9"
   license_type: NOTICE
   last_upgrade_date {
     year: 2020
-    month: 7
-    day: 10
+    month: 8
+    day: 17
   }
 }
diff --git a/RELNOTES.md b/RELNOTES.md
index ae52d83..21f0801 100644
--- a/RELNOTES.md
+++ b/RELNOTES.md
@@ -1,6 +1,40 @@
 iperf3 Release Notes
 ====================
 
+iperf 3.9 2020-08-17
+--------------------
+
+* Notable user-visible changes
+
+  * A --timestamps flag has been added, which prepends a timestamp to
+    each output line.  An optional argument to this flag, which is a
+    format specification to strftime(3), allows for custom timestamp
+    formats (#909, #1028).
+
+  * A --server-bitrate-limit flag has been added as a server-side
+    command-line argument.  It allows a server to enforce a maximum
+    throughput rate; client connections that specify a higher bitrate
+    or exceed this bitrate during a test will be terminated.  The
+    bitrate is expressed in bits per second, with an optional trailing
+    slash and integer count that specifies an averaging interval over
+    which to enforce the limit (#999).
+
+  * A bug that caused increased CPU usage with the --bidir option has
+    been fixed (#1011).
+
+* Notable developer-visible changes
+
+  * Fixed various minor memory leaks (#1023).
+
+iperf 3.8.1 2020-06-10
+----------------------
+
+* Notable user-visible changes
+
+  * A regression with "make install", where the libiperf shared
+    library files were not getting installed, has been fixed (#1013 /
+    #1014).
+
 iperf 3.8 2020-06-08
 --------------------
 
@@ -32,7 +66,7 @@
 
 * Notable developer-visible changes
 
-  * The embedded version of cJSON has been updated to 1.3.17 (#978).
+  * The embedded version of cJSON has been updated to 1.7.13 (#978).
 
   * Some server authentication functions have been added to the API
     (#911).
diff --git a/aclocal.m4 b/aclocal.m4
index 9310d8b..df70996 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -1081,16 +1081,11 @@
       _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;;
     darwin1.*)
       _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
-    darwin*) # darwin 5.x on
-      # if running on 10.5 or later, the deployment target defaults
-      # to the OS version, if on x86, and 10.4, the deployment
-      # target defaults to 10.4. Don't you love it?
-      case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
-	10.0,*86*-darwin8*|10.0,*-darwin[[91]]*)
-	  _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
-	10.[[012]][[,.]]*)
+    darwin*)
+      case ${MACOSX_DEPLOYMENT_TARGET},$host in
+	10.[[012]],*|,*powerpc*)
 	  _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
-	10.*)
+	*)
 	  _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
       esac
     ;;
diff --git a/config/iperf_config_static_bin.m4 b/config/iperf_config_static_bin.m4
index c72efe5..5229394 100644
--- a/config/iperf_config_static_bin.m4
+++ b/config/iperf_config_static_bin.m4
@@ -1,8 +1,9 @@
 # Also link binaries as static
 AC_ARG_ENABLE([static-bin],
     AS_HELP_STRING([--enable-static-bin], [link iperf3 binary statically]),
-    [enable_static_bin=yes
-     AC_DISABLE_SHARED],
+    [enable_static=yes
+     enable_shared=no
+     enable_static_bin=yes],
     [:])
 AM_CONDITIONAL([ENABLE_STATIC_BIN], [test x$enable_static_bin = xno])
 
diff --git a/configure b/configure
index 1ebaffb..ee03ab2 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for iperf 3.8.
+# Generated by GNU Autoconf 2.69 for iperf 3.9.
 #
 # Report bugs to <https://github.com/esnet/iperf>.
 #
@@ -590,8 +590,8 @@
 # Identity of this package.
 PACKAGE_NAME='iperf'
 PACKAGE_TARNAME='iperf'
-PACKAGE_VERSION='3.8'
-PACKAGE_STRING='iperf 3.8'
+PACKAGE_VERSION='3.9'
+PACKAGE_STRING='iperf 3.9'
 PACKAGE_BUGREPORT='https://github.com/esnet/iperf'
 PACKAGE_URL='https://software.es.net/iperf/'
 
@@ -763,8 +763,8 @@
 ac_user_opts='
 enable_option_checking
 enable_static_bin
-enable_shared
 enable_silent_rules
+enable_shared
 enable_static
 with_pic
 enable_fast_install
@@ -1328,7 +1328,7 @@
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures iperf 3.8 to adapt to many kinds of systems.
+\`configure' configures iperf 3.9 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1398,7 +1398,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of iperf 3.8:";;
+     short | recursive ) echo "Configuration of iperf 3.9:";;
    esac
   cat <<\_ACEOF
 
@@ -1407,9 +1407,9 @@
   --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
   --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
   --enable-static-bin     link iperf3 binary statically
-  --enable-shared[=PKGS]  build shared libraries [default=no]
   --enable-silent-rules   less verbose build output (undo: "make V=1")
   --disable-silent-rules  verbose build output (undo: "make V=0")
+  --enable-shared[=PKGS]  build shared libraries [default=yes]
   --enable-static[=PKGS]  build static libraries [default=yes]
   --enable-fast-install[=PKGS]
                           optimize for fast installation [default=yes]
@@ -1516,7 +1516,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-iperf configure 3.8
+iperf configure 3.9
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1885,7 +1885,7 @@
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by iperf $as_me 3.8, which was
+It was created by iperf $as_me 3.9, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2293,38 +2293,9 @@
 # Also link binaries as static
 # Check whether --enable-static-bin was given.
 if test "${enable_static_bin+set}" = set; then :
-  enableval=$enable_static_bin; enable_static_bin=yes
-     # Check whether --enable-shared was given.
-if test "${enable_shared+set}" = set; then :
-  enableval=$enable_shared; p=${PACKAGE-default}
-    case $enableval in
-    yes) enable_shared=yes ;;
-    no) enable_shared=no ;;
-    *)
-      enable_shared=no
-      # Look at the argument we got.  We use all the common list separators.
-      lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
-      for pkg in $enableval; do
-	IFS=$lt_save_ifs
-	if test "X$pkg" = "X$p"; then
-	  enable_shared=yes
-	fi
-      done
-      IFS=$lt_save_ifs
-      ;;
-    esac
-else
-  enable_shared=no
-fi
-
-
-
-
-
-
-
-
-
+  enableval=$enable_static_bin; enable_static=yes
+     enable_shared=no
+     enable_static_bin=yes
 else
   :
 fi
@@ -2870,7 +2841,7 @@
 
 # Define the identity of the package.
  PACKAGE='iperf'
- VERSION='3.8'
+ VERSION='3.9'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -7465,16 +7436,11 @@
       _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;;
     darwin1.*)
       _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
-    darwin*) # darwin 5.x on
-      # if running on 10.5 or later, the deployment target defaults
-      # to the OS version, if on x86, and 10.4, the deployment
-      # target defaults to 10.4. Don't you love it?
-      case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
-	10.0,*86*-darwin8*|10.0,*-darwin[91]*)
-	  _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
-	10.[012][,.]*)
+    darwin*)
+      case ${MACOSX_DEPLOYMENT_TARGET},$host in
+	10.[012],*|,*powerpc*)
 	  _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
-	10.*)
+	*)
 	  _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
       esac
     ;;
@@ -7824,6 +7790,36 @@
   enable_win32_dll=no
 
 
+            # Check whether --enable-shared was given.
+if test "${enable_shared+set}" = set; then :
+  enableval=$enable_shared; p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_shared=yes ;;
+    no) enable_shared=no ;;
+    *)
+      enable_shared=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+      for pkg in $enableval; do
+	IFS=$lt_save_ifs
+	if test "X$pkg" = "X$p"; then
+	  enable_shared=yes
+	fi
+      done
+      IFS=$lt_save_ifs
+      ;;
+    esac
+else
+  enable_shared=yes
+fi
+
+
+
+
+
+
+
+
 
   # Check whether --enable-static was given.
 if test "${enable_static+set}" = set; then :
@@ -12946,9 +12942,7 @@
 # Check if enable profiling
 # Check whether --enable-profiling was given.
 if test "${enable_profiling+set}" = set; then :
-  enableval=$enable_profiling; enable_profiling=yes
-else
-  :
+  enableval=$enable_profiling;
 fi
 
  if test x$enable_profiling = xyes; then
@@ -13415,7 +13409,7 @@
 #define HAVE_NETINET_SCTP_H 1
 _ACEOF
 
-$as_echo "#define HAVE_SCTP 1" >>confdefs.h
+$as_echo "#define HAVE_SCTP_H 1" >>confdefs.h
 
 		 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing sctp_bindx" >&5
 $as_echo_n "checking for library containing sctp_bindx... " >&6; }
@@ -14573,7 +14567,7 @@
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by iperf $as_me 3.8, which was
+This file was extended by iperf $as_me 3.9, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -14640,7 +14634,7 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-iperf config.status 3.8
+iperf config.status 3.9
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
@@ -14769,9 +14763,9 @@
 sed_quote_subst='$sed_quote_subst'
 double_quote_subst='$double_quote_subst'
 delay_variable_subst='$delay_variable_subst'
-enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`'
 macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`'
 macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`'
+enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`'
 enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`'
 pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`'
 enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`'
@@ -15803,13 +15797,13 @@
 
 # ### BEGIN LIBTOOL CONFIG
 
-# Whether or not to build shared libraries.
-build_libtool_libs=$enable_shared
-
 # Which release of libtool.m4 was used?
 macro_version=$macro_version
 macro_revision=$macro_revision
 
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
 # Whether or not to build static libraries.
 build_old_libs=$enable_static
 
diff --git a/configure.ac b/configure.ac
index 25c44bb..939cf0a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -24,7 +24,7 @@
 # file for complete information.
 
 # Initialize the autoconf system for the specified tool, version and mailing list
-AC_INIT(iperf, 3.8, https://github.com/esnet/iperf, iperf, https://software.es.net/iperf/)
+AC_INIT(iperf, 3.9, https://github.com/esnet/iperf, iperf, https://software.es.net/iperf/)
 m4_include([config/ax_check_openssl.m4])
 m4_include([config/iperf_config_static_bin.m4])
 AC_LANG(C)
@@ -58,9 +58,7 @@
 
 # Check if enable profiling
 AC_ARG_ENABLE([profiling],
-    AS_HELP_STRING([--enable-profiling], [Enable iperf3 profiling binary]),
-    [enable_profiling=yes],
-    [:])
+    AS_HELP_STRING([--enable-profiling], [Enable iperf3 profiling binary]))
 AM_CONDITIONAL([ENABLE_PROFILING], [test x$enable_profiling = xyes])
 
 # Checks for header files.
@@ -119,7 +117,7 @@
 if $try_sctp; then
 AC_CHECK_HEADERS([sys/socket.h])
 AC_CHECK_HEADERS([netinet/sctp.h],
-		 AC_DEFINE([HAVE_SCTP], [1], [Have SCTP support.])
+		 AC_DEFINE([HAVE_SCTP_H], [1], [Have SCTP support.])
 		 AC_SEARCH_LIBS(sctp_bindx, [sctp])
 		 AC_CHECK_TYPES([struct sctp_assoc_value], [], [],
 				[[#include <netinet/sctp.h>]]),
diff --git a/docs/conf.py b/docs/conf.py
index 17aa556..083a3bf 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -52,10 +52,10 @@
 # built documents.
 #
 # The short X.Y version.
-version = '3.7'
+version = '3.8.1'
 # The full version, including alpha/beta/rc tags.
 
-release = '3.7'
+release = '3.8.1'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
diff --git a/docs/faq.rst b/docs/faq.rst
index c7170cc..d7d182e 100644
--- a/docs/faq.rst
+++ b/docs/faq.rst
@@ -65,7 +65,9 @@
       generation of shared libraries and link the executable
       statically.  For iperf-3.8 or later, configuring as ``configure
       --enable-static-bin`` is another, shorter way to accomplish
-      this.
+      this.  If SCTP is installed on the system it might also be
+      necessary to pass the ``--without-sctp`` flag at configure
+      time.
 
   #.  Compile as normal.
 
@@ -74,10 +76,16 @@
 
 How can I build on a system that doesn't support profiled executables?
   This problem has been noted by users attempting to build iperf3 for
-  Android systems.  There are several workarounds. In order from least
+  Android systems, as well as some recent versions of macOS.
+  There are several workarounds. In order from least
   effort to most effort:
 
-  #. Beginning with iperf-3.6, the ``--disable-profiling`` flag can be
+  #. Beginning with iperf-3.8, profiled executables are actually not
+     built by default, so this question becomes somewhat moot.  Pass
+     the ``--enable-profiling`` flag to ``configure`` to build
+     profiled executables.
+
+  #. In iperf-3.6 and iperf-3.7, the ``--disable-profiling`` flag can be
      passed to ``configure`` to disable the building of profiled
      object files and the profiled executable.
 
@@ -119,6 +127,59 @@
 iperf3 UDP does not seem to work at bandwidths less than 100Kbps. Why?
   You'll need to reduce the default packet length to get UDP rates of less that 100Kbps. Try ``-l100``.
  
+TCP throughput drops to (almost) zero during a test, what's going on?
+  A drop in throughput to almost zero, except maybe for the first
+  reported interval(s), may be related to problems in NIC TCP Offload,
+  which is used to offload TCP functionality to the NIC (see
+  https://en.wikipedia.org/wiki/TCP_offload_engine). The goal of TCP
+  Offload is to save main CPU performance, mainly in the areas of
+  segmentation and reassembly of large packets and checksum
+  computation.
+
+  When TCP packets are sent with the "Don't Fragment" flag set, which
+  is the recommended setting, segmentation is done by the TCP stack
+  based on the reported next hop MSS in the ICMP Fragmentation Needed
+  message. With TCP Offload, active segmentation is done by the NIC on
+  the sending side, which is known as TCP Segmentation offload (TSO)
+  or in Windows as Large Send Offload (LSO). It seems that there are
+  TSO/LSO implementations which for some reason ignore the reported
+  MSS and therefore don’t perform segmentation. In these cases, when
+  large packets are sent, e.g. the default iperf3 128KB (131,072
+  bytes), iperf3 will show that data was sent in the first interval,
+  but since the packets don’t get to the server, no ack is received
+  and therefore no data is sent in the following intervals. It may
+  happen that after certain timeout the main CPU will re-send the
+  packet by re-segmenting it, and in these cases data will get to the
+  server after a while. However, it seems that segmentation is not
+  automatically continued with the next packet, so the data transfer
+  rate be very low.
+
+  The recommended solution in such a case is to disable TSO/LSO, at
+  least on the relevant port. See for example:
+  https://atomicit.ca/kb/articles/slow-network-speed-windows-10/. If
+  that doesn’t help then "Don't Fragment" TCP flag may be
+  disabled. See for example:
+  https://support.microsoft.com/en-us/help/900926/recommended-tcp-ip-settings-for-wan-links-with-a-mtu-size-of-less-than. However,
+  note that disabling the “Don’t Fragment” flag may cause other
+  issues.
+
+  To test whether TSO/LSO may be the problem, do the following:
+
+  * If different machine configurations are used for the client and
+    server, try the iperf3 reverse mode (``-R``). If TSO/LSO is only
+    enabled on the client machine, this test should succeed.
+  * Reduce the sending length to a small value that should not require
+    segmentation, using the iperf3 ``-l`` option, e.g. ``-l 512``. It
+    may also help to reduce the MTU by using the iperf3 ``-M`` option,
+    e.g. ``-M 1460``.
+  * Using tools like Wireshark, identify the required MSS in the ICMP
+    Fragmentation Needed messages (if reported). Run tests with the
+    ``-l`` value set to 2 times the MSS and then 4 times, 6 times,
+    etc. With TSO/LSO issue in each test the throughput should be
+    reduced more. It may help to increase the testing time beyond the
+    default 10 seconds to better see the behavior (iperf3 ``-t``
+    option).
+
 What congestion control algorithms are supported?
   On Linux, run this command to see the available congestion control
   algorithms (note that some algorithms are packaged as kernel
diff --git a/docs/news.rst b/docs/news.rst
index 4104d36..72c0d93 100644
--- a/docs/news.rst
+++ b/docs/news.rst
@@ -1,13 +1,31 @@
 iperf3 Project News
 ===================
 
+2020-06-10:  iperf-3.8.1 released
+---------------------------------
+
+| URL:  https://downloads.es.net/pub/iperf/iperf-3.8.1.tar.gz
+| SHA256:  ``e5b080f3273a8a715a4100f13826ac2ca31cc7b1315925631b2ecf64957ded96 iperf-3.8.1.tar.gz``
+
+iperf 3.8.1 fixes a regression with ``make install`` in iperf 3.8.  It
+is otherwise identical to iperf 3.8.
+
+2020-06-08:  iperf-3.8 released
+-------------------------------
+
+| URL:  https://downloads.es.net/pub/iperf/iperf-3.8.tar.gz
+| SHA256:  ``edc1c317b0ae31925e5eb84f0295faefbaa1db3229f4693e11d954d114de4bcd  iperf-3.8.tar.gz``
+
+iperf 3.8 contains minor bugfixes and enhancements.
+
+
 2019-06-21:  iperf-3.7 released
 -------------------------------
 
 | URL:  https://downloads.es.net/pub/iperf/iperf-3.7.tar.gz
 | SHA256:  ``d846040224317caf2f75c843d309a950a7db23f9b44b94688ccbe557d6d1710c  iperf-3.7.tar.gz``
 
-iperf 3.6 adds the ``--bidir`` flag for bidirectional tests, includes
+iperf 3.7 adds the ``--bidir`` flag for bidirectional tests, includes
 some minor enhancements, and fixes a number of bugs.  More details can
 be found in the release notes.
 
diff --git a/src/iperf.h b/src/iperf.h
index 6ce77f5..5b1da46 100644
--- a/src/iperf.h
+++ b/src/iperf.h
@@ -1,5 +1,5 @@
 /*
- * iperf, Copyright (c) 2014-2019, The Regents of the University of
+ * iperf, Copyright (c) 2014-2020, 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.
@@ -68,7 +68,9 @@
 #include <openssl/evp.h>
 #endif // HAVE_SSL
 
+#if !defined(__IPERF_API_H)
 typedef uint64_t iperf_size_t;
+#endif // __IPERF_API_H
 
 struct iperf_interval_results
 {
@@ -135,7 +137,10 @@
     int       domain;               /* AF_INET or AF_INET6 */
     int       socket_bufsize;       /* window size for TCP */
     int       blksize;              /* size of read/writes (-l) */
-    uint64_t  rate;                 /* target data rate for application pacing*/
+    iperf_size_t  rate;                 /* target data rate for application pacing*/
+    iperf_size_t  bitrate_limit;   /* server's maximum allowed total data rate for all streams*/
+    double        bitrate_limit_interval;  /* interval for avaraging total data rate */
+    int           bitrate_limit_stats_per_interval;     /* calculated number of stats periods for averaging total data rate */
     uint64_t  fqrate;               /* target data rate for FQ pacing*/
     int	      pacing_timer;	    /* pacing timer in microseconds */
     int       burst;                /* packets per burst */
@@ -298,6 +303,8 @@
     int       forceflush; /* --forceflush - flushing output at every interval */
     int	      multisend;
     int	      repeating_payload;                /* --repeating-payload */
+    int       timestamps;			/* --timestamps */
+    char     *timestamp_format;
 
     char     *json_output_string; /* rendered JSON output if json_output is set */
     /* Select related parameters */
@@ -328,6 +335,11 @@
     iperf_size_t bytes_received;
     iperf_size_t blocks_received;
 
+    iperf_size_t bitrate_limit_stats_count;               /* Number of stats periods accumulated for server's total bitrate average */
+    iperf_size_t *bitrate_limit_intervals_traffic_bytes;  /* Pointer to a cyclic array that includes the last interval's bytes transferred */
+    iperf_size_t bitrate_limit_last_interval_index;       /* Index of the last interval traffic insrted into the cyclic array */
+    int          bitrate_limit_exceeded;                  /* Set by callback routine when average data rate exceeded the server's bitrate limit */
+
     char      cookie[COOKIE_SIZE];
 //    struct iperf_stream *streams;               /* pointer to list of struct stream */
     SLIST_HEAD(slisthead, iperf_stream) streams;
@@ -385,6 +397,8 @@
 #define MAX_MSS (9 * 1024)
 #define MAX_STREAMS 128
 
+#define TIMESTAMP_FORMAT "%c "
+
 extern int gerror; /* error value from getaddrinfo(3), for use in internal error handling */
 
 #endif /* !__IPERF_H */
diff --git a/src/iperf3.1 b/src/iperf3.1
index 93fe7b9..97d66ed 100644
--- a/src/iperf3.1
+++ b/src/iperf3.1
@@ -1,4 +1,4 @@
-.TH IPERF3 1 "June 2019" ESnet "User Manuals"
+.TH IPERF3 1 "July 2020" ESnet "User Manuals"
 .SH NAME
 iperf3 \- perform network throughput tests
 .SH SYNOPSIS
@@ -153,6 +153,14 @@
 force flushing output at every interval.
 Used to avoid buffering when sending output to pipe.
 .TP
+.BR --timestamps " [\fIformat\fR]"
+prepend a timestamp at the start of each output line.
+By default, timestamps have the format emitted by
+.BR ctime ( 1 ).
+Optionally, a format specification can be passed to customize the
+timestamps, see
+.BR strftime ( 3 ).
+.TP
 .BR -d ", " --debug " "
 emit debugging output.
 Primarily (perhaps exclusively) of use to developers.
@@ -177,6 +185,15 @@
 .BR -1 ", " --one-off
 handle one client connection, then exit.
 .TP
+.BR --server-bitrate-limit " \fIn\fR[KMGT]"
+set a limit on the server side, which will cause a test to abort if
+the client specifies a test of more than \fIn\fR bits per second, or
+if the average data sent or received by the client (including all data
+streams) is greater than \fIn\fR bits per second.  The default limit
+is zero, which implies no limit.  The interval over which to average
+the data rate is 5 seconds by default, but can be specified by adding
+a '/' and a number to the bitrate specifier.
+.TP
 .BR --rsa-private-key-path " \fIfile\fR"
 path to the RSA private key (not password-protected) used to decrypt 
 authentication credentials from the client (if built with OpenSSL
@@ -209,7 +226,7 @@
 Providing a shorter value may speed up detection of a down iperf3
 server.
 .TP
-.BR -b ", " --bitrate " \fIn\fR[KM]"
+.BR -b ", " --bitrate " \fIn\fR[KMGT]"
 set target bitrate to \fIn\fR bits/sec (default 1 Mbit/sec for UDP,
 unlimited for TCP/SCTP).
 If there are multiple streams (\-P flag), the throughput limit is applied
@@ -226,7 +243,7 @@
 This option replaces the \--bandwidth flag, which is now deprecated
 but (at least for now) still accepted.
 .TP
-.BR --pacing-timer " \fIn\fR[KMG]"
+.BR --pacing-timer " \fIn\fR[KMGT]"
 set pacing timer interval in microseconds (default 1000 microseconds,
 or 1 ms).
 This controls iperf3's internal pacing timer for the \-b/\--bitrate
@@ -236,7 +253,7 @@
 emitted by iperf3, but potentially at the cost of performance due to
 more frequent timer processing.
 .TP
-.BR --fq-rate " \fIn\fR[KM]"
+.BR --fq-rate " \fIn\fR[KMGT]"
 Set a rate to be used with fair-queueing based socket-level pacing,
 in bits per second.
 This pacing (if specified) will be in addition to any pacing due to
@@ -253,13 +270,13 @@
 .BR -t ", " --time " \fIn\fR"
 time in seconds to transmit for (default 10 secs)
 .TP
-.BR -n ", " --bytes " \fIn\fR[KM]"
+.BR -n ", " --bytes " \fIn\fR[KMGT]"
 number of bytes to transmit (instead of \-t)
 .TP
-.BR -k ", " --blockcount " \fIn\fR[KM]"
+.BR -k ", " --blockcount " \fIn\fR[KMGT]"
 number of blocks (packets) to transmit (instead of \-t or \-n)
 .TP
-.BR -l ", " --length " \fIn\fR[KM]"
+.BR -l ", " --length " \fIn\fR[KMGT]"
 length of buffer to read or write.  For TCP tests, the default value
 is 128KB.
 In the case of UDP, iperf3 tries to dynamically determine a reasonable
@@ -282,7 +299,7 @@
 test in both directions (normal and reverse), with both the client and
 server sending and receiving data simultaneously
 .TP
-.BR -w ", " --window " \fIn\fR[KM]"
+.BR -w ", " --window " \fIn\fR[KMGT]"
 window size / socket buffer size (this gets sent to the server and used on that side too)
 .TP
 .BR -M ", " --set-mss " \fIn\fR"
diff --git a/src/iperf_api.c b/src/iperf_api.c
index ed643b7..88fed30 100644
--- a/src/iperf_api.c
+++ b/src/iperf_api.c
@@ -57,6 +57,7 @@
 #include <sched.h>
 #include <setjmp.h>
 #include <stdarg.h>
+#include <math.h>
 
 #if defined(HAVE_CPUSET_SETAFFINITY)
 #include <sys/param.h>
@@ -76,9 +77,9 @@
 #include "iperf_api.h"
 #include "iperf_udp.h"
 #include "iperf_tcp.h"
-#if defined(HAVE_SCTP)
+#if defined(HAVE_SCTP_H)
 #include "iperf_sctp.h"
-#endif /* HAVE_SCTP */
+#endif /* HAVE_SCTP_H */
 #include "timer.h"
 
 #include "cjson.h"
@@ -119,7 +120,7 @@
 }
 
 
-void warning(char *str)
+void warning(const char *str)
 {
     fprintf(stderr, "warning: %s\n", str);
 }
@@ -164,6 +165,24 @@
 }
 
 uint64_t
+iperf_get_test_bitrate_limit(struct iperf_test *ipt)
+{
+    return ipt->settings->bitrate_limit;
+}
+
+double
+iperf_get_test_bitrate_limit_interval(struct iperf_test *ipt)
+{
+    return ipt->settings->bitrate_limit_interval;
+}
+
+int
+iperf_get_test_bitrate_limit_stats_per_interval(struct iperf_test *ipt)
+{
+    return ipt->settings->bitrate_limit_stats_per_interval;
+}
+
+uint64_t
 iperf_get_test_fqrate(struct iperf_test *ipt)
 {
     return ipt->settings->fqrate;
@@ -242,6 +261,18 @@
 }
 
 int
+iperf_get_test_timestamps(struct iperf_test *ipt)
+{
+    return ipt->timestamps;
+}
+
+const char *
+iperf_get_test_timestamp_format(struct iperf_test *ipt)
+{
+    return ipt->timestamp_format;
+}
+
+int
 iperf_get_test_repeating_payload(struct iperf_test *ipt)
 {
     return ipt->repeating_payload;
@@ -401,7 +432,7 @@
 }
 
 void
-iperf_set_test_logfile(struct iperf_test *ipt, char *logfile)
+iperf_set_test_logfile(struct iperf_test *ipt, const char *logfile)
 {
     ipt->logfile = strdup(logfile);
 }
@@ -413,6 +444,24 @@
 }
 
 void
+iperf_set_test_bitrate_limit_maximum(struct iperf_test *ipt, uint64_t total_rate)
+{
+    ipt->settings->bitrate_limit = total_rate;
+}
+
+void
+iperf_set_test_bitrate_limit_interval(struct iperf_test *ipt, uint64_t bitrate_limit_interval)
+{
+    ipt->settings->bitrate_limit_interval = bitrate_limit_interval;
+}
+
+void
+iperf_set_test_bitrate_limit_stats_per_interval(struct iperf_test *ipt, uint64_t bitrate_limit_stats_per_interval)
+{
+    ipt->settings->bitrate_limit_stats_per_interval = bitrate_limit_stats_per_interval;
+}
+
+void
 iperf_set_test_fqrate(struct iperf_test *ipt, uint64_t fqrate)
 {
     ipt->settings->fqrate = fqrate;
@@ -466,6 +515,18 @@
     ipt->repeating_payload = repeating_payload;
 }
 
+void
+iperf_set_test_timestamps(struct iperf_test *ipt, int timestamps)
+{
+    ipt->timestamps = timestamps;
+}
+
+void
+iperf_set_test_timestamp_format(struct iperf_test *ipt, const char *tf)
+{
+    ipt->timestamp_format = strdup(tf);
+}
+
 static void
 check_sender_has_retransmits(struct iperf_test *ipt)
 {
@@ -496,13 +557,13 @@
 }
 
 void
-iperf_set_test_server_hostname(struct iperf_test *ipt, char *server_hostname)
+iperf_set_test_server_hostname(struct iperf_test *ipt, const char *server_hostname)
 {
     ipt->server_hostname = strdup(server_hostname);
 }
 
 void
-iperf_set_test_template(struct iperf_test *ipt, char *tmp_template)
+iperf_set_test_template(struct iperf_test *ipt, const char *tmp_template)
 {
     ipt->tmp_template = strdup(tmp_template);
 }
@@ -557,38 +618,38 @@
 
 #if defined(HAVE_SSL)
 void
-iperf_set_test_client_username(struct iperf_test *ipt, char *client_username)
+iperf_set_test_client_username(struct iperf_test *ipt, const char *client_username)
 {
     ipt->settings->client_username = strdup(client_username);
 }
 
 void
-iperf_set_test_client_password(struct iperf_test *ipt, char *client_password)
+iperf_set_test_client_password(struct iperf_test *ipt, const char *client_password)
 {
     ipt->settings->client_password = strdup(client_password);
 }
 
 void
-iperf_set_test_client_rsa_pubkey(struct iperf_test *ipt, char *client_rsa_pubkey_base64)
+iperf_set_test_client_rsa_pubkey(struct iperf_test *ipt, const char *client_rsa_pubkey_base64)
 {
     ipt->settings->client_rsa_pubkey = load_pubkey_from_base64(client_rsa_pubkey_base64);
 }
 
 void
-iperf_set_test_server_authorized_users(struct iperf_test *ipt, char *server_authorized_users)
+iperf_set_test_server_authorized_users(struct iperf_test *ipt, const char *server_authorized_users)
 {
     ipt->server_authorized_users = strdup(server_authorized_users);
 }
 
 void
-iperf_set_test_server_rsa_privkey(struct iperf_test *ipt, char *server_rsa_privkey_base64)
+iperf_set_test_server_rsa_privkey(struct iperf_test *ipt, const char *server_rsa_privkey_base64)
 {
     ipt->server_rsa_private_key = load_privkey_from_base64(server_rsa_privkey_base64);
 }
 #endif // HAVE_SSL
 
 void
-iperf_set_test_bind_address(struct iperf_test *ipt, char *bnd_address)
+iperf_set_test_bind_address(struct iperf_test *ipt, const char *bnd_address)
 {
     ipt->bind_address = strdup(bnd_address);
 }
@@ -612,7 +673,7 @@
 }
 
 void
-iperf_set_test_extra_data(struct iperf_test *ipt, char *dat)
+iperf_set_test_extra_data(struct iperf_test *ipt, const char *dat)
 {
     ipt->extra_data = strdup(dat);
 }
@@ -816,6 +877,7 @@
         {"udp", no_argument, NULL, 'u'},
         {"bitrate", required_argument, NULL, 'b'},
         {"bandwidth", required_argument, NULL, 'b'},
+	{"server-bitrate-limit", required_argument, NULL, OPT_SERVER_BITRATE_LIMIT},
         {"time", required_argument, NULL, 't'},
         {"bytes", required_argument, NULL, 'n'},
         {"blockcount", required_argument, NULL, 'k'},
@@ -840,6 +902,7 @@
         {"omit", required_argument, NULL, 'O'},
         {"file", required_argument, NULL, 'F'},
         {"repeating-payload", no_argument, NULL, OPT_REPEATING_PAYLOAD},
+        {"timestamps", optional_argument, NULL, OPT_TIMESTAMPS},
 #if defined(HAVE_CPU_AFFINITY)
         {"affinity", required_argument, NULL, 'A'},
 #endif /* HAVE_CPU_AFFINITY */
@@ -848,7 +911,7 @@
         {"congestion", required_argument, NULL, 'C'},
         {"linux-congestion", required_argument, NULL, 'C'},
 #endif /* HAVE_TCP_CONGESTION */
-#if defined(HAVE_SCTP)
+#if defined(HAVE_SCTP_H)
         {"sctp", no_argument, NULL, OPT_SCTP},
         {"nstreams", required_argument, NULL, OPT_NUMSTREAMS},
         {"xbind", required_argument, NULL, 'X'},
@@ -968,14 +1031,14 @@
 		client_flag = 1;
                 break;
             case OPT_SCTP:
-#if defined(HAVE_SCTP)
+#if defined(HAVE_SCTP_H)
                 set_protocol(test, Psctp);
                 client_flag = 1;
                 break;
-#else /* HAVE_SCTP */
+#else /* HAVE_SCTP_H */
                 i_errno = IEUNIMP;
                 return -1;
-#endif /* HAVE_SCTP */
+#endif /* HAVE_SCTP_H */
 
             case OPT_NUMSTREAMS:
 #if defined(linux) || defined(__FreeBSD__)
@@ -1001,6 +1064,21 @@
 		rate_flag = 1;
 		client_flag = 1;
                 break;
+            case OPT_SERVER_BITRATE_LIMIT:
+		slash = strchr(optarg, '/');
+		if (slash) {
+		    *slash = '\0';
+		    ++slash;
+		    test->settings->bitrate_limit_interval = atof(slash);
+		    if (test->settings->bitrate_limit_interval != 0 &&	/* Using same Max/Min limits as for Stats Interval */
+		        (test->settings->bitrate_limit_interval < MIN_INTERVAL || test->settings->bitrate_limit_interval > MAX_INTERVAL) ) {
+			i_errno = IETOTALINTERVAL;
+			return -1;
+		    }
+		}
+		test->settings->bitrate_limit = unit_atof_rate(optarg);
+		server_flag = 1;
+	        break;
             case 't':
                 test->duration = atoi(optarg);
                 if (test->duration > MAX_TIME) {
@@ -1149,6 +1227,15 @@
                 test->repeating_payload = 1;
                 client_flag = 1;
                 break;
+            case OPT_TIMESTAMPS:
+                iperf_set_test_timestamps(test, 1);
+		if (optarg) {
+		    iperf_set_test_timestamp_format(test, optarg);
+		}
+		else {
+		    iperf_set_test_timestamp_format(test, TIMESTAMP_FORMAT);
+		}
+                break;
             case 'O':
                 test->omit = atoi(optarg);
                 if (test->omit < 0 || test->omit > 60) {
@@ -1292,6 +1379,7 @@
         if ((client_password = getenv("IPERF3_PASSWORD")) != NULL)
              client_password = strdup(client_password);
         else if (iperf_getpass(&client_password, &s, stdin) < 0){
+            i_errno = IESETCLIENTAUTH;
             return -1;
         } 
         if (test_load_pubkey_from_file(client_rsa_public_key) < 0){
@@ -1374,6 +1462,13 @@
         return -1;
     }
 
+    /* Set Total-rate average interval to multiplicity of State interval */
+    if (test->settings->bitrate_limit_interval != 0) {
+	test->settings->bitrate_limit_stats_per_interval =
+	    (test->settings->bitrate_limit_interval <= test->stats_interval ?
+	    1 : round(test->settings->bitrate_limit_interval/test->stats_interval) );
+    }
+
     /* Show warning if JSON output is used with explicit report format */
     if ((test->json_output) && (test->settings->unit_format != 'a')) {
         warning("Report format (-f) flag ignored with JSON output (-J)");
@@ -1436,6 +1531,45 @@
     }
 }
 
+/* Verify that average traffic is not greater than the specifid limit */
+void
+iperf_check_total_rate(struct iperf_test *test, iperf_size_t last_interval_bytes_transferred)
+{
+    double seconds;
+    uint64_t bits_per_second;
+    iperf_size_t total_bytes;
+    int i;
+
+    if (test->done || test->settings->bitrate_limit == 0)    // Continue only if check should be done
+        return;
+    
+    /* Add last inetrval's transffered bytes to the array */
+    if (++test->bitrate_limit_last_interval_index >= test->settings->bitrate_limit_stats_per_interval)
+        test->bitrate_limit_last_interval_index = 0;
+    test->bitrate_limit_intervals_traffic_bytes[test->bitrate_limit_last_interval_index] = last_interval_bytes_transferred;
+
+    /* Ensure that enough stats periods passed to allow averaging throughput */
+    test->bitrate_limit_stats_count += 1;
+    if (test->bitrate_limit_stats_count < test->settings->bitrate_limit_stats_per_interval)
+        return;
+ 
+     /* Calculating total bytes traffic to be averaged */
+    for (total_bytes = 0, i = 0; i < test->settings->bitrate_limit_stats_per_interval; i++) {
+        total_bytes += test->bitrate_limit_intervals_traffic_bytes[i];
+    }
+
+    seconds = test->stats_interval * test->settings->bitrate_limit_stats_per_interval;
+    bits_per_second = total_bytes * 8 / seconds;
+    if (test->debug) {
+        iperf_printf(test,"Interval %" PRIu64 " - throughput %" PRIu64 " bps (limit %" PRIu64 ")\n", test->bitrate_limit_stats_count, bits_per_second, test->settings->bitrate_limit);
+    }
+
+    if (bits_per_second  > test->settings->bitrate_limit) {
+	iperf_err(test, "Total throughput of %" PRIu64 " bps exceeded %" PRIu64 " bps limit", bits_per_second, test->settings->bitrate_limit);
+	test->bitrate_limit_exceeded = 1;
+    }
+}
+
 int
 iperf_send(struct iperf_test *test, fd_set *write_setP)
 {
@@ -1480,7 +1614,8 @@
     if (test->settings->burst != 0) {
 	iperf_time_now(&now);
 	SLIST_FOREACH(sp, &test->streams, streams)
-	    iperf_check_throttle(sp, &now);
+	    if (sp->sender)
+	        iperf_check_throttle(sp, &now);
     }
     if (write_setP != NULL)
 	SLIST_FOREACH(sp, &test->streams, streams)
@@ -1562,7 +1697,7 @@
     }
     SLIST_FOREACH(sp, &test->streams, streams) {
         sp->green_light = 1;
-	if (test->settings->rate != 0) {
+	if (test->settings->rate != 0 && sp->sender) {
 	    cd.p = sp;
 	    sp->send_timer = tmr_create(NULL, send_timer_proc, cd, test->settings->pacing_timer, 1);
 	    if (sp->send_timer == NULL) {
@@ -1654,6 +1789,7 @@
             }
             return -1;
         }
+
         FD_SET(s, &test->read_set);
         test->max_fd = (s > test->max_fd) ? s : test->max_fd;
         test->prot_listener = s;
@@ -2289,6 +2425,14 @@
     }
     memset(test->settings, 0, sizeof(struct iperf_settings));
 
+    test->bitrate_limit_intervals_traffic_bytes = (iperf_size_t *) malloc(sizeof(iperf_size_t) * MAX_INTERVAL);
+    if (!test->bitrate_limit_intervals_traffic_bytes) {
+        free(test);
+	i_errno = IENEWTEST;
+	return NULL;
+    }
+    memset(test->bitrate_limit_intervals_traffic_bytes, 0, sizeof(sizeof(iperf_size_t) * MAX_INTERVAL));   
+
     /* By default all output goes to stdout */
     test->outfile = stdout;
 
@@ -2322,9 +2466,9 @@
 iperf_defaults(struct iperf_test *testp)
 {
     struct protocol *tcp, *udp;
-#if defined(HAVE_SCTP)
+#if defined(HAVE_SCTP_H)
     struct protocol *sctp;
-#endif /* HAVE_SCTP */
+#endif /* HAVE_SCTP_H */
 
     testp->omit = OMIT;
     testp->duration = DURATION;
@@ -2356,6 +2500,9 @@
     testp->settings->socket_bufsize = 0;    /* use autotuning */
     testp->settings->blksize = DEFAULT_TCP_BLKSIZE;
     testp->settings->rate = 0;
+    testp->settings->bitrate_limit = 0;
+    testp->settings->bitrate_limit_interval = 5;
+    testp->settings->bitrate_limit_stats_per_interval = 0;
     testp->settings->fqrate = 0;
     testp->settings->pacing_timer = 1000;
     testp->settings->burst = 0;
@@ -2403,7 +2550,7 @@
 
     set_protocol(testp, Ptcp);
 
-#if defined(HAVE_SCTP)
+#if defined(HAVE_SCTP_H)
     sctp = protocol_new();
     if (!sctp) {
         protocol_free(tcp);
@@ -2421,7 +2568,7 @@
     sctp->init = iperf_sctp_init;
 
     SLIST_INSERT_AFTER(udp, sctp, protocols);
-#endif /* HAVE_SCTP */
+#endif /* HAVE_SCTP_H */
 
     testp->on_new_stream = iperf_on_new_stream;
     testp->on_test_start = iperf_on_test_start;
@@ -2497,6 +2644,8 @@
 	free(test->congestion_used);
     if (test->remote_congestion_used)
 	free(test->remote_congestion_used);
+    if (test->timestamp_format)
+	free(test->timestamp_format);
     if (test->omit_timer != NULL)
 	tmr_cancel(test->omit_timer);
     if (test->timer != NULL)
@@ -2513,6 +2662,15 @@
         free(prot);
     }
 
+    if (test->logfile) {
+	free(test->logfile);
+	test->logfile = NULL;
+	if (test->outfile) {
+	    fclose(test->outfile);
+	    test->outfile = NULL;
+	}
+    }
+
     if (test->server_output_text) {
 	free(test->server_output_text);
 	test->server_output_text = NULL;
@@ -2544,6 +2702,10 @@
         }
     }
 
+    /* Free interval's traffic array for avrage rate calculations */
+    if (test->bitrate_limit_intervals_traffic_bytes != NULL)
+        free(test->bitrate_limit_intervals_traffic_bytes);
+
     /* XXX: Why are we setting these values to NULL? */
     // test->streams = NULL;
     test->stats_callback = NULL;
@@ -2556,6 +2718,7 @@
 iperf_reset_test(struct iperf_test *test)
 {
     struct iperf_stream *sp;
+    int i;
 
     /* Free streams */
     while (!SLIST_EMPTY(&test->streams)) {
@@ -2609,6 +2772,13 @@
 
     test->other_side_has_retransmits = 0;
 
+    test->bitrate_limit_stats_count = 0;
+    test->bitrate_limit_last_interval_index = 0;
+    test->bitrate_limit_exceeded = 0;
+
+    for (i = 0; i < MAX_INTERVAL; i++)
+        test->bitrate_limit_intervals_traffic_bytes[i] = 0;
+
     test->reverse = 0;
     test->bidirectional = 0;
     test->no_delay = 0;
@@ -2712,12 +2882,16 @@
     struct iperf_stream_result *rp = NULL;
     struct iperf_interval_results *irp, temp;
     struct iperf_time temp_time;
+    iperf_size_t total_interval_bytes_transferred = 0;
 
     temp.omitted = test->omitting;
     SLIST_FOREACH(sp, &test->streams, streams) {
         rp = sp->result;
 	temp.bytes_transferred = sp->sender ? rp->bytes_sent_this_interval : rp->bytes_received_this_interval;
-     
+
+        // Total bytes transferred this interval
+	total_interval_bytes_transferred += rp->bytes_sent_this_interval + rp->bytes_received_this_interval;
+    
 	irp = TAILQ_LAST(&rp->interval_results, irlisthead);
         /* result->end_time contains timestamp of previous interval */
         if ( irp != NULL ) /* not the 1st interval */
@@ -2776,6 +2950,11 @@
         add_to_interval_list(rp, &temp);
         rp->bytes_sent_this_interval = rp->bytes_received_this_interval = 0;
     }
+
+    /* Verify that total server's throughput is not above specified limit */
+    if (test->role == 's') {
+	iperf_check_total_rate(test, total_interval_bytes_transferred);
+    }
 }
 
 /**
@@ -4135,11 +4314,24 @@
 #endif /* neither HAVE_SCHED_SETAFFINITY nor HAVE_CPUSET_SETAFFINITY nor HAVE_SETPROCESSAFFINITYMASK */
 }
 
+char iperf_timestr[100];
+
 int
 iperf_printf(struct iperf_test *test, const char* format, ...)
 {
     va_list argp;
     int r = -1;
+    time_t now;
+    struct tm *ltm = NULL;
+    char *ct = NULL;
+
+    /* Timestamp if requested */
+    if (iperf_get_test_timestamps(test)) {
+	time(&now);
+	ltm = localtime(&now);
+	strftime(iperf_timestr, sizeof(iperf_timestr), iperf_get_test_timestamp_format(test), ltm);
+	ct = iperf_timestr;
+    }
 
     /*
      * There are roughly two use cases here.  If we're the client,
@@ -4154,6 +4346,9 @@
      * to be buffered up anyway.
      */
     if (test->role == 'c') {
+	if (ct) {
+	    fprintf(test->outfile, "%s", ct);
+	}
 	if (test->title)
 	    fprintf(test->outfile, "%s:  ", test->title);
 	va_start(argp, format);
@@ -4162,8 +4357,12 @@
     }
     else if (test->role == 's') {
 	char linebuffer[1024];
+	int i = 0;
+	if (ct) {
+	    i = sprintf(linebuffer, "%s", ct);
+	}
 	va_start(argp, format);
-	r = vsnprintf(linebuffer, sizeof(linebuffer), format, argp);
+	r = vsnprintf(linebuffer + i, sizeof(linebuffer), format, argp);
 	va_end(argp);
 	fprintf(test->outfile, "%s", linebuffer);
 
diff --git a/src/iperf_api.h b/src/iperf_api.h
index 3770b37..a51b773 100644
--- a/src/iperf_api.h
+++ b/src/iperf_api.h
@@ -45,6 +45,10 @@
 struct iperf_stream;
 struct iperf_time;
 
+#if !defined(__IPERF_H)
+typedef uint64_t iperf_size_t;
+#endif // __IPERF_H
+
 /* default settings */
 #define Ptcp SOCK_STREAM
 #define Pudp SOCK_DGRAM
@@ -73,6 +77,8 @@
 #define OPT_REPEATING_PAYLOAD 18
 #define OPT_EXTRA_DATA 19
 #define OPT_BIDIRECTIONAL 20
+#define OPT_SERVER_BITRATE_LIMIT 21
+#define OPT_TIMESTAMPS 22
 
 /* states */
 #define TEST_START 1
@@ -113,6 +119,8 @@
 double	iperf_get_test_stats_interval( struct iperf_test* ipt );
 int	iperf_get_test_num_streams( struct iperf_test* ipt );
 int	iperf_get_test_repeating_payload( struct iperf_test* ipt );
+int	iperf_get_test_timestamps( struct iperf_test* ipt );
+const char* iperf_get_test_timestamp_format( struct iperf_test* ipt );
 int	iperf_get_test_server_port( struct iperf_test* ipt );
 char*	iperf_get_test_server_hostname( struct iperf_test* ipt );
 char*	iperf_get_test_template( struct iperf_test* ipt );
@@ -139,7 +147,7 @@
 void	iperf_set_test_stats_interval( struct iperf_test* ipt, double stats_interval );
 void	iperf_set_test_state( struct iperf_test* ipt, signed char state );
 void	iperf_set_test_blksize( struct iperf_test* ipt, int blksize );
-void	iperf_set_test_logfile( struct iperf_test* ipt, char *logfile );
+void	iperf_set_test_logfile( struct iperf_test* ipt, const char *logfile );
 void	iperf_set_test_rate( struct iperf_test* ipt, uint64_t rate );
 void    iperf_set_test_pacing_timer( struct iperf_test* ipt, int pacing_timer );
 void    iperf_set_test_bytes( struct iperf_test* ipt, uint64_t bytes );
@@ -149,28 +157,30 @@
 void	iperf_set_test_socket_bufsize( struct iperf_test* ipt, int socket_bufsize );
 void	iperf_set_test_num_streams( struct iperf_test* ipt, int num_streams );
 void	iperf_set_test_repeating_payload( struct iperf_test* ipt, int repeating_payload );
+void	iperf_set_test_timestamps( struct iperf_test* ipt, int timestamps );
+void	iperf_set_test_timestamp_format( struct iperf_test*, const char *tf );
 void	iperf_set_test_role( struct iperf_test* ipt, char role );
-void	iperf_set_test_server_hostname( struct iperf_test* ipt, char* server_hostname );
-void    iperf_set_test_template( struct iperf_test *ipt, char *tmp_template );
+void	iperf_set_test_server_hostname( struct iperf_test* ipt, const char* server_hostname );
+void    iperf_set_test_template( struct iperf_test *ipt, const char *tmp_template );
 void	iperf_set_test_reverse( struct iperf_test* ipt, int reverse );
 void	iperf_set_test_json_output( struct iperf_test* ipt, int json_output );
 int	iperf_has_zerocopy( void );
 void	iperf_set_test_zerocopy( struct iperf_test* ipt, int zerocopy );
 void	iperf_set_test_get_server_output( struct iperf_test* ipt, int get_server_output );
-void	iperf_set_test_bind_address( struct iperf_test* ipt, char *bind_address );
+void	iperf_set_test_bind_address( struct iperf_test* ipt, const char *bind_address );
 void	iperf_set_test_udp_counters_64bit( struct iperf_test* ipt, int udp_counters_64bit );
 void	iperf_set_test_one_off( struct iperf_test* ipt, int one_off );
 void    iperf_set_test_tos( struct iperf_test* ipt, int tos );
-void	iperf_set_test_extra_data( struct iperf_test* ipt, char *dat );
+void	iperf_set_test_extra_data( struct iperf_test* ipt, const char *dat );
 void    iperf_set_test_bidirectional( struct iperf_test* ipt, int bidirectional);
 void    iperf_set_test_no_delay( struct iperf_test* ipt, int no_delay);
 
 #if defined(HAVE_SSL)
-void    iperf_set_test_client_username(struct iperf_test *ipt, char *client_username);
-void    iperf_set_test_client_password(struct iperf_test *ipt, char *client_password);
-void    iperf_set_test_client_rsa_pubkey(struct iperf_test *ipt, char *client_rsa_pubkey_base64);
-void    iperf_set_test_server_authorized_users(struct iperf_test *ipt, char *server_authorized_users);
-void    iperf_set_test_server_rsa_privkey(struct iperf_test *ipt, char *server_rsa_privkey_base64);
+void    iperf_set_test_client_username(struct iperf_test *ipt, const char *client_username);
+void    iperf_set_test_client_password(struct iperf_test *ipt, const char *client_password);
+void    iperf_set_test_client_rsa_pubkey(struct iperf_test *ipt, const char *client_rsa_pubkey_base64);
+void    iperf_set_test_server_authorized_users(struct iperf_test *ipt, const char *server_authorized_users);
+void    iperf_set_test_server_rsa_privkey(struct iperf_test *ipt, const char *server_rsa_privkey_base64);
 #endif // HAVE_SSL
 
 void	iperf_set_test_connect_timeout(struct iperf_test *ipt, int ct);
@@ -268,7 +278,7 @@
 void iperf_got_sigend(struct iperf_test *test) __attribute__ ((noreturn));
 void usage(void);
 void usage_long(FILE * f);
-void warning(char *);
+void warning(const char *);
 int iperf_exchange_results(struct iperf_test *);
 int iperf_init_test(struct iperf_test *);
 int iperf_create_send_timers(struct iperf_test *);
@@ -301,6 +311,7 @@
 int iperf_handle_message_server(struct iperf_test *);
 int iperf_create_pidfile(struct iperf_test *);
 int iperf_delete_pidfile(struct iperf_test *);
+void iperf_check_total_rate(struct iperf_test *, iperf_size_t);
 
 /* JSON output routines. */
 int iperf_json_start(struct iperf_test *);
@@ -348,6 +359,8 @@
     IEBADFORMAT = 24,	    // Bad format argument to -f
     IEREVERSEBIDIR = 25,    // Iperf cannot be both reverse and bidirectional
     IEBADPORT = 26,	    // Bad port number
+    IETOTALRATE = 27,       // Total required bandwidth is larger than server's limit
+    IETOTALINTERVAL = 28,   // Invalid time interval for calculating average data rate
     /* Test errors */
     IENEWTEST = 100,        // Unable to create a new test (check perror)
     IEINITTEST = 101,       // Test initialization failed (check perror)
diff --git a/src/iperf_auth.c b/src/iperf_auth.c
index 46211e0..eb4610f 100644
--- a/src/iperf_auth.c
+++ b/src/iperf_auth.c
@@ -174,6 +174,7 @@
 
     BIO* bio = BIO_new(BIO_s_mem());
     BIO_write(bio, key, key_len);
+    free(key);
     EVP_PKEY *pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL);
     BIO_free(bio);
     return (pkey);
@@ -199,6 +200,7 @@
 
     BIO* bio = BIO_new(BIO_s_mem());
     BIO_write(bio, key, key_len);
+    free(key);
     EVP_PKEY *pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
     BIO_free(bio);
     return (pkey);
@@ -304,7 +306,7 @@
     return (0); //success
 }
 
-int decode_auth_setting(int enable_debug, char *authtoken, EVP_PKEY *private_key, char **username, char **password, time_t *ts){
+int decode_auth_setting(int enable_debug, const char *authtoken, EVP_PKEY *private_key, char **username, char **password, time_t *ts){
     unsigned char *encrypted_b64 = NULL;
     size_t encrypted_len_b64;
     Base64Decode(authtoken, &encrypted_b64, &encrypted_len_b64);        
diff --git a/src/iperf_client_api.c b/src/iperf_client_api.c
index 20ea6fd..d0edf7d 100644
--- a/src/iperf_client_api.c
+++ b/src/iperf_client_api.c
@@ -1,5 +1,5 @@
 /*
- * iperf, Copyright (c) 2014-2018, The Regents of the University of
+ * iperf, Copyright (c) 2014-2020, 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.
@@ -478,7 +478,7 @@
 
     /* Start the client and connect to the server */
     if (iperf_connect(test) < 0)
-        return -1;
+        goto cleanup_and_fail;
 
     /* Begin calculating CPU utilization */
     cpu_util(NULL);
@@ -492,12 +492,12 @@
 	result = select(test->max_fd + 1, &read_set, &write_set, NULL, timeout);
 	if (result < 0 && errno != EINTR) {
   	    i_errno = IESELECT;
-	    return -1;
+	    goto cleanup_and_fail;
 	}
 	if (result > 0) {
 	    if (FD_ISSET(test->ctrl_sck, &read_set)) {
  	        if (iperf_handle_message_client(test) < 0) {
-		    return -1;
+		    goto cleanup_and_fail;
 		}
 		FD_CLR(test->ctrl_sck, &read_set);
 	    }
@@ -521,17 +521,17 @@
 	    if (test->mode == BIDIRECTIONAL)
 	    {
                 if (iperf_send(test, &write_set) < 0)
-                    return -1;
+                    goto cleanup_and_fail;
                 if (iperf_recv(test, &read_set) < 0)
-                    return -1;
+                    goto cleanup_and_fail;
 	    } else if (test->mode == SENDER) {
                 // Regular mode. Client sends.
                 if (iperf_send(test, &write_set) < 0)
-                    return -1;
+                    goto cleanup_and_fail;
 	    } else {
                 // Reverse mode. Client receives.
                 if (iperf_recv(test, &read_set) < 0)
-                    return -1;
+                    goto cleanup_and_fail;
 	    }
 
 
@@ -557,7 +557,7 @@
 		cpu_util(test->cpu_util);
 		test->stats_callback(test);
 		if (iperf_set_send_state(test, TEST_END) != 0)
-		    return -1;
+                    goto cleanup_and_fail;
 	    }
 	}
 	// If we're in reverse mode, continue draining the data
@@ -567,7 +567,7 @@
 	// from the client side.
 	else if (test->mode == RECEIVER && test->state == TEST_END) {
 	    if (iperf_recv(test, &read_set) < 0)
-		return -1;
+		goto cleanup_and_fail;
 	}
     }
 
@@ -582,4 +582,11 @@
     iflush(test);
 
     return 0;
+
+  cleanup_and_fail:
+    iperf_client_end(test);
+    if (test->json_output)
+	iperf_json_finish(test);
+    iflush(test);
+    return -1;
 }
diff --git a/src/iperf_config.h.in b/src/iperf_config.h.in
index e543cbd..1a7cbec 100644
--- a/src/iperf_config.h.in
+++ b/src/iperf_config.h.in
@@ -40,7 +40,7 @@
 #undef HAVE_SCHED_SETAFFINITY
 
 /* Have SCTP support. */
-#undef HAVE_SCTP
+#undef HAVE_SCTP_H
 
 /* Define to 1 if you have the `sendfile' function. */
 #undef HAVE_SENDFILE
diff --git a/src/iperf_error.c b/src/iperf_error.c
index c6e5ee4..cfe4cbd 100644
--- a/src/iperf_error.c
+++ b/src/iperf_error.c
@@ -35,12 +35,25 @@
 
 int gerror;
 
+char iperf_timestrerr[100];
+
 /* Do a printf to stderr. */
 void
 iperf_err(struct iperf_test *test, const char *format, ...)
 {
     va_list argp;
     char str[1000];
+    time_t now;
+    struct tm *ltm = NULL;
+    char *ct = NULL;
+
+    /* Timestamp if requested */
+    if (test != NULL && test->timestamps) {
+	time(&now);
+	ltm = localtime(&now);
+	strftime(iperf_timestrerr, sizeof(iperf_timestrerr), test->timestamp_format, ltm);
+	ct = iperf_timestrerr;
+    }
 
     va_start(argp, format);
     vsnprintf(str, sizeof(str), format, argp);
@@ -48,9 +61,15 @@
 	cJSON_AddStringToObject(test->json_top, "error", str);
     else
 	if (test && test->outfile && test->outfile != stdout) {
+	    if (ct) {
+		fprintf(test->outfile, "%s", ct);
+	    }
 	    fprintf(test->outfile, "iperf3: %s\n", str);
 	}
 	else {
+	    if (ct) {
+		fprintf(stderr, "%s", ct);
+	    }
 	    fprintf(stderr, "iperf3: %s\n", str);
 	}
     va_end(argp);
@@ -62,6 +81,17 @@
 {
     va_list argp;
     char str[1000];
+    time_t now;
+    struct tm *ltm = NULL;
+    char *ct = NULL;
+
+    /* Timestamp if requested */
+    if (test != NULL && test->timestamps) {
+	time(&now);
+	ltm = localtime(&now);
+	strftime(iperf_timestrerr, sizeof(iperf_timestrerr), "%c ", ltm);
+	ct = iperf_timestrerr;
+    }
 
     va_start(argp, format);
     vsnprintf(str, sizeof(str), format, argp);
@@ -70,9 +100,15 @@
 	iperf_json_finish(test);
     } else
 	if (test && test->outfile && test->outfile != stdout) {
+	    if (ct) {
+		fprintf(test->outfile, "%s", ct);
+	    }
 	    fprintf(test->outfile, "iperf3: %s\n", str);
 	}
 	else {
+	    if (ct) {
+		fprintf(stderr, "%s", ct);
+	    }
 	    fprintf(stderr, "iperf3: %s\n", str);
 	}
     va_end(argp);
@@ -385,7 +421,13 @@
 	case IEREVERSEBIDIR:
 	    snprintf(errstr, len, "cannot be both reverse and bidirectional");
             break;
-	
+	case IETOTALRATE:
+	    snprintf(errstr, len, "total required bandwidth is larger than server limit");
+            break;
+	default:
+	    snprintf(errstr, len, "int_errno=%d", int_errno);
+	    perr = 1;
+	    break;
     }
 
     /* Append the result of strerror() or gai_strerror() if appropriate */
diff --git a/src/iperf_locale.c b/src/iperf_locale.c
index 2dd5a5b..d5a5354 100644
--- a/src/iperf_locale.c
+++ b/src/iperf_locale.c
@@ -109,6 +109,9 @@
                            "  -J, --json                output in JSON format\n"
                            "  --logfile f               send output to a log file\n"
                            "  --forceflush              force flushing output at every interval\n"
+                           "  --timestamps    <format>  emit a timestamp at the start of each output line\n"
+                           "                            (using optional format string as per strftime(3))\n"
+    
                            "  -d, --debug               emit debugging output\n"
                            "  -v, --version             show version information and quit\n"
                            "  -h, --help                show this message and quit\n"
@@ -117,6 +120,9 @@
                            "  -D, --daemon              run the server as a daemon\n"
                            "  -I, --pidfile file        write PID file\n"
                            "  -1, --one-off             handle one client connection then exit\n"
+			   "  --server-bitrate-limit #[KMG][/#]   server's total bit rate limit (default 0 = no limit)\n"
+			   "                            (optional slash and number of secs interval for averaging\n"
+			   "                            total data rate.  Default is 5 seconds)\n"
 #if defined(HAVE_SSL)
                            "  --rsa-private-key-path    path to the RSA private key used to decrypt\n"
 			   "                            authentication credentials\n"
@@ -125,11 +131,11 @@
 #endif //HAVE_SSL
                            "Client specific:\n"
                            "  -c, --client    <host>    run in client mode, connecting to <host>\n"
-#if defined(HAVE_SCTP)
+#if defined(HAVE_SCTP_H)
                            "  --sctp                    use SCTP rather than TCP\n"
                            "  -X, --xbind <name>        bind SCTP association to links\n"
                            "  --nstreams      #         number of SCTP streams\n"
-#endif /* HAVE_SCTP */
+#endif /* HAVE_SCTP_H */
                            "  -u, --udp                 use UDP rather than TCP\n"
                            "  --connect-timeout #       timeout for control connection setup (ms)\n"
                            "  -b, --bitrate #[KMG][/#]  target bitrate in bits/sec (0 for unlimited)\n"
diff --git a/src/iperf_sctp.c b/src/iperf_sctp.c
index 0bc98ba..e0c1ec1 100644
--- a/src/iperf_sctp.c
+++ b/src/iperf_sctp.c
@@ -57,7 +57,7 @@
 int
 iperf_sctp_recv(struct iperf_stream *sp)
 {
-#if defined(HAVE_SCTP)
+#if defined(HAVE_SCTP_H)
     int r;
 
     r = Nread(sp->socket, sp->buffer, sp->settings->blksize, Psctp);
@@ -78,7 +78,7 @@
 #else
     i_errno = IENOSCTP;
     return -1;
-#endif /* HAVE_SCTP */
+#endif /* HAVE_SCTP_H */
 }
 
 
@@ -89,7 +89,7 @@
 int
 iperf_sctp_send(struct iperf_stream *sp)
 {
-#if defined(HAVE_SCTP)
+#if defined(HAVE_SCTP_H)
     int r;
 
     r = Nwrite(sp->socket, sp->buffer, sp->settings->blksize, Psctp);
@@ -103,7 +103,7 @@
 #else
     i_errno = IENOSCTP;
     return -1;
-#endif /* HAVE_SCTP */
+#endif /* HAVE_SCTP_H */
 }
 
 
@@ -115,7 +115,7 @@
 int
 iperf_sctp_accept(struct iperf_test * test)
 {
-#if defined(HAVE_SCTP)
+#if defined(HAVE_SCTP_H)
     int     s;
     signed char rbuf = ACCESS_DENIED;
     char    cookie[COOKIE_SIZE];
@@ -148,7 +148,7 @@
 #else
     i_errno = IENOSCTP;
     return -1;
-#endif /* HAVE_SCTP */
+#endif /* HAVE_SCTP_H */
 }
 
 
@@ -159,7 +159,7 @@
 int
 iperf_sctp_listen(struct iperf_test *test)
 {
-#if defined(HAVE_SCTP)
+#if defined(HAVE_SCTP_H)
     struct addrinfo hints, *res;
     char portstr[6];
     int s, opt, saved_errno;
@@ -270,7 +270,7 @@
 #else
     i_errno = IENOSCTP;
     return -1;
-#endif /* HAVE_SCTP */
+#endif /* HAVE_SCTP_H */
 }
 
 
@@ -281,7 +281,7 @@
 int
 iperf_sctp_connect(struct iperf_test *test)
 {
-#if defined(HAVE_SCTP)
+#if defined(HAVE_SCTP_H)
     int s, opt, saved_errno;
     char portstr[6];
     struct addrinfo hints, *local_res, *server_res;
@@ -527,7 +527,7 @@
 #else
     i_errno = IENOSCTP;
     return -1;
-#endif /* HAVE_SCTP */
+#endif /* HAVE_SCTP_H */
 }
 
 
@@ -535,12 +535,12 @@
 int
 iperf_sctp_init(struct iperf_test *test)
 {
-#if defined(HAVE_SCTP)
+#if defined(HAVE_SCTP_H)
     return 0;
 #else
     i_errno = IENOSCTP;
     return -1;
-#endif /* HAVE_SCTP */
+#endif /* HAVE_SCTP_H */
 }
 
 
@@ -552,7 +552,7 @@
 int
 iperf_sctp_bindx(struct iperf_test *test, int s, int is_server)
 {
-#if defined(HAVE_SCTP)
+#if defined(HAVE_SCTP_H)
     struct addrinfo hints;
     char portstr[6];
     char *servname;
@@ -701,5 +701,5 @@
 #else
     i_errno = IENOSCTP;
     return -1;
-#endif /* HAVE_SCTP */
+#endif /* HAVE_SCTP_H */
 }
diff --git a/src/iperf_server_api.c b/src/iperf_server_api.c
index 40d99bc..e2ddf7f 100644
--- a/src/iperf_server_api.c
+++ b/src/iperf_server_api.c
@@ -1,5 +1,5 @@
 /*
- * iperf, Copyright (c) 2014-2018 The Regents of the University of
+ * iperf, Copyright (c) 2014-2020 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.
@@ -354,6 +354,15 @@
 static void
 cleanup_server(struct iperf_test *test)
 {
+    struct iperf_stream *sp;
+
+    /* Close open streams */
+    SLIST_FOREACH(sp, &test->streams, streams) {
+	FD_CLR(sp->socket, &test->read_set);
+	FD_CLR(sp->socket, &test->write_set);
+	close(sp->socket);
+    }
+
     /* Close open test sockets */
     if (test->ctrl_sck) {
 	close(test->ctrl_sck);
@@ -437,12 +446,20 @@
 
     while (test->state != IPERF_DONE) {
 
+        // Check if average transfer rate was exceeded (condition set in the callback routines)
+	if (test->bitrate_limit_exceeded) {
+	    cleanup_server(test);
+            i_errno = IETOTALRATE;
+            return -1;	
+	}
+
         memcpy(&read_set, &test->read_set, sizeof(fd_set));
         memcpy(&write_set, &test->write_set, sizeof(fd_set));
 
 	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) {
 	    cleanup_server(test);
             i_errno = IESELECT;
@@ -596,6 +613,17 @@
                         }
                     }
                     test->prot_listener = -1;
+
+		    /* Ensure that total requested data rate is not above limit */
+		    iperf_size_t total_requested_rate = test->num_streams * test->settings->rate * (test->mode == BIDIRECTIONAL? 2 : 1);
+		    if (test->settings->bitrate_limit > 0 && total_requested_rate > test->settings->bitrate_limit) {
+			iperf_err(test, "Client total requested throughput rate of %" PRIu64 " bps exceeded %" PRIu64 " bps limit",
+				total_requested_rate, test->settings->bitrate_limit);
+			cleanup_server(test);
+			i_errno = IETOTALRATE;
+			return -1;
+		    }
+
 		    if (iperf_set_send_state(test, TEST_START) != 0) {
 			cleanup_server(test);
                         return -1;
@@ -647,7 +675,7 @@
                         return -1;
 		    }
                 }
-            }
+	    }
         }
 
 	if (result == 0 ||
diff --git a/src/iperf_udp.c b/src/iperf_udp.c
index ab6be5e..2fd7bf5 100644
--- a/src/iperf_udp.c
+++ b/src/iperf_udp.c
@@ -52,7 +52,13 @@
 #if defined(HAVE_INTTYPES_H)
 # include <inttypes.h>
 #else
-# define PRIu64		"llu"
+# ifndef PRIu64
+#  if sizeof(long) == 8
+#   define PRIu64		"lu"
+#  else
+#   define PRIu64		"llu"
+#  endif
+# endif
 #endif
 
 /* iperf_udp_recv
diff --git a/src/iperf_util.c b/src/iperf_util.c
index 412397a..9ca1eec 100644
--- a/src/iperf_util.c
+++ b/src/iperf_util.c
@@ -111,7 +111,7 @@
  */
 
 void
-make_cookie(char *cookie)
+make_cookie(const char *cookie)
 {
     unsigned char *out = (unsigned char*)cookie;
     size_t pos;
@@ -267,7 +267,7 @@
     numfeatures++;
 #endif /* HAVE_FLOWLABEL */
     
-#if defined(HAVE_SCTP)
+#if defined(HAVE_SCTP_H)
     if (numfeatures > 0) {
 	strncat(features, ", ", 
 		sizeof(features) - strlen(features) - 1);
@@ -275,7 +275,7 @@
     strncat(features, "SCTP", 
 	sizeof(features) - strlen(features) - 1);
     numfeatures++;
-#endif /* HAVE_SCTP */
+#endif /* HAVE_SCTP_H */
     
 #if defined(HAVE_TCP_CONGESTION)
     if (numfeatures > 0) {
@@ -402,7 +402,7 @@
 
 /* Debugging routine to dump out an fd_set. */
 void
-iperf_dump_fdset(FILE *fp, char *str, int nfds, fd_set *fds)
+iperf_dump_fdset(FILE *fp, const char *str, int nfds, fd_set *fds)
 {
     int fd;
     int comma;
diff --git a/src/iperf_util.h b/src/iperf_util.h
index 76bfd20..b109af2 100644
--- a/src/iperf_util.h
+++ b/src/iperf_util.h
@@ -54,7 +54,7 @@
 
 cJSON* iperf_json_printf(const char *format, ...);
 
-void iperf_dump_fdset(FILE *fp, char *str, int nfds, fd_set *fds);
+void iperf_dump_fdset(FILE *fp, const char *str, int nfds, fd_set *fds);
 
 #ifndef HAVE_DAEMON
 extern int daemon(int nochdir, int noclose);
diff --git a/src/net.c b/src/net.c
index b475ed0..8fde9c3 100644
--- a/src/net.c
+++ b/src/net.c
@@ -121,7 +121,7 @@
 
 /* make connection to server */
 int
-netdial(int domain, int proto, char *local, int local_port, char *server, int port, int timeout)
+netdial(int domain, int proto, const char *local, int local_port, const char *server, int port, int timeout)
 {
     struct addrinfo hints, *local_res, *server_res;
     int s, saved_errno;
@@ -218,7 +218,7 @@
 /***************************************************************/
 
 int
-netannounce(int domain, int proto, char *local, int port)
+netannounce(int domain, int proto, const char *local, int port)
 {
     struct addrinfo hints, *res;
     char portstr[6];
diff --git a/src/net.h b/src/net.h
index 3738d6a..80a2161 100644
--- a/src/net.h
+++ b/src/net.h
@@ -28,8 +28,8 @@
 #define __NET_H
 
 int timeout_connect(int s, const struct sockaddr *name, socklen_t namelen, int timeout);
-int netdial(int domain, int proto, char *local, int local_port, char *server, int port, int timeout);
-int netannounce(int domain, int proto, char *local, int port);
+int netdial(int domain, int proto, const char *local, int local_port, const char *server, int port, int timeout);
+int netannounce(int domain, int proto, const char *local, int port);
 int Nread(int fd, char *buf, size_t count, int prot);
 int Nwrite(int fd, const char *buf, size_t count, int prot) /* __attribute__((hot)) */;
 int has_sendfile(void);
diff --git a/test_commands.sh b/test_commands.sh
index 2ed0f82..146d1da 100755
--- a/test_commands.sh
+++ b/test_commands.sh
@@ -29,12 +29,20 @@
 # force V6
 ./src/iperf3 -c $host -6 -t 5
 ./src/iperf3 -c $host -6 -u -t 5
+# FQ rate
+./src/iperf3 -c $host -V -t 5 --fq-rate 5m
+./src/iperf3 -c $host -u -V -t 5 --fq-rate 5m
+# SCTP
+./src/iperf3 -c $host --sctp -V -t 5
 # parallel streams
 ./src/iperf3 -c $host -P 3 -t 5 
 ./src/iperf3 -c $host -u -P 3 -t 5
 # reverse mode
 ./src/iperf3 -c $host -P 2 -t 5 -R
 ./src/iperf3 -c $host -u -P 2 -t 5 -R
+# bidirectional mode
+./src/iperf3 -c $host -P 2 -t 5 --bidir
+./src/iperf3 -c $host -u -P 2 -t 5 --bidir
 # zero copy
 ./src/iperf3 -c $host -Z -t 5 
 ./src/iperf3 -c $host -Z -t 5 -R