Hello community, here is the log from the commit of package iperf for openSUSE:Factory checked in at 2020-09-21 17:26:00 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/iperf (Old) and /work/SRC/openSUSE:Factory/.iperf.new.4249 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "iperf" Mon Sep 21 17:26:00 2020 rev:29 rq:835352 version:3.9 Changes: -------- --- /work/SRC/openSUSE:Factory/iperf/iperf.changes 2020-07-30 15:48:27.941986817 +0200 +++ /work/SRC/openSUSE:Factory/.iperf.new.4249/iperf.changes 2020-09-21 17:27:47.152163598 +0200 @@ -1,0 +2,19 @@ +Mon Sep 14 10:48:05 UTC 2020 - Dirk Mueller <[email protected]> + +- update to 3.9: + * 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). + * Fixed various minor memory leaks (#1023). + +------------------------------------------------------------------- Old: ---- iperf-3.8.1.tar.gz New: ---- iperf-3.9.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ iperf.spec ++++++ --- /var/tmp/diff_new_pack.oV5Tzd/_old 2020-09-21 17:27:48.640165024 +0200 +++ /var/tmp/diff_new_pack.oV5Tzd/_new 2020-09-21 17:27:48.640165024 +0200 @@ -1,7 +1,7 @@ # # spec file for package iperf # -# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2020 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -18,7 +18,7 @@ %define soname 0 Name: iperf -Version: 3.8.1 +Version: 3.9 Release: 0 Summary: A tool to measure network performance License: BSD-3-Clause @@ -26,13 +26,12 @@ URL: https://software.es.net/iperf/ #Source URL: http://downloads.es.net/pub/iperf/%{name}-%{version}.tar.gz Source: http://downloads.es.net/pub/iperf/%{name}-%{version}.tar.gz +Requires: lib%{name}%{soname} = %{version}-%{release} %if %{?sles_version} && %{?sles_version} <= 11 BuildRequires: libuuid-devel %else BuildRequires: pkgconfig(uuid) %endif -BuildRoot: %{_tmppath}/%{name}-%{version}-build -Requires: lib%{name}%{soname} = %{version}-%{release} %description Iperf is a tool for active measurements of the maximum achievable bandwidth @@ -83,7 +82,7 @@ %build %configure --disable-static -make %{?_smp_mflags} +%make_build %install %make_install @@ -95,19 +94,17 @@ %postun -n lib%{name}%{soname} -p /sbin/ldconfig %files -%defattr(-, root, root) -%doc LICENSE README.md RELNOTES.md +%license LICENSE +%doc README.md RELNOTES.md %{_bindir}/%{name}3 %{_mandir}/man1/%{name}3.1%{?ext_man} %files -n lib%{name}%{soname} -%defattr(-, root, root) -%doc LICENSE +%license LICENSE %{_libdir}/lib%{name}.so.* %files devel -%defattr(-, root, root) -%doc LICENSE +%license LICENSE %{_includedir}/%{name}_api.h %{_libdir}/lib%{name}.so %{_mandir}/man3/lib%{name}.3%{?ext_man} ++++++ iperf-3.8.1.tar.gz -> iperf-3.9.tar.gz ++++++ ++++ 1742 lines of diff (skipped) ++++ retrying with extended exclude list diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/iperf-3.8.1/RELNOTES.md new/iperf-3.9/RELNOTES.md --- old/iperf-3.8.1/RELNOTES.md 2020-06-10 17:18:27.000000000 +0200 +++ new/iperf-3.9/RELNOTES.md 2020-08-15 00:08:27.000000000 +0200 @@ -1,6 +1,31 @@ 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 ---------------------- @@ -41,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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/iperf-3.8.1/configure.ac new/iperf-3.9/configure.ac --- old/iperf-3.8.1/configure.ac 2020-06-10 17:18:27.000000000 +0200 +++ new/iperf-3.9/configure.ac 2020-08-15 00:08:27.000000000 +0200 @@ -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.1, 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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/iperf-3.8.1/docs/conf.py new/iperf-3.9/docs/conf.py --- old/iperf-3.8.1/docs/conf.py 2020-06-10 17:18:27.000000000 +0200 +++ new/iperf-3.9/docs/conf.py 2020-08-15 00:08:27.000000000 +0200 @@ -52,10 +52,10 @@ # built documents. # # The short X.Y version. -version = '3.8' +version = '3.8.1' # The full version, including alpha/beta/rc tags. -release = '3.8' +release = '3.8.1' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/iperf-3.8.1/docs/faq.rst new/iperf-3.9/docs/faq.rst --- old/iperf-3.8.1/docs/faq.rst 2020-06-10 17:18:27.000000000 +0200 +++ new/iperf-3.9/docs/faq.rst 2020-08-15 00:08:27.000000000 +0200 @@ -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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/iperf-3.8.1/docs/news.rst new/iperf-3.9/docs/news.rst --- old/iperf-3.8.1/docs/news.rst 2020-06-10 17:18:27.000000000 +0200 +++ new/iperf-3.9/docs/news.rst 2020-08-15 00:08:27.000000000 +0200 @@ -1,6 +1,15 @@ 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 ------------------------------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/iperf-3.8.1/src/iperf.h new/iperf-3.9/src/iperf.h --- old/iperf-3.8.1/src/iperf.h 2020-06-10 17:18:27.000000000 +0200 +++ new/iperf-3.9/src/iperf.h 2020-08-15 00:08:27.000000000 +0200 @@ -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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/iperf-3.8.1/src/iperf3.1 new/iperf-3.9/src/iperf3.1 --- old/iperf-3.8.1/src/iperf3.1 2020-06-10 17:18:27.000000000 +0200 +++ new/iperf-3.9/src/iperf3.1 2020-08-15 00:08:27.000000000 +0200 @@ -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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/iperf-3.8.1/src/iperf_api.c new/iperf-3.9/src/iperf_api.c --- old/iperf-3.8.1/src/iperf_api.c 2020-06-10 17:18:27.000000000 +0200 +++ new/iperf-3.9/src/iperf_api.c 2020-08-15 00:08:27.000000000 +0200 @@ -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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/iperf-3.8.1/src/iperf_api.h new/iperf-3.9/src/iperf_api.h --- old/iperf-3.8.1/src/iperf_api.h 2020-06-10 17:18:27.000000000 +0200 +++ new/iperf-3.9/src/iperf_api.h 2020-08-15 00:08:27.000000000 +0200 @@ -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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/iperf-3.8.1/src/iperf_auth.c new/iperf-3.9/src/iperf_auth.c --- old/iperf-3.8.1/src/iperf_auth.c 2020-06-10 17:18:27.000000000 +0200 +++ new/iperf-3.9/src/iperf_auth.c 2020-08-15 00:08:27.000000000 +0200 @@ -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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/iperf-3.8.1/src/iperf_client_api.c new/iperf-3.9/src/iperf_client_api.c --- old/iperf-3.8.1/src/iperf_client_api.c 2020-06-10 17:18:27.000000000 +0200 +++ new/iperf-3.9/src/iperf_client_api.c 2020-08-15 00:08:27.000000000 +0200 @@ -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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/iperf-3.8.1/src/iperf_config.h.in new/iperf-3.9/src/iperf_config.h.in --- old/iperf-3.8.1/src/iperf_config.h.in 2020-06-10 17:18:27.000000000 +0200 +++ new/iperf-3.9/src/iperf_config.h.in 2020-08-15 00:08:27.000000000 +0200 @@ -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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/iperf-3.8.1/src/iperf_error.c new/iperf-3.9/src/iperf_error.c --- old/iperf-3.8.1/src/iperf_error.c 2020-06-10 17:18:27.000000000 +0200 +++ new/iperf-3.9/src/iperf_error.c 2020-08-15 00:08:27.000000000 +0200 @@ -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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/iperf-3.8.1/src/iperf_locale.c new/iperf-3.9/src/iperf_locale.c --- old/iperf-3.8.1/src/iperf_locale.c 2020-06-10 17:18:27.000000000 +0200 +++ new/iperf-3.9/src/iperf_locale.c 2020-08-15 00:08:27.000000000 +0200 @@ -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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/iperf-3.8.1/src/iperf_sctp.c new/iperf-3.9/src/iperf_sctp.c --- old/iperf-3.8.1/src/iperf_sctp.c 2020-06-10 17:18:27.000000000 +0200 +++ new/iperf-3.9/src/iperf_sctp.c 2020-08-15 00:08:27.000000000 +0200 @@ -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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/iperf-3.8.1/src/iperf_server_api.c new/iperf-3.9/src/iperf_server_api.c --- old/iperf-3.8.1/src/iperf_server_api.c 2020-06-10 17:18:27.000000000 +0200 +++ new/iperf-3.9/src/iperf_server_api.c 2020-08-15 00:08:27.000000000 +0200 @@ -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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/iperf-3.8.1/src/iperf_udp.c new/iperf-3.9/src/iperf_udp.c --- old/iperf-3.8.1/src/iperf_udp.c 2020-06-10 17:18:27.000000000 +0200 +++ new/iperf-3.9/src/iperf_udp.c 2020-08-15 00:08:27.000000000 +0200 @@ -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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/iperf-3.8.1/src/iperf_util.c new/iperf-3.9/src/iperf_util.c --- old/iperf-3.8.1/src/iperf_util.c 2020-06-10 17:18:27.000000000 +0200 +++ new/iperf-3.9/src/iperf_util.c 2020-08-15 00:08:27.000000000 +0200 @@ -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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/iperf-3.8.1/src/iperf_util.h new/iperf-3.9/src/iperf_util.h --- old/iperf-3.8.1/src/iperf_util.h 2020-06-10 17:18:27.000000000 +0200 +++ new/iperf-3.9/src/iperf_util.h 2020-08-15 00:08:27.000000000 +0200 @@ -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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/iperf-3.8.1/src/net.c new/iperf-3.9/src/net.c --- old/iperf-3.8.1/src/net.c 2020-06-10 17:18:27.000000000 +0200 +++ new/iperf-3.9/src/net.c 2020-08-15 00:08:27.000000000 +0200 @@ -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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/iperf-3.8.1/src/net.h new/iperf-3.9/src/net.h --- old/iperf-3.8.1/src/net.h 2020-06-10 17:18:27.000000000 +0200 +++ new/iperf-3.9/src/net.h 2020-08-15 00:08:27.000000000 +0200 @@ -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);
