diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 18:20:54 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 18:20:54 +0000 |
commit | 7c720bec5600a9e607c875c670ca30ed351fa4ba (patch) | |
tree | c38c9bedf07616180feee6b91a1dbea038500b54 | |
parent | Initial commit. (diff) | |
download | iperf-7c720bec5600a9e607c875c670ca30ed351fa4ba.tar.xz iperf-7c720bec5600a9e607c875c670ca30ed351fa4ba.zip |
Adding upstream version 2.1.9+dfsg.upstream/2.1.9+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
121 files changed, 52985 insertions, 0 deletions
@@ -0,0 +1,38 @@ +Mark Gates +Alex Warshavsky + + * original authors + +Ajay Tirumala + + * general improvements + +Jim Ferguson <ferguson@ncsa.uiuc.edu> + + * Project management + +Jon Dugan <jdugan@x1024.net> + + * Project maintainer and release coordinator + * various patches and autoconf fixes, general maintenance + +Feng Qin +Kevin Gibbs + + * windows porting work + +John Estabrook <jestabro@ncsa.uiuc.edu> + +Andrew Gallatin <gallatin@gmail.com> + * threading fix and non Linux performance improvements + +Stephen Hemminger <shemminger@linux-foundation.org> + * Linux congestion control selection and theading improvements + +Nathan Jones <nmjones@users.sourceforge.net> + * patch for underflow when value specified in -n is not a multiple of -l + +Gerrit Renker <grenker@users.sourceforge.net> + * replace costly gettimeofday() with nanonsleep() + +Robert J. McMahon & Tim Auckland @@ -0,0 +1,40 @@ +Copyright (c) 1999-2007, The Board of Trustees of the University of Illinois +All Rights Reserved. + +Iperf performance test +Mark Gates +Ajay Tirumala +Jim Ferguson +Jon Dugan +Feng Qin +Kevin Gibbs +John Estabrook +National Laboratory for Applied Network Research +National Center for Supercomputing Applications +University of Illinois at Urbana-Champaign +http://www.ncsa.uiuc.edu + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software (Iperf) and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + + +Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimers. + +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimers in the documentation and/or +other materials provided with the distribution. + +Neither the names of the University of Illinois, NCSA, nor the names of its +contributors may be used to endorse or promote products derived from this +Software without specific prior written permission. THE SOFTWARE IS PROVIDED +"AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE +AND NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..4cc5011 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,106 @@ +2014-3010 Robert McMahon <rjmcmahon@rjmcmahon.com> +* increased NUN_REPORT_HEADERS to reduce conditional semaphore contention +* Allowed for small report intervals (5 ms vs 500 ms) + +2010-07-08 Jon Dugan <jdugan@x1024.net> + +* bumped default TCP send/recv buffer to 128K (this is not the kernel buffer +that controls the window, but rather the Iperf internal buffer) + +2010-04-10 Jon Dugan <jdugan@x1024.net> + +* update autoconf goo using Autoconf 2.65, this should help portability a bit + +2010-04-02 Ralf Lübben + +* honor -i flag when for a server (-s) when using TCP +* tracker issue 2836973 + +2010-04-01 Deny IP Any Any <denyipanyany@gmail.com> + +* Exit rather than warn on connection failure +* http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=518033 + +2010-03-31 Gerrit Renker <grenker@users.sourceforge.net> + +* Gerrit Renker's version of Ingo's Molnar's patch to further reduce CPU usage +* tracker issue 2006708 + +2010-03-31 Gerrit Renker <grenker@users.sourceforge.net> + +* "neater" output for some units, eg Kbps, Mbps, Gbps +* addresses some typos + +2008-05-09 Gerrit Renker <grenker@users.sourceforge.net> + +* replace costly gettimeofday() with nanonsleep() See: +https://sourceforge.net/tracker/index.php?func=detail&aid=1940009&group_id=128336&atid=711373 + +2008-05-09 Jon Dugan <jdugan@x1024.net> + +* change currLen to unsigned to squelch warning generated by Nathan's patch + +2008-05-09 Nathan Jones <nmjones@users.sourceforge.net> + +* prevent underflow when the amount of data to be transmitted (-n) is not a +multiple of the buffer size (-l) Patch: +https://sourceforge.net/tracker/index.php?func=detail&aid=1943432&group_id=128336&atid=711373 + +2008-04-08 Jon Dugan <jdugan@x1024.net> + +* print report headers only once +* use appropriate report header for UDP tests + +2008-04-07 Jon Dugan <jdugan@x1024.net> + +* Add man page to autoconf goo +* Bump the version in autoconf +* Add missing LICENSE file + +2008-04-04 Jon Dugan <jdugan@x1024.net> + +* Incorporate help string fixes from Claus Klein +* Incorporate patch to restore header line in stats output from Claus Klein +* Reworked help string code to remove redundancy +* Add initial man page + +2008-03-19 Stephen Hemminger <shemminger@linux-foundation.org> + +* Add new option to allow selecting the sender congestion control +algorithm. This is a Linux specific extension useful for testing +other congestion control algorithms. + +2008-03-19 Stephen Hemminger <shemminger@linux-foundation.org> + +* Use sched_yield rather than usleep(0) as it behaves better on Linux + +2008-03-12 Jon Dugan <jdugan@x1024.net> + +* Rework Client::RunTCP so to update the stats for every packet if -i is set. +If -i is not set then the stats are only updated at the end of the run. This +was fallout of Andrew's patch. + +* Added -Wall to CXXFLAGS and CFLAGS. This generated a lot of noise in the +autotools generated files. + +* Added initial AUTHORS file. This is incomplete, but it's a start. + +2008-03-12 Andrew Gallatin <gallatin@gmail.com> + +* Rework threading. This is done by having a condition variable for the reporting +thread rather than using sched_yield and/or usleep. + +* Address performance issues on non Linux systems by avoiding system calls +which are expensive on platforms other than Linux. + +* Fixes from FreeBSD ports: max_size_t is now 64 bits and not Iperf does not +exit on ENOBUFS. + +2007-10-01 JSE <jestabro@ncsa.uiuc.edu> + +* ChangeLog file added + +2007-10-05 JSE <jestabro@ncsa.uiuc.edu> + +* Thread.c (thread_stop): "pthread_cancel (oldTID )" should be +"pthread_cancel (thread->mTID)" @@ -0,0 +1,141 @@ +$Id: INSTALL,v 1.1.1.1 2004/05/18 01:50:44 kgibbs Exp $ + +Briefly: + +Do one-time if needed, e.g. for systems with dnf + dnf install gcc + dnf install gcc-c++ + dnf install make + dnf install automake + +then to build do: + ./configure -- configure for your machine + make -- compile Iperf + make install -- install Iperf, if desired, from root + +and to use: + iperf -s (on machine "foo.bar.edu") + iperf -c foo.bar.edu (on some other machine) + iperf -h (for help screen) + iperf -v (for version information) + + +Platform Specific Notes + +FreeBSD + + If you use a cc or c++ other than the system one, threads may not be + detected properly. To work around this set the following environment + variables: + + setenv CC /usr/bin/cc + setenv CXX /usr/bin/c++ + +--- + +Windows (cross compile from Linux) + +# dnf install mingw32-gcc mingw32-gcc-c++ mingw32-winpthreads-static + +$ ../iperf2-code/configure --host=i686-w64-mingw32 +$ make + +--- + +Windows (Cygwin) + + configure / make as normal: + + $ ../iperf2-code/configure + $ make + + The result requires Cygwin on client machines. + +--- + +Windows (Cygwin + i686-w64-mingw32) + + Use Cygwin Setup to install i686-w64-mingw32 and related packages + + Configure as a cross-compile: + + $ ../iperf2-code/configure -host i686-w64-mingw32 + $ make + + The result runs natively on WinXP and above without requiring Cygwin + +--- + +Windows (MinGW + Msys) + + Install MinGW+Msys + https://sourceforge.net/projects/mingw/ + http://www.mingw.org/wiki/MinGW + http://www.mingw.org/wiki/MSYS + + configure / make as normal: + + $ ../iperf2-code/configure + $ make + + The result runs natively on WinXP and above without requiring + MinGW+Msys on client machines. + +--- + +OpenWRT cross compile (example only) + + Setup buildroot (not fully described here, link https://electrosome.com/cross-compile-openwrt-c-program/) + determine the target environment from the openwrt banner (this example is openwrt) + get the build environment, e.g. git clone https://github.com/openwrt/openwrt.git + update feeds + $ ./scripts/feeds update -a + $ ./scripts/feeds install -a + configure target + $ make menuconfig + Then select Target System, Subtarget and Target Profile as per your target environment, e.g. + Target System: MediaTek Ralink MIPS + Subtarget system: MT7620 based boards + Target profile: NETGEAR R6350 + + Set environment variables (via any editor or manual exports to get) + [rjmcmahon@localhost iperf2-code]$ more ../openwrt.config + export STAGING_DIR=/home/usernmae/Code/openwrt/staging_dir + export TOOLCHAIN_DIR=$STAGING_DIR/toolchain-mipsel_24kc_gcc-8.4.0_musl (this is target dependent) + export LDCFLAGS=$TOOLCHAIN_DIR/usr/lib + export LD_LIBRARY_PATH=$TOOLCHAIN_DIR/usr/lib + export PATH=$TOOLCHAIN_DIR/bin:$PATH + $ source ../openwrt.config + + Download iperf 2 source + $ cd iperf2-code + Run configure, e.g. (replace /home/rjmcmahon/Code with your directory) + $ ./configure --target=mips-buildroot-linux-gnu --host=mips-buildroot-linux-gnu CC=/home/rjmcmahon/Code/openwrt/staging_dir/toolchain-mipsel_24kc_gcc-8.4.0_musl/bin/mipsel-openwrt-linux-gcc CXX=/home/rjmcmahon/Code/openwrt/staging_dir/toolchain-mipsel_24kc_gcc-8.4.0_musl/bin/mipsel-openwrt-linux-g++ + + Cross compile (binary in the src/ directory) + $ make + + Install iperf and shared libraries onto openwrt device + ssh into openwrt device, $ opkg install libstdcpp + $ scp src/iperf user@host:/usr/bin + +--- +Other configure and compile options + + ./configure --enable-thread-debug - used for tool debug + ./configure --enable-fastsampling - sub millisecond timestamping + ./configure --enable-packet-debug - show packet sequence numbers - very chatty + ./configure --enable-checkprograms - compile supplmentary test programs + ./configure --disable-ipv6 + ./configure --disable-multicast + ./configure --disable-threads + ./configure --enable-debuginfo + ./configure --enable-debug-symbols - enable debugging with symbols + ./configure --enable-default-localonly - limit test traffic to the local network (off by default) +--- + +dnf installs needed for build: + + dnf install gcc + dnf install gcc-c++ + dnf install automake
\ No newline at end of file diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..1251caa --- /dev/null +++ b/Makefile.am @@ -0,0 +1,18 @@ +AUTOMAKE_OPTIONS = foreign +SUBDIRS = compat doc include src man + +AM_CPPFLAGS = @STRIP_BEGIN@ \ + -I$(top_srcdir)/include \ + -I$(top_builddir)/include \ + @STRIP_END@ + +AM_CXXFLAGS = -Wall +AM_FLAGS = -Wall + +EXTRA_DIST = t +TEST_EXTENSIONS = .sh +TESTS = t/t1_tcp.sh t/t2_tcp6.sh t/t3_udp.sh t/t4_udp6.sh \ + t/t5_f.sh t/t6_filelong.sh t/t7_n.sh t/t8_num.sh \ + t/t9_parallel.sh t/t10_dualtest.sh t/t11_tradeoff.sh \ + t/t12_full_duplex.sh t/t13_reverse.sh + diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 0000000..ca7d36d --- /dev/null +++ b/Makefile.in @@ -0,0 +1,1180 @@ +# Makefile.in generated by automake 1.16.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = . +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/m4/dast.m4 $(top_srcdir)/m4/ax_pthread.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ + $(am__configure_deps) $(am__DIST_COMMON) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno config.status.lineno +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + cscope check recheck distdir distdir-am dist dist-all \ + distcheck +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) \ + config.h.in +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +CSCOPE = cscope +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red='[0;31m'; \ + grn='[0;32m'; \ + lgn='[1;32m'; \ + blu='[1;34m'; \ + mgn='[0;35m'; \ + brg='[1m'; \ + std='[m'; \ + fi; \ +} +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__recheck_rx = ^[ ]*:recheck:[ ]* +am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* +am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* +# A command that, given a newline-separated list of test names on the +# standard input, print the name of the tests that are to be re-run +# upon "make recheck". +am__list_recheck_tests = $(AWK) '{ \ + recheck = 1; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + { \ + if ((getline line2 < ($$0 ".log")) < 0) \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ + { \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ + { \ + break; \ + } \ + }; \ + if (recheck) \ + print $$0; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# A command that, given a newline-separated list of test names on the +# standard input, create the global log from their .trs and .log files. +am__create_global_log = $(AWK) ' \ +function fatal(msg) \ +{ \ + print "fatal: making $@: " msg | "cat >&2"; \ + exit 1; \ +} \ +function rst_section(header) \ +{ \ + print header; \ + len = length(header); \ + for (i = 1; i <= len; i = i + 1) \ + printf "="; \ + printf "\n\n"; \ +} \ +{ \ + copy_in_global_log = 1; \ + global_test_result = "RUN"; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".trs"); \ + if (line ~ /$(am__global_test_result_rx)/) \ + { \ + sub("$(am__global_test_result_rx)", "", line); \ + sub("[ ]*$$", "", line); \ + global_test_result = line; \ + } \ + else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ + copy_in_global_log = 0; \ + }; \ + if (copy_in_global_log) \ + { \ + rst_section(global_test_result ": " $$0); \ + while ((rc = (getline line < ($$0 ".log"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".log"); \ + print line; \ + }; \ + printf "\n"; \ + }; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# Restructured Text title. +am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } +# Solaris 10 'make', and several other traditional 'make' implementations, +# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it +# by disabling -e (using the XSI extension "set +e") if it's set. +am__sh_e_setup = case $$- in *e*) set +e;; esac +# Default flags passed to test drivers. +am__common_driver_flags = \ + --color-tests "$$am__color_tests" \ + --enable-hard-errors "$$am__enable_hard_errors" \ + --expect-failure "$$am__expect_failure" +# To be inserted before the command running the test. Creates the +# directory for the log if needed. Stores in $dir the directory +# containing $f, in $tst the test, in $log the log. Executes the +# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and +# passes TESTS_ENVIRONMENT. Set up options for the wrapper that +# will run the test scripts (or their associated LOG_COMPILER, if +# thy have one). +am__check_pre = \ +$(am__sh_e_setup); \ +$(am__vpath_adj_setup) $(am__vpath_adj) \ +$(am__tty_colors); \ +srcdir=$(srcdir); export srcdir; \ +case "$@" in \ + */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ + *) am__odir=.;; \ +esac; \ +test "x$$am__odir" = x"." || test -d "$$am__odir" \ + || $(MKDIR_P) "$$am__odir" || exit $$?; \ +if test -f "./$$f"; then dir=./; \ +elif test -f "$$f"; then dir=; \ +else dir="$(srcdir)/"; fi; \ +tst=$$dir$$f; log='$@'; \ +if test -n '$(DISABLE_HARD_ERRORS)'; then \ + am__enable_hard_errors=no; \ +else \ + am__enable_hard_errors=yes; \ +fi; \ +case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ + am__expect_failure=yes;; \ + *) \ + am__expect_failure=no;; \ +esac; \ +$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) +# A shell command to get the names of the tests scripts with any registered +# extension removed (i.e., equivalently, the names of the test logs, with +# the '.log' extension removed). The result is saved in the shell variable +# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, +# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", +# since that might cause problem with VPATH rewrites for suffix-less tests. +# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. +am__set_TESTS_bases = \ + bases='$(TEST_LOGS)'; \ + bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ + bases=`echo $$bases` +RECHECK_LOGS = $(TEST_LOGS) +TEST_SUITE_LOG = test-suite.log +am__test_logs1 = $(TESTS:=.log) +am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) +TEST_LOGS = $(am__test_logs2:.sh.log=.log) +SH_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver +SH_LOG_COMPILE = $(SH_LOG_COMPILER) $(AM_SH_LOG_FLAGS) $(SH_LOG_FLAGS) +am__set_b = \ + case '$@' in \ + */*) \ + case '$*' in \ + */*) b='$*';; \ + *) b=`echo '$@' | sed 's/\.log$$//'`; \ + esac;; \ + *) \ + b='$*';; \ + esac +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in AUTHORS \ + COPYING ChangeLog INSTALL README compile config.guess \ + config.sub depcomp install-sh missing test-driver +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + if test -d "$(distdir)"; then \ + find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -rf "$(distdir)" \ + || { sleep 5 && rm -rf "$(distdir)"; }; \ + else :; fi +am__post_remove_distdir = $(am__remove_distdir) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +DIST_ARCHIVES = $(distdir).tar.gz +GZIP_ENV = --best +DIST_TARGETS = dist-gzip +distuninstallcheck_listfiles = find . -type f -print +am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ + | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' +distcleancheck_listfiles = find . -type f -print +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +STRIP_BEGIN = @STRIP_BEGIN@ +STRIP_DUMMY = @STRIP_DUMMY@ +STRIP_END = @STRIP_END@ +VERSION = @VERSION@ +WEB100_CFLAGS = @WEB100_CFLAGS@ +WEB100_CONFIG = @WEB100_CONFIG@ +WEB100_LIBS = @WEB100_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = foreign +SUBDIRS = compat doc include src man +AM_CPPFLAGS = @STRIP_BEGIN@ \ + -I$(top_srcdir)/include \ + -I$(top_builddir)/include \ + @STRIP_END@ + +AM_CXXFLAGS = -Wall +AM_FLAGS = -Wall +EXTRA_DIST = t +TEST_EXTENSIONS = .sh +TESTS = t/t1_tcp.sh t/t2_tcp6.sh t/t3_udp.sh t/t4_udp6.sh \ + t/t5_f.sh t/t6_filelong.sh t/t7_n.sh t/t8_num.sh \ + t/t9_parallel.sh t/t10_dualtest.sh t/t11_tradeoff.sh \ + t/t12_full_duplex.sh t/t13_reverse.sh + +all: config.h + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +.SUFFIXES: +.SUFFIXES: .log .sh .sh$(EXEEXT) .trs +am--refresh: Makefile + @: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ + $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + $(am__cd) $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +$(am__aclocal_m4_deps): + +config.h: stamp-h1 + @test -f $@ || rm -f stamp-h1 + @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 + +stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status config.h +$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) + rm -f stamp-h1 + touch $@ + +distclean-hdr: + -rm -f config.h stamp-h1 + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscope: cscope.files + test ! -s cscope.files \ + || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) +clean-cscope: + -rm -f cscope.files +cscope.files: clean-cscope cscopelist +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + -rm -f cscope.out cscope.in.out cscope.po.out cscope.files + +# Recover from deleted '.trs' file; this should ensure that +# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create +# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells +# to avoid problems with "make -n". +.log.trs: + rm -f $< $@ + $(MAKE) $(AM_MAKEFLAGS) $< + +# Leading 'am--fnord' is there to ensure the list of targets does not +# expand to empty, as could happen e.g. with make check TESTS=''. +am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) +am--force-recheck: + @: + +$(TEST_SUITE_LOG): $(TEST_LOGS) + @$(am__set_TESTS_bases); \ + am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ + redo_bases=`for i in $$bases; do \ + am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ + done`; \ + if test -n "$$redo_bases"; then \ + redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ + redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ + if $(am__make_dryrun); then :; else \ + rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ + fi; \ + fi; \ + if test -n "$$am__remaking_logs"; then \ + echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ + "recursion detected" >&2; \ + elif test -n "$$redo_logs"; then \ + am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ + fi; \ + if $(am__make_dryrun); then :; else \ + st=0; \ + errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ + for i in $$redo_bases; do \ + test -f $$i.trs && test -r $$i.trs \ + || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ + test -f $$i.log && test -r $$i.log \ + || { echo "$$errmsg $$i.log" >&2; st=1; }; \ + done; \ + test $$st -eq 0 || exit 1; \ + fi + @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ + ws='[ ]'; \ + results=`for b in $$bases; do echo $$b.trs; done`; \ + test -n "$$results" || results=/dev/null; \ + all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ + pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ + fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ + skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ + xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ + xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ + error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ + if test `expr $$fail + $$xpass + $$error` -eq 0; then \ + success=true; \ + else \ + success=false; \ + fi; \ + br='==================='; br=$$br$$br$$br$$br; \ + result_count () \ + { \ + if test x"$$1" = x"--maybe-color"; then \ + maybe_colorize=yes; \ + elif test x"$$1" = x"--no-color"; then \ + maybe_colorize=no; \ + else \ + echo "$@: invalid 'result_count' usage" >&2; exit 4; \ + fi; \ + shift; \ + desc=$$1 count=$$2; \ + if test $$maybe_colorize = yes && test $$count -gt 0; then \ + color_start=$$3 color_end=$$std; \ + else \ + color_start= color_end=; \ + fi; \ + echo "$${color_start}# $$desc $$count$${color_end}"; \ + }; \ + create_testsuite_report () \ + { \ + result_count $$1 "TOTAL:" $$all "$$brg"; \ + result_count $$1 "PASS: " $$pass "$$grn"; \ + result_count $$1 "SKIP: " $$skip "$$blu"; \ + result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ + result_count $$1 "FAIL: " $$fail "$$red"; \ + result_count $$1 "XPASS:" $$xpass "$$red"; \ + result_count $$1 "ERROR:" $$error "$$mgn"; \ + }; \ + { \ + echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ + $(am__rst_title); \ + create_testsuite_report --no-color; \ + echo; \ + echo ".. contents:: :depth: 2"; \ + echo; \ + for b in $$bases; do echo $$b; done \ + | $(am__create_global_log); \ + } >$(TEST_SUITE_LOG).tmp || exit 1; \ + mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ + if $$success; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ + fi; \ + echo "$${col}$$br$${std}"; \ + echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ + echo "$${col}$$br$${std}"; \ + create_testsuite_report --maybe-color; \ + echo "$$col$$br$$std"; \ + if $$success; then :; else \ + echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ + if test -n "$(PACKAGE_BUGREPORT)"; then \ + echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ + fi; \ + echo "$$col$$br$$std"; \ + fi; \ + $$success || exit 1 + +check-TESTS: + @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list + @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + trs_list=`for i in $$bases; do echo $$i.trs; done`; \ + log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ + exit $$?; +recheck: all + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + bases=`for i in $$bases; do echo $$i; done \ + | $(am__list_recheck_tests)` || exit 1; \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + log_list=`echo $$log_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ + am__force_recheck=am--force-recheck \ + TEST_LOGS="$$log_list"; \ + exit $$? +.sh.log: + @p='$<'; \ + $(am__set_b); \ + $(am__check_pre) $(SH_LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_SH_LOG_DRIVER_FLAGS) $(SH_LOG_DRIVER_FLAGS) -- $(SH_LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +@am__EXEEXT_TRUE@.sh$(EXEEXT).log: +@am__EXEEXT_TRUE@ @p='$<'; \ +@am__EXEEXT_TRUE@ $(am__set_b); \ +@am__EXEEXT_TRUE@ $(am__check_pre) $(SH_LOG_DRIVER) --test-name "$$f" \ +@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ +@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_SH_LOG_DRIVER_FLAGS) $(SH_LOG_DRIVER_FLAGS) -- $(SH_LOG_COMPILE) \ +@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + $(am__remove_distdir) + test -d "$(distdir)" || mkdir "$(distdir)" + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done + -test -n "$(am__skip_mode_fix)" \ + || find "$(distdir)" -type d ! -perm -755 \ + -exec chmod u+rwx,go+rx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r "$(distdir)" +dist-gzip: distdir + tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz + $(am__post_remove_distdir) + +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 + $(am__post_remove_distdir) + +dist-lzip: distdir + tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz + $(am__post_remove_distdir) + +dist-xz: distdir + tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz + $(am__post_remove_distdir) + +dist-zstd: distdir + tardir=$(distdir) && $(am__tar) | zstd -c $${ZSTD_CLEVEL-$${ZSTD_OPT--19}} >$(distdir).tar.zst + $(am__post_remove_distdir) + +dist-tarZ: distdir + @echo WARNING: "Support for distribution archives compressed with" \ + "legacy program 'compress' is deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z + $(am__post_remove_distdir) + +dist-shar: distdir + @echo WARNING: "Support for shar distribution archives is" \ + "deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 + shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz + $(am__post_remove_distdir) + +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__post_remove_distdir) + +dist dist-all: + $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' + $(am__post_remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.lz*) \ + lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ + *.tar.xz*) \ + xz -dc $(distdir).tar.xz | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + *.tar.zst*) \ + zstd -dc $(distdir).tar.zst | $(am__untar) ;;\ + esac + chmod -R a-w $(distdir) + chmod u+w $(distdir) + mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst + chmod a-w $(distdir) + test -d $(distdir)/_build || exit 0; \ + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && am__cwd=`pwd` \ + && $(am__cd) $(distdir)/_build/sub \ + && ../../configure \ + $(AM_DISTCHECK_CONFIGURE_FLAGS) \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + --srcdir=../.. --prefix="$$dc_install_base" \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ + && cd "$$am__cwd" \ + || exit 1 + $(am__post_remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' +distuninstallcheck: + @test -n '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: trying to run $@ with an empty' \ + '$$(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + $(am__cd) '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-recursive +all-am: Makefile config.h +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) + -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) + -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-hdr distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) all check-am install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ + am--refresh check check-TESTS check-am clean clean-cscope \ + clean-generic cscope cscopelist-am ctags ctags-am dist \ + dist-all dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ \ + dist-xz dist-zip dist-zstd distcheck distclean \ + distclean-generic distclean-hdr distclean-tags distcleancheck \ + distdir distuninstallcheck dvi dvi-am html html-am info \ + info-am install install-am install-data install-data-am \ + install-dvi install-dvi-am install-exec install-exec-am \ + install-html install-html-am install-info install-info-am \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ + pdf-am ps ps-am recheck tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: @@ -0,0 +1,38 @@ +This is Iperf v2.0.x, a tool for measuring Internet bandwidth performance. +See the doc directory for more documentation. + +Briefly: + +Do one-time if needed: + dnf install gcc + dnf install gcc-c++ + dnf install automake + +then to build do: + ./configure -- configure for your machine + make -- compile Iperf + make install -- install Iperf, if desired, from root + +and to use: + iperf -s (on machine "foo.bar.edu") + iperf -c foo.bar.edu (on some other machine) + iperf -h (for help screen) + iperf -v (for version information) + +and for more information (requires make install) + man iperf + +Finally, see INSTALL, doc/RELEASE_NOTES, and doc/DESIGN_NOTES for a bit more + +The SOURCE CODE is the AUTHORITATIVE source. Any COMMENTS found in the source ARE NOT. + +Copyright 1999, 2000, 2001, 2002, 2003, 2004 +The Board of Trustees of the University of Illinois +All rights reserved +See UI License (doc/ui_license.html) for complete details. + +More copyright per years 2014 - 2020 +Broadcom Corporation +All Rights Reserved + +$Id: README,v 1.1.1.1 2004/05/18 01:50:44 kgibbs Exp $ diff --git a/aclocal.m4 b/aclocal.m4 new file mode 100644 index 0000000..cd1b5c1 --- /dev/null +++ b/aclocal.m4 @@ -0,0 +1,1173 @@ +# generated automatically by aclocal 1.16.2 -*- Autoconf -*- + +# Copyright (C) 1996-2020 Free Software Foundation, Inc. + +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, +[m4_warning([this file was generated for autoconf 2.69. +You have another version of autoconf. It may work, but is not guaranteed to. +If you have problems, you may need to regenerate the build system entirely. +To do so, use the procedure documented by the package, typically 'autoreconf'.])]) + +# Copyright (C) 2002-2020 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +# (This private macro should not be called outside this file.) +AC_DEFUN([AM_AUTOMAKE_VERSION], +[am__api_version='1.16' +dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to +dnl require some minimum version. Point them to the right macro. +m4_if([$1], [1.16.2], [], + [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl +]) + +# _AM_AUTOCONF_VERSION(VERSION) +# ----------------------------- +# aclocal traces this macro to find the Autoconf version. +# This is a private macro too. Using m4_define simplifies +# the logic in aclocal, which can simply ignore this definition. +m4_define([_AM_AUTOCONF_VERSION], []) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. +# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], +[AM_AUTOMAKE_VERSION([1.16.2])dnl +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) + +# AM_AUX_DIR_EXPAND -*- Autoconf -*- + +# Copyright (C) 2001-2020 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to +# '$srcdir', '$srcdir/..', or '$srcdir/../..'. +# +# Of course, Automake must honor this variable whenever it calls a +# tool from the auxiliary directory. The problem is that $srcdir (and +# therefore $ac_aux_dir as well) can be either absolute or relative, +# depending on how configure is run. This is pretty annoying, since +# it makes $ac_aux_dir quite unusable in subdirectories: in the top +# source directory, any form will work fine, but in subdirectories a +# relative path needs to be adjusted first. +# +# $ac_aux_dir/missing +# fails when called from a subdirectory if $ac_aux_dir is relative +# $top_srcdir/$ac_aux_dir/missing +# fails if $ac_aux_dir is absolute, +# fails when called from a subdirectory in a VPATH build with +# a relative $ac_aux_dir +# +# The reason of the latter failure is that $top_srcdir and $ac_aux_dir +# are both prefixed by $srcdir. In an in-source build this is usually +# harmless because $srcdir is '.', but things will broke when you +# start a VPATH build or use an absolute $srcdir. +# +# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, +# iff we strip the leading $srcdir from $ac_aux_dir. That would be: +# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` +# and then we would define $MISSING as +# MISSING="\${SHELL} $am_aux_dir/missing" +# This will work as long as MISSING is not called from configure, because +# unfortunately $(top_srcdir) has no meaning in configure. +# However there are other variables, like CC, which are often used in +# configure, and could therefore not use this "fixed" $ac_aux_dir. +# +# Another solution, used here, is to always expand $ac_aux_dir to an +# absolute PATH. The drawback is that using absolute paths prevent a +# configured tree to be moved without reconfiguration. + +AC_DEFUN([AM_AUX_DIR_EXPAND], +[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` +]) + +# AM_CONDITIONAL -*- Autoconf -*- + +# Copyright (C) 1997-2020 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +AC_DEFUN([AM_CONDITIONAL], +[AC_PREREQ([2.52])dnl + m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_SUBST([$1_TRUE])dnl +AC_SUBST([$1_FALSE])dnl +_AM_SUBST_NOTMAKE([$1_TRUE])dnl +_AM_SUBST_NOTMAKE([$1_FALSE])dnl +m4_define([_AM_COND_VALUE_$1], [$2])dnl +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([[conditional "$1" was never defined. +Usually this means the macro was only invoked conditionally.]]) +fi])]) + +# Copyright (C) 1999-2020 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + + +# There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + +# _AM_DEPENDENCIES(NAME) +# ---------------------- +# See how the compiler implements dependency checking. +# NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". +# We try a few techniques and use that to set a single cache variable. +# +# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was +# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular +# dependency, and given that the user is not expected to run this macro, +# just rely on AC_PROG_CC. +AC_DEFUN([_AM_DEPENDENCIES], +[AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl +AC_REQUIRE([AM_MAKE_INCLUDE])dnl +AC_REQUIRE([AM_DEP_TRACK])dnl + +m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], + [$1], [CXX], [depcc="$CXX" am_compiler_list=], + [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], + [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], + [$1], [UPC], [depcc="$UPC" am_compiler_list=], + [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) + +AC_CACHE_CHECK([dependency style of $depcc], + [am_cv_$1_dependencies_compiler_type], +[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_$1_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` + fi + am__universal=false + m4_case([$1], [CC], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac], + [CXX], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac]) + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_$1_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_$1_dependencies_compiler_type=none +fi +]) +AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) +AM_CONDITIONAL([am__fastdep$1], [ + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) +]) + + +# AM_SET_DEPDIR +# ------------- +# Choose a directory name for dependency files. +# This macro is AC_REQUIREd in _AM_DEPENDENCIES. +AC_DEFUN([AM_SET_DEPDIR], +[AC_REQUIRE([AM_SET_LEADING_DOT])dnl +AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl +]) + + +# AM_DEP_TRACK +# ------------ +AC_DEFUN([AM_DEP_TRACK], +[AC_ARG_ENABLE([dependency-tracking], [dnl +AS_HELP_STRING( + [--enable-dependency-tracking], + [do not reject slow dependency extractors]) +AS_HELP_STRING( + [--disable-dependency-tracking], + [speeds up one-time build])]) +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi +AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +AC_SUBST([AMDEPBACKSLASH])dnl +_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl +AC_SUBST([am__nodep])dnl +_AM_SUBST_NOTMAKE([am__nodep])dnl +]) + +# Generate code to set up dependency tracking. -*- Autoconf -*- + +# Copyright (C) 1999-2020 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_OUTPUT_DEPENDENCY_COMMANDS +# ------------------------------ +AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], +[{ + # Older Autoconf quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + # TODO: see whether this extra hack can be removed once we start + # requiring Autoconf 2.70 or later. + AS_CASE([$CONFIG_FILES], + [*\'*], [eval set x "$CONFIG_FILES"], + [*], [set x $CONFIG_FILES]) + shift + # Used to flag and report bootstrapping failures. + am_rc=0 + for am_mf + do + # Strip MF so we end up with the name of the file. + am_mf=`AS_ECHO(["$am_mf"]) | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile which includes + # dependency-tracking related rules and includes. + # Grep'ing the whole file directly is not great: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ + || continue + am_dirpart=`AS_DIRNAME(["$am_mf"])` + am_filepart=`AS_BASENAME(["$am_mf"])` + AM_RUN_LOG([cd "$am_dirpart" \ + && sed -e '/# am--include-marker/d' "$am_filepart" \ + | $MAKE -f - am--depfiles]) || am_rc=$? + done + if test $am_rc -ne 0; then + AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments + for automatic dependency tracking. If GNU make was not used, consider + re-running the configure script with MAKE="gmake" (or whatever is + necessary). You can also try re-running configure with the + '--disable-dependency-tracking' option to at least be able to build + the package (albeit without support for automatic dependency tracking).]) + fi + AS_UNSET([am_dirpart]) + AS_UNSET([am_filepart]) + AS_UNSET([am_mf]) + AS_UNSET([am_rc]) + rm -f conftest-deps.mk +} +])# _AM_OUTPUT_DEPENDENCY_COMMANDS + + +# AM_OUTPUT_DEPENDENCY_COMMANDS +# ----------------------------- +# This macro should only be invoked once -- use via AC_REQUIRE. +# +# This code is only required when automatic dependency tracking is enabled. +# This creates each '.Po' and '.Plo' makefile fragment that we'll need in +# order to bootstrap the dependency handling code. +AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], +[AC_CONFIG_COMMANDS([depfiles], + [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], + [AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"])]) + +# Do all the work for Automake. -*- Autoconf -*- + +# Copyright (C) 1996-2020 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This macro actually does too much. Some checks are only needed if +# your package does certain things. But this isn't really a big deal. + +dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. +m4_define([AC_PROG_CC], +m4_defn([AC_PROG_CC]) +[_AM_PROG_CC_C_O +]) + +# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) +# AM_INIT_AUTOMAKE([OPTIONS]) +# ----------------------------------------------- +# The call with PACKAGE and VERSION arguments is the old style +# call (pre autoconf-2.50), which is being phased out. PACKAGE +# and VERSION should now be passed to AC_INIT and removed from +# the call to AM_INIT_AUTOMAKE. +# We support both call styles for the transition. After +# the next Automake release, Autoconf can make the AC_INIT +# arguments mandatory, and then we can depend on a new Autoconf +# release and drop the old call support. +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_PREREQ([2.65])dnl +dnl Autoconf wants to disallow AM_ names. We explicitly allow +dnl the ones we care about. +m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl +AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl +AC_REQUIRE([AC_PROG_INSTALL])dnl +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi +AC_SUBST([CYGPATH_W]) + +# Define the identity of the package. +dnl Distinguish between old-style and new-style calls. +m4_ifval([$2], +[AC_DIAGNOSE([obsolete], + [$0: two- and three-arguments forms are deprecated.]) +m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl + AC_SUBST([PACKAGE], [$1])dnl + AC_SUBST([VERSION], [$2])], +[_AM_SET_OPTIONS([$1])dnl +dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. +m4_if( + m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), + [ok:ok],, + [m4_fatal([AC_INIT should be called with package and version arguments])])dnl + AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl + AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl + +_AM_IF_OPTION([no-define],, +[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) + AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) +AM_MISSING_PROG([AUTOCONF], [autoconf]) +AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) +AM_MISSING_PROG([AUTOHEADER], [autoheader]) +AM_MISSING_PROG([MAKEINFO], [makeinfo]) +AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl +AC_REQUIRE([AC_PROG_MKDIR_P])dnl +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# <https://lists.gnu.org/archive/html/automake/2012-07/msg00001.html> +# <https://lists.gnu.org/archive/html/automake/2012-07/msg00014.html> +AC_SUBST([mkdir_p], ['$(MKDIR_P)']) +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl +AC_REQUIRE([AM_SET_LEADING_DOT])dnl +_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], + [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], + [_AM_PROG_TAR([v7])])]) +_AM_IF_OPTION([no-dependencies],, +[AC_PROVIDE_IFELSE([AC_PROG_CC], + [_AM_DEPENDENCIES([CC])], + [m4_define([AC_PROG_CC], + m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_CXX], + [_AM_DEPENDENCIES([CXX])], + [m4_define([AC_PROG_CXX], + m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJC], + [_AM_DEPENDENCIES([OBJC])], + [m4_define([AC_PROG_OBJC], + m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], + [_AM_DEPENDENCIES([OBJCXX])], + [m4_define([AC_PROG_OBJCXX], + m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl +]) +AC_REQUIRE([AM_SILENT_RULES])dnl +dnl The testsuite driver may need to know about EXEEXT, so add the +dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This +dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. +AC_CONFIG_COMMANDS_PRE(dnl +[m4_provide_if([_AM_COMPILER_EXEEXT], + [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl + +# POSIX will say in a future version that running "rm -f" with no argument +# is OK; and we want to be able to make that assumption in our Makefile +# recipes. So use an aggressive probe to check that the usage we want is +# actually supported "in the wild" to an acceptable degree. +# See automake bug#10828. +# To make any issue more visible, cause the running configure to be aborted +# by default if the 'rm' program in use doesn't match our expectations; the +# user can still override this though. +if rm -f && rm -fr && rm -rf; then : OK; else + cat >&2 <<'END' +Oops! + +Your 'rm' program seems unable to run without file operands specified +on the command line, even when the '-f' option is present. This is contrary +to the behaviour of most rm programs out there, and not conforming with +the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542> + +Please tell bug-automake@gnu.org about your system, including the value +of your $PATH and any error possibly output before this message. This +can help us improve future automake versions. + +END + if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then + echo 'Configuration will proceed anyway, since you have set the' >&2 + echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 + echo >&2 + else + cat >&2 <<'END' +Aborting the configuration process, to ensure you take notice of the issue. + +You can download and install GNU coreutils to get an 'rm' implementation +that behaves properly: <https://www.gnu.org/software/coreutils/>. + +If you want to complete the configuration process using your problematic +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM +to "yes", and re-run configure. + +END + AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) + fi +fi +dnl The trailing newline in this macro's definition is deliberate, for +dnl backward compatibility and to allow trailing 'dnl'-style comments +dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. +]) + +dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not +dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further +dnl mangled by Autoconf and run in a shell conditional statement. +m4_define([_AC_COMPILER_EXEEXT], +m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) + +# When config.status generates a header, we must update the stamp-h file. +# This file resides in the same directory as the config header +# that is generated. The stamp files are numbered to have different names. + +# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the +# loop where config.status creates the headers, so we can generate +# our stamp files there. +AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], +[# Compute $1's index in $config_headers. +_am_arg=$1 +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) + +# Copyright (C) 2001-2020 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_SH +# ------------------ +# Define $install_sh. +AC_DEFUN([AM_PROG_INSTALL_SH], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +if test x"${install_sh+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi +AC_SUBST([install_sh])]) + +# Copyright (C) 2003-2020 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# Check whether the underlying file-system supports filenames +# with a leading dot. For instance MS-DOS doesn't. +AC_DEFUN([AM_SET_LEADING_DOT], +[rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null +AC_SUBST([am__leading_dot])]) + +# Add --enable-maintainer-mode option to configure. -*- Autoconf -*- +# From Jim Meyering + +# Copyright (C) 1996-2020 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_MAINTAINER_MODE([DEFAULT-MODE]) +# ---------------------------------- +# Control maintainer-specific portions of Makefiles. +# Default is to disable them, unless 'enable' is passed literally. +# For symmetry, 'disable' may be passed as well. Anyway, the user +# can override the default with the --enable/--disable switch. +AC_DEFUN([AM_MAINTAINER_MODE], +[m4_case(m4_default([$1], [disable]), + [enable], [m4_define([am_maintainer_other], [disable])], + [disable], [m4_define([am_maintainer_other], [enable])], + [m4_define([am_maintainer_other], [enable]) + m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])]) +AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) + dnl maintainer-mode's default is 'disable' unless 'enable' is passed + AC_ARG_ENABLE([maintainer-mode], + [AS_HELP_STRING([--]am_maintainer_other[-maintainer-mode], + am_maintainer_other[ make rules and dependencies not useful + (and sometimes confusing) to the casual installer])], + [USE_MAINTAINER_MODE=$enableval], + [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes])) + AC_MSG_RESULT([$USE_MAINTAINER_MODE]) + AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes]) + MAINT=$MAINTAINER_MODE_TRUE + AC_SUBST([MAINT])dnl +] +) + +# Check to see how 'make' treats includes. -*- Autoconf -*- + +# Copyright (C) 2001-2020 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_MAKE_INCLUDE() +# ----------------- +# Check whether make has an 'include' directive that can support all +# the idioms we need for our automatic dependency tracking code. +AC_DEFUN([AM_MAKE_INCLUDE], +[AC_MSG_CHECKING([whether ${MAKE-make} supports the include directive]) +cat > confinc.mk << 'END' +am__doit: + @echo this is the am__doit target >confinc.out +.PHONY: am__doit +END +am__include="#" +am__quote= +# BSD make does it like this. +echo '.include "confinc.mk" # ignored' > confmf.BSD +# Other make implementations (GNU, Solaris 10, AIX) do it like this. +echo 'include confinc.mk # ignored' > confmf.GNU +_am_result=no +for s in GNU BSD; do + AM_RUN_LOG([${MAKE-make} -f confmf.$s && cat confinc.out]) + AS_CASE([$?:`cat confinc.out 2>/dev/null`], + ['0:this is the am__doit target'], + [AS_CASE([$s], + [BSD], [am__include='.include' am__quote='"'], + [am__include='include' am__quote=''])]) + if test "$am__include" != "#"; then + _am_result="yes ($s style)" + break + fi +done +rm -f confinc.* confmf.* +AC_MSG_RESULT([${_am_result}]) +AC_SUBST([am__include])]) +AC_SUBST([am__quote])]) + +# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- + +# Copyright (C) 1997-2020 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it is modern enough. +# If it is, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([missing])dnl +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --is-lightweight"; then + am_missing_run="$MISSING " +else + am_missing_run= + AC_MSG_WARN(['missing' script is too old or missing]) +fi +]) + +# Helper functions for option handling. -*- Autoconf -*- + +# Copyright (C) 2001-2020 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_MANGLE_OPTION(NAME) +# ----------------------- +AC_DEFUN([_AM_MANGLE_OPTION], +[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) + +# _AM_SET_OPTION(NAME) +# -------------------- +# Set option NAME. Presently that only means defining a flag for this option. +AC_DEFUN([_AM_SET_OPTION], +[m4_define(_AM_MANGLE_OPTION([$1]), [1])]) + +# _AM_SET_OPTIONS(OPTIONS) +# ------------------------ +# OPTIONS is a space-separated list of Automake options. +AC_DEFUN([_AM_SET_OPTIONS], +[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) + +# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) +# ------------------------------------------- +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +AC_DEFUN([_AM_IF_OPTION], +[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) + +# Copyright (C) 1999-2020 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_PROG_CC_C_O +# --------------- +# Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC +# to automatically call this. +AC_DEFUN([_AM_PROG_CC_C_O], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([compile])dnl +AC_LANG_PUSH([C])dnl +AC_CACHE_CHECK( + [whether $CC understands -c and -o together], + [am_cv_prog_cc_c_o], + [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i]) +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +AC_LANG_POP([C])]) + +# For backward compatibility. +AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) + +# Copyright (C) 2001-2020 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_RUN_LOG(COMMAND) +# ------------------- +# Run COMMAND, save the exit status in ac_status, and log it. +# (This has been adapted from Autoconf's _AC_RUN_LOG macro.) +AC_DEFUN([AM_RUN_LOG], +[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD + ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + (exit $ac_status); }]) + +# Check to make sure that the build environment is sane. -*- Autoconf -*- + +# Copyright (C) 1996-2020 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[[\\\"\#\$\&\'\`$am_lf]]*) + AC_MSG_ERROR([unsafe absolute working directory name]);; +esac +case $srcdir in + *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) + AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; +esac + +# Do 'set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken + alias in your environment]) + fi + if test "$[2]" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$[2]" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +AC_MSG_RESULT([yes]) +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi +AC_CONFIG_COMMANDS_PRE( + [AC_MSG_CHECKING([that generated files are newer than configure]) + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + AC_MSG_RESULT([done])]) +rm -f conftest.file +]) + +# Copyright (C) 2009-2020 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_SILENT_RULES([DEFAULT]) +# -------------------------- +# Enable less verbose build rules; with the default set to DEFAULT +# ("yes" being less verbose, "no" or empty being verbose). +AC_DEFUN([AM_SILENT_RULES], +[AC_ARG_ENABLE([silent-rules], [dnl +AS_HELP_STRING( + [--enable-silent-rules], + [less verbose build output (undo: "make V=1")]) +AS_HELP_STRING( + [--disable-silent-rules], + [verbose build output (undo: "make V=0")])dnl +]) +case $enable_silent_rules in @%:@ ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; +esac +dnl +dnl A few 'make' implementations (e.g., NonStop OS and NextStep) +dnl do not support nested variable expansions. +dnl See automake bug#9928 and bug#10237. +am_make=${MAKE-make} +AC_CACHE_CHECK([whether $am_make supports nested variables], + [am_cv_make_support_nested_variables], + [if AS_ECHO([['TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi]) +if test $am_cv_make_support_nested_variables = yes; then + dnl Using '$V' instead of '$(V)' breaks IRIX make. + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AC_SUBST([AM_V])dnl +AM_SUBST_NOTMAKE([AM_V])dnl +AC_SUBST([AM_DEFAULT_V])dnl +AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl +AC_SUBST([AM_DEFAULT_VERBOSITY])dnl +AM_BACKSLASH='\' +AC_SUBST([AM_BACKSLASH])dnl +_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl +]) + +# Copyright (C) 2001-2020 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_STRIP +# --------------------- +# One issue with vendor 'install' (even GNU) is that you can't +# specify the program used to strip binaries. This is especially +# annoying in cross-compiling environments, where the build's strip +# is unlikely to handle the host's binaries. +# Fortunately install-sh will honor a STRIPPROG variable, so we +# always use install-sh in "make install-strip", and initialize +# STRIPPROG with the value of the STRIP variable (set by the user). +AC_DEFUN([AM_PROG_INSTALL_STRIP], +[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. +if test "$cross_compiling" != no; then + AC_CHECK_TOOL([STRIP], [strip], :) +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +# Copyright (C) 2006-2020 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. +# This macro is traced by Automake. +AC_DEFUN([_AM_SUBST_NOTMAKE]) + +# AM_SUBST_NOTMAKE(VARIABLE) +# -------------------------- +# Public sister of _AM_SUBST_NOTMAKE. +AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) + +# Check how to create a tarball. -*- Autoconf -*- + +# Copyright (C) 2004-2020 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_PROG_TAR(FORMAT) +# -------------------- +# Check how to create a tarball in format FORMAT. +# FORMAT should be one of 'v7', 'ustar', or 'pax'. +# +# Substitute a variable $(am__tar) that is a command +# writing to stdout a FORMAT-tarball containing the directory +# $tardir. +# tardir=directory && $(am__tar) > result.tar +# +# Substitute a variable $(am__untar) that extract such +# a tarball read from stdin. +# $(am__untar) < result.tar +# +AC_DEFUN([_AM_PROG_TAR], +[# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AC_SUBST([AMTAR], ['$${TAR-tar}']) + +# We'll loop over all known methods to create a tar archive until one works. +_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' + +m4_if([$1], [v7], + [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], + + [m4_case([$1], + [ustar], + [# The POSIX 1988 'ustar' format is defined with fixed-size fields. + # There is notably a 21 bits limit for the UID and the GID. In fact, + # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 + # and bug#13588). + am_max_uid=2097151 # 2^21 - 1 + am_max_gid=$am_max_uid + # The $UID and $GID variables are not portable, so we need to resort + # to the POSIX-mandated id(1) utility. Errors in the 'id' calls + # below are definitely unexpected, so allow the users to see them + # (that is, avoid stderr redirection). + am_uid=`id -u || echo unknown` + am_gid=`id -g || echo unknown` + AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) + if test $am_uid -le $am_max_uid; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + _am_tools=none + fi + AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) + if test $am_gid -le $am_max_gid; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + _am_tools=none + fi], + + [pax], + [], + + [m4_fatal([Unknown tar format])]) + + AC_MSG_CHECKING([how to create a $1 tar archive]) + + # Go ahead even if we have the value already cached. We do so because we + # need to set the values for the 'am__tar' and 'am__untar' variables. + _am_tools=${am_cv_prog_tar_$1-$_am_tools} + + for _am_tool in $_am_tools; do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; do + AM_RUN_LOG([$_am_tar --version]) && break + done + am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x $1 -w "$$tardir"' + am__tar_='pax -L -x $1 -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H $1 -L' + am__tar_='find "$tardir" -print | cpio -o -H $1 -L' + am__untar='cpio -i -H $1 -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_$1}" && break + + # tar/untar a dummy directory, and stop if the command works. + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + rm -rf conftest.dir + if test -s conftest.tar; then + AM_RUN_LOG([$am__untar <conftest.tar]) + AM_RUN_LOG([cat conftest.dir/file]) + grep GrepMe conftest.dir/file >/dev/null 2>&1 && break + fi + done + rm -rf conftest.dir + + AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) + AC_MSG_RESULT([$am_cv_prog_tar_$1])]) + +AC_SUBST([am__tar]) +AC_SUBST([am__untar]) +]) # _AM_PROG_TAR + diff --git a/compat/Makefile.am b/compat/Makefile.am new file mode 100644 index 0000000..75ac787 --- /dev/null +++ b/compat/Makefile.am @@ -0,0 +1,22 @@ +noinst_LIBRARIES = libcompat.a + +AM_CPPFLAGS = @STRIP_BEGIN@ \ + -I$(top_srcdir)/include \ + -I$(top_builddir)/include \ + @STRIP_END@ + +AM_CXXFLAGS = -Wall +AM_CFLAGS = -Wall +AM_LDFLAGS = -lrt + +libcompat_a_SOURCES = \ + Thread.c \ + error.c \ + delay.c \ + gettimeofday.c \ + gettcpinfo.c \ + inet_ntop.c \ + inet_pton.c \ + signal.c \ + snprintf.c \ + string.c diff --git a/compat/Makefile.in b/compat/Makefile.in new file mode 100644 index 0000000..5d5bbcd --- /dev/null +++ b/compat/Makefile.in @@ -0,0 +1,617 @@ +# Makefile.in generated by automake 1.16.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = compat +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/m4/dast.m4 $(top_srcdir)/m4/ax_pthread.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LIBRARIES = $(noinst_LIBRARIES) +AR = ar +ARFLAGS = cru +AM_V_AR = $(am__v_AR_@AM_V@) +am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@) +am__v_AR_0 = @echo " AR " $@; +am__v_AR_1 = +libcompat_a_AR = $(AR) $(ARFLAGS) +libcompat_a_LIBADD = +am_libcompat_a_OBJECTS = Thread.$(OBJEXT) error.$(OBJEXT) \ + delay.$(OBJEXT) gettimeofday.$(OBJEXT) gettcpinfo.$(OBJEXT) \ + inet_ntop.$(OBJEXT) inet_pton.$(OBJEXT) signal.$(OBJEXT) \ + snprintf.$(OBJEXT) string.$(OBJEXT) +libcompat_a_OBJECTS = $(am_libcompat_a_OBJECTS) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/Thread.Po ./$(DEPDIR)/delay.Po \ + ./$(DEPDIR)/error.Po ./$(DEPDIR)/gettcpinfo.Po \ + ./$(DEPDIR)/gettimeofday.Po ./$(DEPDIR)/inet_ntop.Po \ + ./$(DEPDIR)/inet_pton.Po ./$(DEPDIR)/signal.Po \ + ./$(DEPDIR)/snprintf.Po ./$(DEPDIR)/string.Po +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libcompat_a_SOURCES) +DIST_SOURCES = $(libcompat_a_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +STRIP_BEGIN = @STRIP_BEGIN@ +STRIP_DUMMY = @STRIP_DUMMY@ +STRIP_END = @STRIP_END@ +VERSION = @VERSION@ +WEB100_CFLAGS = @WEB100_CFLAGS@ +WEB100_CONFIG = @WEB100_CONFIG@ +WEB100_LIBS = @WEB100_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LIBRARIES = libcompat.a +AM_CPPFLAGS = @STRIP_BEGIN@ \ + -I$(top_srcdir)/include \ + -I$(top_builddir)/include \ + @STRIP_END@ + +AM_CXXFLAGS = -Wall +AM_CFLAGS = -Wall +AM_LDFLAGS = -lrt +libcompat_a_SOURCES = \ + Thread.c \ + error.c \ + delay.c \ + gettimeofday.c \ + gettcpinfo.c \ + inet_ntop.c \ + inet_pton.c \ + signal.c \ + snprintf.c \ + string.c + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu compat/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu compat/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) + +libcompat.a: $(libcompat_a_OBJECTS) $(libcompat_a_DEPENDENCIES) $(EXTRA_libcompat_a_DEPENDENCIES) + $(AM_V_at)-rm -f libcompat.a + $(AM_V_AR)$(libcompat_a_AR) libcompat.a $(libcompat_a_OBJECTS) $(libcompat_a_LIBADD) + $(AM_V_at)$(RANLIB) libcompat.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Thread.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/delay.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/error.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gettcpinfo.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gettimeofday.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inet_ntop.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inet_pton.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/signal.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snprintf.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/string.Po@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/Thread.Po + -rm -f ./$(DEPDIR)/delay.Po + -rm -f ./$(DEPDIR)/error.Po + -rm -f ./$(DEPDIR)/gettcpinfo.Po + -rm -f ./$(DEPDIR)/gettimeofday.Po + -rm -f ./$(DEPDIR)/inet_ntop.Po + -rm -f ./$(DEPDIR)/inet_pton.Po + -rm -f ./$(DEPDIR)/signal.Po + -rm -f ./$(DEPDIR)/snprintf.Po + -rm -f ./$(DEPDIR)/string.Po + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/Thread.Po + -rm -f ./$(DEPDIR)/delay.Po + -rm -f ./$(DEPDIR)/error.Po + -rm -f ./$(DEPDIR)/gettcpinfo.Po + -rm -f ./$(DEPDIR)/gettimeofday.Po + -rm -f ./$(DEPDIR)/inet_ntop.Po + -rm -f ./$(DEPDIR)/inet_pton.Po + -rm -f ./$(DEPDIR)/signal.Po + -rm -f ./$(DEPDIR)/snprintf.Po + -rm -f ./$(DEPDIR)/string.Po + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-noinstLIBRARIES cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/compat/Thread.c b/compat/Thread.c new file mode 100644 index 0000000..307535e --- /dev/null +++ b/compat/Thread.c @@ -0,0 +1,582 @@ +/*--------------------------------------------------------------- + * Copyright (c) 1999,2000,2001,2002,2003 + * The Board of Trustees of the University of Illinois + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software (Iperf) and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the names of the University of Illinois, NCSA, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * National Laboratory for Applied Network Research + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * http://www.ncsa.uiuc.edu + * ________________________________________________________________ + * + * Thread.c + * by Kevin Gibbs <kgibbs@nlanr.net> + * + * Based on: + * Thread.cpp + * by Mark Gates <mgates@nlanr.net> + * ------------------------------------------------------------------- + * The thread subsystem is responsible for all thread functions. It + * provides a thread implementation agnostic interface to Iperf. If + * threads are not available (HAVE_THREAD is undefined), thread_start + * does not start a new thread but just launches the specified object + * in the current thread. Everything that defines a thread of + * execution in Iperf is contained in an thread_Settings structure. To + * start a thread simply pass one such structure into thread_start. + * ------------------------------------------------------------------- + * headers + * uses + * <stdlib.h> + * <stdio.h> + * <assert.h> + * <errno.h> + * Thread.h may include <pthread.h> + * ------------------------------------------------------------------- */ + +#include "headers.h" + +#include "Thread.h" +#include "Locale.h" +#include "util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if HAVE_THREAD_DEBUG +#include <time.h> +#include <unistd.h> +#if HAVE_GETTID_SYSCALL +#include <sys/syscall.h> +#endif +#include <sys/types.h> +#include <stdarg.h> +#include "Reporter.h" +void reporttype_text(struct ReportHeader *reporthdr, char *rs) { + switch (reporthdr->type) { + case DATA_REPORT: + strncpy(rs,"data", REPORTTXTMAX); + break; + case SUM_REPORT: + strncpy(rs,"sum", REPORTTXTMAX); + break; + case SETTINGS_REPORT: + strncpy(rs,"settings", REPORTTXTMAX); + break; + case CONNECTION_REPORT: + strncpy(rs,"connection", REPORTTXTMAX); + break; + case SERVER_RELAY_REPORT: + strncpy(rs,"server", REPORTTXTMAX); + break; + default : + strncpy(rs,"unknown", REPORTTXTMAX); + } + rs[REPORTTXTMAX-1] = '\0'; +} + +Mutex thread_debug_mutex; +static void __gettimestamp(char *timestr) { + struct timespec t1; + clock_gettime(CLOCK_REALTIME, &t1); + struct tm *t; + t=localtime(&t1.tv_sec); + if (t) { +#if WIN32 + strftime(timestr, 200, "%Y-%m-%d %H:%M:%S", t); +#else + strftime(timestr, 200, "%T", t); +#endif + // strftime(buf, len, "%F %T", &t); + snprintf(×tr[strlen(timestr)], strlen(timestr), ".%09ld", t1.tv_nsec); + timestr[199]='\0'; + } else { + *timestr='\0'; + } +} +static int __log(const char *level, const char *format, va_list args) { + int len; + char *newformat; + char timestamp[200]; + char logformat[]="%s(%ld):[%s] %s\n"; + + __gettimestamp(timestamp); + #if HAVE_GETTID_SYSCALL + unsigned long tid = syscall(SYS_gettid); + #else + unsigned long tid = -1; + #endif + len = snprintf(NULL, 0, logformat, level, tid, timestamp, format); + len++; // Trailing null byte + extra + newformat = malloc(len); + len = snprintf(newformat, len, logformat, level, tid, timestamp, format); + if (len > 0) { + len = vprintf(newformat, args); + } + free(newformat); + return len; +} + +void thread_debug(const char *format, ...) { + Mutex_Lock(&thread_debug_mutex); + va_list ap; + va_start(ap, format); + __log("THREAD", format, ap); + va_end(ap); + fflush(stdout); + Mutex_Unlock(&thread_debug_mutex); +} +#endif + +/* ------------------------------------------------------------------- + * define static variables. + * ------------------------------------------------------------------- */ + +// number of currently running threads +int thread_sNum = 0; +// number of currently running traffic threads +int thread_trfc_sNum = 0; +int thread_trfctx_sNum = 0; +int thread_trfcrx_sNum = 0; +// number of non-terminating running threads (ie listener thread) +int nonterminating_num = 0; +// condition to protect updating the above and alerting on +// changes to above +struct Condition thread_sNum_cond; + + +/* ------------------------------------------------------------------- + * Initialize the thread subsystems variables and set the concurrency + * level in solaris. + * ------------------------------------------------------------------- */ +void thread_init() { + Condition_Initialize(&thread_sNum_cond); +#if defined(sun) + /* Solaris apparently doesn't default to timeslicing threads, + * as such we force it to play nice. This may not work perfectly + * when _sending_ multiple _UDP_ streams. + */ + pthread_setconcurrency (3); +#endif +} + +/* ------------------------------------------------------------------- + * Destroy the thread subsystems variables. + * ------------------------------------------------------------------- */ +void thread_destroy() { + Condition_Destroy(&thread_sNum_cond); +} + +/* ------------------------------------------------------------------- + * Start the specified object's thread execution. Increments thread + * count, spawns new thread, and stores thread ID. + * ------------------------------------------------------------------- */ +void thread_start_all(struct thread_Settings* thread) { + struct thread_Settings *ithread = thread; + while(ithread) { + thread_start(ithread); + ithread = ithread->runNow; + } +} + +void thread_start(struct thread_Settings* thread) { + // Make sure this object has not been started already + if (!thread_equalid(thread->mTID, thread_zeroid())) { + WARN(1, "thread_start called on running thread"); +#if HAVE_THREAD_DEBUG + thread_debug("Thread_start info %p id=%d ", (void *)thread, (int)thread->mTID); +#endif + } else { + // increment thread count + Condition_Lock(thread_sNum_cond); + thread_sNum++; + if ((thread->mThreadMode == kMode_Client) || (thread->mThreadMode == kMode_Server)) { + thread_trfc_sNum++; + } + Condition_Unlock(thread_sNum_cond); + +#if defined(HAVE_POSIX_THREAD) + // pthreads -- spawn new thread + if (pthread_create(&thread->mTID, NULL, thread_run_wrapper, thread) != 0) { + WARN(1, "pthread_create"); + + // decrement thread count + Condition_Lock(thread_sNum_cond); + thread_sNum--; + if (thread->mThreadMode == kMode_Client) { + thread_trfc_sNum--; + thread_trfctx_sNum--; + } + if (thread->mThreadMode == kMode_Server) { + thread_trfc_sNum--; + thread_trfcrx_sNum--; + } + Condition_Unlock(thread_sNum_cond); + } +#if HAVE_THREAD_DEBUG + thread_debug("Thread_run_wrapper(%p mode=%x) thread counts tot/trfc=%d/%d (id=%d)", (void *)thread, thread->mThreadMode, thread_sNum, thread_trfc_sNum, (int)thread->mTID); +#endif +#elif defined(HAVE_WIN32_THREAD) + // Win32 threads -- spawn new thread + // Win32 has a thread handle in addition to the thread ID + thread->mHandle = CreateThread(NULL, 0, thread_run_wrapper, thread, 0, &thread->mTID); + if (thread->mHandle == NULL) { + WARN(1, "CreateThread"); + + // decrement thread count + Condition_Lock(thread_sNum_cond); + thread_sNum--; + if ((thread->mThreadMode == kMode_Client) || (thread->mThreadMode == kMode_Server)) { + thread_trfc_sNum--; + } + Condition_Unlock(thread_sNum_cond); + } +#else + // single-threaded -- call Run_Wrapper in this thread + thread_run_wrapper(thread); +#endif + } +} // end thread_start + +/* ------------------------------------------------------------------- + * Stop the specified object's thread execution (if any) immediately. + * Decrements thread count and resets the thread ID. + * + * Note: This does not free any objects and calling it without + * lots of conideration will likely cause memory leaks. Better to let + * thread_start's thread_run_wrapper run to completion and not + * preemptively stop a thread. + * ------------------------------------------------------------------- */ +void thread_stop(struct thread_Settings* thread) { +#ifdef HAVE_THREAD + #ifdef HAVE_THREAD_DEBUG + thread_debug("Thread stop invoked %p (%d/%d)", (void *)thread, thread_sNum, thread_trfc_sNum); + #endif + // Make sure we have been started + if (!thread_equalid(thread->mTID, thread_zeroid())) { + + // decrement thread count + Condition_Lock(thread_sNum_cond); + thread_sNum--; + if ((thread->mThreadMode == kMode_Client) || (thread->mThreadMode == kMode_Server)) { + thread_trfc_sNum--; + } + Condition_Signal(&thread_sNum_cond); + Condition_Unlock(thread_sNum_cond); + + // use exit() if called from within this thread + // use cancel() if called from a different thread + if (thread_equalid(thread_getid(), thread->mTID)) { + + // Destroy the object + Settings_Destroy(thread); + + // Exit +#if defined(HAVE_POSIX_THREAD) + pthread_exit(NULL); +#else // Win32 + CloseHandle(thread->mHandle); + ExitThread(0); +#endif + } else { + + // Cancel +#if defined(HAVE_POSIX_THREAD) + // Cray J90 doesn't have pthread_cancel; Iperf works okay without +#ifdef HAVE_PTHREAD_CANCEL + pthread_cancel(thread->mTID); +#endif +#else // Win32 + // this is a somewhat dangerous function; it's not + // suggested to Stop() threads a lot. + TerminateThread(thread->mHandle, 0); +#endif + + // Destroy the object only after killing the thread + Settings_Destroy(thread); + } + } +#endif +} // end Stop + +/* ------------------------------------------------------------------- + * This function is the entry point for new threads created in + * thread_start. + * ------------------------------------------------------------------- */ +#if defined(HAVE_WIN32_THREAD) +DWORD WINAPI +#else +void* +#endif +thread_run_wrapper(void* paramPtr) { + bool signal_on_exit = false; + struct thread_Settings* thread = (struct thread_Settings*) paramPtr; + + // which type of object are we + switch (thread->mThreadMode) { + case kMode_Server: + { + signal_on_exit = true; + /* Spawn a Server thread with these settings */ + server_spawn(thread); + } break; + case kMode_Client: + { + signal_on_exit = true; + /* Spawn a Client thread with these settings */ + client_spawn(thread); + } break; + case kMode_Reporter: + case kMode_ReporterClient: + { + /* Spawn a Reporter thread with these settings */ + reporter_spawn(thread); + } break; + case kMode_Listener: + { + // Increment the non-terminating thread count + thread_register_nonterm(); + /* Spawn a Listener thread with these settings */ + listener_spawn(thread); + // Decrement the non-terminating thread count + thread_unregister_nonterm(); + } break; + default: + { + FAIL(1, "Unknown Thread Type!\n", thread); + } break; + } + +#ifdef HAVE_POSIX_THREAD + // detach Thread. If someone already joined it will not do anything + // If none has then it will free resources upon return from this + // function (Run_Wrapper) + pthread_detach(thread->mTID); +#endif + + // decrement thread count and send condition signal + Condition_Lock(thread_sNum_cond); + thread_sNum--; + if ((thread->mThreadMode == kMode_Client) || (thread->mThreadMode == kMode_Server)) { + thread_trfc_sNum--; + } + Condition_Signal(&thread_sNum_cond); + Condition_Unlock(thread_sNum_cond); + + // Check if we need to start up a thread after executing this one + if (thread->runNext != NULL) { + thread_start(thread->runNext); + } + // Destroy this thread object + Settings_Destroy(thread); + // signal the reporter thread now that thread state has changed + if (signal_on_exit) { + Condition_Signal(&ReportCond); +#if HAVE_THREAD_DEBUG + thread_debug("Signal sent to reporter thread"); +#endif + } + return 0; +} // end run_wrapper + +/* ------------------------------------------------------------------- + * Wait for all thread object's execution to complete. Depends on the + * thread count being accurate and the threads sending a condition + * signal when they terminate. + * ------------------------------------------------------------------- */ +void thread_joinall(void) { + Condition_Lock(thread_sNum_cond); + while (thread_sNum > 0) { + Condition_Wait(&thread_sNum_cond); + } + Condition_Unlock(thread_sNum_cond); +} // end Joinall + + +/* ------------------------------------------------------------------- + * Compare the thread ID's (inLeft == inRight); return true if they + * are equal. On some OS's nthread_t is a struct so == will not work. + * TODO use pthread_equal. Any Win32 equivalent?? + * ------------------------------------------------------------------- */ +int thread_equalid(nthread_t inLeft, nthread_t inRight) { + return(memcmp(&inLeft, &inRight, sizeof(inLeft)) == 0); +} + +/* ------------------------------------------------------------------- + * Return a zero'd out thread ID. On some OS's nthread_t is a struct + * so == 0 will not work. + * [static] + * ------------------------------------------------------------------- */ +nthread_t thread_zeroid(void) { + nthread_t a; + memset(&a, 0, sizeof(a)); + return a; +} + +/* ------------------------------------------------------------------- + * set a thread to be ignorable, so joinall won't wait on it + * this simply decrements the thread count that joinall uses. + * This is utilized by the reporter thread which knows when it + * is ok to quit (aka no pending reports). + * ------------------------------------------------------------------- */ +void thread_setignore() { + Condition_Lock(thread_sNum_cond); + thread_sNum--; + Condition_Signal(&thread_sNum_cond); + Condition_Unlock(thread_sNum_cond); +} + +/* ------------------------------------------------------------------- + * unset a thread from being ignorable, so joinall will wait on it + * this simply increments the thread count that joinall uses. + * This is utilized by the reporter thread which knows when it + * is ok to quit (aka no pending reports). + * ------------------------------------------------------------------- */ +void thread_unsetignore(void) { + Condition_Lock(thread_sNum_cond); + thread_sNum++; + Condition_Signal(&thread_sNum_cond); + Condition_Unlock(thread_sNum_cond); +} + +/* ------------------------------------------------------------------- + * set a thread to be non-terminating, so if you cancel through + * Ctrl-C they can be ignored by the joinall. + * ------------------------------------------------------------------- */ +void thread_register_nonterm(void) { + Condition_Lock(thread_sNum_cond); + nonterminating_num++; + Condition_Unlock(thread_sNum_cond); +} + +/* ------------------------------------------------------------------- + * unset a thread from being non-terminating, so if you cancel through + * Ctrl-C they can be ignored by the joinall. + * ------------------------------------------------------------------- */ +void thread_unregister_nonterm(void) { + Condition_Lock(thread_sNum_cond); + if (nonterminating_num == 0) { + // nonterminating has been released with release_nonterm + // Add back to the threads to wait on + thread_sNum++; + } else { + nonterminating_num--; + } + Condition_Unlock(thread_sNum_cond); +} + +/* ------------------------------------------------------------------- + * this function releases all non-terminating threads from the list + * of active threads, so that when all terminating threads quit + * the joinall will complete. This is called on a Ctrl-C input. It is + * also used by the -P usage on the server side + * ------------------------------------------------------------------- */ +int thread_release_nonterm(int interrupt) { + Condition_Lock(thread_sNum_cond); + thread_sNum -= nonterminating_num; + if (thread_sNum > 1 && nonterminating_num > 0 && interrupt != 0) { + fprintf(stderr, "%s", wait_server_threads); + } + nonterminating_num = 0; + Condition_Signal(&thread_sNum_cond); + Condition_Unlock(thread_sNum_cond); + return thread_sNum; +} + +/* ------------------------------------------------------------------- + * Return the number of threads currently running (doesn't include + * active threads that have called setdaemon (aka reporter thread)) + * ------------------------------------------------------------------- */ +int thread_numuserthreads(void) { + return thread_sNum; +} + +/* ------------------------------------------------------------------- + * Return the number of taffic threads currently running + * ------------------------------------------------------------------- */ +int thread_numtrafficthreads(void) { + return thread_trfc_sNum; +} + +/* ------------------------------------------------------------------- + * Support for realtime scheduling of threads + * ------------------------------------------------------------------- */ +#if HAVE_SCHED_SETSCHEDULER +#include <sched.h> +#endif +#ifdef HAVE_MLOCKALL +#include <sys/mman.h> +#endif +void thread_setscheduler(struct thread_Settings *thread) { +#if HAVE_SCHED_SETSCHEDULER + if (isRealtime(thread)) { + struct sched_param sp; + sp.sched_priority = sched_get_priority_max(SCHED_RR); + // SCHED_OTHER, SCHED_FIFO, SCHED_RR + if (sched_setscheduler(0, SCHED_RR, &sp) < 0) { + perror("Client set scheduler"); +#ifdef HAVE_MLOCKALL + } else if (mlockall(MCL_CURRENT | MCL_FUTURE) != 0) { + // lock the threads memory + perror ("mlockall"); +#endif // MLOCK + } + } +#endif // SCHED +} + +/* + * ------------------------------------------------------------------- + * Allow another thread to execute. If no other threads are runable this + * is not guarenteed to actually rest. + * ------------------------------------------------------------------- */ +void thread_rest (void) { +#if defined(HAVE_THREAD) +#if defined(HAVE_POSIX_THREAD) + #if HAVE_SCHED_YIELD + sched_yield(); + #endif +#else // Win32 + SwitchToThread(); +#endif +#endif +} + +#ifdef __cplusplus +} /* end extern "C" */ +#endif diff --git a/compat/delay.c b/compat/delay.c new file mode 100644 index 0000000..95bde3e --- /dev/null +++ b/compat/delay.c @@ -0,0 +1,407 @@ +/*--------------------------------------------------------------- + * Copyright (c) 1999,2000,2001,2002,2003 + * The Board of Trustees of the University of Illinois + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software (Iperf) and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the names of the University of Illinois, NCSA, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * National Laboratory for Applied Network Research + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * http://www.ncsa.uiuc.edu + * ________________________________________________________________ + * + * delay.c + * by Mark Gates <mgates@nlanr.net> + * updates + * by Robert J. McMahon <rmcmahon@broadcom.com> <rjmcmahon@rjmcmahon.com> + * ------------------------------------------------------------------- + * attempts at accurate microsecond delays + * ------------------------------------------------------------------- */ +#include "headers.h" +#include "util.h" +#include "delay.h" +#include "Thread.h" +#include <math.h> + +#define MILLION 1000000 +#define BILLION 1000000000 + +/* ------------------------------------------------------------------- + * A micro-second delay function + * o Use a busy loop or nanosleep + * + * Some notes: + * o clock nanosleep with a relative is preferred (see man page for why) + * o clock_gettime() (if available) is preferred over gettimeofday() + * as it give nanosecond resolution and should be more efficient. + * It also supports CLOCK_MONOTONIC and CLOCK_MONOTONIC_RAW + * though CLOCK_REALTIME is being used by the code. + * o This code does not use Timestamp object, as the goal of these + * functions is accurate delays (vs accurate timestamps.) + * o The syscalls such as nanosleep guarantee at least the request time + * and can and will delay longer, particularly due to things like context + * switching, causing the delay to lose accuracy + * o Kalman filtering is used to predict delay error which in turn + * is used to adjust the delay, hopefully mitigating the above. + * Note: This can cause the delay to return faster than the request, + * i.e. the *at least* guarantee is not preserved for the kalman + * adjusted delay calls. + * o Remember, the Client is keeping a running average delay for the + * thread so errors in delay will also be adjusted there. (Assuming + * it's possible. It's not really possible at top line link rates + * because lost time can't be made up for by speeding up the transmits. + * Hence, don't lose time with delay calls which error on the side of + * taking too long. Kalman should help much here.) + * + * POSIX nanosleep(). This allows a higher timing resolution + * (under Linux e.g. it uses hrtimers), does not affect any signals, + * and will use up remaining time when interrupted. + * ------------------------------------------------------------------- */ + +void delay_loop(unsigned long usec) +{ +#ifdef HAVE_CLOCK_NANOSLEEP + { + struct timespec res; + res.tv_sec = usec/MILLION; + res.tv_nsec = (usec * 1000) % BILLION; + #ifndef WIN32 + clock_nanosleep(CLOCK_MONOTONIC, 0, &res, NULL); + #else + clock_nanosleep(0, 0, &res, NULL); + #endif + } +#else + #ifdef HAVE_KALMAN + delay_kalman(usec); + #else + #ifdef HAVE_NANOSLEEP + delay_nanosleep(usec); + #else + delay_busyloop(usec); + #endif + #endif +#endif +} + +int clock_usleep (struct timeval *request) { + int rc = 0; +#if HAVE_THREAD_DEBUG + thread_debug("Thread called clock_usleep() until %ld.%ld", request->tv_sec, request->tv_usec); +#endif +#ifdef HAVE_CLOCK_NANOSLEEP + struct timespec tmp; + tmp.tv_sec = request->tv_sec; + tmp.tv_nsec = request->tv_usec * 1000; + +// Cygwin systems have an issue with CLOCK_MONOTONIC +#if defined(CLOCK_MONOTONIC) && !defined(WIN32) + rc = clock_nanosleep(CLOCK_MONOTONIC, 0, &tmp, NULL); +#else + rc = clock_nanosleep(0, 0, &tmp, NULL); +#endif + if (rc) { + fprintf(stderr, "failed clock_nanosleep()=%d\n", rc); + } +#else + struct timeval now; + struct timeval next = *request; +#ifdef HAVE_CLOCK_GETTIME + struct timespec t1; + clock_gettime(CLOCK_REALTIME, &t1); + now.tv_sec = t1.tv_sec; + now.tv_usec = t1.tv_nsec / 1000; +#else + gettimeofday(&now, NULL); +#endif + double delta_usecs; + if ((delta_usecs = TimeDifference(next, now)) > 0.0) { + delay_loop(delta_usecs); + } +#endif + return rc; +} + +int clock_usleep_abstime (struct timeval *request) { + int rc = 0; +#if defined(HAVE_CLOCK_NANOSLEEP) && defined(TIMER_ABSTIME) && !defined(WIN32) + struct timespec tmp; + tmp.tv_sec = request->tv_sec; + tmp.tv_nsec = request->tv_usec * 1000; + rc = clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &tmp, NULL); + if (rc) { + fprintf(stderr, "failed clock_nanosleep()=%d\n", rc); + } +#else + struct timeval now; + struct timeval next = *request; +#ifdef HAVE_CLOCK_GETTIME + struct timespec t1; + clock_gettime(CLOCK_REALTIME, &t1); + now.tv_sec = t1.tv_sec; + now.tv_usec = t1.tv_nsec / 1000; +#else + gettimeofday(&now, NULL); +#endif + double delta_usecs; + if ((delta_usecs = (1e6 * TimeDifference(next, now))) > 0.0) { + delay_loop(delta_usecs); + } +#endif + return rc; +} + +#ifdef HAVE_NANOSLEEP +// Can use the nanosleep syscall suspending the thread +void delay_nanosleep (unsigned long usec) { + struct timespec requested, remaining; + requested.tv_sec = 0; + requested.tv_nsec = usec * 1000L; + // Note, signals will cause the nanosleep + // to return early. That's fine. + nanosleep(&requested, &remaining); +} +#endif + +#if defined (HAVE_NANOSLEEP) || defined (HAVE_CLOCK_GETTIME) +static void timespec_add_ulong (struct timespec *tv0, unsigned long value) { + tv0->tv_sec += (value / BILLION); + tv0->tv_nsec += (value % BILLION); + if (tv0->tv_nsec >= BILLION) { + tv0->tv_sec++; + tv0->tv_nsec -= BILLION; + } +} +#endif + +#ifdef HAVE_KALMAN +// Kalman versions attempt to support delay request +// accuracy over a minimum guaranteed delay by +// prediciting the delay error. This is +// the basic recursive algorithm. +static void kalman_update (struct kalman_state *state, double measurement) { + //prediction update + state->p = state->p + state->q; + //measurement update + state->k = state->p / (state->p + state->r); + state->x = state->x + (state->k * (measurement - state->x)); + state->p = (1 - state->k) * state->p; +} +#endif + +#ifdef HAVE_CLOCK_GETTIME +// Delay calls for systems with clock_gettime +// Working units are nanoseconds and structures are timespec +static void timespec_add_double (struct timespec *tv0, double value) { + tv0->tv_nsec += (unsigned long) value; + if (tv0->tv_nsec >= BILLION) { + tv0->tv_sec++; + tv0->tv_nsec -= BILLION; + } +} +// tv1 assumed greater than tv0 +static double timespec_diff (struct timespec tv1, struct timespec tv0) { + double result; + if (tv1.tv_nsec < tv0.tv_nsec) { + tv1.tv_nsec += BILLION; + tv1.tv_sec--; + } + result = (double) (((tv1.tv_sec - tv0.tv_sec) * BILLION) + (tv1.tv_nsec - tv0.tv_nsec)); + return result; +} +static void timespec_add( struct timespec *tv0, struct timespec *tv1) +{ + tv0->tv_sec += tv1->tv_sec; + tv0->tv_nsec += tv1->tv_nsec; + if ( tv0->tv_nsec >= BILLION ) { + tv0->tv_nsec -= BILLION; + tv0->tv_sec++; + } +} +static inline +int timespec_greaterthan(struct timespec tv1, struct timespec tv0) { + if (tv1.tv_sec > tv0.tv_sec || \ + ((tv0.tv_sec == tv1.tv_sec) && (tv1.tv_nsec > tv0.tv_nsec))) { + return 1; + } else { + return 0; + } +} +// A cpu busy loop for systems with clock_gettime +void delay_busyloop (unsigned long usec) { + struct timespec t1, t2; + clock_gettime(CLOCK_REALTIME, &t1); + timespec_add_ulong(&t1, (usec * 1000L)); + while (1) { + clock_gettime(CLOCK_REALTIME, &t2); + if (timespec_greaterthan(t2, t1)) + break; + } +} +// Kalman routines for systems with clock_gettime +#ifdef HAVE_KALMAN +// Request units is microseconds +// Adjust units is nanoseconds +void delay_kalman (unsigned long usec) { + struct timespec t1, t2, finishtime, requested={0,0}, remaining; + double nsec_adjusted, err; + static struct kalman_state kalmanerr={ + 0.00001, //q process noise covariance + 0.1, //r measurement noise covariance + 0.0, //x value, error predictio (units nanoseconds) + 1, //p estimation error covariance + 0.75 //k kalman gain + }; + // Get the current clock + clock_gettime(CLOCK_REALTIME, &t1); + // Perform the kalman adjust per the predicted delay error + nsec_adjusted = (usec * 1000.0) - kalmanerr.x; + // Set a timespec to be used by the nanosleep + // as well as for the finished time calculation + timespec_add_double(&requested, nsec_adjusted); + // Set the finish time in timespec format + finishtime = t1; + timespec_add(&finishtime, &requested); +# ifdef HAVE_NANOSLEEP + // Don't call nanosleep for values less than 10 microseconds + // as the syscall is too expensive. Let the busy loop + // provide the delay for times under that. + if (nsec_adjusted > 10000) { + nanosleep(&requested, &remaining); + } +# endif + while (1) { + clock_gettime(CLOCK_REALTIME, &t2); + if (timespec_greaterthan(t2, finishtime)) + break; + } + // Compute the delay error in units of nanoseconds + // and cast to type double + err = (timespec_diff(t2, t1) - (usec * 1000)); + // printf("req: %ld adj: %f err: %.5f (ns)\n", usec, nsec_adjusted, kalmanerr.x); + kalman_update(&kalmanerr, err); +} +#endif // HAVE_KALMAN +#else +// Sadly, these systems must use the not so efficient gettimeofday() +// and working units are microseconds, struct is timeval +static void timeval_add_ulong (struct timeval *tv0, unsigned long value) { + tv0->tv_usec += value; + if (tv0->tv_usec >= MILLION) { + tv0->tv_sec++; + tv0->tv_usec -= MILLION; + } +} +static inline +int timeval_greaterthan(struct timeval tv1, struct timeval tv0) { + if (tv1.tv_sec > tv0.tv_sec || \ + ((tv0.tv_sec == tv1.tv_sec) && (tv1.tv_usec > tv0.tv_usec))) { + return 1; + } else { + return 0; + } +} +// tv1 assumed greater than tv0 +static double timeval_diff (struct timeval tv1, struct timeval tv0) { + double result; + if (tv1.tv_usec < tv0.tv_usec) { + tv1.tv_usec += MILLION; + tv1.tv_sec--; + } + result = (double) (((tv1.tv_sec - tv0.tv_sec) * MILLION) + (tv1.tv_usec - tv0.tv_usec)); + return result; +} +void delay_busyloop (unsigned long usec) { + struct timeval t1, t2; + gettimeofday( &t1, NULL ); + timeval_add_ulong(&t1, usec); + while (1) { + gettimeofday( &t2, NULL ); + if (timeval_greaterthan(t2, t1)) + break; + } +} +#ifdef HAVE_KALMAN +// Request units is microseconds +// Adjust units is microseconds +void delay_kalman (unsigned long usec) { + struct timeval t1, t2, finishtime; + long usec_adjusted; + double err; + static struct kalman_state kalmanerr={ + 0.00001, //q process noise covariance + 0.1, //r measurement noise covariance + 0.0, //x value, error predictio (units nanoseconds) + 1, //p estimation error covariance + 0.25 //k kalman gain + }; + // Get the current clock + gettimeofday( &t1, NULL ); + // Perform the kalman adjust per the predicted delay error + if (kalmanerr.x > 0) { + usec_adjusted = usec - (long) floor(kalmanerr.x); + if (usec_adjusted < 0) + usec_adjusted = 0; + } + else + usec_adjusted = usec + (long) floor(kalmanerr.x); + // Set the finishtime + finishtime = t1; + timeval_add_ulong(&finishtime, usec_adjusted); +# ifdef HAVE_NANOSLEEP + // Don't call nanosleep for values less than 10 microseconds + // as the syscall is too expensive. Let the busy loop + // provide the delay for times under that. + if (usec_adjusted > 10) { + struct timespec requested={0,0}, remaining; + timespec_add_ulong(&requested, (usec_adjusted * 1000)); + nanosleep(&requested, &remaining); + } +# endif + while (1) { + gettimeofday(&t2, NULL ); + if (timeval_greaterthan(t2, finishtime)) + break; + } + // Compute the delay error in units of microseconds + // and cast to type double + err = (double)(timeval_diff(t2, t1) - usec); + // printf("req: %ld adj: %ld err: %.5f (us)\n", usec, usec_adjusted, kalmanerr.x); + kalman_update(&kalmanerr, err); +} +#endif // Kalman +#endif diff --git a/compat/error.c b/compat/error.c new file mode 100644 index 0000000..53d1727 --- /dev/null +++ b/compat/error.c @@ -0,0 +1,210 @@ +/*--------------------------------------------------------------- + * Copyright (c) 1999,2000,2001,2002,2003 + * The Board of Trustees of the University of Illinois + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software (Iperf) and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the names of the University of Illinois, NCSA, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * National Laboratory for Applied Network Research + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * http://www.ncsa.uiuc.edu + * ________________________________________________________________ + * + * error.c + * by Mark Gates <mgates@nlanr.net> + * ------------------------------------------------------------------- + * error handlers + * ------------------------------------------------------------------- */ + +#include "headers.h" +#include "util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef WIN32 + +/* ------------------------------------------------------------------- + * Implement a simple Win32 strerror function for our purposes. + * These error values weren't handled by FormatMessage; + * any particular reason why not?? + * ------------------------------------------------------------------- */ + +struct mesg { + DWORD err; + const char* str; +}; + +const struct mesg error_mesgs[] = +{ + { WSAEACCES, "Permission denied"}, + { WSAEADDRINUSE, "Address already in use"}, + { WSAEADDRNOTAVAIL, "Cannot assign requested address"}, + { WSAEAFNOSUPPORT, "Address family not supported by protocol family"}, + { WSAEALREADY, "Operation already in progress"}, + { WSAECONNABORTED, "Software caused connection abort"}, + { WSAECONNREFUSED, "Connection refused"}, + { WSAECONNRESET, "Connection reset by peer"}, + { WSAEDESTADDRREQ, "Destination address required"}, + { WSAEFAULT, "Bad address"}, + { WSAEHOSTDOWN, "Host is down"}, + { WSAEHOSTUNREACH, "No route to host"}, + { WSAEINPROGRESS, "Operation now in progress"}, + { WSAEINTR, "Interrupted function call."}, + { WSAEINVAL, "Invalid argument."}, + { WSAEISCONN, "Socket is already connected."}, + { WSAEMFILE, "Too many open files."}, + { WSAEMSGSIZE, "Message too long"}, + { WSAENETDOWN, "Network is down"}, + { WSAENETRESET, "Network dropped connection on reset"}, + { WSAENETUNREACH, "Network is unreachable"}, + { WSAENOBUFS, "No buffer space available."}, + { WSAENOPROTOOPT, "Bad protocol option."}, + { WSAENOTCONN, "Socket is not connected"}, + { WSAENOTSOCK, "Socket operation on non-socket."}, + { WSAEOPNOTSUPP, "Operation not supported"}, + { WSAEPFNOSUPPORT, "Protocol family not supported"}, + { WSAEPROCLIM, "Too many processes."}, + { WSAEPROTONOSUPPORT, "Protocol not supported"}, + { WSAEPROTOTYPE, "Protocol wrong type for socket"}, + { WSAESHUTDOWN, "Cannot send after socket shutdown"}, + { WSAESOCKTNOSUPPORT, "Socket type not supported."}, + { WSAETIMEDOUT, "Connection timed out."}, + { WSATYPE_NOT_FOUND, "Class type not found."}, + { WSAEWOULDBLOCK, "Resource temporarily unavailable"}, + { WSAHOST_NOT_FOUND, "Host not found."}, + { WSA_INVALID_HANDLE, "Specified event object handle is invalid."}, + { WSA_INVALID_PARAMETER, "One or more parameters are invalid."}, + { WSA_IO_INCOMPLETE, "Overlapped I/O event object not in signaled state."}, + { WSA_IO_PENDING, "Overlapped operations will complete later."}, + { WSA_NOT_ENOUGH_MEMORY, "Insufficient memory available."}, + { WSANOTINITIALISED, "Successful WSAStartup not yet performed."}, + { WSANO_DATA, "Valid name, no data record of requested type."}, + { WSANO_RECOVERY, "This is a non-recoverable error."}, + { WSASYSCALLFAILURE, "System call failure."}, + { WSASYSNOTREADY, "Network subsystem is unavailable."}, + { WSATRY_AGAIN, "Non-authoritative host not found."}, + { WSAVERNOTSUPPORTED, "WINSOCK.DLL version out of range."}, + { WSAEDISCON, "Graceful shutdown in progress."}, + { WSA_OPERATION_ABORTED, "Overlapped operation aborted."}, + { 0, "No error."} + + /* These appeared in the documentation, but didn't compile. + * { WSAINVALIDPROCTABLE, "Invalid procedure table from service provider." }, + * { WSAINVALIDPROVIDER, "Invalid service provider version number." }, + * { WSAPROVIDERFAILEDINIT, "Unable to initialize a service provider." }, + */ + +}; /* end error_mesgs[] */ + +const char* winsock_strerror( DWORD inErrno ); + +/* ------------------------------------------------------------------- + * winsock_strerror + * + * returns a string representing the error code. The error messages + * were taken from Microsoft's online developer library. + * ------------------------------------------------------------------- */ + +const char* winsock_strerror( DWORD inErrno ) { + const char* str = "Unknown error"; + int i; + for ( i = 0; i < sizeof(error_mesgs); i++ ) { + if ( error_mesgs[i].err == inErrno ) { + str = error_mesgs[i].str; + break; + } + } + + return str; +} /* end winsock_strerror */ + +#endif /* WIN32 */ + +/* ------------------------------------------------------------------- + * warn + * + * Prints message and return + * ------------------------------------------------------------------- */ + +void warn( const char *inMessage, const char *inFile, int inLine ) { + fflush( 0 ); + +#ifdef NDEBUG + fprintf( stderr, "%s failed\n", inMessage ); +#else + + /* while debugging output file/line number also */ + fprintf( stderr, "%s failed (%s:%d)\n", inMessage, inFile, inLine ); +#endif +} /* end warn */ + +/* ------------------------------------------------------------------- + * warn_errno + * + * Prints message and errno message, and return. + * ------------------------------------------------------------------- */ + +void warn_errno( const char *inMessage, const char *inFile, int inLine ) { + int my_err; + const char* my_str; + + /* get platform's errno and error message */ +#ifdef WIN32 + my_err = WSAGetLastError(); + my_str = winsock_strerror( my_err ); +#else + my_err = errno; + my_str = strerror( my_err ); +#endif + + fflush( 0 ); + +#ifdef NDEBUG + fprintf( stderr, "%s failed: %s\n", inMessage, my_str ); +#else + + /* while debugging output file/line number and errno value also */ + fprintf( stderr, "%s failed (%s:%d): %s (%d)\n", + inMessage, inFile, inLine, my_str, my_err ); +#endif +} /* end warn_errno */ + +#ifdef __cplusplus +} /* end extern "C" */ +#endif diff --git a/compat/gettcpinfo.c b/compat/gettcpinfo.c new file mode 100644 index 0000000..11f92fe --- /dev/null +++ b/compat/gettcpinfo.c @@ -0,0 +1,110 @@ +/*--------------------------------------------------------------- + * Copyright (c) 2021 + * Broadcom Corporation + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the name of Broadcom Coporation, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * + * gettcpinfo.c + * Suppport for tcp info in a portable way + * + * by Robert J. McMahon (rjmcmahon@rjmcmahon.com, bob.mcmahon@broadcom.com) + * ------------------------------------------------------------------- + */ +#include "headers.h" +#include "gettcpinfo.h" +#ifdef HAVE_THREAD_DEBUG +// needed for thread_debug +#include "Thread.h" +#endif + +#if HAVE_TCP_STATS +inline void gettcpinfo (int sock, struct iperf_tcpstats *stats) { + assert(stats); +#if HAVE_DECL_TCP_INFO + struct tcp_info tcp_info_buf; + socklen_t tcp_info_length = sizeof(struct tcp_info); + if ((sock > 0) && !(getsockopt(sock, IPPROTO_TCP, TCP_INFO, &tcp_info_buf, &tcp_info_length) < 0)) { + stats->cwnd = tcp_info_buf.tcpi_snd_cwnd * tcp_info_buf.tcpi_snd_mss / 1024; + stats->rtt = tcp_info_buf.tcpi_rtt; + stats->rttvar = tcp_info_buf.tcpi_rttvar; + stats->retry_tot = tcp_info_buf.tcpi_total_retrans; + stats->mss_negotiated = tcp_info_buf.tcpi_snd_mss; + stats->isValid = true; +#elif HAVE_DECL_TCP_CONNECTION_INFO + struct tcp_connection_info tcp_info_buf; + socklen_t tcp_info_length = sizeof(struct tcp_connection_info); + if ((sock > 0) && !(getsockopt(sock, IPPROTO_TCP, TCP_CONNECTION_INFO, &tcp_info_buf, &tcp_info_length) < 0)) { +#ifdef __APPLE__ + stats->cwnd = tcp_info_buf.tcpi_snd_cwnd / 1024; +#else + stats->cwnd = tcp_info_buf.tcpi_snd_cwnd * tcp_info_buf.tcpi_maxseg / 1024; +#endif + stats->rtt = tcp_info_buf.tcpi_rttcur * 1000; // OS X units is ms + stats->rttvar = tcp_info_buf.tcpi_rttvar; + stats->retry_tot = tcp_info_buf.tcpi_txretransmitpackets; + stats->mss_negotiated = tcp_info_buf.tcpi_maxseg; + stats->isValid = true; +#endif + } else { + stats->rtt = 1; + stats->isValid = false; + } +} +inline void tcpstats_copy (struct iperf_tcpstats *stats_dst, struct iperf_tcpstats *stats_src) { + stats_dst->cwnd = stats_src->cwnd; + stats_dst->rtt = stats_src->rtt; + stats_dst->rttvar = stats_src->rttvar; + stats_dst->mss_negotiated = stats_src->mss_negotiated; + stats_dst->retry_tot = stats_src->retry_tot; + stats_dst->connecttime = stats_src->connecttime; + stats_dst->isValid = stats_src->isValid; +} +#else +#if WIN32 +inline void gettcpinfo (SOCKET sock, struct iperf_tcpstats *stats) { +#else +inline void gettcpinfo (int sock, struct iperf_tcpstats *stats) { +#endif + stats->rtt = 1; + stats->isValid = false; +}; +inline void tcpstats_copy (struct iperf_tcpstats *stats_dst, struct iperf_tcpstats *stats_src) { + stats_dst->rtt = stats_src->rtt; + stats_dst->isValid = stats_src->isValid; +} +#endif diff --git a/compat/gettimeofday.c b/compat/gettimeofday.c new file mode 100644 index 0000000..0e20123 --- /dev/null +++ b/compat/gettimeofday.c @@ -0,0 +1,92 @@ +/*--------------------------------------------------------------- + * Copyright (c) 1999,2000,2001,2002,2003 + * The Board of Trustees of the University of Illinois + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software (Iperf) and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the names of the University of Illinois, NCSA, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * National Laboratory for Applied Network Research + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * http://www.ncsa.uiuc.edu + * ________________________________________________________________ + * + * gettimeofday.c + * by Mark Gates <mgates@nlanr.net> + * ------------------------------------------------------------------- + * A (hack) implementation of gettimeofday for Windows. + * Since I send sec/usec in UDP packets, this made the most sense. + * ------------------------------------------------------------------- */ + +#ifdef HAVE_CONFIG_H + #include "config.h" +#endif + +#ifndef HAVE_GETTIMEOFDAY + + #include "headers.h" + #include "gettimeofday.h" + + #ifdef __cplusplus +extern "C" { +#endif + +int gettimeofday( struct timeval* tv, void* timezone ) { + FILETIME time; + double timed; + + GetSystemTimeAsFileTime( &time ); + + // Apparently Win32 has units of 1e-7 sec (tenths of microsecs) + // 4294967296 is 2^32, to shift high word over + // 11644473600 is the number of seconds between + // the Win32 epoch 1601-Jan-01 and the Unix epoch 1970-Jan-01 + // Tests found floating point to be 10x faster than 64bit int math. + + timed = ((time.dwHighDateTime * 4294967296e-7) - 11644473600.0) + + (time.dwLowDateTime * 1e-7); + + tv->tv_sec = (long) timed; + tv->tv_usec = (long) ((timed - tv->tv_sec) * 1e6); + + return 0; +} + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif /* HAVE_GETTIMEOFDAY */ diff --git a/compat/inet_ntop.c b/compat/inet_ntop.c new file mode 100644 index 0000000..d34e737 --- /dev/null +++ b/compat/inet_ntop.c @@ -0,0 +1,210 @@ +#include "inet_aton.h" +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Copyright (C) 1996-2001 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +// support for hiding v4 addresses from outputs +const char* +inet_ntop_hide(int af, const void *src, char *dst, socklen_t size) { + switch ( af ) { + case AF_INET: + return(inet_ntop4_hide(src, dst, size)); + default: + return NULL; + } + /* NOTREACHED */ +} +const char* +inet_ntop4_hide(const unsigned char *src, char *dst, socklen_t size) { + static const char *fmt = "%s.%s.%s.%u"; + char tmp[sizeof "255.255.255.255"]; + + if ( (size_t)sprintf(tmp, fmt, "*","*","*", src[3]) >= size ) { + return NULL; + } + strcpy(dst, tmp); + + return dst; +} + + +#ifndef HAVE_INET_NTOP +#define NS_INT16SZ 2 +#define NS_INADDRSZ 4 +#define NS_IN6ADDRSZ 16 + +/* + * WARNING: Don't even consider trying to compile this on a system where + * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. + */ + + +/* char * + * isc_net_ntop(af, src, dst, size) + * convert a network format address to presentation format. + * return: + * pointer to presentation format address (`dst'), or NULL (see errno). + * author: + * Paul Vixie, 1996. + */ +const char* +inet_ntop(int af, const void *src, char *dst, socklen_t size) { + switch ( af ) { + case AF_INET: + return(inet_ntop4(src, dst, size)); +#if HAVE_IPV6 + case AF_INET6: + return(inet_ntop6(src, dst, size)); +#endif + default: + return NULL; + } + /* NOTREACHED */ +} + + +/* const char * + * inet_ntop4(src, dst, size) + * format an IPv4 address + * return: + * `dst' (as a const) + * notes: + * (1) uses no statics + * (2) takes a unsigned char* not an in_addr as input + * author: + * Paul Vixie, 1996. + */ +const char* +inet_ntop4(const unsigned char *src, char *dst, socklen_t size) { + static const char *fmt = "%u.%u.%u.%u"; + char tmp[sizeof "255.255.255.255"]; + + if ( (size_t)sprintf(tmp, fmt, src[0], src[1], src[2], src[3]) >= size ) { + return NULL; + } + strcpy(dst, tmp); + + return dst; +} + +/* const char * + * isc_inet_ntop6(src, dst, size) + * convert IPv6 binary address into presentation (printable) format + * author: + * Paul Vixie, 1996. + */ +#if HAVE_IPV6 +const char* +inet_ntop6(const unsigned char *src, char *dst, socklen_t size) { + /* + * Note that int32_t and int16_t need only be "at least" large enough + * to contain a value of the specified size. On some systems, like + * Crays, there is no such thing as an integer variable with 16 bits. + * Keep this in mind if you think this function should have been coded + * to use pointer overlays. All the world's not a VAX. + */ + char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp; + struct { + int base, len; + } best, cur; + unsigned int words[NS_IN6ADDRSZ / NS_INT16SZ]; + int i; + + /* + * Preprocess: + * Copy the input (bytewise) array into a wordwise array. + * Find the longest run of 0x00's in src[] for :: shorthanding. + */ + memset(words, '\0', sizeof words); + for ( i = 0; i < NS_IN6ADDRSZ; i++ ) + words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3)); + best.base = -1; + best.len = 0; + cur.base = -1; + cur.len = 0; + for ( i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++ ) { + if ( words[i] == 0 ) { + if ( cur.base == -1 ) + cur.base = i, cur.len = 1; + else + cur.len++; + } else { + if ( cur.base != -1 ) { + if ( best.base == -1 || cur.len > best.len ) + best = cur; + cur.base = -1; + } + } + } + if ( cur.base != -1 ) { + if ( best.base == -1 || cur.len > best.len ) + best = cur; + } + if ( best.base != -1 && best.len < 2 ) + best.base = -1; + + /* + * Format the result. + */ + tp = tmp; + for ( i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++ ) { + /* Are we inside the best run of 0x00's? */ + if ( best.base != -1 && i >= best.base && + i < (best.base + best.len) ) { + if ( i == best.base ) + *tp++ = ':'; + continue; + } + /* Are we following an initial run of 0x00s or any real hex? */ + if ( i != 0 ) + *tp++ = ':'; + /* Is this address an encapsulated IPv4? */ + if ( i == 6 && best.base == 0 && + (best.len == 6 || (best.len == 5 && words[5] == 0xffff)) ) { + if ( !inet_ntop4(src+12, tp, + sizeof tmp - (tp - tmp)) ) + return NULL; + tp += strlen(tp); + break; + } + tp += sprintf(tp, "%x", words[i]); + } + /* Was it a trailing run of 0x00's? */ + if ( best.base != -1 && (best.base + best.len) == + (NS_IN6ADDRSZ / NS_INT16SZ) ) + *tp++ = ':'; + *tp++ = '\0'; + + /* + * Check for overflow, copy, and we're done. + */ + if ( (size_t)(tp - tmp) > size ) { + errno = ENOSPC; + return NULL; + } + strcpy(dst, tmp); + return dst; +} +#endif /* HAVE_IPV6 */ +#endif /* HAVE_INET_NTOP */ + +#ifdef __cplusplus +} /* end extern "C" */ +#endif diff --git a/compat/inet_pton.c b/compat/inet_pton.c new file mode 100644 index 0000000..32ee887 --- /dev/null +++ b/compat/inet_pton.c @@ -0,0 +1,209 @@ +#include "inet_aton.h" +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Copyright (C) 1996-2001 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#ifndef HAVE_INET_PTON +#define NS_INT16SZ 2 +#define NS_INADDRSZ 4 +#define NS_IN6ADDRSZ 16 + +/* int + * isc_net_pton(af, src, dst) + * convert from presentation format (which usually means ASCII printable) + * to network format (which is usually some kind of binary format). + * return: + * 1 if the address was valid for the specified address family + * 0 if the address wasn't valid (`dst' is untouched in this case) + * author: + * Paul Vixie, 1996. + */ +int +inet_pton(int af, + const char *src, + void *dst) { + switch ( af ) { + case AF_INET: + return(inet_pton4(src, dst)); +#if HAVE_IPV6 + case AF_INET6: + return(inet_pton6(src, dst)); +#endif + default: + return 0; + } + /* NOTREACHED */ +} + +/* int + * inet_pton4(src, dst) + * like inet_aton() but without all the hexadecimal and shorthand. + * return: + * 1 if `src' is a valid dotted quad, else 0. + * notice: + * does not touch `dst' unless it's returning 1. + * author: + * Paul Vixie, 1996. + */ +int +inet_pton4(src, dst) +const char *src; +unsigned char *dst; +{ + static const char digits[] = "0123456789"; + int saw_digit, octets, ch; + unsigned char tmp[NS_INADDRSZ], *tp; + + saw_digit = 0; + octets = 0; + *(tp = tmp) = 0; + while ( (ch = *src++) != '\0' ) { + const char *pch; + + if ( (pch = strchr(digits, ch)) != NULL ) { + unsigned int new = *tp * 10 + (pch - digits); + + if ( new > 255 ) + return(0); + *tp = new; + if ( ! saw_digit ) { + if ( ++octets > 4 ) + return(0); + saw_digit = 1; + } + } else if ( ch == '.' && saw_digit ) { + if ( octets == 4 ) + return(0); + *++tp = 0; + saw_digit = 0; + } else + return(0); + } + if ( octets < 4 ) + return(0); + memcpy(dst, tmp, NS_INADDRSZ); + return(1); +} + +/* int + * inet_pton6(src, dst) + * convert presentation level address to network order binary form. + * return: + * 1 if `src' is a valid [RFC1884 2.2] address, else 0. + * notice: + * (1) does not touch `dst' unless it's returning 1. + * (2) :: in a full address is silently ignored. + * credit: + * inspired by Mark Andrews. + * author: + * Paul Vixie, 1996. + */ +#if HAVE_IPV6 +int +inet_pton6(src, dst) +const char *src; +unsigned char *dst; +{ + static const char xdigits_l[] = "0123456789abcdef", + xdigits_u[] = "0123456789ABCDEF"; + unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp; + const char *xdigits, *curtok; + int ch, saw_xdigit; + unsigned int val; + + memset((tp = tmp), '\0', NS_IN6ADDRSZ); + endp = tp + NS_IN6ADDRSZ; + colonp = NULL; + /* Leading :: requires some special handling. */ + if ( *src == ':' ) + if ( *++src != ':' ) + return(0); + curtok = src; + saw_xdigit = 0; + val = 0; + while ( (ch = *src++) != '\0' ) { + const char *pch; + + if ( (pch = strchr((xdigits = xdigits_l), ch)) == NULL ) + pch = strchr((xdigits = xdigits_u), ch); + if ( pch != NULL ) { + val <<= 4; + val |= (pch - xdigits); + if ( val > 0xffff ) + return(0); + saw_xdigit = 1; + continue; + } + if ( ch == ':' ) { + curtok = src; + if ( !saw_xdigit ) { + if ( colonp ) + return(0); + colonp = tp; + continue; + } + if ( tp + NS_INT16SZ > endp ) + return(0); + *tp++ = (unsigned char) (val >> 8) & 0xff; + *tp++ = (unsigned char) val & 0xff; + saw_xdigit = 0; + val = 0; + continue; + } + if ( ch == '.' && ((tp + NS_INADDRSZ) <= endp) && + inet_pton4(curtok, tp) > 0 ) { + tp += NS_INADDRSZ; + saw_xdigit = 0; + break; /* '\0' was seen by inet_pton4(). */ + } + return(0); + } + if ( saw_xdigit ) { + if ( tp + NS_INT16SZ > endp ) + return(0); + *tp++ = (unsigned char) (val >> 8) & 0xff; + *tp++ = (unsigned char) val & 0xff; + } + if ( colonp != NULL ) { + /* + * Since some memmove()'s erroneously fail to handle + * overlapping regions, we'll do the shift by hand. + */ + const int n = tp - colonp; + int i; + + for ( i = 1; i <= n; i++ ) { + endp[- i] = colonp[n - i]; + colonp[n - i] = 0; + } + tp = endp; + } + if ( tp != endp ) + return(0); + memcpy(dst, tmp, NS_IN6ADDRSZ); + return(1); +} +#endif + +#endif /* HAVE_INET_PTON */ + +#ifdef __cplusplus +} /* end extern "C" */ +#endif diff --git a/compat/signal.c b/compat/signal.c new file mode 100644 index 0000000..7060305 --- /dev/null +++ b/compat/signal.c @@ -0,0 +1,204 @@ +/*--------------------------------------------------------------- + * Copyright (c) 1999,2000,2001,2002,2003 + * The Board of Trustees of the University of Illinois + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software (Iperf) and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the names of the University of Illinois, NCSA, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * National Laboratory for Applied Network Research + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * http://www.ncsa.uiuc.edu + * ________________________________________________________________ + * + * signal.c + * by Mark Gates <mgates@nlanr.net> + * ------------------------------------------------------------------- + * standard signal installer + * ------------------------------------------------------------------- */ + +#include "headers.h" +#include "util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef WIN32 + +/* list of signal handlers. _NSIG is number of signals defined. */ + +static SigfuncPtr handlers[ _NSIG ] = { 0}; + +/* ------------------------------------------------------------------- + * sig_dispatcher + * + * dispatches the signal to appropriate signal handler. This emulates + * the signal handling of Unix. + * + * ------------------------------------------------------------------- */ + +BOOL WINAPI sig_dispatcher( DWORD type ) { + SigfuncPtr h = NULL; + int signo; + + switch ( type ) { + case CTRL_C_EVENT: + signo = SIGINT; + h = handlers[ SIGINT ]; + break; + + case CTRL_CLOSE_EVENT: + case CTRL_LOGOFF_EVENT: + case CTRL_SHUTDOWN_EVENT: + signo = SIGTERM; + h = handlers[ SIGTERM ]; + break; + + default: + break; + } + + if ( h != NULL ) { + // call the signal handler + h( signo ); + return 1; + } else { + return 0; + } +} + +/* ------------------------------------------------------------------- + * my_signal + * + * installs a signal handler. I emulate Unix signals by storing the + * function pointers and dispatching events myself, using the + * sig_dispatcher above. + * ------------------------------------------------------------------- */ + +SigfuncPtr my_signal( int inSigno, SigfuncPtr inFunc ) { + SigfuncPtr old = NULL; + + if ( inSigno >= 0 && inSigno < _NSIG ) { + old = handlers[ inSigno ]; + handlers[ inSigno ] = inFunc; + } + + return old; +} /* end my_signal */ + +#else /* not WIN32 */ + +/* ------------------------------------------------------------------- + * my_signal + * + * installs a signal handler, and returns the old handler. + * This emulates the semi-standard signal() function in a + * standard way using the Posix sigaction function. + * + * from Stevens, 1998, section 5.8 + * ------------------------------------------------------------------- */ + +SigfuncPtr my_signal( int inSigno, SigfuncPtr inFunc ) { + struct sigaction theNewAction, theOldAction; + + assert( inFunc != NULL ); + + theNewAction.sa_handler = inFunc; + sigemptyset( &theNewAction.sa_mask ); + theNewAction.sa_flags = 0; + + if ( inSigno == SIGALRM ) { +#ifdef SA_INTERRUPT + theNewAction.sa_flags |= SA_INTERRUPT; /* SunOS 4.x */ +#endif + } else { +#ifdef SA_RESTART + theNewAction.sa_flags |= SA_RESTART; /* SVR4, 4.4BSD */ +#endif + } + + if ( sigaction( inSigno, &theNewAction, &theOldAction ) < 0 ) { + return SIG_ERR; + } else { + return theOldAction.sa_handler; + } +} /* end my_signal */ + +#endif /* not WIN32 */ + +/* ------------------------------------------------------------------- + * sig_exit + * + * Quietly exits. This protects some against being called multiple + * times. (TODO: should use a mutex to ensure (num++ == 0) is atomic.) + * ------------------------------------------------------------------- */ + +void sig_exit( int inSigno ) { + static int num = 0; + if ( num++ == 0 ) { + fflush( 0 ); + _exit(0); + } +} /* end sig_exit */ + +void disarm_itimer(void) { +#ifdef HAVE_SETITIMER + struct itimerval it; + memset (&it, 0, sizeof (it)); + setitimer(ITIMER_REAL, &it, NULL); +#endif +} + +int set_itimer(uintmax_t usecs) { + int err = 0; +#ifdef HAVE_SETITIMER + if (usecs < 0) { + WARN(1, "set_itimer value invalid"); + } else { + struct itimerval it; + memset (&it, 0, sizeof (it)); + it.it_value.tv_sec = (int)(usecs / 1000000); + it.it_value.tv_usec = (int)(usecs % 1000000); + err = setitimer(ITIMER_REAL, &it, NULL); + } +#endif + return err; +} + +#ifdef __cplusplus +} /* end extern "C" */ +#endif diff --git a/compat/snprintf.c b/compat/snprintf.c new file mode 100644 index 0000000..be56a53 --- /dev/null +++ b/compat/snprintf.c @@ -0,0 +1,101 @@ +/*--------------------------------------------------------------- + * Copyright (c) 1999,2000,2001,2002,2003 + * The Board of Trustees of the University of Illinois + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software (Iperf) and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the names of the University of Illinois, NCSA, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * National Laboratory for Applied Network Research + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * http://www.ncsa.uiuc.edu + * ________________________________________________________________ + * Author: Mark Gates + * + * snprintf.c + * + * This is from + * W. Richard Stevens, 'UNIX Network Programming', Vol 1, 2nd Edition, + * Prentice Hall, 1998. + * + * + * Throughout the book I use snprintf() because it's safer than sprintf(). + * But as of the time of this writing, not all systems provide this + * function. The function below should only be built on those systems + * that do not provide a real snprintf(). + * The function below just acts like sprintf(); it is not safe, but it + * tries to detect overflow. + * ________________________________________________________________ */ + +#ifdef HAVE_CONFIG_H + #include "config.h" +#endif + +#ifndef HAVE_SNPRINTF + + #include <stdlib.h> + #include <string.h> + #include <stdio.h> + #include <stdarg.h> + + #include "snprintf.h" + + #ifdef __cplusplus +extern "C" { +#endif + +int snprintf(char *buf, size_t size, const char *fmt, ...) { + int n; + va_list ap; + + va_start(ap, fmt); + vsprintf(buf, fmt, ap); /* Sigh, some vsprintf's return ptr, not length */ + n = strlen(buf); + va_end(ap); + + if ( n >= size ) { + fprintf( stderr, "snprintf: overflowed array\n" ); + exit(1); + } + + return(n); +} + +#ifdef __cplusplus +} /* end extern "C" */ + #endif + +#endif /* HAVE_SNPRINTF */ diff --git a/compat/string.c b/compat/string.c new file mode 100644 index 0000000..99415b5 --- /dev/null +++ b/compat/string.c @@ -0,0 +1,76 @@ +/*--------------------------------------------------------------- + * Copyright (c) 1999,2000,2001,2002,2003 + * The Board of Trustees of the University of Illinois + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software (Iperf) and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the names of the University of Illinois, NCSA, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * National Laboratory for Applied Network Research + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * http://www.ncsa.uiuc.edu + * ________________________________________________________________ + * + * string.c + * by Mark Gates <mgates@nlanr.net> + * ------------------------------------------------------------------- + * various string utilities + * ------------------------------------------------------------------- */ + +#include "headers.h" +#include "util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* ------------------------------------------------------------------- + * pattern + * + * Initialize the buffer with a pattern of (index mod 10). + * ------------------------------------------------------------------- */ + +void pattern( char *outBuf, int inBytes ) { + assert( outBuf != NULL ); + + while ( inBytes-- > 0 ) { + outBuf[ inBytes ] = (inBytes % 10) + '0'; + } +} /* end pattern */ + +#ifdef __cplusplus +} /* end extern "C" */ +#endif @@ -0,0 +1,348 @@ +#! /bin/sh +# Wrapper for compilers which do not understand '-c -o'. + +scriptversion=2018-03-07.03; # UTC + +# Copyright (C) 1999-2018 Free Software Foundation, Inc. +# Written by Tom Tromey <tromey@cygnus.com>. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to <bug-automake@gnu.org> or send patches to +# <automake-patches@gnu.org>. + +nl=' +' + +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent tools from complaining about whitespace usage. +IFS=" "" $nl" + +file_conv= + +# func_file_conv build_file lazy +# Convert a $build file to $host form and store it in $file +# Currently only supports Windows hosts. If the determined conversion +# type is listed in (the comma separated) LAZY, no conversion will +# take place. +func_file_conv () +{ + file=$1 + case $file in + / | /[!/]*) # absolute file, and not a UNC file + if test -z "$file_conv"; then + # lazily determine how to convert abs files + case `uname -s` in + MINGW*) + file_conv=mingw + ;; + CYGWIN*) + file_conv=cygwin + ;; + *) + file_conv=wine + ;; + esac + fi + case $file_conv/,$2, in + *,$file_conv,*) + ;; + mingw/*) + file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` + ;; + cygwin/*) + file=`cygpath -m "$file" || echo "$file"` + ;; + wine/*) + file=`winepath -w "$file" || echo "$file"` + ;; + esac + ;; + esac +} + +# func_cl_dashL linkdir +# Make cl look for libraries in LINKDIR +func_cl_dashL () +{ + func_file_conv "$1" + if test -z "$lib_path"; then + lib_path=$file + else + lib_path="$lib_path;$file" + fi + linker_opts="$linker_opts -LIBPATH:$file" +} + +# func_cl_dashl library +# Do a library search-path lookup for cl +func_cl_dashl () +{ + lib=$1 + found=no + save_IFS=$IFS + IFS=';' + for dir in $lib_path $LIB + do + IFS=$save_IFS + if $shared && test -f "$dir/$lib.dll.lib"; then + found=yes + lib=$dir/$lib.dll.lib + break + fi + if test -f "$dir/$lib.lib"; then + found=yes + lib=$dir/$lib.lib + break + fi + if test -f "$dir/lib$lib.a"; then + found=yes + lib=$dir/lib$lib.a + break + fi + done + IFS=$save_IFS + + if test "$found" != yes; then + lib=$lib.lib + fi +} + +# func_cl_wrapper cl arg... +# Adjust compile command to suit cl +func_cl_wrapper () +{ + # Assume a capable shell + lib_path= + shared=: + linker_opts= + for arg + do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + eat=1 + case $2 in + *.o | *.[oO][bB][jJ]) + func_file_conv "$2" + set x "$@" -Fo"$file" + shift + ;; + *) + func_file_conv "$2" + set x "$@" -Fe"$file" + shift + ;; + esac + ;; + -I) + eat=1 + func_file_conv "$2" mingw + set x "$@" -I"$file" + shift + ;; + -I*) + func_file_conv "${1#-I}" mingw + set x "$@" -I"$file" + shift + ;; + -l) + eat=1 + func_cl_dashl "$2" + set x "$@" "$lib" + shift + ;; + -l*) + func_cl_dashl "${1#-l}" + set x "$@" "$lib" + shift + ;; + -L) + eat=1 + func_cl_dashL "$2" + ;; + -L*) + func_cl_dashL "${1#-L}" + ;; + -static) + shared=false + ;; + -Wl,*) + arg=${1#-Wl,} + save_ifs="$IFS"; IFS=',' + for flag in $arg; do + IFS="$save_ifs" + linker_opts="$linker_opts $flag" + done + IFS="$save_ifs" + ;; + -Xlinker) + eat=1 + linker_opts="$linker_opts $2" + ;; + -*) + set x "$@" "$1" + shift + ;; + *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) + func_file_conv "$1" + set x "$@" -Tp"$file" + shift + ;; + *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) + func_file_conv "$1" mingw + set x "$@" "$file" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift + done + if test -n "$linker_opts"; then + linker_opts="-link$linker_opts" + fi + exec "$@" $linker_opts + exit 1 +} + +eat= + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: compile [--help] [--version] PROGRAM [ARGS] + +Wrapper for compilers which do not understand '-c -o'. +Remove '-o dest.o' from ARGS, run PROGRAM with the remaining +arguments, and rename the output as expected. + +If you are trying to build a whole package this is not the +right script to run: please start by reading the file 'INSTALL'. + +Report bugs to <bug-automake@gnu.org>. +EOF + exit $? + ;; + -v | --v*) + echo "compile $scriptversion" + exit $? + ;; + cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \ + icl | *[/\\]icl | icl.exe | *[/\\]icl.exe ) + func_cl_wrapper "$@" # Doesn't return... + ;; +esac + +ofile= +cfile= + +for arg +do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + # So we strip '-o arg' only if arg is an object. + eat=1 + case $2 in + *.o | *.obj) + ofile=$2 + ;; + *) + set x "$@" -o "$2" + shift + ;; + esac + ;; + *.c) + cfile=$1 + set x "$@" "$1" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift +done + +if test -z "$ofile" || test -z "$cfile"; then + # If no '-o' option was seen then we might have been invoked from a + # pattern rule where we don't need one. That is ok -- this is a + # normal compilation that the losing compiler can handle. If no + # '.c' file was seen then we are probably linking. That is also + # ok. + exec "$@" +fi + +# Name of file we expect compiler to create. +cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` + +# Create the lock directory. +# Note: use '[/\\:.-]' here to ensure that we don't use the same name +# that we are using for the .o file. Also, base the name on the expected +# object file name, since that is what matters with a parallel build. +lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d +while true; do + if mkdir "$lockdir" >/dev/null 2>&1; then + break + fi + sleep 1 +done +# FIXME: race condition here if user kills between mkdir and trap. +trap "rmdir '$lockdir'; exit 1" 1 2 15 + +# Run the compile. +"$@" +ret=$? + +if test -f "$cofile"; then + test "$cofile" = "$ofile" || mv "$cofile" "$ofile" +elif test -f "${cofile}bj"; then + test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" +fi + +rmdir "$lockdir" +exit $ret + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC0" +# time-stamp-end: "; # UTC" +# End: diff --git a/config.guess b/config.guess new file mode 100755 index 0000000..1972fda --- /dev/null +++ b/config.guess @@ -0,0 +1,1700 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright 1992-2021 Free Software Foundation, Inc. + +timestamp='2021-01-25' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <https://www.gnu.org/licenses/>. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). +# +# Originally written by Per Bothner; maintained since 2000 by Ben Elliston. +# +# You can get the latest version of this script from: +# https://git.savannah.gnu.org/cgit/config.git/plain/config.guess +# +# Please send patches to <config-patches@gnu.org>. + + +me=$(echo "$0" | sed -e 's,.*/,,') + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Options: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to <config-patches@gnu.org>." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright 1992-2021 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +tmp= +# shellcheck disable=SC2172 +trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15 + +set_cc_for_build() { + # prevent multiple calls if $tmp is already set + test "$tmp" && return 0 + : "${TMPDIR=/tmp}" + # shellcheck disable=SC2039 + { tmp=$( (umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null) && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } + dummy=$tmp/dummy + case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in + ,,) echo "int x;" > "$dummy.c" + for driver in cc gcc c89 c99 ; do + if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then + CC_FOR_BUILD="$driver" + break + fi + done + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; + esac +} + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if test -f /.attbin/uname ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=$( (uname -m) 2>/dev/null) || UNAME_MACHINE=unknown +UNAME_RELEASE=$( (uname -r) 2>/dev/null) || UNAME_RELEASE=unknown +UNAME_SYSTEM=$( (uname -s) 2>/dev/null) || UNAME_SYSTEM=unknown +UNAME_VERSION=$( (uname -v) 2>/dev/null) || UNAME_VERSION=unknown + +case "$UNAME_SYSTEM" in +Linux|GNU|GNU/*) + LIBC=unknown + + set_cc_for_build + cat <<-EOF > "$dummy.c" + #include <features.h> + #if defined(__UCLIBC__) + LIBC=uclibc + #elif defined(__dietlibc__) + LIBC=dietlibc + #elif defined(__GLIBC__) + LIBC=gnu + #else + #include <stdarg.h> + /* First heuristic to detect musl libc. */ + #ifdef __DEFINED_va_list + LIBC=musl + #endif + #endif + EOF + eval "$($CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g')" + + # Second heuristic to detect musl libc. + if [ "$LIBC" = unknown ] && + command -v ldd >/dev/null && + ldd --version 2>&1 | grep -q ^musl; then + LIBC=musl + fi + + # If the system lacks a compiler, then just pick glibc. + # We could probably try harder. + if [ "$LIBC" = unknown ]; then + LIBC=gnu + fi + ;; +esac + +# Note: order is significant - the case branches are not exclusive. + +case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + UNAME_MACHINE_ARCH=$( (uname -p 2>/dev/null || \ + /sbin/sysctl -n hw.machine_arch 2>/dev/null || \ + /usr/sbin/sysctl -n hw.machine_arch 2>/dev/null || \ + echo unknown)) + case "$UNAME_MACHINE_ARCH" in + aarch64eb) machine=aarch64_be-unknown ;; + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + earmv*) + arch=$(echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,') + endian=$(echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p') + machine="${arch}${endian}"-unknown + ;; + *) machine="$UNAME_MACHINE_ARCH"-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently (or will in the future) and ABI. + case "$UNAME_MACHINE_ARCH" in + earm*) + os=netbsdelf + ;; + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # Determine ABI tags. + case "$UNAME_MACHINE_ARCH" in + earm*) + expr='s/^earmv[0-9]/-eabi/;s/eb$//' + abi=$(echo "$UNAME_MACHINE_ARCH" | sed -e "$expr") + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "$UNAME_VERSION" in + Debian*) + release='-gnu' + ;; + *) + release=$(echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2) + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "$machine-${os}${release}${abi-}" + exit ;; + *:Bitrig:*:*) + UNAME_MACHINE_ARCH=$(arch | sed 's/Bitrig.//') + echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=$(arch | sed 's/OpenBSD.//') + echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE" + exit ;; + *:LibertyBSD:*:*) + UNAME_MACHINE_ARCH=$(arch | sed 's/^.*BSD\.//') + echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE" + exit ;; + *:MidnightBSD:*:*) + echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE" + exit ;; + *:ekkoBSD:*:*) + echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE" + exit ;; + *:SolidBSD:*:*) + echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE" + exit ;; + *:OS108:*:*) + echo "$UNAME_MACHINE"-unknown-os108_"$UNAME_RELEASE" + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd"$UNAME_RELEASE" + exit ;; + *:MirBSD:*:*) + echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE" + exit ;; + *:Sortix:*:*) + echo "$UNAME_MACHINE"-unknown-sortix + exit ;; + *:Twizzler:*:*) + echo "$UNAME_MACHINE"-unknown-twizzler + exit ;; + *:Redox:*:*) + echo "$UNAME_MACHINE"-unknown-redox + exit ;; + mips:OSF1:*.*) + echo mips-dec-osf1 + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=$(/usr/sbin/sizer -v | awk '{print $3}') + ;; + *5.*) + UNAME_RELEASE=$(/usr/sbin/sizer -v | awk '{print $4}') + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=$(/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1) + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE=alpha ;; + "EV4.5 (21064)") + UNAME_MACHINE=alpha ;; + "LCA4 (21066/21068)") + UNAME_MACHINE=alpha ;; + "EV5 (21164)") + UNAME_MACHINE=alphaev5 ;; + "EV5.6 (21164A)") + UNAME_MACHINE=alphaev56 ;; + "EV5.6 (21164PC)") + UNAME_MACHINE=alphapca56 ;; + "EV5.7 (21164PC)") + UNAME_MACHINE=alphapca57 ;; + "EV6 (21264)") + UNAME_MACHINE=alphaev6 ;; + "EV6.7 (21264A)") + UNAME_MACHINE=alphaev67 ;; + "EV6.8CB (21264C)") + UNAME_MACHINE=alphaev68 ;; + "EV6.8AL (21264B)") + UNAME_MACHINE=alphaev68 ;; + "EV6.8CX (21264D)") + UNAME_MACHINE=alphaev68 ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE=alphaev69 ;; + "EV7 (21364)") + UNAME_MACHINE=alphaev7 ;; + "EV7.9 (21364A)") + UNAME_MACHINE=alphaev79 ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo "$UNAME_MACHINE"-dec-osf"$(echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz)" + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo "$UNAME_MACHINE"-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo "$UNAME_MACHINE"-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix"$UNAME_RELEASE" + exit ;; + arm*:riscos:*:*|arm*:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "$( (/bin/universe) 2>/dev/null)" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case $(/usr/bin/uname -p) in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo "$UNAME_MACHINE"-ibm-solaris2"$(echo "$UNAME_RELEASE" | sed -e 's/[^.]*//')" + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')" + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2"$(echo "$UNAME_RELEASE" | sed -e 's/[^.]*//')" + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux"$UNAME_RELEASE" + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + set_cc_for_build + SUN_ARCH=i386 + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if test "$CC_FOR_BUILD" != no_compiler_found; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH=x86_64 + fi + fi + echo "$SUN_ARCH"-pc-solaris2"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')" + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')" + exit ;; + sun4*:SunOS:*:*) + case "$(/usr/bin/arch -k)" in + Series*|S4*) + UNAME_RELEASE=$(uname -v) + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos"$(echo "$UNAME_RELEASE"|sed -e 's/-/_/')" + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos"$UNAME_RELEASE" + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=$( (sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null) + test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3 + case "$(/bin/arch)" in + sun3) + echo m68k-sun-sunos"$UNAME_RELEASE" + ;; + sun4) + echo sparc-sun-sunos"$UNAME_RELEASE" + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos"$UNAME_RELEASE" + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint"$UNAME_RELEASE" + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint"$UNAME_RELEASE" + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint"$UNAME_RELEASE" + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint"$UNAME_RELEASE" + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint"$UNAME_RELEASE" + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint"$UNAME_RELEASE" + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten"$UNAME_RELEASE" + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten"$UNAME_RELEASE" + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix"$UNAME_RELEASE" + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix"$UNAME_RELEASE" + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix"$UNAME_RELEASE" + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + set_cc_for_build + sed 's/^ //' << EOF > "$dummy.c" +#ifdef __cplusplus +#include <stdio.h> /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && + dummyarg=$(echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p') && + SYSTEM_NAME=$("$dummy" "$dummyarg") && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos"$UNAME_RELEASE" + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=$(/usr/bin/uname -p) + if test "$UNAME_PROCESSOR" = mc88100 || test "$UNAME_PROCESSOR" = mc88110 + then + if test "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx || \ + test "$TARGET_BINARY_INTERFACE"x = x + then + echo m88k-dg-dgux"$UNAME_RELEASE" + else + echo m88k-dg-dguxbcs"$UNAME_RELEASE" + fi + else + echo i586-dg-dgux"$UNAME_RELEASE" + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix"$(echo "$UNAME_RELEASE"|sed -e 's/-/_/g')" + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'$(uname -s)'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if test -x /usr/bin/oslevel ; then + IBM_REV=$(/usr/bin/oslevel) + else + IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" + fi + echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV" + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + set_cc_for_build + sed 's/^ //' << EOF > "$dummy.c" + #include <sys/systemcfg.h> + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=$("$dummy") + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[4567]) + IBM_CPU_ID=$(/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }') + if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if test -x /usr/bin/lslpp ; then + IBM_REV=$(/usr/bin/lslpp -Lqc bos.rte.libc | + awk -F: '{ print $3 }' | sed s/[0-9]*$/0/) + else + IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" + fi + echo "$IBM_ARCH"-ibm-aix"$IBM_REV" + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd"$UNAME_RELEASE" # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//') + case "$UNAME_MACHINE" in + 9000/31?) HP_ARCH=m68000 ;; + 9000/[34]??) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if test -x /usr/bin/getconf; then + sc_cpu_version=$(/usr/bin/getconf SC_CPU_VERSION 2>/dev/null) + sc_kernel_bits=$(/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null) + case "$sc_cpu_version" in + 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 + 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "$sc_kernel_bits" in + 32) HP_ARCH=hppa2.0n ;; + 64) HP_ARCH=hppa2.0w ;; + '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 + esac ;; + esac + fi + if test "$HP_ARCH" = ""; then + set_cc_for_build + sed 's/^ //' << EOF > "$dummy.c" + + #define _HPUX_SOURCE + #include <stdlib.h> + #include <unistd.h> + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=$("$dummy") + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if test "$HP_ARCH" = hppa2.0w + then + set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH=hppa2.0w + else + HP_ARCH=hppa64 + fi + fi + echo "$HP_ARCH"-hp-hpux"$HPUX_REV" + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//') + echo ia64-hp-hpux"$HPUX_REV" + exit ;; + 3050*:HI-UX:*:*) + set_cc_for_build + sed 's/^ //' << EOF > "$dummy.c" + #include <unistd.h> + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=$("$dummy") && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if test -x /usr/sbin/sysversion ; then + echo "$UNAME_MACHINE"-unknown-osf1mk + else + echo "$UNAME_MACHINE"-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=$(uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz) + FUJITSU_SYS=$(uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///') + FUJITSU_REL=$(echo "$UNAME_RELEASE" | sed -e 's/ /_/') + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=$(uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///') + FUJITSU_REL=$(echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/') + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE" + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi"$UNAME_RELEASE" + exit ;; + *:BSD/OS:*:*) + echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE" + exit ;; + arm:FreeBSD:*:*) + UNAME_PROCESSOR=$(uname -p) + set_cc_for_build + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo "${UNAME_PROCESSOR}"-unknown-freebsd"$(echo ${UNAME_RELEASE}|sed -e 's/[-(].*//')"-gnueabi + else + echo "${UNAME_PROCESSOR}"-unknown-freebsd"$(echo ${UNAME_RELEASE}|sed -e 's/[-(].*//')"-gnueabihf + fi + exit ;; + *:FreeBSD:*:*) + UNAME_PROCESSOR=$(/usr/bin/uname -p) + case "$UNAME_PROCESSOR" in + amd64) + UNAME_PROCESSOR=x86_64 ;; + i386) + UNAME_PROCESSOR=i586 ;; + esac + echo "$UNAME_PROCESSOR"-unknown-freebsd"$(echo "$UNAME_RELEASE"|sed -e 's/[-(].*//')" + exit ;; + i*:CYGWIN*:*) + echo "$UNAME_MACHINE"-pc-cygwin + exit ;; + *:MINGW64*:*) + echo "$UNAME_MACHINE"-pc-mingw64 + exit ;; + *:MINGW*:*) + echo "$UNAME_MACHINE"-pc-mingw32 + exit ;; + *:MSYS*:*) + echo "$UNAME_MACHINE"-pc-msys + exit ;; + i*:PW*:*) + echo "$UNAME_MACHINE"-pc-pw32 + exit ;; + *:Interix*:*) + case "$UNAME_MACHINE" in + x86) + echo i586-pc-interix"$UNAME_RELEASE" + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix"$UNAME_RELEASE" + exit ;; + IA64) + echo ia64-unknown-interix"$UNAME_RELEASE" + exit ;; + esac ;; + i*:UWIN*:*) + echo "$UNAME_MACHINE"-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-pc-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')" + exit ;; + *:GNU:*:*) + # the GNU system + echo "$(echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,')-unknown-$LIBC$(echo "$UNAME_RELEASE"|sed -e 's,/.*$,,')" + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo "$UNAME_MACHINE-unknown-$(echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]")$(echo "$UNAME_RELEASE"|sed -e 's/[-(].*//')-$LIBC" + exit ;; + *:Minix:*:*) + echo "$UNAME_MACHINE"-unknown-minix + exit ;; + aarch64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + alpha:Linux:*:*) + case $(sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null) in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC=gnulibc1 ; fi + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + arc:Linux:*:* | arceb:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + arm*:Linux:*:*) + set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi + else + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + cris:Linux:*:*) + echo "$UNAME_MACHINE"-axis-linux-"$LIBC" + exit ;; + crisv32:Linux:*:*) + echo "$UNAME_MACHINE"-axis-linux-"$LIBC" + exit ;; + e2k:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + frv:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + hexagon:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + i*86:Linux:*:*) + echo "$UNAME_MACHINE"-pc-linux-"$LIBC" + exit ;; + ia64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + k1om:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + loongarch32:Linux:*:* | loongarch64:Linux:*:* | loongarchx32:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + m32r*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + m68*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + set_cc_for_build + IS_GLIBC=0 + test x"${LIBC}" = xgnu && IS_GLIBC=1 + sed 's/^ //' << EOF > "$dummy.c" + #undef CPU + #undef mips + #undef mipsel + #undef mips64 + #undef mips64el + #if ${IS_GLIBC} && defined(_ABI64) + LIBCABI=gnuabi64 + #else + #if ${IS_GLIBC} && defined(_ABIN32) + LIBCABI=gnuabin32 + #else + LIBCABI=${LIBC} + #endif + #endif + + #if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 + CPU=mipsisa64r6 + #else + #if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 + CPU=mipsisa32r6 + #else + #if defined(__mips64) + CPU=mips64 + #else + CPU=mips + #endif + #endif + #endif + + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + MIPS_ENDIAN=el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + MIPS_ENDIAN= + #else + MIPS_ENDIAN= + #endif + #endif +EOF + eval "$($CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI')" + test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; } + ;; + mips64el:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + openrisc*:Linux:*:*) + echo or1k-unknown-linux-"$LIBC" + exit ;; + or32:Linux:*:* | or1k*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-"$LIBC" + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-"$LIBC" + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case $(grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2) in + PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;; + PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;; + *) echo hppa-unknown-linux-"$LIBC" ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-"$LIBC" + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-"$LIBC" + exit ;; + ppc64le:Linux:*:*) + echo powerpc64le-unknown-linux-"$LIBC" + exit ;; + ppcle:Linux:*:*) + echo powerpcle-unknown-linux-"$LIBC" + exit ;; + riscv32:Linux:*:* | riscv32be:Linux:*:* | riscv64:Linux:*:* | riscv64be:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo "$UNAME_MACHINE"-ibm-linux-"$LIBC" + exit ;; + sh64*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + sh*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + tile*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + vax:Linux:*:*) + echo "$UNAME_MACHINE"-dec-linux-"$LIBC" + exit ;; + x86_64:Linux:*:*) + set_cc_for_build + LIBCABI=$LIBC + if test "$CC_FOR_BUILD" != no_compiler_found; then + if (echo '#ifdef __ILP32__'; echo IS_X32; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_X32 >/dev/null + then + LIBCABI="$LIBC"x32 + fi + fi + echo "$UNAME_MACHINE"-pc-linux-"$LIBCABI" + exit ;; + xtensa*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION" + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo "$UNAME_MACHINE"-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo "$UNAME_MACHINE"-unknown-stop + exit ;; + i*86:atheos:*:*) + echo "$UNAME_MACHINE"-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo "$UNAME_MACHINE"-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos"$UNAME_RELEASE" + exit ;; + i*86:*DOS:*:*) + echo "$UNAME_MACHINE"-pc-msdosdjgpp + exit ;; + i*86:*:4.*:*) + UNAME_REL=$(echo "$UNAME_RELEASE" | sed 's/\/MP$//') + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL" + else + echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL" + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case $(/bin/uname -X | grep "^Machine") in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}" + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=$(sed -n 's/.*Version //p' </usr/options/cb.name) + echo "$UNAME_MACHINE"-pc-isc"$UNAME_REL" + elif /bin/uname -X 2>/dev/null >/dev/null ; then + UNAME_REL=$( (/bin/uname -X|grep Release|sed -e 's/.*= //')) + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL" + else + echo "$UNAME_MACHINE"-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configure will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv"$UNAME_RELEASE" # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.$(sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.$(sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos"$UNAME_RELEASE" + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos"$UNAME_RELEASE" + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos"$UNAME_RELEASE" + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos"$UNAME_RELEASE" + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv"$UNAME_RELEASE" + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=$( (uname -p) 2>/dev/null) + echo "$UNAME_MACHINE"-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says <Richard.M.Bartel@ccMail.Census.GOV> + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes <hewes@openmarket.com>. + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo "$UNAME_MACHINE"-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux"$UNAME_RELEASE" + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if test -d /usr/nec; then + echo mips-nec-sysv"$UNAME_RELEASE" + else + echo mips-unknown-sysv"$UNAME_RELEASE" + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + x86_64:Haiku:*:*) + echo x86_64-unknown-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux"$UNAME_RELEASE" + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux"$UNAME_RELEASE" + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux"$UNAME_RELEASE" + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux"$UNAME_RELEASE" + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux"$UNAME_RELEASE" + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux"$UNAME_RELEASE" + exit ;; + SX-ACE:SUPER-UX:*:*) + echo sxace-nec-superux"$UNAME_RELEASE" + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody"$UNAME_RELEASE" + exit ;; + *:Rhapsody:*:*) + echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE" + exit ;; + arm64:Darwin:*:*) + echo aarch64-apple-darwin"$UNAME_RELEASE" + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=$(uname -p) + case $UNAME_PROCESSOR in + unknown) UNAME_PROCESSOR=powerpc ;; + esac + if command -v xcode-select > /dev/null 2> /dev/null && \ + ! xcode-select --print-path > /dev/null 2> /dev/null ; then + # Avoid executing cc if there is no toolchain installed as + # cc will be a stub that puts up a graphical alert + # prompting the user to install developer tools. + CC_FOR_BUILD=no_compiler_found + else + set_cc_for_build + fi + if test "$CC_FOR_BUILD" != no_compiler_found; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi + # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc + if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_PPC >/dev/null + then + UNAME_PROCESSOR=powerpc + fi + elif test "$UNAME_PROCESSOR" = i386 ; then + # uname -m returns i386 or x86_64 + UNAME_PROCESSOR=$UNAME_MACHINE + fi + echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE" + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=$(uname -p) + if test "$UNAME_PROCESSOR" = x86; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE" + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NEO-*:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSE-*:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSR-*:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSV-*:NONSTOP_KERNEL:*:*) + echo nsv-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSX-*:NONSTOP_KERNEL:*:*) + echo nsx-tandem-nsk"$UNAME_RELEASE" + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE" + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + # shellcheck disable=SC2154 + if test "$cputype" = 386; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo "$UNAME_MACHINE"-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux"$UNAME_RELEASE" + exit ;; + *:DragonFly:*:*) + echo "$UNAME_MACHINE"-unknown-dragonfly"$(echo "$UNAME_RELEASE"|sed -e 's/[-(].*//')" + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=$( (uname -p) 2>/dev/null) + case "$UNAME_MACHINE" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo "$UNAME_MACHINE"-pc-skyos"$(echo "$UNAME_RELEASE" | sed -e 's/ .*$//')" + exit ;; + i*86:rdos:*:*) + echo "$UNAME_MACHINE"-pc-rdos + exit ;; + *:AROS:*:*) + echo "$UNAME_MACHINE"-unknown-aros + exit ;; + x86_64:VMkernel:*:*) + echo "$UNAME_MACHINE"-unknown-esx + exit ;; + amd64:Isilon\ OneFS:*:*) + echo x86_64-unknown-onefs + exit ;; + *:Unleashed:*:*) + echo "$UNAME_MACHINE"-unknown-unleashed"$UNAME_RELEASE" + exit ;; +esac + +# No uname command or uname output not recognized. +set_cc_for_build +cat > "$dummy.c" <<EOF +#ifdef _SEQUENT_ +#include <sys/types.h> +#include <sys/utsname.h> +#endif +#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) +#if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) +#include <signal.h> +#if defined(_SIZE_T_) || defined(SIGLOST) +#include <sys/utsname.h> +#endif +#endif +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include <sys/param.h> + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=$( (hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null); + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); +#endif + +#if defined (vax) +#if !defined (ultrix) +#include <sys/param.h> +#if defined (BSD) +#if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +#else +#if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +#else + printf ("vax-dec-bsd\n"); exit (0); +#endif +#endif +#else + printf ("vax-dec-bsd\n"); exit (0); +#endif +#else +#if defined(_SIZE_T_) || defined(SIGLOST) + struct utsname un; + uname (&un); + printf ("vax-dec-ultrix%s\n", un.release); exit (0); +#else + printf ("vax-dec-ultrix\n"); exit (0); +#endif +#endif +#endif +#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) +#if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) +#if defined(_SIZE_T_) || defined(SIGLOST) + struct utsname *un; + uname (&un); + printf ("mips-dec-ultrix%s\n", un.release); exit (0); +#else + printf ("mips-dec-ultrix\n"); exit (0); +#endif +#endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=$($dummy) && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. +test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; } + +echo "$0: unable to guess system type" >&2 + +case "$UNAME_MACHINE:$UNAME_SYSTEM" in + mips:Linux | mips64:Linux) + # If we got here on MIPS GNU/Linux, output extra information. + cat >&2 <<EOF + +NOTE: MIPS GNU/Linux systems require a C compiler to fully recognize +the system type. Please install a C compiler and try again. +EOF + ;; +esac + +cat >&2 <<EOF + +This script (version $timestamp), has failed to recognize the +operating system you are using. If your script is old, overwrite *all* +copies of config.guess and config.sub with the latest versions from: + + https://git.savannah.gnu.org/cgit/config.git/plain/config.guess +and + https://git.savannah.gnu.org/cgit/config.git/plain/config.sub +EOF + +year=$(echo $timestamp | sed 's,-.*,,') +# shellcheck disable=SC2003 +if test "$(expr "$(date +%Y)" - "$year")" -lt 3 ; then + cat >&2 <<EOF + +If $0 has already been updated, send the following data and any +information you think might be pertinent to config-patches@gnu.org to +provide the necessary information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = $( (uname -m) 2>/dev/null || echo unknown) +uname -r = $( (uname -r) 2>/dev/null || echo unknown) +uname -s = $( (uname -s) 2>/dev/null || echo unknown) +uname -v = $( (uname -v) 2>/dev/null || echo unknown) + +/usr/bin/uname -p = $( (/usr/bin/uname -p) 2>/dev/null) +/bin/uname -X = $( (/bin/uname -X) 2>/dev/null) + +hostinfo = $( (hostinfo) 2>/dev/null) +/bin/universe = $( (/bin/universe) 2>/dev/null) +/usr/bin/arch -k = $( (/usr/bin/arch -k) 2>/dev/null) +/bin/arch = $( (/bin/arch) 2>/dev/null) +/usr/bin/oslevel = $( (/usr/bin/oslevel) 2>/dev/null) +/usr/convex/getsysinfo = $( (/usr/convex/getsysinfo) 2>/dev/null) + +UNAME_MACHINE = "$UNAME_MACHINE" +UNAME_RELEASE = "$UNAME_RELEASE" +UNAME_SYSTEM = "$UNAME_SYSTEM" +UNAME_VERSION = "$UNAME_VERSION" +EOF +fi + +exit 1 + +# Local variables: +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/config.h.in b/config.h.in new file mode 100644 index 0000000..267e661 --- /dev/null +++ b/config.h.in @@ -0,0 +1,509 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define if building universal (internal helper macro) */ +#undef AC_APPLE_UNIVERSAL_BUILD + +/* Define if debugging info is desired */ +#undef DBG_MJZ + +/* Define if default UDP payload length is based on device MTU and socket + buffer size */ +#undef DEFAULT_PAYLOAD_LEN_PER_MTU_DISCOVERY + +/* AF_PACKET support is available */ +#undef HAVE_AF_PACKET + +/* Define to 1 if you have the <arpa/inet.h> header file. */ +#undef HAVE_ARPA_INET_H + +/* Define to 1 if you have the `atexit' function. */ +#undef HAVE_ATEXIT + +/* Define to 1 if you have the `clock_gettime' function. */ +#undef HAVE_CLOCK_GETTIME + +/* Define to 1 if you have the `clock_nanosleep' function. */ +#undef HAVE_CLOCK_NANOSLEEP + +/* Define to 1 if you have the declaration of `AF_INET6', and to 0 if you + don't. */ +#undef HAVE_DECL_AF_INET6 + +/* Define to 1 if you have the declaration of `CPU_SET', and to 0 if you + don't. */ +#undef HAVE_DECL_CPU_SET + +/* Define to 1 if you have the declaration of `ENOBUFS', and to 0 if you + don't. */ +#undef HAVE_DECL_ENOBUFS + +/* Define to 1 if you have the declaration of `EWOULDBLOCK', and to 0 if you + don't. */ +#undef HAVE_DECL_EWOULDBLOCK + +/* Define to 1 if you have the declaration of `IFF_TAP', and to 0 if you + don't. */ +#undef HAVE_DECL_IFF_TAP + +/* Define to 1 if you have the declaration of `IFF_TUN', and to 0 if you + don't. */ +#undef HAVE_DECL_IFF_TUN + +/* Define to 1 if you have the declaration of `IPV6_ADD_MEMBERSHIP', and to 0 + if you don't. */ +#undef HAVE_DECL_IPV6_ADD_MEMBERSHIP + +/* Define to 1 if you have the declaration of `IPV6_JOIN_GROUP', and to 0 if + you don't. */ +#undef HAVE_DECL_IPV6_JOIN_GROUP + +/* Define to 1 if you have the declaration of `IPV6_MULTICAST_HOPS', and to 0 + if you don't. */ +#undef HAVE_DECL_IPV6_MULTICAST_HOPS + +/* Define to 1 if you have the declaration of `IPV6_TCLASS', and to 0 if you + don't. */ +#undef HAVE_DECL_IPV6_TCLASS + +/* Define to 1 if you have the declaration of `IPV6_V6ONLY', and to 0 if you + don't. */ +#undef HAVE_DECL_IPV6_V6ONLY + +/* Define to 1 if you have the declaration of `IP_ADD_MEMBERSHIP', and to 0 if + you don't. */ +#undef HAVE_DECL_IP_ADD_MEMBERSHIP + +/* Define to 1 if you have the declaration of `IP_ADD_SOURCE_MEMBERSHIP', and + to 0 if you don't. */ +#undef HAVE_DECL_IP_ADD_SOURCE_MEMBERSHIP + +/* Define to 1 if you have the declaration of `IP_MULTICAST_ALL', and to 0 if + you don't. */ +#undef HAVE_DECL_IP_MULTICAST_ALL + +/* Define to 1 if you have the declaration of `IP_TOS', and to 0 if you don't. + */ +#undef HAVE_DECL_IP_TOS + +/* Define to 1 if you have the declaration of `MCAST_JOIN_GROUP', and to 0 if + you don't. */ +#undef HAVE_DECL_MCAST_JOIN_GROUP + +/* Define to 1 if you have the declaration of `MCAST_JOIN_SOURCE_GROUP', and + to 0 if you don't. */ +#undef HAVE_DECL_MCAST_JOIN_SOURCE_GROUP + +/* Define to 1 if you have the declaration of `MSG_DONTWAIT', and to 0 if you + don't. */ +#undef HAVE_DECL_MSG_DONTWAIT + +/* Define to 1 if you have the declaration of `MSG_PEEK', and to 0 if you + don't. */ +#undef HAVE_DECL_MSG_PEEK + +/* Define to 1 if you have the declaration of `MSG_WAITALL', and to 0 if you + don't. */ +#undef HAVE_DECL_MSG_WAITALL + +/* Define to 1 if you have the declaration of `pthread_cancel', and to 0 if + you don't. */ +#undef HAVE_DECL_PTHREAD_CANCEL + +/* Define to 1 if you have the declaration of `SIGALRM', and to 0 if you + don't. */ +#undef HAVE_DECL_SIGALRM + +/* Define to 1 if you have the declaration of `SIOCGIFMTU', and to 0 if you + don't. */ +#undef HAVE_DECL_SIOCGIFMTU + +/* Define to 1 if you have the declaration of `SO_BINDTODEVICE', and to 0 if + you don't. */ +#undef HAVE_DECL_SO_BINDTODEVICE + +/* Define to 1 if you have the declaration of `SO_DONTROUTE', and to 0 if you + don't. */ +#undef HAVE_DECL_SO_DONTROUTE + +/* Define to 1 if you have the declaration of `SO_MAX_PACING_RATE', and to 0 + if you don't. */ +#undef HAVE_DECL_SO_MAX_PACING_RATE + +/* Define to 1 if you have the declaration of `SO_REUSEPORT', and to 0 if you + don't. */ +#undef HAVE_DECL_SO_REUSEPORT + +/* Define to 1 if you have the declaration of `SO_SNDTIMEO', and to 0 if you + don't. */ +#undef HAVE_DECL_SO_SNDTIMEO + +/* Define to 1 if you have the declaration of `SO_TIMESTAMP', and to 0 if you + don't. */ +#undef HAVE_DECL_SO_TIMESTAMP + +/* Define to 1 if you have the declaration of `TCP_CONNECTION_INFO', and to 0 + if you don't. */ +#undef HAVE_DECL_TCP_CONNECTION_INFO + +/* Define to 1 if you have the declaration of `TCP_INFO', and to 0 if you + don't. */ +#undef HAVE_DECL_TCP_INFO + +/* Define to 1 if you have the declaration of `TCP_MAXSEG', and to 0 if you + don't. */ +#undef HAVE_DECL_TCP_MAXSEG + +/* Define to 1 if you have the declaration of `TCP_NODELAY', and to 0 if you + don't. */ +#undef HAVE_DECL_TCP_NODELAY + +/* Define to 1 if you have the declaration of `TCP_NOTSENT_LOWAT', and to 0 if + you don't. */ +#undef HAVE_DECL_TCP_NOTSENT_LOWAT + +/* Define to 1 if you have the declaration of `TCP_QUICKACK', and to 0 if you + don't. */ +#undef HAVE_DECL_TCP_QUICKACK + +/* Define to 1 if you have the declaration of `TCP_WINDOW_CLAMP', and to 0 if + you don't. */ +#undef HAVE_DECL_TCP_WINDOW_CLAMP + +/* Define if limiting test traffic to the local-only network (via socket + SO_DONTROUTE) should be the default */ +#undef HAVE_DEFAULT_DONTROUTE_ON + +/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ +#undef HAVE_DOPRNT + +/* Define if fast sampling for report intervals is desired */ +#undef HAVE_FASTSAMPLING + +/* Define to 1 if you have the `freopen' function. */ +#undef HAVE_FREOPEN + +/* Define if syscall(SYS_gettid) available. */ +#undef HAVE_GETTID_SYSCALL + +/* Define to 1 if you have the `gettimeofday' function. */ +#undef HAVE_GETTIMEOFDAY + +/* Define to 1 if you have the <ifaddrs.h> header file. */ +#undef HAVE_IFADDRS_H + +/* Define to 1 if you have the `inet_ntop' function. */ +#undef HAVE_INET_NTOP + +/* Define to 1 if you have the `inet_pton' function. */ +#undef HAVE_INET_PTON + +/* Define to 1 if the system has the type `int64_t'. */ +#undef HAVE_INT64_T + +/* Define to 1 if you have the <inttypes.h> header file. */ +#undef HAVE_INTTYPES_H + +/* Define to enable IPv6 support */ +#undef HAVE_IPV6 + +/* Define to enable IPv6 multicast support */ +#undef HAVE_IPV6_MULTICAST + +/* Define if isochronous traffic option is desired and available */ +#undef HAVE_ISOCHRONOUS + +/* Define if Kalman tuning is desired and available */ +#undef HAVE_KALMAN + +/* Define to 1 if you have the <libintl.h> header file. */ +#undef HAVE_LIBINTL_H + +/* Define to 1 if you have the `rt' library (-lrt). */ +#undef HAVE_LIBRT + +/* Define to 1 if you have the <linux/filter.h> header file. */ +#undef HAVE_LINUX_FILTER_H + +/* Define to 1 if you have the <linux/if_packet.h> header file. */ +#undef HAVE_LINUX_IF_PACKET_H + +/* Define to 1 if you have the <linux/if_tun.h> header file. */ +#undef HAVE_LINUX_IF_TUN_H + +/* Define to 1 if you have the <linux/ip.h> header file. */ +#undef HAVE_LINUX_IP_H + +/* Define to 1 if you have the <linux/sockios.h> header file. */ +#undef HAVE_LINUX_SOCKIOS_H + +/* Define to 1 if you have the <linux/udp.h> header file. */ +#undef HAVE_LINUX_UDP_H + +/* Define to 1 if you have the <memory.h> header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `memset' function. */ +#undef HAVE_MEMSET + +/* Define to 1 if you have the `mlockall' function. */ +#undef HAVE_MLOCKALL + +/* Define to enable multicast support */ +#undef HAVE_MULTICAST + +/* Define to 1 if you have the `nanosleep' function. */ +#undef HAVE_NANOSLEEP + +/* Define to 1 if you have the <netdb.h> header file. */ +#undef HAVE_NETDB_H + +/* Define to 1 if you have the <netinet/in.h> header file. */ +#undef HAVE_NETINET_IN_H + +/* Define to 1 if you have the <netinet/tcp.h> header file. */ +#undef HAVE_NETINET_TCP_H + +/* Define to 1 if you have the <net/ethernet.h> header file. */ +#undef HAVE_NET_ETHERNET_H + +/* Define to 1 if you have the <net/if.h> header file. */ +#undef HAVE_NET_IF_H + +/* Define if packet level debugging is desired */ +#undef HAVE_PACKET_DEBUG + +/* */ +#undef HAVE_POSIX_THREAD + +/* Define if you have POSIX threads libraries and header files. */ +#undef HAVE_PTHREAD + +/* Have PTHREAD_PRIO_INHERIT. */ +#undef HAVE_PTHREAD_PRIO_INHERIT + +/* Define if role reversal ids are desired */ +#undef HAVE_ROLE_REVERSAL_ID + +/* Define to 1 if you have the `sched_setscheduler' function. */ +#undef HAVE_SCHED_SETSCHEDULER + +/* Define to 1 if you have the `sched_yield' function. */ +#undef HAVE_SCHED_YIELD + +/* Define to 1 if you have the `select' function. */ +#undef HAVE_SELECT + +/* Define if 64 bit sequence numbers are desired and available */ +#undef HAVE_SEQNO64b + +/* Define to 1 if you have the `setitimer' function. */ +#undef HAVE_SETITIMER + +/* Define to 1 if you have the <signal.h> header file. */ +#undef HAVE_SIGNAL_H + +/* Define to 1 if you have the `snprintf' function. */ +#undef HAVE_SNPRINTF + +/* Define to 1 if the system has the type `ssize_t'. */ +#undef HAVE_SSIZE_T + +/* Define to enable ssm multicast support */ +#undef HAVE_SSM_MULTICAST + +/* Define to 1 if stdbool.h conforms to C99. */ +#undef HAVE_STDBOOL_H + +/* Define to 1 if you have the <stdint.h> header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the <stdlib.h> header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the `strchr' function. */ +#undef HAVE_STRCHR + +/* Define to 1 if you have the `strerror' function. */ +#undef HAVE_STRERROR + +/* Define to 1 if you have the `strftime' function. */ +#undef HAVE_STRFTIME + +/* Define to 1 if you have the <strings.h> header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the <string.h> header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the `strtod' function. */ +#undef HAVE_STRTOD + +/* Define to 1 if you have the `strtol' function. */ +#undef HAVE_STRTOL + +/* Define to 1 if you have the `strtoll' function. */ +#undef HAVE_STRTOLL + +/* Define to 1 if the system has the type `struct group_source_req'. */ +#undef HAVE_STRUCT_GROUP_SOURCE_REQ + +/* Define to 1 if the system has the type `struct ipv6_mreq'. */ +#undef HAVE_STRUCT_IPV6_MREQ + +/* Define to 1 if the system has the type `struct ip_mreq'. */ +#undef HAVE_STRUCT_IP_MREQ + +/* Define to 1 if the system has the type `struct ip_mreq_source'. */ +#undef HAVE_STRUCT_IP_MREQ_SOURCE + +/* Define to 1 if `imr_multiaddr.s_addr' is a member of `struct + ip_mreq_source'. */ +#undef HAVE_STRUCT_IP_MREQ_SOURCE_IMR_MULTIADDR_S_ADDR + +/* Define to 1 if the system has the type `struct sockaddr_in6'. */ +#undef HAVE_STRUCT_SOCKADDR_IN6 + +/* Define to 1 if `sin6_len' is a member of `struct sockaddr_in6'. */ +#undef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN + +/* Define to 1 if the system has the type `struct sockaddr_storage'. */ +#undef HAVE_STRUCT_SOCKADDR_STORAGE + +/* Define to 1 if `tcpi_total_retrans' is a member of `struct tcp_info'. */ +#undef HAVE_STRUCT_TCP_INFO_TCPI_TOTAL_RETRANS + +/* Define to 1 if you have the <syslog.h> header file. */ +#undef HAVE_SYSLOG_H + +/* Define to 1 if you have the <sys/ioctl.h> header file. */ +#undef HAVE_SYS_IOCTL_H + +/* Define to 1 if you have the <sys/select.h> header file. */ +#undef HAVE_SYS_SELECT_H + +/* Define to 1 if you have the <sys/socket.h> header file. */ +#undef HAVE_SYS_SOCKET_H + +/* Define to 1 if you have the <sys/sockio.h> header file. */ +#undef HAVE_SYS_SOCKIO_H + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the <sys/time.h> header file. */ +#undef HAVE_SYS_TIME_H + +/* Define to 1 if you have the <sys/types.h> header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to enable tcp stats support */ +#undef HAVE_TCP_STATS + +/* Define for thread level debugging of the code */ +#undef HAVE_THREAD_DEBUG + +/* TUNTAP_TAP support is available */ +#undef HAVE_TUNTAP_TAP + +/* TUNTAP_TUN support is available */ +#undef HAVE_TUNTAP_TUN + +/* Define to 1 if you have the <unistd.h> header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the `usleep' function. */ +#undef HAVE_USLEEP + +/* Define to 1 if you have the `vprintf' function. */ +#undef HAVE_VPRINTF + +/* Define if Web100 is desired and available */ +#undef HAVE_WEB100 + +/* Define if using WIN32 threads */ +#undef HAVE_WIN32_THREAD + +/* Define if winsock2.h exists. */ +#undef HAVE_WINSOCK2_H + +/* Define to 1 if the system has the type `_Bool'. */ +#undef HAVE__BOOL + +/* Define to disable asserts */ +#undef NDEBUG + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to necessary symbol if this constant uses a non-standard name on + your system. */ +#undef PTHREAD_CREATE_JOINABLE + +/* Define as the return type of signal handlers (`int' or `void'). */ +#undef RETSIGTYPE + +/* Define to the type of arg 1 for `select'. */ +#undef SELECT_TYPE_ARG1 + +/* Define to the type of args 2, 3 and 4 for `select'. */ +#undef SELECT_TYPE_ARG234 + +/* Define to the type of arg 5 for `select'. */ +#undef SELECT_TYPE_ARG5 + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define 3rd arg of accept */ +#undef Socklen_t + +/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */ +#undef TIME_WITH_SYS_TIME + +/* Define to 1 if your <sys/time.h> declares `struct tm'. */ +#undef TM_IN_SYS_TIME + +/* Version number of package */ +#undef VERSION + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +# undef WORDS_BIGENDIAN +# endif +#endif + +/* */ +#undef _REENTRANT + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Define to `unsigned int' if <sys/types.h> does not define. */ +#undef size_t + +/* Define to "int" if <sys/types.h> does not define. */ +#undef ssize_t diff --git a/config.sub b/config.sub new file mode 100755 index 0000000..63c1f1c --- /dev/null +++ b/config.sub @@ -0,0 +1,1860 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright 1992-2021 Free Software Foundation, Inc. + +timestamp='2021-01-08' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <https://www.gnu.org/licenses/>. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). + + +# Please send patches to <config-patches@gnu.org>. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# https://git.savannah.gnu.org/cgit/config.git/plain/config.sub + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=$(echo "$0" | sed -e 's,.*/,,') + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS + +Canonicalize a configuration name. + +Options: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to <config-patches@gnu.org>." + +version="\ +GNU config.sub ($timestamp) + +Copyright 1992-2021 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo "$1" + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Split fields of configuration type +# shellcheck disable=SC2162 +IFS="-" read field1 field2 field3 field4 <<EOF +$1 +EOF + +# Separate into logical components for further validation +case $1 in + *-*-*-*-*) + echo Invalid configuration \`"$1"\': more than four components >&2 + exit 1 + ;; + *-*-*-*) + basic_machine=$field1-$field2 + basic_os=$field3-$field4 + ;; + *-*-*) + # Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two + # parts + maybe_os=$field2-$field3 + case $maybe_os in + nto-qnx* | linux-* | uclinux-uclibc* \ + | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \ + | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \ + | storm-chaos* | os2-emx* | rtmk-nova*) + basic_machine=$field1 + basic_os=$maybe_os + ;; + android-linux) + basic_machine=$field1-unknown + basic_os=linux-android + ;; + *) + basic_machine=$field1-$field2 + basic_os=$field3 + ;; + esac + ;; + *-*) + # A lone config we happen to match not fitting any pattern + case $field1-$field2 in + decstation-3100) + basic_machine=mips-dec + basic_os= + ;; + *-*) + # Second component is usually, but not always the OS + case $field2 in + # Prevent following clause from handling this valid os + sun*os*) + basic_machine=$field1 + basic_os=$field2 + ;; + # Manufacturers + dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \ + | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \ + | unicom* | ibm* | next | hp | isi* | apollo | altos* \ + | convergent* | ncr* | news | 32* | 3600* | 3100* \ + | hitachi* | c[123]* | convex* | sun | crds | omron* | dg \ + | ultra | tti* | harris | dolphin | highlevel | gould \ + | cbm | ns | masscomp | apple | axis | knuth | cray \ + | microblaze* | sim | cisco \ + | oki | wec | wrs | winbond) + basic_machine=$field1-$field2 + basic_os= + ;; + *) + basic_machine=$field1 + basic_os=$field2 + ;; + esac + ;; + esac + ;; + *) + # Convert single-component short-hands not valid as part of + # multi-component configurations. + case $field1 in + 386bsd) + basic_machine=i386-pc + basic_os=bsd + ;; + a29khif) + basic_machine=a29k-amd + basic_os=udi + ;; + adobe68k) + basic_machine=m68010-adobe + basic_os=scout + ;; + alliant) + basic_machine=fx80-alliant + basic_os= + ;; + altos | altos3068) + basic_machine=m68k-altos + basic_os= + ;; + am29k) + basic_machine=a29k-none + basic_os=bsd + ;; + amdahl) + basic_machine=580-amdahl + basic_os=sysv + ;; + amiga) + basic_machine=m68k-unknown + basic_os= + ;; + amigaos | amigados) + basic_machine=m68k-unknown + basic_os=amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + basic_os=sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + basic_os=sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + basic_os=bsd + ;; + aros) + basic_machine=i386-pc + basic_os=aros + ;; + aux) + basic_machine=m68k-apple + basic_os=aux + ;; + balance) + basic_machine=ns32k-sequent + basic_os=dynix + ;; + blackfin) + basic_machine=bfin-unknown + basic_os=linux + ;; + cegcc) + basic_machine=arm-unknown + basic_os=cegcc + ;; + convex-c1) + basic_machine=c1-convex + basic_os=bsd + ;; + convex-c2) + basic_machine=c2-convex + basic_os=bsd + ;; + convex-c32) + basic_machine=c32-convex + basic_os=bsd + ;; + convex-c34) + basic_machine=c34-convex + basic_os=bsd + ;; + convex-c38) + basic_machine=c38-convex + basic_os=bsd + ;; + cray) + basic_machine=j90-cray + basic_os=unicos + ;; + crds | unos) + basic_machine=m68k-crds + basic_os= + ;; + da30) + basic_machine=m68k-da30 + basic_os= + ;; + decstation | pmax | pmin | dec3100 | decstatn) + basic_machine=mips-dec + basic_os= + ;; + delta88) + basic_machine=m88k-motorola + basic_os=sysv3 + ;; + dicos) + basic_machine=i686-pc + basic_os=dicos + ;; + djgpp) + basic_machine=i586-pc + basic_os=msdosdjgpp + ;; + ebmon29k) + basic_machine=a29k-amd + basic_os=ebmon + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + basic_os=ose + ;; + gmicro) + basic_machine=tron-gmicro + basic_os=sysv + ;; + go32) + basic_machine=i386-pc + basic_os=go32 + ;; + h8300hms) + basic_machine=h8300-hitachi + basic_os=hms + ;; + h8300xray) + basic_machine=h8300-hitachi + basic_os=xray + ;; + h8500hms) + basic_machine=h8500-hitachi + basic_os=hms + ;; + harris) + basic_machine=m88k-harris + basic_os=sysv3 + ;; + hp300 | hp300hpux) + basic_machine=m68k-hp + basic_os=hpux + ;; + hp300bsd) + basic_machine=m68k-hp + basic_os=bsd + ;; + hppaosf) + basic_machine=hppa1.1-hp + basic_os=osf + ;; + hppro) + basic_machine=hppa1.1-hp + basic_os=proelf + ;; + i386mach) + basic_machine=i386-mach + basic_os=mach + ;; + isi68 | isi) + basic_machine=m68k-isi + basic_os=sysv + ;; + m68knommu) + basic_machine=m68k-unknown + basic_os=linux + ;; + magnum | m3230) + basic_machine=mips-mips + basic_os=sysv + ;; + merlin) + basic_machine=ns32k-utek + basic_os=sysv + ;; + mingw64) + basic_machine=x86_64-pc + basic_os=mingw64 + ;; + mingw32) + basic_machine=i686-pc + basic_os=mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + basic_os=mingw32ce + ;; + monitor) + basic_machine=m68k-rom68k + basic_os=coff + ;; + morphos) + basic_machine=powerpc-unknown + basic_os=morphos + ;; + moxiebox) + basic_machine=moxie-unknown + basic_os=moxiebox + ;; + msdos) + basic_machine=i386-pc + basic_os=msdos + ;; + msys) + basic_machine=i686-pc + basic_os=msys + ;; + mvs) + basic_machine=i370-ibm + basic_os=mvs + ;; + nacl) + basic_machine=le32-unknown + basic_os=nacl + ;; + ncr3000) + basic_machine=i486-ncr + basic_os=sysv4 + ;; + netbsd386) + basic_machine=i386-pc + basic_os=netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + basic_os=linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + basic_os=newsos + ;; + news1000) + basic_machine=m68030-sony + basic_os=newsos + ;; + necv70) + basic_machine=v70-nec + basic_os=sysv + ;; + nh3000) + basic_machine=m68k-harris + basic_os=cxux + ;; + nh[45]000) + basic_machine=m88k-harris + basic_os=cxux + ;; + nindy960) + basic_machine=i960-intel + basic_os=nindy + ;; + mon960) + basic_machine=i960-intel + basic_os=mon960 + ;; + nonstopux) + basic_machine=mips-compaq + basic_os=nonstopux + ;; + os400) + basic_machine=powerpc-ibm + basic_os=os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + basic_os=ose + ;; + os68k) + basic_machine=m68k-none + basic_os=os68k + ;; + paragon) + basic_machine=i860-intel + basic_os=osf + ;; + parisc) + basic_machine=hppa-unknown + basic_os=linux + ;; + psp) + basic_machine=mipsallegrexel-sony + basic_os=psp + ;; + pw32) + basic_machine=i586-unknown + basic_os=pw32 + ;; + rdos | rdos64) + basic_machine=x86_64-pc + basic_os=rdos + ;; + rdos32) + basic_machine=i386-pc + basic_os=rdos + ;; + rom68k) + basic_machine=m68k-rom68k + basic_os=coff + ;; + sa29200) + basic_machine=a29k-amd + basic_os=udi + ;; + sei) + basic_machine=mips-sei + basic_os=seiux + ;; + sequent) + basic_machine=i386-sequent + basic_os= + ;; + sps7) + basic_machine=m68k-bull + basic_os=sysv2 + ;; + st2000) + basic_machine=m68k-tandem + basic_os= + ;; + stratus) + basic_machine=i860-stratus + basic_os=sysv4 + ;; + sun2) + basic_machine=m68000-sun + basic_os= + ;; + sun2os3) + basic_machine=m68000-sun + basic_os=sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + basic_os=sunos4 + ;; + sun3) + basic_machine=m68k-sun + basic_os= + ;; + sun3os3) + basic_machine=m68k-sun + basic_os=sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + basic_os=sunos4 + ;; + sun4) + basic_machine=sparc-sun + basic_os= + ;; + sun4os3) + basic_machine=sparc-sun + basic_os=sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + basic_os=sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + basic_os=solaris2 + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + basic_os= + ;; + sv1) + basic_machine=sv1-cray + basic_os=unicos + ;; + symmetry) + basic_machine=i386-sequent + basic_os=dynix + ;; + t3e) + basic_machine=alphaev5-cray + basic_os=unicos + ;; + t90) + basic_machine=t90-cray + basic_os=unicos + ;; + toad1) + basic_machine=pdp10-xkl + basic_os=tops20 + ;; + tpf) + basic_machine=s390x-ibm + basic_os=tpf + ;; + udi29k) + basic_machine=a29k-amd + basic_os=udi + ;; + ultra3) + basic_machine=a29k-nyu + basic_os=sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + basic_os=none + ;; + vaxv) + basic_machine=vax-dec + basic_os=sysv + ;; + vms) + basic_machine=vax-dec + basic_os=vms + ;; + vsta) + basic_machine=i386-pc + basic_os=vsta + ;; + vxworks960) + basic_machine=i960-wrs + basic_os=vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + basic_os=vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + basic_os=vxworks + ;; + xbox) + basic_machine=i686-pc + basic_os=mingw32 + ;; + ymp) + basic_machine=ymp-cray + basic_os=unicos + ;; + *) + basic_machine=$1 + basic_os= + ;; + esac + ;; +esac + +# Decode 1-component or ad-hoc basic machines +case $basic_machine in + # Here we handle the default manufacturer of certain CPU types. It is in + # some cases the only manufacturer, in others, it is the most popular. + w89k) + cpu=hppa1.1 + vendor=winbond + ;; + op50n) + cpu=hppa1.1 + vendor=oki + ;; + op60c) + cpu=hppa1.1 + vendor=oki + ;; + ibm*) + cpu=i370 + vendor=ibm + ;; + orion105) + cpu=clipper + vendor=highlevel + ;; + mac | mpw | mac-mpw) + cpu=m68k + vendor=apple + ;; + pmac | pmac-mpw) + cpu=powerpc + vendor=apple + ;; + + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + cpu=m68000 + vendor=att + ;; + 3b*) + cpu=we32k + vendor=att + ;; + bluegene*) + cpu=powerpc + vendor=ibm + basic_os=cnk + ;; + decsystem10* | dec10*) + cpu=pdp10 + vendor=dec + basic_os=tops10 + ;; + decsystem20* | dec20*) + cpu=pdp10 + vendor=dec + basic_os=tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + cpu=m68k + vendor=motorola + ;; + dpx2*) + cpu=m68k + vendor=bull + basic_os=sysv3 + ;; + encore | umax | mmax) + cpu=ns32k + vendor=encore + ;; + elxsi) + cpu=elxsi + vendor=elxsi + basic_os=${basic_os:-bsd} + ;; + fx2800) + cpu=i860 + vendor=alliant + ;; + genix) + cpu=ns32k + vendor=ns + ;; + h3050r* | hiux*) + cpu=hppa1.1 + vendor=hitachi + basic_os=hiuxwe2 + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + cpu=hppa1.0 + vendor=hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + cpu=m68000 + vendor=hp + ;; + hp9k3[2-9][0-9]) + cpu=m68k + vendor=hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + cpu=hppa1.0 + vendor=hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + cpu=hppa1.1 + vendor=hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + cpu=hppa1.1 + vendor=hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + cpu=hppa1.1 + vendor=hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + cpu=hppa1.1 + vendor=hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + cpu=hppa1.0 + vendor=hp + ;; + i*86v32) + cpu=$(echo "$1" | sed -e 's/86.*/86/') + vendor=pc + basic_os=sysv32 + ;; + i*86v4*) + cpu=$(echo "$1" | sed -e 's/86.*/86/') + vendor=pc + basic_os=sysv4 + ;; + i*86v) + cpu=$(echo "$1" | sed -e 's/86.*/86/') + vendor=pc + basic_os=sysv + ;; + i*86sol2) + cpu=$(echo "$1" | sed -e 's/86.*/86/') + vendor=pc + basic_os=solaris2 + ;; + j90 | j90-cray) + cpu=j90 + vendor=cray + basic_os=${basic_os:-unicos} + ;; + iris | iris4d) + cpu=mips + vendor=sgi + case $basic_os in + irix*) + ;; + *) + basic_os=irix4 + ;; + esac + ;; + miniframe) + cpu=m68000 + vendor=convergent + ;; + *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*) + cpu=m68k + vendor=atari + basic_os=mint + ;; + news-3600 | risc-news) + cpu=mips + vendor=sony + basic_os=newsos + ;; + next | m*-next) + cpu=m68k + vendor=next + case $basic_os in + openstep*) + ;; + nextstep*) + ;; + ns2*) + basic_os=nextstep2 + ;; + *) + basic_os=nextstep3 + ;; + esac + ;; + np1) + cpu=np1 + vendor=gould + ;; + op50n-* | op60c-*) + cpu=hppa1.1 + vendor=oki + basic_os=proelf + ;; + pa-hitachi) + cpu=hppa1.1 + vendor=hitachi + basic_os=hiuxwe2 + ;; + pbd) + cpu=sparc + vendor=tti + ;; + pbb) + cpu=m68k + vendor=tti + ;; + pc532) + cpu=ns32k + vendor=pc532 + ;; + pn) + cpu=pn + vendor=gould + ;; + power) + cpu=power + vendor=ibm + ;; + ps2) + cpu=i386 + vendor=ibm + ;; + rm[46]00) + cpu=mips + vendor=siemens + ;; + rtpc | rtpc-*) + cpu=romp + vendor=ibm + ;; + sde) + cpu=mipsisa32 + vendor=sde + basic_os=${basic_os:-elf} + ;; + simso-wrs) + cpu=sparclite + vendor=wrs + basic_os=vxworks + ;; + tower | tower-32) + cpu=m68k + vendor=ncr + ;; + vpp*|vx|vx-*) + cpu=f301 + vendor=fujitsu + ;; + w65) + cpu=w65 + vendor=wdc + ;; + w89k-*) + cpu=hppa1.1 + vendor=winbond + basic_os=proelf + ;; + none) + cpu=none + vendor=none + ;; + leon|leon[3-9]) + cpu=sparc + vendor=$basic_machine + ;; + leon-*|leon[3-9]-*) + cpu=sparc + vendor=$(echo "$basic_machine" | sed 's/-.*//') + ;; + + *-*) + # shellcheck disable=SC2162 + IFS="-" read cpu vendor <<EOF +$basic_machine +EOF + ;; + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + cpu=$basic_machine + vendor=pc + ;; + # These rules are duplicated from below for sake of the special case above; + # i.e. things that normalized to x86 arches should also default to "pc" + pc98) + cpu=i386 + vendor=pc + ;; + x64 | amd64) + cpu=x86_64 + vendor=pc + ;; + # Recognize the basic CPU types without company name. + *) + cpu=$basic_machine + vendor=unknown + ;; +esac + +unset -v basic_machine + +# Decode basic machines in the full and proper CPU-Company form. +case $cpu-$vendor in + # Here we handle the default manufacturer of certain CPU types in canonical form. It is in + # some cases the only manufacturer, in others, it is the most popular. + craynv-unknown) + vendor=cray + basic_os=${basic_os:-unicosmp} + ;; + c90-unknown | c90-cray) + vendor=cray + basic_os=${Basic_os:-unicos} + ;; + fx80-unknown) + vendor=alliant + ;; + romp-unknown) + vendor=ibm + ;; + mmix-unknown) + vendor=knuth + ;; + microblaze-unknown | microblazeel-unknown) + vendor=xilinx + ;; + rs6000-unknown) + vendor=ibm + ;; + vax-unknown) + vendor=dec + ;; + pdp11-unknown) + vendor=dec + ;; + we32k-unknown) + vendor=att + ;; + cydra-unknown) + vendor=cydrome + ;; + i370-ibm*) + vendor=ibm + ;; + orion-unknown) + vendor=highlevel + ;; + xps-unknown | xps100-unknown) + cpu=xps100 + vendor=honeywell + ;; + + # Here we normalize CPU types with a missing or matching vendor + dpx20-unknown | dpx20-bull) + cpu=rs6000 + vendor=bull + basic_os=${basic_os:-bosx} + ;; + + # Here we normalize CPU types irrespective of the vendor + amd64-*) + cpu=x86_64 + ;; + blackfin-*) + cpu=bfin + basic_os=linux + ;; + c54x-*) + cpu=tic54x + ;; + c55x-*) + cpu=tic55x + ;; + c6x-*) + cpu=tic6x + ;; + e500v[12]-*) + cpu=powerpc + basic_os=${basic_os}"spe" + ;; + mips3*-*) + cpu=mips64 + ;; + ms1-*) + cpu=mt + ;; + m68knommu-*) + cpu=m68k + basic_os=linux + ;; + m9s12z-* | m68hcs12z-* | hcs12z-* | s12z-*) + cpu=s12z + ;; + openrisc-*) + cpu=or32 + ;; + parisc-*) + cpu=hppa + basic_os=linux + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + cpu=i586 + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-* | athalon_*-*) + cpu=i686 + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + cpu=i686 + ;; + pentium4-*) + cpu=i786 + ;; + pc98-*) + cpu=i386 + ;; + ppc-* | ppcbe-*) + cpu=powerpc + ;; + ppcle-* | powerpclittle-*) + cpu=powerpcle + ;; + ppc64-*) + cpu=powerpc64 + ;; + ppc64le-* | powerpc64little-*) + cpu=powerpc64le + ;; + sb1-*) + cpu=mipsisa64sb1 + ;; + sb1el-*) + cpu=mipsisa64sb1el + ;; + sh5e[lb]-*) + cpu=$(echo "$cpu" | sed 's/^\(sh.\)e\(.\)$/\1\2e/') + ;; + spur-*) + cpu=spur + ;; + strongarm-* | thumb-*) + cpu=arm + ;; + tx39-*) + cpu=mipstx39 + ;; + tx39el-*) + cpu=mipstx39el + ;; + x64-*) + cpu=x86_64 + ;; + xscale-* | xscalee[bl]-*) + cpu=$(echo "$cpu" | sed 's/^xscale/arm/') + ;; + arm64-*) + cpu=aarch64 + ;; + + # Recognize the canonical CPU Types that limit and/or modify the + # company names they are paired with. + cr16-*) + basic_os=${basic_os:-elf} + ;; + crisv32-* | etraxfs*-*) + cpu=crisv32 + vendor=axis + ;; + cris-* | etrax*-*) + cpu=cris + vendor=axis + ;; + crx-*) + basic_os=${basic_os:-elf} + ;; + neo-tandem) + cpu=neo + vendor=tandem + ;; + nse-tandem) + cpu=nse + vendor=tandem + ;; + nsr-tandem) + cpu=nsr + vendor=tandem + ;; + nsv-tandem) + cpu=nsv + vendor=tandem + ;; + nsx-tandem) + cpu=nsx + vendor=tandem + ;; + mipsallegrexel-sony) + cpu=mipsallegrexel + vendor=sony + ;; + tile*-*) + basic_os=${basic_os:-linux-gnu} + ;; + + *) + # Recognize the canonical CPU types that are allowed with any + # company name. + case $cpu in + 1750a | 580 \ + | a29k \ + | aarch64 | aarch64_be \ + | abacus \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] \ + | alphapca5[67] | alpha64pca5[67] \ + | am33_2.0 \ + | amdgcn \ + | arc | arceb \ + | arm | arm[lb]e | arme[lb] | armv* \ + | avr | avr32 \ + | asmjs \ + | ba \ + | be32 | be64 \ + | bfin | bpf | bs2000 \ + | c[123]* | c30 | [cjt]90 | c4x \ + | c8051 | clipper | craynv | csky | cydra \ + | d10v | d30v | dlx | dsp16xx \ + | e2k | elxsi | epiphany \ + | f30[01] | f700 | fido | fr30 | frv | ft32 | fx80 \ + | h8300 | h8500 \ + | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i*86 | i860 | i960 | ia16 | ia64 \ + | ip2k | iq2000 \ + | k1om \ + | le32 | le64 \ + | lm32 \ + | loongarch32 | loongarch64 | loongarchx32 \ + | m32c | m32r | m32rle \ + | m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k \ + | m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \ + | m88110 | m88k | maxq | mb | mcore | mep | metag \ + | microblaze | microblazeel \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64eb | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa32r6 | mipsisa32r6el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r6 | mipsisa64r6el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipsr5900 | mipsr5900el \ + | mipstx39 | mipstx39el \ + | mmix \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nfp \ + | nios | nios2 | nios2eb | nios2el \ + | none | np1 | ns16k | ns32k | nvptx \ + | open8 \ + | or1k* \ + | or32 \ + | orion \ + | picochip \ + | pdp10 | pdp11 | pj | pjl | pn | power \ + | powerpc | powerpc64 | powerpc64le | powerpcle | powerpcspe \ + | pru \ + | pyramid \ + | riscv | riscv32 | riscv32be | riscv64 | riscv64be \ + | rl78 | romp | rs6000 | rx \ + | s390 | s390x \ + | score \ + | sh | shl \ + | sh[1234] | sh[24]a | sh[24]ae[lb] | sh[23]e | she[lb] | sh[lb]e \ + | sh[1234]e[lb] | sh[12345][lb]e | sh[23]ele | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet \ + | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v | sv1 | sx* \ + | spu \ + | tahoe \ + | thumbv7* \ + | tic30 | tic4x | tic54x | tic55x | tic6x | tic80 \ + | tron \ + | ubicom32 \ + | v70 | v850 | v850e | v850e1 | v850es | v850e2 | v850e2v3 \ + | vax \ + | visium \ + | w65 \ + | wasm32 | wasm64 \ + | we32k \ + | x86 | x86_64 | xc16x | xgate | xps100 \ + | xstormy16 | xtensa* \ + | ymp \ + | z8k | z80) + ;; + + *) + echo Invalid configuration \`"$1"\': machine \`"$cpu-$vendor"\' not recognized 1>&2 + exit 1 + ;; + esac + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $vendor in + digital*) + vendor=dec + ;; + commodore*) + vendor=cbm + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if test x$basic_os != x +then + +# First recognize some ad-hoc caes, or perhaps split kernel-os, or else just +# set os. +case $basic_os in + gnu/linux*) + kernel=linux + os=$(echo $basic_os | sed -e 's|gnu/linux|gnu|') + ;; + os2-emx) + kernel=os2 + os=$(echo $basic_os | sed -e 's|os2-emx|emx|') + ;; + nto-qnx*) + kernel=nto + os=$(echo $basic_os | sed -e 's|nto-qnx|qnx|') + ;; + *-*) + # shellcheck disable=SC2162 + IFS="-" read kernel os <<EOF +$basic_os +EOF + ;; + # Default OS when just kernel was specified + nto*) + kernel=nto + os=$(echo $basic_os | sed -e 's|nto|qnx|') + ;; + linux*) + kernel=linux + os=$(echo $basic_os | sed -e 's|linux|gnu|') + ;; + *) + kernel= + os=$basic_os + ;; +esac + +# Now, normalize the OS (knowing we just have one component, it's not a kernel, +# etc.) +case $os in + # First match some system type aliases that might get confused + # with valid system types. + # solaris* is a basic system type, with this one exception. + auroraux) + os=auroraux + ;; + bluegene*) + os=cnk + ;; + solaris1 | solaris1.*) + os=$(echo $os | sed -e 's|solaris1|sunos4|') + ;; + solaris) + os=solaris2 + ;; + unixware*) + os=sysv4.2uw + ;; + # es1800 is here to avoid being matched by es* (a different OS) + es1800*) + os=ose + ;; + # Some version numbers need modification + chorusos*) + os=chorusos + ;; + isc) + os=isc2.2 + ;; + sco6) + os=sco5v6 + ;; + sco5) + os=sco3.2v5 + ;; + sco4) + os=sco3.2v4 + ;; + sco3.2.[4-9]*) + os=$(echo $os | sed -e 's/sco3.2./sco3.2v/') + ;; + sco*v* | scout) + # Don't match below + ;; + sco*) + os=sco3.2v2 + ;; + psos*) + os=psos + ;; + qnx*) + os=qnx + ;; + hiux*) + os=hiuxwe2 + ;; + lynx*178) + os=lynxos178 + ;; + lynx*5) + os=lynxos5 + ;; + lynxos*) + # don't get caught up in next wildcard + ;; + lynx*) + os=lynxos + ;; + mac[0-9]*) + os=$(echo "$os" | sed -e 's|mac|macos|') + ;; + opened*) + os=openedition + ;; + os400*) + os=os400 + ;; + sunos5*) + os=$(echo "$os" | sed -e 's|sunos5|solaris2|') + ;; + sunos6*) + os=$(echo "$os" | sed -e 's|sunos6|solaris3|') + ;; + wince*) + os=wince + ;; + utek*) + os=bsd + ;; + dynix*) + os=bsd + ;; + acis*) + os=aos + ;; + atheos*) + os=atheos + ;; + syllable*) + os=syllable + ;; + 386bsd) + os=bsd + ;; + ctix* | uts*) + os=sysv + ;; + nova*) + os=rtmk-nova + ;; + ns2) + os=nextstep2 + ;; + # Preserve the version number of sinix5. + sinix5.*) + os=$(echo $os | sed -e 's|sinix|sysv|') + ;; + sinix*) + os=sysv4 + ;; + tpf*) + os=tpf + ;; + triton*) + os=sysv3 + ;; + oss*) + os=sysv3 + ;; + svr4*) + os=sysv4 + ;; + svr3) + os=sysv3 + ;; + sysvr4) + os=sysv4 + ;; + ose*) + os=ose + ;; + *mint | mint[0-9]* | *MiNT | MiNT[0-9]*) + os=mint + ;; + dicos*) + os=dicos + ;; + pikeos*) + # Until real need of OS specific support for + # particular features comes up, bare metal + # configurations are quite functional. + case $cpu in + arm*) + os=eabi + ;; + *) + os=elf + ;; + esac + ;; + *) + # No normalization, but not necessarily accepted, that comes below. + ;; +esac + +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +kernel= +case $cpu-$vendor in + score-*) + os=elf + ;; + spu-*) + os=elf + ;; + *-acorn) + os=riscix1.2 + ;; + arm*-rebel) + kernel=linux + os=gnu + ;; + arm*-semi) + os=aout + ;; + c4x-* | tic4x-*) + os=coff + ;; + c8051-*) + os=elf + ;; + clipper-intergraph) + os=clix + ;; + hexagon-*) + os=elf + ;; + tic54x-*) + os=coff + ;; + tic55x-*) + os=coff + ;; + tic6x-*) + os=coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=tops20 + ;; + pdp11-*) + os=none + ;; + *-dec | vax-*) + os=ultrix4.2 + ;; + m68*-apollo) + os=domain + ;; + i386-sun) + os=sunos4.0.2 + ;; + m68000-sun) + os=sunos3 + ;; + m68*-cisco) + os=aout + ;; + mep-*) + os=elf + ;; + mips*-cisco) + os=elf + ;; + mips*-*) + os=elf + ;; + or32-*) + os=coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=sysv3 + ;; + sparc-* | *-sun) + os=sunos4.1.1 + ;; + pru-*) + os=elf + ;; + *-be) + os=beos + ;; + *-ibm) + os=aix + ;; + *-knuth) + os=mmixware + ;; + *-wec) + os=proelf + ;; + *-winbond) + os=proelf + ;; + *-oki) + os=proelf + ;; + *-hp) + os=hpux + ;; + *-hitachi) + os=hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=sysv + ;; + *-cbm) + os=amigaos + ;; + *-dg) + os=dgux + ;; + *-dolphin) + os=sysv3 + ;; + m68k-ccur) + os=rtu + ;; + m88k-omron*) + os=luna + ;; + *-next) + os=nextstep + ;; + *-sequent) + os=ptx + ;; + *-crds) + os=unos + ;; + *-ns) + os=genix + ;; + i370-*) + os=mvs + ;; + *-gould) + os=sysv + ;; + *-highlevel) + os=bsd + ;; + *-encore) + os=bsd + ;; + *-sgi) + os=irix + ;; + *-siemens) + os=sysv4 + ;; + *-masscomp) + os=rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=uxpv + ;; + *-rom68k) + os=coff + ;; + *-*bug) + os=coff + ;; + *-apple) + os=macos + ;; + *-atari*) + os=mint + ;; + *-wrs) + os=vxworks + ;; + *) + os=none + ;; +esac + +fi + +# Now, validate our (potentially fixed-up) OS. +case $os in + # Sometimes we do "kernel-libc", so those need to count as OSes. + musl* | newlib* | uclibc*) + ;; + # Likewise for "kernel-abi" + eabi* | gnueabi*) + ;; + # VxWorks passes extra cpu info in the 4th filed. + simlinux | simwindows | spe) + ;; + # Now accept the basic system types. + # The portable systems comes first. + # Each alternative MUST end in a * to match a version number. + gnu* | android* | bsd* | mach* | minix* | genix* | ultrix* | irix* \ + | *vms* | esix* | aix* | cnk* | sunos | sunos[34]* \ + | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \ + | sym* | plan9* | psp* | sim* | xray* | os68k* | v88r* \ + | hiux* | abug | nacl* | netware* | windows* \ + | os9* | macos* | osx* | ios* \ + | mpw* | magic* | mmixware* | mon960* | lnews* \ + | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \ + | aos* | aros* | cloudabi* | sortix* | twizzler* \ + | nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \ + | clix* | riscos* | uniplus* | iris* | isc* | rtu* | xenix* \ + | mirbsd* | netbsd* | dicos* | openedition* | ose* \ + | bitrig* | openbsd* | solidbsd* | libertybsd* | os108* \ + | ekkobsd* | freebsd* | riscix* | lynxos* | os400* \ + | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \ + | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \ + | udi* | lites* | ieee* | go32* | aux* | hcos* \ + | chorusrdb* | cegcc* | glidix* \ + | cygwin* | msys* | pe* | moss* | proelf* | rtems* \ + | midipix* | mingw32* | mingw64* | mint* \ + | uxpv* | beos* | mpeix* | udk* | moxiebox* \ + | interix* | uwin* | mks* | rhapsody* | darwin* \ + | openstep* | oskit* | conix* | pw32* | nonstopux* \ + | storm-chaos* | tops10* | tenex* | tops20* | its* \ + | os2* | vos* | palmos* | uclinux* | nucleus* | morphos* \ + | scout* | superux* | sysv* | rtmk* | tpf* | windiss* \ + | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \ + | skyos* | haiku* | rdos* | toppers* | drops* | es* \ + | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \ + | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \ + | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx*) + ;; + # This one is extra strict with allowed versions + sco3.2v2 | sco3.2v[4-9]* | sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + ;; + none) + ;; + *) + echo Invalid configuration \`"$1"\': OS \`"$os"\' not recognized 1>&2 + exit 1 + ;; +esac + +# As a final step for OS-related things, validate the OS-kernel combination +# (given a valid OS), if there is a kernel. +case $kernel-$os in + linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* | linux-musl* | linux-uclibc* ) + ;; + uclinux-uclibc* ) + ;; + -dietlibc* | -newlib* | -musl* | -uclibc* ) + # These are just libc implementations, not actual OSes, and thus + # require a kernel. + echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2 + exit 1 + ;; + kfreebsd*-gnu* | kopensolaris*-gnu*) + ;; + vxworks-simlinux | vxworks-simwindows | vxworks-spe) + ;; + nto-qnx*) + ;; + os2-emx) + ;; + *-eabi* | *-gnueabi*) + ;; + -*) + # Blank kernel with real OS is always fine. + ;; + *-*) + echo "Invalid configuration \`$1': Kernel \`$kernel' not known to work with OS \`$os'." 1>&2 + exit 1 + ;; +esac + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +case $vendor in + unknown) + case $cpu-$os in + *-riscix*) + vendor=acorn + ;; + *-sunos*) + vendor=sun + ;; + *-cnk* | *-aix*) + vendor=ibm + ;; + *-beos*) + vendor=be + ;; + *-hpux*) + vendor=hp + ;; + *-mpeix*) + vendor=hp + ;; + *-hiux*) + vendor=hitachi + ;; + *-unos*) + vendor=crds + ;; + *-dgux*) + vendor=dg + ;; + *-luna*) + vendor=omron + ;; + *-genix*) + vendor=ns + ;; + *-clix*) + vendor=intergraph + ;; + *-mvs* | *-opened*) + vendor=ibm + ;; + *-os400*) + vendor=ibm + ;; + s390-* | s390x-*) + vendor=ibm + ;; + *-ptx*) + vendor=sequent + ;; + *-tpf*) + vendor=ibm + ;; + *-vxsim* | *-vxworks* | *-windiss*) + vendor=wrs + ;; + *-aux*) + vendor=apple + ;; + *-hms*) + vendor=hitachi + ;; + *-mpw* | *-macos*) + vendor=apple + ;; + *-*mint | *-mint[0-9]* | *-*MiNT | *-MiNT[0-9]*) + vendor=atari + ;; + *-vos*) + vendor=stratus + ;; + esac + ;; +esac + +echo "$cpu-$vendor-${kernel:+$kernel-}$os" +exit + +# Local variables: +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/configure b/configure new file mode 100755 index 0000000..693b629 --- /dev/null +++ b/configure @@ -0,0 +1,10617 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.69 for Iperf 2.1.9. +# +# +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, +$0: including any error possibly output before this +$0: message. Then install a modern shell, or manually run +$0: the script under such a shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +test -n "$DJDIR" || exec 7<&0 </dev/null +exec 6>&1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='Iperf' +PACKAGE_TARNAME='iperf' +PACKAGE_VERSION='2.1.9' +PACKAGE_STRING='Iperf 2.1.9' +PACKAGE_BUGREPORT='' +PACKAGE_URL='' + +# Factoring default headers for most tests. +ac_includes_default="\ +#include <stdio.h> +#ifdef HAVE_SYS_TYPES_H +# include <sys/types.h> +#endif +#ifdef HAVE_SYS_STAT_H +# include <sys/stat.h> +#endif +#ifdef STDC_HEADERS +# include <stdlib.h> +# include <stddef.h> +#else +# ifdef HAVE_STDLIB_H +# include <stdlib.h> +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include <memory.h> +# endif +# include <string.h> +#endif +#ifdef HAVE_STRINGS_H +# include <strings.h> +#endif +#ifdef HAVE_INTTYPES_H +# include <inttypes.h> +#endif +#ifdef HAVE_STDINT_H +# include <stdint.h> +#endif +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif" + +ac_subst_vars='am__EXEEXT_FALSE +am__EXEEXT_TRUE +LTLIBOBJS +STRIP_END +STRIP_BEGIN +STRIP_DUMMY +WEB100_LIBS +WEB100_CFLAGS +WEB100_CONFIG +LIBOBJS +PTHREAD_CFLAGS +PTHREAD_LIBS +PTHREAD_CC +ax_pthread_config +EGREP +GREP +CPP +SED +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +RANLIB +am__fastdepCXX_FALSE +am__fastdepCXX_TRUE +CXXDEPMODE +ac_ct_CXX +CXXFLAGS +CXX +TUNTAP_TAP_FALSE +TUNTAP_TAP_TRUE +TUNTAP_TUN_FALSE +TUNTAP_TUN_TRUE +AF_PACKET_FALSE +AF_PACKET_TRUE +am__fastdepCC_FALSE +am__fastdepCC_TRUE +CCDEPMODE +am__nodep +AMDEPBACKSLASH +AMDEP_FALSE +AMDEP_TRUE +am__include +DEPDIR +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +DEBUG_SYMBOLS_FALSE +DEBUG_SYMBOLS_TRUE +ENABLE_STATIC_BIN_FALSE +ENABLE_STATIC_BIN_TRUE +CHECKPROGRAMS_FALSE +CHECKPROGRAMS_TRUE +PACKET_DEBUG_FALSE +PACKET_DEBUG_TRUE +THREAD_DEBUG_FALSE +THREAD_DEBUG_TRUE +DISCOVER_DEFAULTLEN_FALSE +DISCOVER_DEFAULTLEN_TRUE +FASTSAMPLING_FALSE +FASTSAMPLING_TRUE +MAINT +MAINTAINER_MODE_FALSE +MAINTAINER_MODE_TRUE +AM_BACKSLASH +AM_DEFAULT_VERBOSITY +AM_DEFAULT_V +AM_V +am__untar +am__tar +AMTAR +am__leading_dot +SET_MAKE +AWK +mkdir_p +MKDIR_P +INSTALL_STRIP_PROGRAM +STRIP +install_sh +MAKEINFO +AUTOHEADER +AUTOMAKE +AUTOCONF +ACLOCAL +VERSION +PACKAGE +CYGPATH_W +am__isrc +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +runstatedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL +am__quote' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +enable_silent_rules +enable_maintainer_mode +enable_ipv6 +enable_multicast +enable_tcpstats +enable_threads +enable_debuginfo +enable_web100 +enable_kalman +enable_role_reversal_id +enable_default_localonly +enable_seqno64b +enable_fastsampling +enable_discover_defaultlen +enable_thread_debug +enable_packet_debug +enable_checkprograms +enable_static_bin +enable_debug_symbols +enable_af_packet +enable_dependency_tracking +enable_tuntap_tun +enable_tuntap_tap +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CXX +CXXFLAGS +CCC +CPP' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +runstatedir='${localstatedir}/run' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -runstatedir | --runstatedir | --runstatedi | --runstated \ + | --runstate | --runstat | --runsta | --runst | --runs \ + | --run | --ru | --r) + ac_prev=runstatedir ;; + -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ + | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ + | --run=* | --ru=* | --r=*) + runstatedir=$ac_optarg ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir runstatedir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # 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 2.1.9 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/iperf] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +Program names: + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM run sed PROGRAM on installed program names + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of Iperf 2.1.9:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-silent-rules less verbose build output (undo: "make V=1") + --disable-silent-rules verbose build output (undo: "make V=0") + --enable-maintainer-mode + enable make rules and dependencies not useful (and + sometimes confusing) to the casual installer + --disable-ipv6 disable ipv6 support (default is autodetect) + --disable-multicast disable multicast support (default is autodetect) + --disable-tcpstats disable tcpstats support (default is autodetect) + --disable-threads disable thread support (default is autodetect) + --enable-debuginfo enable asserts and debugging info for sockets + (default is no) + --disable-web100 disable web100 support (default is autodetect) + --disable-kalman disable kalman delay tuning (default is enable) + --disable-role-reversal-id + disable role reversal special characters (default is + enable) + --enable-default-localonly + enforce limiting test traffic to local-only network + (via socket SO_DONTROUTE) as the default mode + --disable-seqno64b disable 64 bit sequence numer support (default is + enable) + --enable-fastsampling enable support for 100 microsecond report intervals + (default is disable) + --enable-discover-defaultlen + enable support to set the default payload size after + device MTU discovery (default is disable) + --enable-thread-debug enable support for thread debugging (default is + disable) + --enable-packet-debug enable support for packet level debugging (default + is disable) + --enable-checkprograms enable support for building support programs such as + checkdelay, checkpdfs, etc. (default is disable) + --enable-static-bin link iperf binary statically + --enable-debug-symbols enable debugging with symbols, default: no + --enable-af-packet Enable AF_PACKET support [default=yes] + --enable-dependency-tracking + do not reject slow dependency extractors + --disable-dependency-tracking + speeds up one-time build + --enable-tuntap-tun Enable TUNTAP_TUN support [default=yes] + --enable-tuntap-tap Enable TUNTAP_TAP support [default=yes] + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a + nonstandard directory <lib dir> + LIBS libraries to pass to the linker, e.g. -l<library> + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if + you have headers in a nonstandard directory <include dir> + CXX C++ compiler command + CXXFLAGS C++ compiler flags + CPP C preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to the package provider. +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +Iperf configure 2.1.9 +generated by GNU Autoconf 2.69 + +Copyright (C) 2012 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES +# --------------------------------------------- +# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR +# accordingly. +ac_fn_c_check_decl () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + as_decl_name=`echo $2|sed 's/ *(.*//'` + as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 +$as_echo_n "checking whether $as_decl_name is declared... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +#ifndef $as_decl_name +#ifdef __cplusplus + (void) $as_decl_use; +#else + (void) $as_decl_name; +#endif +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_decl + +# ac_fn_cxx_try_compile LINENO +# ---------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_compile + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_mongrel + +# ac_fn_c_check_type LINENO TYPE VAR INCLUDES +# ------------------------------------------- +# Tests whether TYPE exists after having included INCLUDES, setting cache +# variable VAR accordingly. +ac_fn_c_check_type () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=no" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof ($2)) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof (($2))) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + eval "$3=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_type + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case <limits.h> declares $2. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func + +# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES +# ---------------------------------------------------- +# Tries to find if the field MEMBER exists in type AGGR, after including +# INCLUDES, setting cache variable VAR accordingly. +ac_fn_c_check_member () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5 +$as_echo_n "checking for $2.$3... " >&6; } +if eval \${$4+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$5 +int +main () +{ +static $2 ac_aggr; +if (ac_aggr.$3) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$4=yes" +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$5 +int +main () +{ +static $2 ac_aggr; +if (sizeof ac_aggr.$3) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$4=yes" +else + eval "$4=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$4 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_member +cat >config.log <<_ACEOF +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 2.1.9, which was +generated by GNU Autoconf 2.69. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +ac_config_headers="$ac_config_headers config.h" + +am__api_version='1.16' + +ac_aux_dir= +for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +# Reject install programs that cannot install multiple files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if ${ac_cv_path_install+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in #(( + ./ | .// | /[cC]/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; +esac + + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 +$as_echo_n "checking whether build environment is sane... " >&6; } +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[\\\"\#\$\&\'\`$am_lf]*) + as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; +esac +case $srcdir in + *[\\\"\#\$\&\'\`$am_lf\ \ ]*) + as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; +esac + +# Do 'set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + as_fn_error $? "ls -t appears to fail. Make sure there is not a broken + alias in your environment" "$LINENO" 5 + fi + if test "$2" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$2" = conftest.file + ) +then + # Ok. + : +else + as_fn_error $? "newly created file is older than distributed files! +Check your system clock" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi + +rm -f conftest.file + +test "$program_prefix" != NONE && + program_transform_name="s&^&$program_prefix&;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s&\$&$program_suffix&;$program_transform_name" +# Double any \ or $. +# By default was `s,x,x', remove it if useless. +ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' +program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` + +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` + +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --is-lightweight"; then + am_missing_run="$MISSING " +else + am_missing_run= + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 +$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} +fi + +if test x"${install_sh+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi + +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 +$as_echo_n "checking for a thread-safe mkdir -p... " >&6; } +if test -z "$MKDIR_P"; then + if ${ac_cv_path_mkdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in mkdir gmkdir; do + for ac_exec_ext in '' $ac_executable_extensions; do + as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue + case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( + 'mkdir (GNU coreutils) '* | \ + 'mkdir (coreutils) '* | \ + 'mkdir (fileutils) '4.1*) + ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext + break 3;; + esac + done + done + done +IFS=$as_save_IFS + +fi + + test -d ./--version && rmdir ./--version + if test "${ac_cv_path_mkdir+set}" = set; then + MKDIR_P="$ac_cv_path_mkdir -p" + else + # As a last resort, use the slow shell script. Don't cache a + # value for MKDIR_P within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + MKDIR_P="$ac_install_sh -d" + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 +$as_echo "$MKDIR_P" >&6; } + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AWK+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AWK="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AWK" && break +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null + +# Check whether --enable-silent-rules was given. +if test "${enable_silent_rules+set}" = set; then : + enableval=$enable_silent_rules; +fi + +case $enable_silent_rules in # ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=1;; +esac +am_make=${MAKE-make} +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 +$as_echo_n "checking whether $am_make supports nested variables... " >&6; } +if ${am_cv_make_support_nested_variables+:} false; then : + $as_echo_n "(cached) " >&6 +else + if $as_echo 'TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 +$as_echo "$am_cv_make_support_nested_variables" >&6; } +if test $am_cv_make_support_nested_variables = yes; then + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AM_BACKSLASH='\' + +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + am__isrc=' -I$(srcdir)' + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi + + +# Define the identity of the package. + PACKAGE='iperf' + VERSION='2.1.9' + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE "$PACKAGE" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define VERSION "$VERSION" +_ACEOF + +# Some tools Automake needs. + +ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} + + +AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} + + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} + + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} + + +MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} + +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# <https://lists.gnu.org/archive/html/automake/2012-07/msg00001.html> +# <https://lists.gnu.org/archive/html/automake/2012-07/msg00014.html> +mkdir_p='$(MKDIR_P)' + +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. +# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AMTAR='$${TAR-tar}' + + +# We'll loop over all known methods to create a tar archive until one works. +_am_tools='gnutar pax cpio none' + +am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' + + + + + + +# POSIX will say in a future version that running "rm -f" with no argument +# is OK; and we want to be able to make that assumption in our Makefile +# recipes. So use an aggressive probe to check that the usage we want is +# actually supported "in the wild" to an acceptable degree. +# See automake bug#10828. +# To make any issue more visible, cause the running configure to be aborted +# by default if the 'rm' program in use doesn't match our expectations; the +# user can still override this though. +if rm -f && rm -fr && rm -rf; then : OK; else + cat >&2 <<'END' +Oops! + +Your 'rm' program seems unable to run without file operands specified +on the command line, even when the '-f' option is present. This is contrary +to the behaviour of most rm programs out there, and not conforming with +the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542> + +Please tell bug-automake@gnu.org about your system, including the value +of your $PATH and any error possibly output before this message. This +can help us improve future automake versions. + +END + if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then + echo 'Configuration will proceed anyway, since you have set the' >&2 + echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 + echo >&2 + else + cat >&2 <<'END' +Aborting the configuration process, to ensure you take notice of the issue. + +You can download and install GNU coreutils to get an 'rm' implementation +that behaves properly: <https://www.gnu.org/software/coreutils/>. + +If you want to complete the configuration process using your problematic +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM +to "yes", and re-run configure. + +END + as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 + fi +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5 +$as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; } + # Check whether --enable-maintainer-mode was given. +if test "${enable_maintainer_mode+set}" = set; then : + enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval +else + USE_MAINTAINER_MODE=no +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5 +$as_echo "$USE_MAINTAINER_MODE" >&6; } + if test $USE_MAINTAINER_MODE = yes; then + MAINTAINER_MODE_TRUE= + MAINTAINER_MODE_FALSE='#' +else + MAINTAINER_MODE_TRUE='#' + MAINTAINER_MODE_FALSE= +fi + + MAINT=$MAINTAINER_MODE_TRUE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_pthread.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) +# +# DESCRIPTION +# +# This macro figures out how to build C programs using POSIX threads. It +# sets the PTHREAD_LIBS output variable to the threads library and linker +# flags, and the PTHREAD_CFLAGS output variable to any special C compiler +# flags that are needed. (The user can also force certain compiler +# flags/libs to be tested by setting these environment variables.) +# +# Also sets PTHREAD_CC to any special C compiler that is needed for +# multi-threaded programs (defaults to the value of CC otherwise). (This +# is necessary on AIX to use the special cc_r compiler alias.) +# +# NOTE: You are assumed to not only compile your program with these flags, +# but also to link with them as well. For example, you might link with +# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS +# +# If you are only building threaded programs, you may wish to use these +# variables in your default LIBS, CFLAGS, and CC: +# +# LIBS="$PTHREAD_LIBS $LIBS" +# CFLAGS="$CFLAGS $PTHREAD_CFLAGS" +# CC="$PTHREAD_CC" +# +# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant +# has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to +# that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX). +# +# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the +# PTHREAD_PRIO_INHERIT symbol is defined when compiling with +# PTHREAD_CFLAGS. +# +# ACTION-IF-FOUND is a list of shell commands to run if a threads library +# is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it +# is not found. If ACTION-IF-FOUND is not specified, the default action +# will define HAVE_PTHREAD. +# +# Please let the authors know if this macro fails on any platform, or if +# you have any other suggestions or comments. This macro was based on work +# by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help +# from M. Frigo), as well as ac_pthread and hb_pthread macros posted by +# Alejandro Forero Cuervo to the autoconf macro repository. We are also +# grateful for the helpful feedback of numerous users. +# +# Updated for Autoconf 2.68 by Daniel Richard G. +# +# LICENSE +# +# Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu> +# Copyright (c) 2011 Daniel Richard G. <skunk@iSKUNK.ORG> +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation, either version 3 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see <https://www.gnu.org/licenses/>. +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 26 + +# This is what autoupdate's m4 run will expand. It fires +# the warning (with _au_warn_XXX), outputs it into the +# updated configure.ac (with AC_DIAGNOSE), and then outputs +# the replacement expansion. + + +# This is an auxiliary macro that is also run when +# autoupdate runs m4. It simply calls m4_warning, but +# we need a wrapper so that each warning is emitted only +# once. We break the quoting in m4_warning's argument in +# order to expand this macro's arguments, not AU_DEFUN's. + + +# Finally, this is the expansion that is picked up by +# autoconf. It tells the user to run autoupdate, and +# then outputs the replacement expansion. We do not care +# about autoupdate's warning because that contains +# information on what to do *after* running autoupdate. + + + +# Check whether --enable-ipv6 was given. +if test "${enable_ipv6+set}" = set; then : + enableval=$enable_ipv6; ac_cv_have_ipv6=$enable_ipv6 +fi + + +# Check whether --enable-multicast was given. +if test "${enable_multicast+set}" = set; then : + enableval=$enable_multicast; ac_cv_multicast=$enable_multicast +fi + + +# Check whether --enable-tcpstats was given. +if test "${enable_tcpstats+set}" = set; then : + enableval=$enable_tcpstats; ac_cv_tcpstats=$enable_tcpstats +fi + + +# Check whether --enable-threads was given. +if test "${enable_threads+set}" = set; then : + enableval=$enable_threads; +fi + + +# Check whether --enable-debuginfo was given. +if test "${enable_debuginfo+set}" = set; then : + enableval=$enable_debuginfo; enable_debuginfo=$enableval +else + enable_debuginfo=no +fi + + +# Check whether --enable-web100 was given. +if test "${enable_web100+set}" = set; then : + enableval=$enable_web100; +fi + + +# Check whether --enable-kalman was given. +if test "${enable_kalman+set}" = set; then : + enableval=$enable_kalman; +fi + + +# Check whether --enable-role_reversal_id was given. +if test "${enable_role_reversal_id+set}" = set; then : + enableval=$enable_role_reversal_id; +fi + + +# Check whether --enable-default_localonly was given. +if test "${enable_default_localonly+set}" = set; then : + enableval=$enable_default_localonly; +fi + + +# Check whether --enable-seqno64b was given. +if test "${enable_seqno64b+set}" = set; then : + enableval=$enable_seqno64b; +fi + + +# Check whether --enable-fastsampling was given. +if test "${enable_fastsampling+set}" = set; then : + enableval=$enable_fastsampling; +fi + + if test "x$enable_fastsampling" = "xyes"; then + FASTSAMPLING_TRUE= + FASTSAMPLING_FALSE='#' +else + FASTSAMPLING_TRUE='#' + FASTSAMPLING_FALSE= +fi + + +# Check whether --enable-discover_defaultlen was given. +if test "${enable_discover_defaultlen+set}" = set; then : + enableval=$enable_discover_defaultlen; +fi + + if test "x$enable_discover_defaultlen" = "xyes"; then + DISCOVER_DEFAULTLEN_TRUE= + DISCOVER_DEFAULTLEN_FALSE='#' +else + DISCOVER_DEFAULTLEN_TRUE='#' + DISCOVER_DEFAULTLEN_FALSE= +fi + + +# Check whether --enable-thread_debug was given. +if test "${enable_thread_debug+set}" = set; then : + enableval=$enable_thread_debug; +fi + + if test "x$enable_thread_debug" = "xyes"; then + THREAD_DEBUG_TRUE= + THREAD_DEBUG_FALSE='#' +else + THREAD_DEBUG_TRUE='#' + THREAD_DEBUG_FALSE= +fi + + +# Check whether --enable-packet_debug was given. +if test "${enable_packet_debug+set}" = set; then : + enableval=$enable_packet_debug; +fi + + if test "x$enable_packet_debug" = "xyes"; then + PACKET_DEBUG_TRUE= + PACKET_DEBUG_FALSE='#' +else + PACKET_DEBUG_TRUE='#' + PACKET_DEBUG_FALSE= +fi + + +# Check whether --enable-checkprograms was given. +if test "${enable_checkprograms+set}" = set; then : + enableval=$enable_checkprograms; +fi + + if test "x$enable_checkprograms" = "xyes"; then + CHECKPROGRAMS_TRUE= + CHECKPROGRAMS_FALSE='#' +else + CHECKPROGRAMS_TRUE='#' + CHECKPROGRAMS_FALSE= +fi + + +# Check whether --enable-static-bin was given. +if test "${enable_static_bin+set}" = set; then : + enableval=$enable_static_bin; enable_static_bin=yes +else + : +fi + + if test x$enable_static_bin = xno; then + ENABLE_STATIC_BIN_TRUE= + ENABLE_STATIC_BIN_FALSE='#' +else + ENABLE_STATIC_BIN_TRUE='#' + ENABLE_STATIC_BIN_FALSE= +fi + + +if test "x$enable_static_bin" = xyes; then : + CFLAGS="$CFLAGS --static"; CXXFLAGS="$CXXFLAGS --static"; LDFLAGS="$LDFLAGS --static" + +fi + +# Check whether --enable-debug_symbols was given. +if test "${enable_debug_symbols+set}" = set; then : + enableval=$enable_debug_symbols; case "${enableval}" in + yes) debug_symbols=true ;; + no) debug_symbols=false ;; + *) as_fn_error $? "bad value ${enableval} for --enable-debug-symbols" "$LINENO" 5 ;; +esac +else + debug_symbols=false +fi + + + if test x"$debug_symbols" = x"true"; then + DEBUG_SYMBOLS_TRUE= + DEBUG_SYMBOLS_FALSE='#' +else + DEBUG_SYMBOLS_TRUE='#' + DEBUG_SYMBOLS_FALSE= +fi + + +# Check whether --enable-af-packet was given. +if test "${enable_af_packet+set}" = set; then : + enableval=$enable_af_packet; +else + enable_af_packet=yes +fi + + +DEPDIR="${am__leading_dot}deps" + +ac_config_commands="$ac_config_commands depfiles" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} supports the include directive" >&5 +$as_echo_n "checking whether ${MAKE-make} supports the include directive... " >&6; } +cat > confinc.mk << 'END' +am__doit: + @echo this is the am__doit target >confinc.out +.PHONY: am__doit +END +am__include="#" +am__quote= +# BSD make does it like this. +echo '.include "confinc.mk" # ignored' > confmf.BSD +# Other make implementations (GNU, Solaris 10, AIX) do it like this. +echo 'include confinc.mk # ignored' > confmf.GNU +_am_result=no +for s in GNU BSD; do + { echo "$as_me:$LINENO: ${MAKE-make} -f confmf.$s && cat confinc.out" >&5 + (${MAKE-make} -f confmf.$s && cat confinc.out) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + case $?:`cat confinc.out 2>/dev/null` in #( + '0:this is the am__doit target') : + case $s in #( + BSD) : + am__include='.include' am__quote='"' ;; #( + *) : + am__include='include' am__quote='' ;; +esac ;; #( + *) : + ;; +esac + if test "$am__include" != "#"; then + _am_result="yes ($s style)" + break + fi +done +rm -f confinc.* confmf.* +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${_am_result}" >&5 +$as_echo "${_am_result}" >&6; } + +# Check whether --enable-dependency-tracking was given. +if test "${enable_dependency_tracking+set}" = set; then : + enableval=$enable_dependency_tracking; +fi + +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi + if test "x$enable_dependency_tracking" != xno; then + AMDEP_TRUE= + AMDEP_FALSE='#' +else + AMDEP_TRUE='#' + AMDEP_FALSE= +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdio.h> +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdarg.h> +#include <stdio.h> +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 +$as_echo_n "checking whether $CC understands -c and -o together... " >&6; } +if ${am_cv_prog_cc_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 + ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 +$as_echo "$am_cv_prog_cc_c_o" >&6; } +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +depcc="$CC" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if ${am_cv_CC_dependencies_compiler_type+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CC_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CC_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CC_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } +CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then + am__fastdepCC_TRUE= + am__fastdepCC_FALSE='#' +else + am__fastdepCC_TRUE='#' + am__fastdepCC_FALSE= +fi + + + +if test "x$enable_af_packet" = "xyes"; then : + + ac_fn_c_check_decl "$LINENO" "TPACKET_V2" "ac_cv_have_decl_TPACKET_V2" "#include <sys/socket.h> + #include <linux/if_packet.h> +" +if test "x$ac_cv_have_decl_TPACKET_V2" = xyes; then : + +$as_echo "#define HAVE_AF_PACKET 1" >>confdefs.h + +else + enable_af_packet="no" +fi + + if test "x${enable_af_packet}" = "xyes"; then + AF_PACKET_TRUE= + AF_PACKET_FALSE='#' +else + AF_PACKET_TRUE='#' + AF_PACKET_FALSE= +fi + + +fi + +# Check whether --enable-tuntap-tun was given. +if test "${enable_tuntap_tun+set}" = set; then : + enableval=$enable_tuntap_tun; +else + enable_tuntap_tun=yes +fi + + +if test "x$enable_tuntap_tun" = "xyes"; then : + + ac_fn_c_check_decl "$LINENO" "IFF_TUN" "ac_cv_have_decl_IFF_TUN" "#include <linux/if_tun.h> +" +if test "x$ac_cv_have_decl_IFF_TUN" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_IFF_TUN $ac_have_decl +_ACEOF +if test $ac_have_decl = 1; then : + +$as_echo "#define HAVE_TUNTAP_TUN 1" >>confdefs.h + +else + enable_tuntap_tun="no" +fi + + if test "x${enable_tuntap_tun}" = "xyes"; then + TUNTAP_TUN_TRUE= + TUNTAP_TUN_FALSE='#' +else + TUNTAP_TUN_TRUE='#' + TUNTAP_TUN_FALSE= +fi + + +fi + +# Check whether --enable-tuntap-tap was given. +if test "${enable_tuntap_tap+set}" = set; then : + enableval=$enable_tuntap_tap; +else + enable_tuntap_tap=yes +fi + + +if test "x$enable_tuntap_tap" = "xyes"; then : + + ac_fn_c_check_decl "$LINENO" "IFF_TAP" "ac_cv_have_decl_IFF_TAP" "#include <linux/if_tun.h> +" +if test "x$ac_cv_have_decl_IFF_TAP" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_IFF_TAP $ac_have_decl +_ACEOF +if test $ac_have_decl = 1; then : + +$as_echo "#define HAVE_TUNTAP_TAP 1" >>confdefs.h + +else + enable_tuntap_tap="no" +fi + + if test "x${enable_tuntap_tap}" = "xyes"; then + TUNTAP_TAP_TRUE= + TUNTAP_TAP_FALSE='#' +else + TUNTAP_TAP_TRUE='#' + TUNTAP_TAP_FALSE= +fi + + +fi + + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test -z "$CXX"; then + if test -n "$CCC"; then + CXX=$CCC + else + if test -n "$ac_tool_prefix"; then + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 +$as_echo "$CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CXX="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 +$as_echo "$ac_ct_CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CXX" && break +done + + if test "x$ac_ct_CXX" = x; then + CXX="g++" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CXX=$ac_ct_CXX + fi +fi + + fi +fi +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 +$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } +if ${ac_cv_cxx_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_cxx_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 +$as_echo "$ac_cv_cxx_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GXX=yes +else + GXX= +fi +ac_test_CXXFLAGS=${CXXFLAGS+set} +ac_save_CXXFLAGS=$CXXFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 +$as_echo_n "checking whether $CXX accepts -g... " >&6; } +if ${ac_cv_prog_cxx_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_cxx_werror_flag=$ac_cxx_werror_flag + ac_cxx_werror_flag=yes + ac_cv_prog_cxx_g=no + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_prog_cxx_g=yes +else + CXXFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + +else + ac_cxx_werror_flag=$ac_save_cxx_werror_flag + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_prog_cxx_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_cxx_werror_flag=$ac_save_cxx_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 +$as_echo "$ac_cv_prog_cxx_g" >&6; } +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +depcc="$CXX" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if ${am_cv_CXX_dependencies_compiler_type+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CXX_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CXX_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CXX_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CXX_dependencies_compiler_type" >&6; } +CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then + am__fastdepCXX_TRUE= + am__fastdepCXX_FALSE='#' +else + am__fastdepCXX_TRUE='#' + am__fastdepCXX_FALSE= +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdarg.h> +#include <stdio.h> +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 +$as_echo_n "checking whether $CC understands -c and -o together... " >&6; } +if ${am_cv_prog_cc_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 + ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 +$as_echo "$am_cv_prog_cc_c_o" >&6; } +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +depcc="$CC" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if ${am_cv_CC_dependencies_compiler_type+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CC_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CC_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CC_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } +CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then + am__fastdepCC_TRUE= + am__fastdepCC_FALSE='#' +else + am__fastdepCC_TRUE='#' + am__fastdepCC_FALSE= +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing strerror" >&5 +$as_echo_n "checking for library containing strerror... " >&6; } +if ${ac_cv_search_strerror+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char strerror (); +int +main () +{ +return strerror (); + ; + return 0; +} +_ACEOF +for ac_lib in '' cposix; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_strerror=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_strerror+:} false; then : + break +fi +done +if ${ac_cv_search_strerror+:} false; then : + +else + ac_cv_search_strerror=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_strerror" >&5 +$as_echo "$ac_cv_search_strerror" >&6; } +ac_res=$ac_cv_search_strerror +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if ${ac_cv_build+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if ${ac_cv_host+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5 +$as_echo_n "checking for clock_gettime in -lrt... " >&6; } +if ${ac_cv_lib_rt_clock_gettime+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lrt $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char clock_gettime (); +int +main () +{ +return clock_gettime (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_rt_clock_gettime=yes +else + ac_cv_lib_rt_clock_gettime=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5 +$as_echo "$ac_cv_lib_rt_clock_gettime" >&6; } +if test "x$ac_cv_lib_rt_clock_gettime" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBRT 1 +_ACEOF + + LIBS="-lrt $LIBS" + +fi + + + +if test "$enable_threads" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 +$as_echo_n "checking for a sed that does not truncate output... " >&6; } +if ${ac_cv_path_SED+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for ac_i in 1 2 3 4 5 6 7; do + ac_script="$ac_script$as_nl$ac_script" + done + echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed + { ac_script=; unset ac_script;} + if test -z "$SED"; then + ac_path_SED_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_SED" || continue +# Check for GNU ac_path_SED and select it if it is found. + # Check for GNU $ac_path_SED +case `"$ac_path_SED" --version 2>&1` in +*GNU*) + ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo '' >> "conftest.nl" + "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_SED_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_SED="$ac_path_SED" + ac_path_SED_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_SED_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_SED"; then + as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 + fi +else + ac_cv_path_SED=$SED +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 +$as_echo "$ac_cv_path_SED" >&6; } + SED="$ac_cv_path_SED" + rm -f conftest.sed + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_GREP" || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + + + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ax_pthread_ok=no + +# We used to check for pthread.h first, but this fails if pthread.h +# requires special compiler flags (e.g. on Tru64 or Sequent). +# It gets checked for in the link test anyway. + +# First of all, check if the user has set any of the PTHREAD_LIBS, +# etcetera environment variables, and if threads linking works using +# them: +if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then + ax_pthread_save_CC="$CC" + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + if test "x$PTHREAD_CC" != "x"; then : + CC="$PTHREAD_CC" +fi + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS" >&5 +$as_echo_n "checking for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_join (); +int +main () +{ +return pthread_join (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ax_pthread_ok=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_ok" >&5 +$as_echo "$ax_pthread_ok" >&6; } + if test "x$ax_pthread_ok" = "xno"; then + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" + fi + CC="$ax_pthread_save_CC" + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" +fi + +# We must check for the threads library under a number of different +# names; the ordering is very important because some systems +# (e.g. DEC) have both -lpthread and -lpthreads, where one of the +# libraries is broken (non-POSIX). + +# Create a list of thread flags to try. Items starting with a "-" are +# C compiler flags, and other items are library names, except for "none" +# which indicates that we try without any flags at all, and "pthread-config" +# which is a program returning the flags for the Pth emulation library. + +ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" + +# The ordering *is* (sometimes) important. Some notes on the +# individual items follow: + +# pthreads: AIX (must check this before -lpthread) +# none: in case threads are in libc; should be tried before -Kthread and +# other compiler flags to prevent continual compiler warnings +# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) +# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64 +# (Note: HP C rejects this with "bad form for `-t' option") +# -pthreads: Solaris/gcc (Note: HP C also rejects) +# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it +# doesn't hurt to check since this sometimes defines pthreads and +# -D_REENTRANT too), HP C (must be checked before -lpthread, which +# is present but should not be used directly; and before -mthreads, +# because the compiler interprets this as "-mt" + "-hreads") +# -mthreads: Mingw32/gcc, Lynx/gcc +# pthread: Linux, etcetera +# --thread-safe: KAI C++ +# pthread-config: use pthread-config program (for GNU Pth library) + +case $host_os in + + freebsd*) + + # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) + # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) + + ax_pthread_flags="-kthread lthread $ax_pthread_flags" + ;; + + hpux*) + + # From the cc(1) man page: "[-mt] Sets various -D flags to enable + # multi-threading and also sets -lpthread." + + ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags" + ;; + + openedition*) + + # IBM z/OS requires a feature-test macro to be defined in order to + # enable POSIX threads at all, so give the user a hint if this is + # not set. (We don't define these ourselves, as they can affect + # other portions of the system API in unpredictable ways.) + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS) + AX_PTHREAD_ZOS_MISSING +# endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "AX_PTHREAD_ZOS_MISSING" >/dev/null 2>&1; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support." >&5 +$as_echo "$as_me: WARNING: IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support." >&2;} +fi +rm -f conftest* + + ;; + + solaris*) + + # On Solaris (at least, for some versions), libc contains stubbed + # (non-functional) versions of the pthreads routines, so link-based + # tests will erroneously succeed. (N.B.: The stubs are missing + # pthread_cleanup_push, or rather a function called by this macro, + # so we could check for that, but who knows whether they'll stub + # that too in a future libc.) So we'll check first for the + # standard Solaris way of linking pthreads (-mt -lpthread). + + ax_pthread_flags="-mt,pthread pthread $ax_pthread_flags" + ;; +esac + +# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC) + +if test "x$GCC" = "xyes"; then : + ax_pthread_flags="-pthread -pthreads $ax_pthread_flags" +fi + +# The presence of a feature test macro requesting re-entrant function +# definitions is, on some systems, a strong hint that pthreads support is +# correctly enabled + +case $host_os in + darwin* | hpux* | linux* | osf* | solaris*) + ax_pthread_check_macro="_REENTRANT" + ;; + + aix*) + ax_pthread_check_macro="_THREAD_SAFE" + ;; + + *) + ax_pthread_check_macro="--" + ;; +esac +if test "x$ax_pthread_check_macro" = "x--"; then : + ax_pthread_check_cond=0 +else + ax_pthread_check_cond="!defined($ax_pthread_check_macro)" +fi + +# Are we compiling with Clang? + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC is Clang" >&5 +$as_echo_n "checking whether $CC is Clang... " >&6; } +if ${ax_cv_PTHREAD_CLANG+:} false; then : + $as_echo_n "(cached) " >&6 +else + ax_cv_PTHREAD_CLANG=no + # Note that Autoconf sets GCC=yes for Clang as well as GCC + if test "x$GCC" = "xyes"; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Note: Clang 2.7 lacks __clang_[a-z]+__ */ +# if defined(__clang__) && defined(__llvm__) + AX_PTHREAD_CC_IS_CLANG +# endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "AX_PTHREAD_CC_IS_CLANG" >/dev/null 2>&1; then : + ax_cv_PTHREAD_CLANG=yes +fi +rm -f conftest* + + fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_CLANG" >&5 +$as_echo "$ax_cv_PTHREAD_CLANG" >&6; } +ax_pthread_clang="$ax_cv_PTHREAD_CLANG" + +ax_pthread_clang_warning=no + +# Clang needs special handling, because older versions handle the -pthread +# option in a rather... idiosyncratic way + +if test "x$ax_pthread_clang" = "xyes"; then + + # Clang takes -pthread; it has never supported any other flag + + # (Note 1: This will need to be revisited if a system that Clang + # supports has POSIX threads in a separate library. This tends not + # to be the way of modern systems, but it's conceivable.) + + # (Note 2: On some systems, notably Darwin, -pthread is not needed + # to get POSIX threads support; the API is always present and + # active. We could reasonably leave PTHREAD_CFLAGS empty. But + # -pthread does define _REENTRANT, and while the Darwin headers + # ignore this macro, third-party headers might not.) + + PTHREAD_CFLAGS="-pthread" + PTHREAD_LIBS= + + ax_pthread_ok=yes + + # However, older versions of Clang make a point of warning the user + # that, in an invocation where only linking and no compilation is + # taking place, the -pthread option has no effect ("argument unused + # during compilation"). They expect -pthread to be passed in only + # when source code is being compiled. + # + # Problem is, this is at odds with the way Automake and most other + # C build frameworks function, which is that the same flags used in + # compilation (CFLAGS) are also used in linking. Many systems + # supported by AX_PTHREAD require exactly this for POSIX threads + # support, and in fact it is often not straightforward to specify a + # flag that is used only in the compilation phase and not in + # linking. Such a scenario is extremely rare in practice. + # + # Even though use of the -pthread flag in linking would only print + # a warning, this can be a nuisance for well-run software projects + # that build with -Werror. So if the active version of Clang has + # this misfeature, we search for an option to squash it. + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether Clang needs flag to prevent \"argument unused\" warning when linking with -pthread" >&5 +$as_echo_n "checking whether Clang needs flag to prevent \"argument unused\" warning when linking with -pthread... " >&6; } +if ${ax_cv_PTHREAD_CLANG_NO_WARN_FLAG+:} false; then : + $as_echo_n "(cached) " >&6 +else + ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown + # Create an alternate version of $ac_link that compiles and + # links in two steps (.c -> .o, .o -> exe) instead of one + # (.c -> exe), because the warning occurs only in the second + # step + ax_pthread_save_ac_link="$ac_link" + ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g' + ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"` + ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)" + ax_pthread_save_CFLAGS="$CFLAGS" + for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do + if test "x$ax_pthread_try" = "xunknown"; then : + break +fi + CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS" + ac_link="$ax_pthread_save_ac_link" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int main(void){return 0;} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_link="$ax_pthread_2step_ac_link" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int main(void){return 0;} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + break +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + done + ac_link="$ax_pthread_save_ac_link" + CFLAGS="$ax_pthread_save_CFLAGS" + if test "x$ax_pthread_try" = "x"; then : + ax_pthread_try=no +fi + ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" >&5 +$as_echo "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" >&6; } + + case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in + no | unknown) ;; + *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;; + esac + +fi # $ax_pthread_clang = yes + +if test "x$ax_pthread_ok" = "xno"; then +for ax_pthread_try_flag in $ax_pthread_flags; do + + case $ax_pthread_try_flag in + none) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work without any flags" >&5 +$as_echo_n "checking whether pthreads work without any flags... " >&6; } + ;; + + -mt,pthread) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with -mt -lpthread" >&5 +$as_echo_n "checking whether pthreads work with -mt -lpthread... " >&6; } + PTHREAD_CFLAGS="-mt" + PTHREAD_LIBS="-lpthread" + ;; + + -*) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with $ax_pthread_try_flag" >&5 +$as_echo_n "checking whether pthreads work with $ax_pthread_try_flag... " >&6; } + PTHREAD_CFLAGS="$ax_pthread_try_flag" + ;; + + pthread-config) + # Extract the first word of "pthread-config", so it can be a program name with args. +set dummy pthread-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ax_pthread_config+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ax_pthread_config"; then + ac_cv_prog_ax_pthread_config="$ax_pthread_config" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ax_pthread_config="yes" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_prog_ax_pthread_config" && ac_cv_prog_ax_pthread_config="no" +fi +fi +ax_pthread_config=$ac_cv_prog_ax_pthread_config +if test -n "$ax_pthread_config"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_config" >&5 +$as_echo "$ax_pthread_config" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test "x$ax_pthread_config" = "xno"; then : + continue +fi + PTHREAD_CFLAGS="`pthread-config --cflags`" + PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" + ;; + + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the pthreads library -l$ax_pthread_try_flag" >&5 +$as_echo_n "checking for the pthreads library -l$ax_pthread_try_flag... " >&6; } + PTHREAD_LIBS="-l$ax_pthread_try_flag" + ;; + esac + + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + + # Check for various functions. We must include pthread.h, + # since some functions may be macros. (On the Sequent, we + # need a special flag -Kthread to make this header compile.) + # We check for pthread_join because it is in -lpthread on IRIX + # while pthread_create is in libc. We check for pthread_attr_init + # due to DEC craziness with -lpthreads. We check for + # pthread_cleanup_push because it is one of the few pthread + # functions on Solaris that doesn't have a non-functional libc stub. + # We try pthread_create on general principles. + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <pthread.h> +# if $ax_pthread_check_cond +# error "$ax_pthread_check_macro must be defined" +# endif + static void *some_global = NULL; + static void routine(void *a) + { + /* To avoid any unused-parameter or + unused-but-set-parameter warning. */ + some_global = a; + } + static void *start_routine(void *a) { return a; } +int +main () +{ +pthread_t th; pthread_attr_t attr; + pthread_create(&th, 0, start_routine, 0); + pthread_join(th, 0); + pthread_attr_init(&attr); + pthread_cleanup_push(routine, 0); + pthread_cleanup_pop(0) /* ; */ + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ax_pthread_ok=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_ok" >&5 +$as_echo "$ax_pthread_ok" >&6; } + if test "x$ax_pthread_ok" = "xyes"; then : + break +fi + + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" +done +fi + +# Various other checks: +if test "x$ax_pthread_ok" = "xyes"; then + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + + # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for joinable pthread attribute" >&5 +$as_echo_n "checking for joinable pthread attribute... " >&6; } +if ${ax_cv_PTHREAD_JOINABLE_ATTR+:} false; then : + $as_echo_n "(cached) " >&6 +else + ax_cv_PTHREAD_JOINABLE_ATTR=unknown + for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <pthread.h> +int +main () +{ +int attr = $ax_pthread_attr; return attr /* ; */ + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + done + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_JOINABLE_ATTR" >&5 +$as_echo "$ax_cv_PTHREAD_JOINABLE_ATTR" >&6; } + if test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \ + test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \ + test "x$ax_pthread_joinable_attr_defined" != "xyes"; then : + +cat >>confdefs.h <<_ACEOF +#define PTHREAD_CREATE_JOINABLE $ax_cv_PTHREAD_JOINABLE_ATTR +_ACEOF + + ax_pthread_joinable_attr_defined=yes + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether more special flags are required for pthreads" >&5 +$as_echo_n "checking whether more special flags are required for pthreads... " >&6; } +if ${ax_cv_PTHREAD_SPECIAL_FLAGS+:} false; then : + $as_echo_n "(cached) " >&6 +else + ax_cv_PTHREAD_SPECIAL_FLAGS=no + case $host_os in + solaris*) + ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS" + ;; + esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_SPECIAL_FLAGS" >&5 +$as_echo "$ax_cv_PTHREAD_SPECIAL_FLAGS" >&6; } + if test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \ + test "x$ax_pthread_special_flags_added" != "xyes"; then : + PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS" + ax_pthread_special_flags_added=yes +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PTHREAD_PRIO_INHERIT" >&5 +$as_echo_n "checking for PTHREAD_PRIO_INHERIT... " >&6; } +if ${ax_cv_PTHREAD_PRIO_INHERIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <pthread.h> +int +main () +{ +int i = PTHREAD_PRIO_INHERIT; + return i; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ax_cv_PTHREAD_PRIO_INHERIT=yes +else + ax_cv_PTHREAD_PRIO_INHERIT=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_PRIO_INHERIT" >&5 +$as_echo "$ax_cv_PTHREAD_PRIO_INHERIT" >&6; } + if test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \ + test "x$ax_pthread_prio_inherit_defined" != "xyes"; then : + +$as_echo "#define HAVE_PTHREAD_PRIO_INHERIT 1" >>confdefs.h + + ax_pthread_prio_inherit_defined=yes + +fi + + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" + + # More AIX lossage: compile with *_r variant + if test "x$GCC" != "xyes"; then + case $host_os in + aix*) + case "x/$CC" in #( + x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6) : + #handle absolute path differently from PATH based program lookup + case "x$CC" in #( + x/*) : + if as_fn_executable_p ${CC}_r; then : + PTHREAD_CC="${CC}_r" +fi ;; #( + *) : + for ac_prog in ${CC}_r +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_PTHREAD_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$PTHREAD_CC"; then + ac_cv_prog_PTHREAD_CC="$PTHREAD_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_PTHREAD_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +PTHREAD_CC=$ac_cv_prog_PTHREAD_CC +if test -n "$PTHREAD_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PTHREAD_CC" >&5 +$as_echo "$PTHREAD_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$PTHREAD_CC" && break +done +test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" + ;; +esac ;; #( + *) : + ;; +esac + ;; + esac + fi +fi + +test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" + + + + + +# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: +if test "x$ax_pthread_ok" = "xyes"; then + +$as_echo "#define HAVE_PTHREAD 1" >>confdefs.h + + : +else + ax_pthread_ok=no + +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + if test "$ax_pthread_ok" = yes; then + $as_echo "#define HAVE_POSIX_THREAD 1" >>confdefs.h + + $as_echo "#define _REENTRANT 1" >>confdefs.h + + fi +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing gethostbyname" >&5 +$as_echo_n "checking for library containing gethostbyname... " >&6; } +if ${ac_cv_search_gethostbyname+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gethostbyname (); +int +main () +{ +return gethostbyname (); + ; + return 0; +} +_ACEOF +for ac_lib in '' nsl; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_gethostbyname=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_gethostbyname+:} false; then : + break +fi +done +if ${ac_cv_search_gethostbyname+:} false; then : + +else + ac_cv_search_gethostbyname=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_gethostbyname" >&5 +$as_echo "$ac_cv_search_gethostbyname" >&6; } +ac_res=$ac_cv_search_gethostbyname +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing socket" >&5 +$as_echo_n "checking for library containing socket... " >&6; } +if ${ac_cv_search_socket+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char socket (); +int +main () +{ +return socket (); + ; + return 0; +} +_ACEOF +for ac_lib in '' socket; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_socket=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_socket+:} false; then : + break +fi +done +if ${ac_cv_search_socket+:} false; then : + +else + ac_cv_search_socket=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_socket" >&5 +$as_echo "$ac_cv_search_socket" >&6; } +ac_res=$ac_cv_search_socket +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +else + ac_fn_c_check_header_compile "$LINENO" "winsock2.h" "ac_cv_header_winsock2_h" "#include <windows.h> +" +if test "x$ac_cv_header_winsock2_h" = xyes; then : + + + +$as_echo "#define HAVE_WINSOCK2_H 1" >>confdefs.h + + if test "$ax_pthread_ok" != yes; then + +$as_echo "#define HAVE_WIN32_THREAD 1" >>confdefs.h + + fi + LIBS="-lws2_32 $LIBS" +fi + + +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <float.h> + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <string.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdlib.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <ctype.h> +#include <stdlib.h> +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_header in arpa/inet.h libintl.h net/ethernet.h net/if.h sys/ioctl.h sys/sockio.h linux/sockios.h linux/ip.h linux/udp.h linux/if_packet.h linux/filter.h linux/if_tun.h netdb.h netinet/in.h netinet/tcp.h stdlib.h string.h strings.h sys/socket.h sys/time.h syslog.h unistd.h signal.h ifaddrs.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 +$as_echo_n "checking for an ANSI C-conforming const... " >&6; } +if ${ac_cv_c_const+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + +#ifndef __cplusplus + /* Ultrix mips cc rejects this sort of thing. */ + typedef int charset[2]; + const charset cs = { 0, 0 }; + /* SunOS 4.1.1 cc rejects this. */ + char const *const *pcpcc; + char **ppc; + /* NEC SVR4.0.2 mips cc rejects this. */ + struct point {int x, y;}; + static struct point const zero = {0,0}; + /* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in + an arm of an if-expression whose if-part is not a constant + expression */ + const char *g = "string"; + pcpcc = &g + (g ? g-g : 0); + /* HPUX 7.0 cc rejects these. */ + ++pcpcc; + ppc = (char**) pcpcc; + pcpcc = (char const *const *) ppc; + { /* SCO 3.2v4 cc rejects this sort of thing. */ + char tx; + char *t = &tx; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; + if (s) return 0; + } + { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; + } + { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; + } + { /* AIX XL C 1.02.0.0 rejects this sort of thing, saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; } bx; + struct s *b = &bx; b->j = 5; + } + { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; + if (!foo) return 0; + } + return !cs[0] && !zero.x; +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_const=yes +else + ac_cv_c_const=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5 +$as_echo "$ac_cv_c_const" >&6; } +if test $ac_cv_c_const = no; then + +$as_echo "#define const /**/" >>confdefs.h + +fi + +ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" +if test "x$ac_cv_type_size_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define size_t unsigned int +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "ssize_t" "ac_cv_type_ssize_t" "$ac_includes_default" +if test "x$ac_cv_type_ssize_t" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_SSIZE_T 1 +_ACEOF + + +else + cat >>confdefs.h <<_ACEOF +#define ssize_t int +_ACEOF + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether time.h and sys/time.h may both be included" >&5 +$as_echo_n "checking whether time.h and sys/time.h may both be included... " >&6; } +if ${ac_cv_header_time+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <sys/types.h> +#include <sys/time.h> +#include <time.h> + +int +main () +{ +if ((struct tm *) 0) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_time=yes +else + ac_cv_header_time=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_time" >&5 +$as_echo "$ac_cv_header_time" >&6; } +if test $ac_cv_header_time = yes; then + +$as_echo "#define TIME_WITH_SYS_TIME 1" >>confdefs.h + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether struct tm is in sys/time.h or time.h" >&5 +$as_echo_n "checking whether struct tm is in sys/time.h or time.h... " >&6; } +if ${ac_cv_struct_tm+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <sys/types.h> +#include <time.h> + +int +main () +{ +struct tm tm; + int *p = &tm.tm_sec; + return !p; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_struct_tm=time.h +else + ac_cv_struct_tm=sys/time.h +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_struct_tm" >&5 +$as_echo "$ac_cv_struct_tm" >&6; } +if test $ac_cv_struct_tm = sys/time.h; then + +$as_echo "#define TM_IN_SYS_TIME 1" >>confdefs.h + +fi + + +ac_fn_c_check_type "$LINENO" "int64_t" "ac_cv_type_int64_t" "$ac_includes_default" +if test "x$ac_cv_type_int64_t" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_INT64_T 1 +_ACEOF + + +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking 3rd argument of accept" >&5 +$as_echo_n "checking 3rd argument of accept... " >&6; } +if ${ac_cv_accept_arg+:} false; then : + $as_echo_n "(cached) " >&6 +else + + + if test -z "$ac_cv_accept_arg" ; then + + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default + #include <sys/socket.h> +int +main () +{ +socklen_t length; + accept( 0, 0, &length ); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_accept_arg=socklen_t +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + fi + + + + if test -z "$ac_cv_accept_arg" ; then + + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default + #include <sys/socket.h> +int +main () +{ +int length; + accept( 0, 0, &length ); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_accept_arg=int +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + fi + + + + if test -z "$ac_cv_accept_arg" ; then + + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default + #include <sys/socket.h> +int +main () +{ +size_t length; + accept( 0, 0, &length ); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_accept_arg=size_t +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + fi + + + + if test -z "$ac_cv_accept_arg" ; then + + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default + #include <sys/socket.h> +int +main () +{ +short length; + accept( 0, 0, &length ); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_accept_arg=short +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + fi + + + + if test -z "$ac_cv_accept_arg" ; then + + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default + #include <sys/socket.h> +int +main () +{ +long length; + accept( 0, 0, &length ); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_accept_arg=long +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + fi + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_accept_arg" >&5 +$as_echo "$ac_cv_accept_arg" >&6; } + +if test -z "$ac_cv_accept_arg" ; then + ac_cv_accept_arg=int +fi + + +cat >>confdefs.h <<_ACEOF +#define Socklen_t $ac_cv_accept_arg +_ACEOF + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working memcmp" >&5 +$as_echo_n "checking for working memcmp... " >&6; } +if ${ac_cv_func_memcmp_working+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_func_memcmp_working=no +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ + + /* Some versions of memcmp are not 8-bit clean. */ + char c0 = '\100', c1 = '\200', c2 = '\201'; + if (memcmp(&c0, &c2, 1) >= 0 || memcmp(&c1, &c2, 1) >= 0) + return 1; + + /* The Next x86 OpenStep bug shows up only when comparing 16 bytes + or more and with at least one buffer not starting on a 4-byte boundary. + William Lewis provided this test program. */ + { + char foo[21]; + char bar[21]; + int i; + for (i = 0; i < 4; i++) + { + char *a = foo + i; + char *b = bar + i; + strcpy (a, "--------01111111"); + strcpy (b, "--------10000000"); + if (memcmp (a, b, 16) >= 0) + return 1; + } + return 0; + } + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_func_memcmp_working=yes +else + ac_cv_func_memcmp_working=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_memcmp_working" >&5 +$as_echo "$ac_cv_func_memcmp_working" >&6; } +test $ac_cv_func_memcmp_working = no && case " $LIBOBJS " in + *" memcmp.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS memcmp.$ac_objext" + ;; +esac + + +for ac_header in sys/select.h sys/socket.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking types of arguments for select" >&5 +$as_echo_n "checking types of arguments for select... " >&6; } +if ${ac_cv_func_select_args+:} false; then : + $as_echo_n "(cached) " >&6 +else + for ac_arg234 in 'fd_set *' 'int *' 'void *'; do + for ac_arg1 in 'int' 'size_t' 'unsigned long int' 'unsigned int'; do + for ac_arg5 in 'struct timeval *' 'const struct timeval *'; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +#ifdef HAVE_SYS_SELECT_H +# include <sys/select.h> +#endif +#ifdef HAVE_SYS_SOCKET_H +# include <sys/socket.h> +#endif + +int +main () +{ +extern int select ($ac_arg1, + $ac_arg234, $ac_arg234, $ac_arg234, + $ac_arg5); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_func_select_args="$ac_arg1,$ac_arg234,$ac_arg5"; break 3 +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + done + done +done +# Provide a safe default value. +: "${ac_cv_func_select_args=int,int *,struct timeval *}" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_select_args" >&5 +$as_echo "$ac_cv_func_select_args" >&6; } +ac_save_IFS=$IFS; IFS=',' +set dummy `echo "$ac_cv_func_select_args" | sed 's/\*/\*/g'` +IFS=$ac_save_IFS +shift + +cat >>confdefs.h <<_ACEOF +#define SELECT_TYPE_ARG1 $1 +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define SELECT_TYPE_ARG234 ($2) +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define SELECT_TYPE_ARG5 ($3) +_ACEOF + +rm -f conftest* + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking return type of signal handlers" >&5 +$as_echo_n "checking return type of signal handlers... " >&6; } +if ${ac_cv_type_signal+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <sys/types.h> +#include <signal.h> + +int +main () +{ +return *(signal (0, 0)) (0) == 1; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_type_signal=int +else + ac_cv_type_signal=void +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_signal" >&5 +$as_echo "$ac_cv_type_signal" >&6; } + +cat >>confdefs.h <<_ACEOF +#define RETSIGTYPE $ac_cv_type_signal +_ACEOF + + +for ac_func in strftime +do : + ac_fn_c_check_func "$LINENO" "strftime" "ac_cv_func_strftime" +if test "x$ac_cv_func_strftime" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STRFTIME 1 +_ACEOF + +else + # strftime is in -lintl on SCO UNIX. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for strftime in -lintl" >&5 +$as_echo_n "checking for strftime in -lintl... " >&6; } +if ${ac_cv_lib_intl_strftime+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lintl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char strftime (); +int +main () +{ +return strftime (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_intl_strftime=yes +else + ac_cv_lib_intl_strftime=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_strftime" >&5 +$as_echo "$ac_cv_lib_intl_strftime" >&6; } +if test "x$ac_cv_lib_intl_strftime" = xyes; then : + $as_echo "#define HAVE_STRFTIME 1" >>confdefs.h + +LIBS="-lintl $LIBS" +fi + +fi +done + +for ac_func in vprintf +do : + ac_fn_c_check_func "$LINENO" "vprintf" "ac_cv_func_vprintf" +if test "x$ac_cv_func_vprintf" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_VPRINTF 1 +_ACEOF + +ac_fn_c_check_func "$LINENO" "_doprnt" "ac_cv_func__doprnt" +if test "x$ac_cv_func__doprnt" = xyes; then : + +$as_echo "#define HAVE_DOPRNT 1" >>confdefs.h + +fi + +fi +done + + +for ac_func in atexit memset select strchr strerror strtol strtoll strtod usleep clock_gettime sched_setscheduler sched_yield mlockall setitimer nanosleep clock_nanosleep freopen +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +ac_fn_c_check_func "$LINENO" "snprintf" "ac_cv_func_snprintf" +if test "x$ac_cv_func_snprintf" = xyes; then : + $as_echo "#define HAVE_SNPRINTF 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" snprintf.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS snprintf.$ac_objext" + ;; +esac + +fi + +ac_fn_c_check_func "$LINENO" "inet_pton" "ac_cv_func_inet_pton" +if test "x$ac_cv_func_inet_pton" = xyes; then : + $as_echo "#define HAVE_INET_PTON 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" inet_pton.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS inet_pton.$ac_objext" + ;; +esac + +fi + +ac_fn_c_check_func "$LINENO" "inet_ntop" "ac_cv_func_inet_ntop" +if test "x$ac_cv_func_inet_ntop" = xyes; then : + $as_echo "#define HAVE_INET_NTOP 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" inet_ntop.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS inet_ntop.$ac_objext" + ;; +esac + +fi + +ac_fn_c_check_func "$LINENO" "gettimeofday" "ac_cv_func_gettimeofday" +if test "x$ac_cv_func_gettimeofday" = xyes; then : + $as_echo "#define HAVE_GETTIMEOFDAY 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" gettimeofday.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS gettimeofday.$ac_objext" + ;; +esac + +fi + + +ac_fn_c_check_decl "$LINENO" "ENOBUFS" "ac_cv_have_decl_ENOBUFS" "#include <errno.h> +" +if test "x$ac_cv_have_decl_ENOBUFS" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_ENOBUFS $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "EWOULDBLOCK" "ac_cv_have_decl_EWOULDBLOCK" "#include <errno.h> +" +if test "x$ac_cv_have_decl_EWOULDBLOCK" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_EWOULDBLOCK $ac_have_decl +_ACEOF + +ac_fn_c_check_decl "$LINENO" "SIOCGIFMTU" "ac_cv_have_decl_SIOCGIFMTU" " +#ifdef HAVE_LINUX_SOCKIOS_H +#include <linux/sockios.h> +#endif +#ifdef HAVE_SYS_SOCKIO_H +#include <sys/sockio.h> +#endif + +" +if test "x$ac_cv_have_decl_SIOCGIFMTU" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_SIOCGIFMTU $ac_have_decl +_ACEOF + +ac_fn_c_check_decl "$LINENO" "pthread_cancel" "ac_cv_have_decl_pthread_cancel" "#include <pthread.h> +" +if test "x$ac_cv_have_decl_pthread_cancel" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_PTHREAD_CANCEL $ac_have_decl +_ACEOF + +ac_fn_c_check_decl "$LINENO" "CPU_SET" "ac_cv_have_decl_CPU_SET" " + #define _GNU_SOURCE + #include <sched.h> + +" +if test "x$ac_cv_have_decl_CPU_SET" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_CPU_SET $ac_have_decl +_ACEOF + +ac_fn_c_check_decl "$LINENO" "SIGALRM" "ac_cv_have_decl_SIGALRM" "#include <signal.h> +" +if test "x$ac_cv_have_decl_SIGALRM" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_SIGALRM $ac_have_decl +_ACEOF + + + +in_h=' +#ifdef HAVE_WINSOCK2_H +#define _WIN32_WINNT 0x0501 /* use (at least) WinXP API */ +#define WIN32_LEAN_AND_MEAN /* exclude unnecesary headers */ +#include <windows.h> +#include <winsock2.h> +#include <ws2tcpip.h> +#else +#include <sys/socket.h> +#include <netinet/in.h> +#include <netinet/tcp.h> +#endif +' + +ac_fn_c_check_decl "$LINENO" "AF_INET6" "ac_cv_have_decl_AF_INET6" "$in_h +" +if test "x$ac_cv_have_decl_AF_INET6" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_AF_INET6 $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "SO_TIMESTAMP" "ac_cv_have_decl_SO_TIMESTAMP" "$in_h +" +if test "x$ac_cv_have_decl_SO_TIMESTAMP" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_SO_TIMESTAMP $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "SO_SNDTIMEO" "ac_cv_have_decl_SO_SNDTIMEO" "$in_h +" +if test "x$ac_cv_have_decl_SO_SNDTIMEO" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_SO_SNDTIMEO $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "SO_REUSEPORT" "ac_cv_have_decl_SO_REUSEPORT" "$in_h +" +if test "x$ac_cv_have_decl_SO_REUSEPORT" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_SO_REUSEPORT $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "SO_BINDTODEVICE" "ac_cv_have_decl_SO_BINDTODEVICE" "$in_h +" +if test "x$ac_cv_have_decl_SO_BINDTODEVICE" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_SO_BINDTODEVICE $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "MSG_DONTWAIT" "ac_cv_have_decl_MSG_DONTWAIT" "$in_h +" +if test "x$ac_cv_have_decl_MSG_DONTWAIT" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_MSG_DONTWAIT $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "SO_MAX_PACING_RATE" "ac_cv_have_decl_SO_MAX_PACING_RATE" "$in_h +" +if test "x$ac_cv_have_decl_SO_MAX_PACING_RATE" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_SO_MAX_PACING_RATE $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "SO_DONTROUTE" "ac_cv_have_decl_SO_DONTROUTE" "$in_h +" +if test "x$ac_cv_have_decl_SO_DONTROUTE" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_SO_DONTROUTE $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "IPV6_TCLASS" "ac_cv_have_decl_IPV6_TCLASS" "$in_h +" +if test "x$ac_cv_have_decl_IPV6_TCLASS" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_IPV6_TCLASS $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "IP_MULTICAST_ALL" "ac_cv_have_decl_IP_MULTICAST_ALL" "$in_h +" +if test "x$ac_cv_have_decl_IP_MULTICAST_ALL" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_IP_MULTICAST_ALL $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "IP_TOS" "ac_cv_have_decl_IP_TOS" "$in_h +" +if test "x$ac_cv_have_decl_IP_TOS" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_IP_TOS $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "MCAST_JOIN_GROUP" "ac_cv_have_decl_MCAST_JOIN_GROUP" "$in_h +" +if test "x$ac_cv_have_decl_MCAST_JOIN_GROUP" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_MCAST_JOIN_GROUP $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "MCAST_JOIN_SOURCE_GROUP" "ac_cv_have_decl_MCAST_JOIN_SOURCE_GROUP" "$in_h +" +if test "x$ac_cv_have_decl_MCAST_JOIN_SOURCE_GROUP" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_MCAST_JOIN_SOURCE_GROUP $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "IPV6_JOIN_GROUP" "ac_cv_have_decl_IPV6_JOIN_GROUP" "$in_h +" +if test "x$ac_cv_have_decl_IPV6_JOIN_GROUP" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_IPV6_JOIN_GROUP $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "IPV6_V6ONLY" "ac_cv_have_decl_IPV6_V6ONLY" "$in_h +" +if test "x$ac_cv_have_decl_IPV6_V6ONLY" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_IPV6_V6ONLY $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "IPV6_ADD_MEMBERSHIP" "ac_cv_have_decl_IPV6_ADD_MEMBERSHIP" "$in_h +" +if test "x$ac_cv_have_decl_IPV6_ADD_MEMBERSHIP" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_IPV6_ADD_MEMBERSHIP $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "IPV6_MULTICAST_HOPS" "ac_cv_have_decl_IPV6_MULTICAST_HOPS" "$in_h +" +if test "x$ac_cv_have_decl_IPV6_MULTICAST_HOPS" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_IPV6_MULTICAST_HOPS $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "MSG_PEEK" "ac_cv_have_decl_MSG_PEEK" "$in_h +" +if test "x$ac_cv_have_decl_MSG_PEEK" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_MSG_PEEK $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "MSG_WAITALL" "ac_cv_have_decl_MSG_WAITALL" "$in_h +" +if test "x$ac_cv_have_decl_MSG_WAITALL" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_MSG_WAITALL $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "TCP_NODELAY" "ac_cv_have_decl_TCP_NODELAY" "$in_h +" +if test "x$ac_cv_have_decl_TCP_NODELAY" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_TCP_NODELAY $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "TCP_INFO" "ac_cv_have_decl_TCP_INFO" "$in_h +" +if test "x$ac_cv_have_decl_TCP_INFO" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_TCP_INFO $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "TCP_CONNECTION_INFO" "ac_cv_have_decl_TCP_CONNECTION_INFO" "$in_h +" +if test "x$ac_cv_have_decl_TCP_CONNECTION_INFO" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_TCP_CONNECTION_INFO $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "TCP_WINDOW_CLAMP" "ac_cv_have_decl_TCP_WINDOW_CLAMP" "$in_h +" +if test "x$ac_cv_have_decl_TCP_WINDOW_CLAMP" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_TCP_WINDOW_CLAMP $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "TCP_QUICKACK" "ac_cv_have_decl_TCP_QUICKACK" "$in_h +" +if test "x$ac_cv_have_decl_TCP_QUICKACK" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_TCP_QUICKACK $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "TCP_NOTSENT_LOWAT" "ac_cv_have_decl_TCP_NOTSENT_LOWAT" "$in_h +" +if test "x$ac_cv_have_decl_TCP_NOTSENT_LOWAT" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_TCP_NOTSENT_LOWAT $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "TCP_MAXSEG" "ac_cv_have_decl_TCP_MAXSEG" "$in_h +" +if test "x$ac_cv_have_decl_TCP_MAXSEG" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_TCP_MAXSEG $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "IP_ADD_MEMBERSHIP" "ac_cv_have_decl_IP_ADD_MEMBERSHIP" "$in_h +" +if test "x$ac_cv_have_decl_IP_ADD_MEMBERSHIP" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_IP_ADD_MEMBERSHIP $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "IP_ADD_SOURCE_MEMBERSHIP" "ac_cv_have_decl_IP_ADD_SOURCE_MEMBERSHIP" "$in_h +" +if test "x$ac_cv_have_decl_IP_ADD_SOURCE_MEMBERSHIP" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_IP_ADD_SOURCE_MEMBERSHIP $ac_have_decl +_ACEOF + + +ac_fn_c_check_type "$LINENO" "struct sockaddr_storage" "ac_cv_type_struct_sockaddr_storage" "$in_h +" +if test "x$ac_cv_type_struct_sockaddr_storage" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_SOCKADDR_STORAGE 1 +_ACEOF + + +fi +ac_fn_c_check_type "$LINENO" "struct sockaddr_in6" "ac_cv_type_struct_sockaddr_in6" "$in_h +" +if test "x$ac_cv_type_struct_sockaddr_in6" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_SOCKADDR_IN6 1 +_ACEOF + + +fi +ac_fn_c_check_type "$LINENO" "struct group_source_req" "ac_cv_type_struct_group_source_req" "$in_h +" +if test "x$ac_cv_type_struct_group_source_req" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_GROUP_SOURCE_REQ 1 +_ACEOF + + +fi +ac_fn_c_check_type "$LINENO" "struct ip_mreq" "ac_cv_type_struct_ip_mreq" "$in_h +" +if test "x$ac_cv_type_struct_ip_mreq" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_IP_MREQ 1 +_ACEOF + + +fi +ac_fn_c_check_type "$LINENO" "struct ipv6_mreq" "ac_cv_type_struct_ipv6_mreq" "$in_h +" +if test "x$ac_cv_type_struct_ipv6_mreq" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_IPV6_MREQ 1 +_ACEOF + + +fi +ac_fn_c_check_type "$LINENO" "struct ip_mreq_source" "ac_cv_type_struct_ip_mreq_source" "$in_h +" +if test "x$ac_cv_type_struct_ip_mreq_source" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_IP_MREQ_SOURCE 1 +_ACEOF + + +fi + + +ac_fn_c_check_member "$LINENO" "struct sockaddr_in6" "sin6_len" "ac_cv_member_struct_sockaddr_in6_sin6_len" "$in_h +" +if test "x$ac_cv_member_struct_sockaddr_in6_sin6_len" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN 1 +_ACEOF + + +fi +ac_fn_c_check_member "$LINENO" "struct ip_mreq_source" "imr_multiaddr.s_addr" "ac_cv_member_struct_ip_mreq_source_imr_multiaddr_s_addr" "$in_h +" +if test "x$ac_cv_member_struct_ip_mreq_source_imr_multiaddr_s_addr" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_IP_MREQ_SOURCE_IMR_MULTIADDR_S_ADDR 1 +_ACEOF + + +fi + + +ac_fn_c_check_member "$LINENO" "struct tcp_info" "tcpi_total_retrans" "ac_cv_member_struct_tcp_info_tcpi_total_retrans" " +#include <netinet/in.h> +#include <netinet/tcp.h> + +" +if test "x$ac_cv_member_struct_tcp_info_tcpi_total_retrans" = xyes; then : + +fi + + +ac_fn_c_check_member "$LINENO" "struct tcp_info" "tcpi_total_retrans" "ac_cv_member_struct_tcp_info_tcpi_total_retrans" " +#include <netinet/in.h> +#include <netinet/tcp.h> + +" +if test "x$ac_cv_member_struct_tcp_info_tcpi_total_retrans" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_TCP_INFO_TCPI_TOTAL_RETRANS 1 +_ACEOF + + +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdbool.h that conforms to C99" >&5 +$as_echo_n "checking for stdbool.h that conforms to C99... " >&6; } +if ${ac_cv_header_stdbool_h+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include <stdbool.h> + #ifndef bool + "error: bool is not defined" + #endif + #ifndef false + "error: false is not defined" + #endif + #if false + "error: false is not 0" + #endif + #ifndef true + "error: true is not defined" + #endif + #if true != 1 + "error: true is not 1" + #endif + #ifndef __bool_true_false_are_defined + "error: __bool_true_false_are_defined is not defined" + #endif + + struct s { _Bool s: 1; _Bool t; } s; + + char a[true == 1 ? 1 : -1]; + char b[false == 0 ? 1 : -1]; + char c[__bool_true_false_are_defined == 1 ? 1 : -1]; + char d[(bool) 0.5 == true ? 1 : -1]; + /* See body of main program for 'e'. */ + char f[(_Bool) 0.0 == false ? 1 : -1]; + char g[true]; + char h[sizeof (_Bool)]; + char i[sizeof s.t]; + enum { j = false, k = true, l = false * true, m = true * 256 }; + /* The following fails for + HP aC++/ANSI C B3910B A.05.55 [Dec 04 2003]. */ + _Bool n[m]; + char o[sizeof n == m * sizeof n[0] ? 1 : -1]; + char p[-1 - (_Bool) 0 < 0 && -1 - (bool) 0 < 0 ? 1 : -1]; + /* Catch a bug in an HP-UX C compiler. See + http://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html + http://lists.gnu.org/archive/html/bug-coreutils/2005-11/msg00161.html + */ + _Bool q = true; + _Bool *pq = &q; + +int +main () +{ + + bool e = &s; + *pq |= q; + *pq |= ! q; + /* Refer to every declared value, to avoid compiler optimizations. */ + return (!a + !b + !c + !d + !e + !f + !g + !h + !i + !!j + !k + !!l + + !m + !n + !o + !p + !q + !pq); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdbool_h=yes +else + ac_cv_header_stdbool_h=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdbool_h" >&5 +$as_echo "$ac_cv_header_stdbool_h" >&6; } + ac_fn_c_check_type "$LINENO" "_Bool" "ac_cv_type__Bool" "$ac_includes_default" +if test "x$ac_cv_type__Bool" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE__BOOL 1 +_ACEOF + + +fi + + +if test $ac_cv_header_stdbool_h = yes; then + +$as_echo "#define HAVE_STDBOOL_H 1" >>confdefs.h + +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 +$as_echo_n "checking whether byte ordering is bigendian... " >&6; } +if ${ac_cv_c_bigendian+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_bigendian=unknown + # See if we're dealing with a universal compiler. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifndef __APPLE_CC__ + not a universal capable compiler + #endif + typedef int dummy; + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + # Check for potential -arch flags. It is not universal unless + # there are at least two -arch flags with different values. + ac_arch= + ac_prev= + for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do + if test -n "$ac_prev"; then + case $ac_word in + i?86 | x86_64 | ppc | ppc64) + if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then + ac_arch=$ac_word + else + ac_cv_c_bigendian=universal + break + fi + ;; + esac + ac_prev= + elif test "x$ac_word" = "x-arch"; then + ac_prev=arch + fi + done +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + if test $ac_cv_c_bigendian = unknown; then + # See if sys/param.h defines the BYTE_ORDER macro. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <sys/types.h> + #include <sys/param.h> + +int +main () +{ +#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ + && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ + && LITTLE_ENDIAN) + bogus endian macros + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <sys/types.h> + #include <sys/param.h> + +int +main () +{ +#if BYTE_ORDER != BIG_ENDIAN + not big endian + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_bigendian=yes +else + ac_cv_c_bigendian=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # See if <limits.h> defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <limits.h> + +int +main () +{ +#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) + bogus endian macros + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to _BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <limits.h> + +int +main () +{ +#ifndef _BIG_ENDIAN + not big endian + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_bigendian=yes +else + ac_cv_c_bigendian=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # Compile a test program. + if test "$cross_compiling" = yes; then : + # Try to guess by grepping values from an object file. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +short int ascii_mm[] = + { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; + short int ascii_ii[] = + { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; + int use_ascii (int i) { + return ascii_mm[i] + ascii_ii[i]; + } + short int ebcdic_ii[] = + { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; + short int ebcdic_mm[] = + { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; + int use_ebcdic (int i) { + return ebcdic_mm[i] + ebcdic_ii[i]; + } + extern int foo; + +int +main () +{ +return use_ascii (foo) == use_ebcdic (foo); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then + ac_cv_c_bigendian=yes + fi + if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then + if test "$ac_cv_c_bigendian" = unknown; then + ac_cv_c_bigendian=no + else + # finding both strings is unlikely to happen, but who knows? + ac_cv_c_bigendian=unknown + fi + fi +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ + + /* Are we little or big endian? From Harbison&Steele. */ + union + { + long int l; + char c[sizeof (long int)]; + } u; + u.l = 1; + return u.c[sizeof (long int) - 1] == 1; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_c_bigendian=no +else + ac_cv_c_bigendian=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 +$as_echo "$ac_cv_c_bigendian" >&6; } + case $ac_cv_c_bigendian in #( + yes) + $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h +;; #( + no) + ;; #( + universal) + +$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h + + ;; #( + *) + as_fn_error $? "unknown endianness + presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; + esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gettid syscall" >&5 +$as_echo_n "checking for gettid syscall... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <unistd.h> +#include <sys/syscall.h> + +int +main () +{ +syscall(SYS_gettid); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ok=yes +else + ok=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +if test "$ok" = "yes"; then + +$as_echo "#define HAVE_GETTID_SYSCALL 1" >>confdefs.h + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${ok}" >&5 +$as_echo "${ok}" >&6; } + +if test "$ac_cv_multicast" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for multicast support" >&5 +$as_echo_n "checking for multicast support... " >&6; } + ac_cv_multicast=no + if test "$ac_cv_have_decl_IP_ADD_MEMBERSHIP" = yes; then + if test "$ac_cv_type_struct_ip_mreq" = yes; then + ac_cv_multicast=yes + fi + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_multicast" >&5 +$as_echo "$ac_cv_multicast" >&6; } + if test "$ac_cv_multicast" = yes; then + +$as_echo "#define HAVE_MULTICAST 1" >>confdefs.h + + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for multicast ssm support" >&5 +$as_echo_n "checking for multicast ssm support... " >&6; } + ac_cv_ssm_multicast=no + if test "$ac_cv_have_decl_MCAST_JOIN_SOURCE_GROUP" = yes || test "$ac_cv_have_decl_IP_ADD_SOURCE_MEMBERSHIP" = yes; then + if test "$ac_cv_type_struct_group_source_req" = yes; then + ac_cv_ssm_multicast=yes + fi + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_ssm_multicast" >&5 +$as_echo "$ac_cv_ssm_multicast" >&6; } + if test "$ac_cv_ssm_multicast" = yes; then + +$as_echo "#define HAVE_SSM_MULTICAST 1" >>confdefs.h + + fi +fi + +if test "$ac_cv_tcpstats" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for tcpstats support" >&5 +$as_echo_n "checking for tcpstats support... " >&6; } + ac_cv_tcpstats=no + if test "$ac_cv_have_decl_TCP_INFO" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for TCP_INFO_TCPI_TOTAL_RETRANS support" >&5 +$as_echo_n "checking for TCP_INFO_TCPI_TOTAL_RETRANS support... " >&6; } + if test "$ac_cv_member_struct_tcp_info_tcpi_total_retrans" = yes; then + ac_cv_tcpstats=yes + fi + fi + if test "$ac_cv_have_decl_TCP_CONNECTION_INFO" = yes; then + ac_cv_tcpstats=yes + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_tcpstats" >&5 +$as_echo "$ac_cv_tcpstats" >&6; } + if test "$ac_cv_tcpstats" = yes; then + +$as_echo "#define HAVE_TCP_STATS 1" >>confdefs.h + + fi +fi + +if test "$ac_cv_have_ipv6" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for IPv6 headers and structures" >&5 +$as_echo_n "checking for IPv6 headers and structures... " >&6; } + ac_cv_have_ipv6=no + if test "$ac_cv_type_struct_sockaddr_storage" = yes; then + if test "$ac_cv_type_struct_sockaddr_in6" = yes; then + if test "$ac_cv_have_decl_AF_INET6" = yes; then + +$as_echo "#define HAVE_IPV6 1" >>confdefs.h + + ac_cv_have_ipv6=yes + fi + fi + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_ipv6" >&5 +$as_echo "$ac_cv_have_ipv6" >&6; } +fi + +if test "$ac_cv_have_ipv6" = yes; then + if test "$ac_cv_multicast" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for IPv6 multicast support" >&5 +$as_echo_n "checking for IPv6 multicast support... " >&6; } + ac_cv_have_ipv6_multicast=no + if test "$ac_cv_type_struct_ipv6_mreq" = yes; then + if test "$ac_cv_have_decl_IPV6_ADD_MEMBERSHIP" = yes; then + if test "$ac_cv_have_decl_IPV6_MULTICAST_HOPS" = yes; then + +$as_echo "#define HAVE_IPV6_MULTICAST 1" >>confdefs.h + + ac_cv_have_ipv6_multicast=yes + fi + fi + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_ipv6_multicast" >&5 +$as_echo "$ac_cv_have_ipv6_multicast" >&6; } + fi +fi + + +if test "$enable_thread_debug" = yes; then + +$as_echo "#define HAVE_THREAD_DEBUG 1" >>confdefs.h + +else + if test "$enable_debuginfo" = yes; then + +$as_echo "#define DBG_MJZ 1" >>confdefs.h + + else + +$as_echo "#define NDEBUG 1" >>confdefs.h + + fi +fi + +if test "$enable_web100" != no; then +if test -e "/proc/web100"; then +if test -d "/proc/web100"; then +if test -e "/proc/web100/header"; then +if test -f "/proc/web100/header"; then +if test -r "/proc/web100/header"; then + +web100_success="" + +# Extract the first word of "web100-config", so it can be a program name with args. +set dummy web100-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_WEB100_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $WEB100_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_WEB100_CONFIG="$WEB100_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_WEB100_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_WEB100_CONFIG" && ac_cv_path_WEB100_CONFIG="no" + ;; +esac +fi +WEB100_CONFIG=$ac_cv_path_WEB100_CONFIG +if test -n "$WEB100_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $WEB100_CONFIG" >&5 +$as_echo "$WEB100_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Web100" >&5 +$as_echo_n "checking for Web100... " >&6; } + +if test "$WEB100_CONFIG" != "no"; then + WEB100_CFLAGS=`$WEB100_CONFIG --cflags` + WEB100_LIBS=`$WEB100_CONFIG --libs` + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + echo "*** The web100-config script installed by Web100 could not be found" + echo "*** If Web100 was installed in PREFIX, make sure PREFIX/bin is in" + echo "*** your path, or set the WEB100_CONFIG environment variable to the" + echo "*** full path to web100-config" + web100_success="no" +fi + +if test x$web100_success = x; then + if test "x" != "x"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Web100 - version " >&5 +$as_echo_n "checking for Web100 - version ... " >&6; } + + WEB100_VERSION=`$WEB100_CONFIG --version` + if test "$WEB100_VERSION" = ""; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + echo "*** The requested () and installed ($WEB100_VERSION) versions" + echo "*** of Web100 do not match." + web100_success="no" + fi + fi +fi + +if test x$web100_success = x; then + web100_success="yes" +fi + +if test x$web100_success = xyes; then + : +else + WEB100_CFLAGS="" + WEB100_LIBS="" + : +fi + + + + +if test "$web100_success" = yes; then + +$as_echo "#define HAVE_WEB100 1" >>confdefs.h + +fi fi fi fi fi fi +fi + +if test "$enable_kalman" != no; then + +$as_echo "#define HAVE_KALMAN 1" >>confdefs.h + +fi + +if test "$enable_role_reversal_id" != no; then + +$as_echo "#define HAVE_ROLE_REVERSAL_ID 1" >>confdefs.h + +fi + +if test "$enable_default_localonly" = yes; then + +$as_echo "#define HAVE_DEFAULT_DONTROUTE_ON 1" >>confdefs.h + +fi + +if test "$enable_seqno64b" != no; then + +$as_echo "#define HAVE_SEQNO64b 1" >>confdefs.h + +fi + +if test "$enable_isochronous" != no; then + +$as_echo "#define HAVE_ISOCHRONOUS 1" >>confdefs.h + +fi + +if test "$enable_fastsampling" = yes; then + +$as_echo "#define HAVE_FASTSAMPLING 1" >>confdefs.h + +fi +if test "$enable_discover_defaultlen" = yes; then + +$as_echo "#define DEFAULT_PAYLOAD_LEN_PER_MTU_DISCOVERY 1" >>confdefs.h + +fi + +if test "$enable_packet_debug" = yes; then + +$as_echo "#define HAVE_PACKET_DEBUG 1" >>confdefs.h + +fi + +case "$ac_cv_host" in +*-mingw32) + LIBS="$LIBS -static-libstdc++ -static";; +*-android) + CFLAGS="$CFLAGS -fPIE"; LDFLAGS="$LDFLAGS -pie";; +esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether make is GNU make" >&5 +$as_echo_n "checking whether make is GNU make... " >&6; } +STRIP_BEGIN= +STRIP_END= +if $ac_make --version 2> /dev/null | grep '^GNU Make ' > /dev/null ; then + STRIP_BEGIN='$(strip $(STRIP_DUMMY)' + STRIP_END=')' + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +STRIP_DUMMY= + + + + +ac_config_files="$ac_config_files Makefile compat/Makefile doc/Makefile include/Makefile src/Makefile man/Makefile" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 +$as_echo_n "checking that generated files are newer than configure... " >&6; } + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 +$as_echo "done" >&6; } + if test -n "$EXEEXT"; then + am__EXEEXT_TRUE= + am__EXEEXT_FALSE='#' +else + am__EXEEXT_TRUE='#' + am__EXEEXT_FALSE= +fi + +if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then + as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${FASTSAMPLING_TRUE}" && test -z "${FASTSAMPLING_FALSE}"; then + as_fn_error $? "conditional \"FASTSAMPLING\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${DISCOVER_DEFAULTLEN_TRUE}" && test -z "${DISCOVER_DEFAULTLEN_FALSE}"; then + as_fn_error $? "conditional \"DISCOVER_DEFAULTLEN\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${THREAD_DEBUG_TRUE}" && test -z "${THREAD_DEBUG_FALSE}"; then + as_fn_error $? "conditional \"THREAD_DEBUG\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${PACKET_DEBUG_TRUE}" && test -z "${PACKET_DEBUG_FALSE}"; then + as_fn_error $? "conditional \"PACKET_DEBUG\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${CHECKPROGRAMS_TRUE}" && test -z "${CHECKPROGRAMS_FALSE}"; then + as_fn_error $? "conditional \"CHECKPROGRAMS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${ENABLE_STATIC_BIN_TRUE}" && test -z "${ENABLE_STATIC_BIN_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_STATIC_BIN\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${DEBUG_SYMBOLS_TRUE}" && test -z "${DEBUG_SYMBOLS_FALSE}"; then + as_fn_error $? "conditional \"DEBUG_SYMBOLS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then + as_fn_error $? "conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${AF_PACKET_TRUE}" && test -z "${AF_PACKET_FALSE}"; then + as_fn_error $? "conditional \"AF_PACKET\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${TUNTAP_TUN_TRUE}" && test -z "${TUNTAP_TUN_FALSE}"; then + as_fn_error $? "conditional \"TUNTAP_TUN\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${TUNTAP_TAP_TRUE}" && test -z "${TUNTAP_TAP_FALSE}"; then + as_fn_error $? "conditional \"TUNTAP_TAP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepCXX\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# 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 2.1.9, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" +config_commands="$ac_config_commands" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to the package provider." + +_ACEOF +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 2.1.9 +configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2012 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +MKDIR_P='$MKDIR_P' +AWK='$AWK' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# +# INIT-COMMANDS +# +AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "compat/Makefile") CONFIG_FILES="$CONFIG_FILES compat/Makefile" ;; + "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; + "include/Makefile") CONFIG_FILES="$CONFIG_FILES include/Makefile" ;; + "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; + "man/Makefile") CONFIG_FILES="$CONFIG_FILES man/Makefile" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' <conf$$subs.awk | sed ' +/^[^""]/{ + N + s/\n// +} +' >>$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' <confdefs.h | sed ' +s/'"$ac_delim"'/"\\\ +"/g' >>$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac + ac_MKDIR_P=$MKDIR_P + case $MKDIR_P in + [\\/$]* | ?:[\\/]* ) ;; + */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +s&@MKDIR_P@&$ac_MKDIR_P&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi +# Compute "$ac_file"'s index in $config_headers. +_am_arg="$ac_file" +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || +$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$_am_arg" : 'X\(//\)[^/]' \| \ + X"$_am_arg" : 'X\(//\)$' \| \ + X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$_am_arg" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'`/stamp-h$_am_stamp_count + ;; + + :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 +$as_echo "$as_me: executing $ac_file commands" >&6;} + ;; + esac + + + case $ac_file$ac_mode in + "depfiles":C) test x"$AMDEP_TRUE" != x"" || { + # Older Autoconf quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + # TODO: see whether this extra hack can be removed once we start + # requiring Autoconf 2.70 or later. + case $CONFIG_FILES in #( + *\'*) : + eval set x "$CONFIG_FILES" ;; #( + *) : + set x $CONFIG_FILES ;; #( + *) : + ;; +esac + shift + # Used to flag and report bootstrapping failures. + am_rc=0 + for am_mf + do + # Strip MF so we end up with the name of the file. + am_mf=`$as_echo "$am_mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile which includes + # dependency-tracking related rules and includes. + # Grep'ing the whole file directly is not great: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ + || continue + am_dirpart=`$as_dirname -- "$am_mf" || +$as_expr X"$am_mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$am_mf" : 'X\(//\)[^/]' \| \ + X"$am_mf" : 'X\(//\)$' \| \ + X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$am_mf" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + am_filepart=`$as_basename -- "$am_mf" || +$as_expr X/"$am_mf" : '.*/\([^/][^/]*\)/*$' \| \ + X"$am_mf" : 'X\(//\)$' \| \ + X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$am_mf" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + { echo "$as_me:$LINENO: cd "$am_dirpart" \ + && sed -e '/# am--include-marker/d' "$am_filepart" \ + | $MAKE -f - am--depfiles" >&5 + (cd "$am_dirpart" \ + && sed -e '/# am--include-marker/d' "$am_filepart" \ + | $MAKE -f - am--depfiles) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } || am_rc=$? + done + if test $am_rc -ne 0; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "Something went wrong bootstrapping makefile fragments + for automatic dependency tracking. If GNU make was not used, consider + re-running the configure script with MAKE=\"gmake\" (or whatever is + necessary). You can also try re-running configure with the + '--disable-dependency-tracking' option to at least be able to build + the package (albeit without support for automatic dependency tracking). +See \`config.log' for more details" "$LINENO" 5; } + fi + { am_dirpart=; unset am_dirpart;} + { am_filepart=; unset am_filepart;} + { am_mf=; unset am_mf;} + { am_rc=; unset am_rc;} + rm -f conftest-deps.mk +} + ;; + + esac +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..274bb9c --- /dev/null +++ b/configure.ac @@ -0,0 +1,460 @@ +dnl =================================================================== +dnl configure.ac +dnl Process this file with autogen.sh to produce configure files +dnl =================================================================== + + +AC_PREREQ(2.59) +AC_INIT(Iperf,2.1.9) +AC_CONFIG_HEADER([config.h]) +AM_INIT_AUTOMAKE() + +dnl The end user may not have autotools +AM_MAINTAINER_MODE([disable]) + +m4_include([m4/ax_create_stdint_h.m4]) +m4_include([m4/dast.m4]) +m4_include([m4/ax_pthread.m4]) + +AC_ARG_ENABLE(ipv6, AC_HELP_STRING([--disable-ipv6], + [disable ipv6 support (default is autodetect)]), + ac_cv_have_ipv6=$enable_ipv6) + +AC_ARG_ENABLE(multicast, AC_HELP_STRING([--disable-multicast], + [disable multicast support (default is autodetect)]), + ac_cv_multicast=$enable_multicast) + +AC_ARG_ENABLE(tcpstats, AC_HELP_STRING([--disable-tcpstats], + [disable tcpstats support (default is autodetect)]), + ac_cv_tcpstats=$enable_tcpstats) + +AC_ARG_ENABLE(threads, AC_HELP_STRING([--disable-threads], + [disable thread support (default is autodetect)])) + +AC_ARG_ENABLE(debuginfo, AC_HELP_STRING([--enable-debuginfo], + [enable asserts and debugging info for sockets (default is no)]), + enable_debuginfo=$enableval, + enable_debuginfo=no) + +AC_ARG_ENABLE(web100, AC_HELP_STRING([--disable-web100], + [disable web100 support (default is autodetect)])) + +AC_ARG_ENABLE(kalman, AC_HELP_STRING([--disable-kalman], + [disable kalman delay tuning (default is enable)])) + +AC_ARG_ENABLE(role_reversal_id, AC_HELP_STRING([--disable-role-reversal-id], + [disable role reversal special characters (default is enable)])) + +AC_ARG_ENABLE(default_localonly, AC_HELP_STRING([--enable-default-localonly], + [enforce limiting test traffic to local-only network (via socket SO_DONTROUTE) as the default mode])) + +AC_ARG_ENABLE(seqno64b, AC_HELP_STRING([--disable-seqno64b], + [disable 64 bit sequence numer support (default is enable)])) + +AC_ARG_ENABLE(fastsampling, AC_HELP_STRING([--enable-fastsampling], + [enable support for 100 microsecond report intervals (default is disable)])) +AM_CONDITIONAL([FASTSAMPLING], [test "x$enable_fastsampling" = "xyes"]) + +AC_ARG_ENABLE(discover_defaultlen, AC_HELP_STRING([--enable-discover-defaultlen], + [enable support to set the default payload size after device MTU discovery (default is disable)])) +AM_CONDITIONAL([DISCOVER_DEFAULTLEN], [test "x$enable_discover_defaultlen" = "xyes"]) + +AC_ARG_ENABLE(thread_debug, AC_HELP_STRING([--enable-thread-debug], + [enable support for thread debugging (default is disable)])) +AM_CONDITIONAL([THREAD_DEBUG], [test "x$enable_thread_debug" = "xyes"]) + +AC_ARG_ENABLE(packet_debug, AC_HELP_STRING([--enable-packet-debug], + [enable support for packet level debugging (default is disable)])) +AM_CONDITIONAL([PACKET_DEBUG], [test "x$enable_packet_debug" = "xyes"]) + +AC_ARG_ENABLE(checkprograms, AC_HELP_STRING([--enable-checkprograms], + [enable support for building support programs such as checkdelay, checkpdfs, etc. (default is disable)])) +AM_CONDITIONAL([CHECKPROGRAMS], [test "x$enable_checkprograms" = "xyes"]) + +AC_ARG_ENABLE([static-bin], + AS_HELP_STRING([--enable-static-bin], [link iperf binary statically]), + [enable_static_bin=yes], + [:]) +AM_CONDITIONAL([ENABLE_STATIC_BIN], [test x$enable_static_bin = xno]) + +AS_IF([test "x$enable_static_bin" = xyes], + [CFLAGS="$CFLAGS --static"; CXXFLAGS="$CXXFLAGS --static"; LDFLAGS="$LDFLAGS --static"] + []) + +AC_ARG_ENABLE(debug_symbols, +AS_HELP_STRING([--enable-debug-symbols], + [enable debugging with symbols, default: no]), +[case "${enableval}" in + yes) debug_symbols=true ;; + no) debug_symbols=false ;; + *) AC_MSG_ERROR([bad value ${enableval} for --enable-debug-symbols]) ;; +esac], +[debug_symbols=false]) + +AM_CONDITIONAL(DEBUG_SYMBOLS, test x"$debug_symbols" = x"true") + +dnl AF_PACKET support +AC_ARG_ENABLE(af-packet, + AS_HELP_STRING([--enable-af-packet], [Enable AF_PACKET support [default=yes]]),,[enable_af_packet=yes]) + +AS_IF([test "x$enable_af_packet" = "xyes"], [ + AC_CHECK_DECL([TPACKET_V2], + AC_DEFINE([HAVE_AF_PACKET],[1],[AF_PACKET support is available]), + [enable_af_packet="no"], + [[#include <sys/socket.h> + #include <linux/if_packet.h>]]) + AM_CONDITIONAL([AF_PACKET], [test "x${enable_af_packet}" = "xyes"]) +]) + +dnl TUNTAP_TUN support +AC_ARG_ENABLE(tuntap-tun, + AS_HELP_STRING([--enable-tuntap-tun], [Enable TUNTAP_TUN support [default=yes]]),,[enable_tuntap_tun=yes]) + +AS_IF([test "x$enable_tuntap_tun" = "xyes"], [ + AC_CHECK_DECLS([IFF_TUN], + AC_DEFINE([HAVE_TUNTAP_TUN],[1],[TUNTAP_TUN support is available]), + [enable_tuntap_tun="no"], + [[#include <linux/if_tun.h>]]) + AM_CONDITIONAL([TUNTAP_TUN], [test "x${enable_tuntap_tun}" = "xyes"]) +]) + +dnl TUNTAP_TAP support +AC_ARG_ENABLE(tuntap-tap, + AS_HELP_STRING([--enable-tuntap-tap], [Enable TUNTAP_TAP support [default=yes]]),,[enable_tuntap_tap=yes]) + +AS_IF([test "x$enable_tuntap_tap" = "xyes"], [ + AC_CHECK_DECLS([IFF_TAP], + AC_DEFINE([HAVE_TUNTAP_TAP],[1],[TUNTAP_TAP support is available]), + [enable_tuntap_tap="no"], + [[#include <linux/if_tun.h>]]) + AM_CONDITIONAL([TUNTAP_TAP], [test "x${enable_tuntap_tap}" = "xyes"]) +]) + +dnl =================================================================== +dnl Checks for programs +dnl =================================================================== + +AC_PROG_CXX +AC_PROG_CC +AC_ISC_POSIX +AC_PROG_INSTALL +AC_PROG_MAKE_SET +AC_PROG_RANLIB +AC_LANG(C) +AC_CANONICAL_HOST + +dnl =================================================================== +dnl Checks for libraries. +dnl =================================================================== +AC_CHECK_LIB([rt], [clock_gettime]) + +dnl check for -lpthread + +if test "$enable_threads" != no; then + AX_PTHREAD() + if test "$ax_pthread_ok" = yes; then + AC_DEFINE([HAVE_POSIX_THREAD], 1,) + AC_DEFINE([_REENTRANT], 1,) + fi +fi + +dnl check for -lnsl, -lsocket +AC_SEARCH_LIBS([gethostbyname], [nsl]) +AC_SEARCH_LIBS([socket], [socket], [], + [AC_CHECK_HEADER([winsock2.h],[ + + AC_DEFINE([HAVE_WINSOCK2_H], 1, [Define if winsock2.h exists.]) + if test "$ax_pthread_ok" != yes; then + AC_DEFINE([HAVE_WIN32_THREAD], 1, [Define if using WIN32 threads]) + fi + LIBS="-lws2_32 $LIBS"], + [], + [#include <windows.h>])]) + +dnl Checks for header files. +AC_HEADER_STDC +AC_CHECK_HEADERS([arpa/inet.h libintl.h net/ethernet.h net/if.h sys/ioctl.h sys/sockio.h linux/sockios.h linux/ip.h linux/udp.h linux/if_packet.h linux/filter.h linux/if_tun.h netdb.h netinet/in.h netinet/tcp.h stdlib.h string.h strings.h sys/socket.h sys/time.h syslog.h unistd.h signal.h ifaddrs.h]) + +dnl =================================================================== +dnl Checks for typedefs, structures +dnl =================================================================== + +AC_C_CONST +AC_TYPE_SIZE_T +AC_CHECK_TYPES(ssize_t,,AC_DEFINE_UNQUOTED(ssize_t, int)) +AC_HEADER_TIME +AC_STRUCT_TM + +AC_CHECK_TYPES(int64_t) + +AC_CACHE_CHECK(3rd argument of accept, ac_cv_accept_arg, [ + dnl Try socklen_t (POSIX) + DAST_ACCEPT_ARG(socklen_t) + + dnl Try int (original BSD) + DAST_ACCEPT_ARG(int) + + dnl Try size_t (older standard; AIX) + DAST_ACCEPT_ARG(size_t) + + dnl Try short (shouldn't be) + DAST_ACCEPT_ARG(short) + + dnl Try long (shouldn't be) + DAST_ACCEPT_ARG(long) +]) + +if test -z "$ac_cv_accept_arg" ; then + ac_cv_accept_arg=int +fi + +AC_DEFINE_UNQUOTED([Socklen_t], $ac_cv_accept_arg, [Define 3rd arg of accept]) + +dnl Checks for library functions. +AC_FUNC_MEMCMP +AC_FUNC_SELECT_ARGTYPES +AC_TYPE_SIGNAL +AC_FUNC_STRFTIME +AC_FUNC_VPRINTF +AC_CHECK_FUNCS([atexit memset select strchr strerror strtol strtoll strtod usleep clock_gettime sched_setscheduler sched_yield mlockall setitimer nanosleep clock_nanosleep freopen]) +AC_REPLACE_FUNCS(snprintf inet_pton inet_ntop gettimeofday) +AC_CHECK_DECLS([ENOBUFS, EWOULDBLOCK],[],[],[#include <errno.h>]) +AC_CHECK_DECLS([SIOCGIFMTU],[],[],[ +#ifdef HAVE_LINUX_SOCKIOS_H +#include <linux/sockios.h> +#endif +#ifdef HAVE_SYS_SOCKIO_H +#include <sys/sockio.h> +#endif +]) +AC_CHECK_DECLS([pthread_cancel],[],[],[#include <pthread.h>]) +AC_CHECK_DECLS([CPU_SET],[],[],[ + #define _GNU_SOURCE + #include <sched.h> + ]) +AC_CHECK_DECLS([SIGALRM],[],[],[#include <signal.h>]) + + +in_h=' +#ifdef HAVE_WINSOCK2_H +#define _WIN32_WINNT 0x0501 /* use (at least) WinXP API */ +#define WIN32_LEAN_AND_MEAN /* exclude unnecesary headers */ +#include <windows.h> +#include <winsock2.h> +#include <ws2tcpip.h> +#else +#include <sys/socket.h> +#include <netinet/in.h> +#include <netinet/tcp.h> +#endif +' + +AC_CHECK_DECLS([AF_INET6, SO_TIMESTAMP, SO_SNDTIMEO, SO_REUSEPORT, SO_BINDTODEVICE, MSG_DONTWAIT, + SO_MAX_PACING_RATE, SO_DONTROUTE, IPV6_TCLASS, IP_MULTICAST_ALL, IP_TOS, + MCAST_JOIN_GROUP, MCAST_JOIN_SOURCE_GROUP, IPV6_JOIN_GROUP, IPV6_V6ONLY, + IPV6_ADD_MEMBERSHIP, IPV6_MULTICAST_HOPS, MSG_PEEK, MSG_WAITALL, + TCP_NODELAY, TCP_INFO, TCP_CONNECTION_INFO, TCP_WINDOW_CLAMP, TCP_QUICKACK, + TCP_NOTSENT_LOWAT, TCP_MAXSEG, IP_ADD_MEMBERSHIP, IP_ADD_SOURCE_MEMBERSHIP], + [],[],[$in_h]) + +AC_CHECK_TYPES([struct sockaddr_storage, struct sockaddr_in6, + struct group_source_req, struct ip_mreq, + struct ipv6_mreq, struct ip_mreq_source],,,[$in_h]) + +AC_CHECK_MEMBERS([struct sockaddr_in6.sin6_len, + struct ip_mreq_source.imr_multiaddr.s_addr], [], [],[$in_h]) + +AC_CHECK_MEMBER([struct tcp_info.tcpi_total_retrans], [], [],[ +#include <netinet/in.h> +#include <netinet/tcp.h> +]) + +AC_CHECK_MEMBERS([struct tcp_info.tcpi_total_retrans], [], [],[ +#include <netinet/in.h> +#include <netinet/tcp.h> +]) + +dnl =================================================================== +dnl Check for compiler characteristics + +AC_HEADER_STDBOOL + +AC_C_BIGENDIAN + +dnl =================================================================== +dnl Check for system services +AC_MSG_CHECKING([for gettid syscall]) +AC_TRY_LINK([#include <unistd.h> +#include <sys/syscall.h> +], [syscall(SYS_gettid);], [ok=yes], [ok=no]) +if test "$ok" = "yes"; then + AC_DEFINE(HAVE_GETTID_SYSCALL,1,[Define if syscall(SYS_gettid) available.]) +fi +AC_MSG_RESULT(${ok}) + +dnl check for multicast +if test "$ac_cv_multicast" != no; then + AC_MSG_CHECKING(for multicast support) + ac_cv_multicast=no + if test "$ac_cv_have_decl_IP_ADD_MEMBERSHIP" = yes; then + if test "$ac_cv_type_struct_ip_mreq" = yes; then + ac_cv_multicast=yes + fi + fi + AC_MSG_RESULT($ac_cv_multicast) + if test "$ac_cv_multicast" = yes; then + AC_DEFINE([HAVE_MULTICAST], 1, [Define to enable multicast support]) + fi + AC_MSG_CHECKING(for multicast ssm support) + ac_cv_ssm_multicast=no + if test "$ac_cv_have_decl_MCAST_JOIN_SOURCE_GROUP" = yes || test "$ac_cv_have_decl_IP_ADD_SOURCE_MEMBERSHIP" = yes; then + if test "$ac_cv_type_struct_group_source_req" = yes; then + ac_cv_ssm_multicast=yes + fi + fi + AC_MSG_RESULT($ac_cv_ssm_multicast) + if test "$ac_cv_ssm_multicast" = yes; then + AC_DEFINE([HAVE_SSM_MULTICAST], 1, [Define to enable ssm multicast support]) + fi +fi + +dnl check for tcpstats +if test "$ac_cv_tcpstats" != no; then + AC_MSG_CHECKING(for tcpstats support) + ac_cv_tcpstats=no + if test "$ac_cv_have_decl_TCP_INFO" = yes; then + AC_MSG_CHECKING(for TCP_INFO_TCPI_TOTAL_RETRANS support) + if test "$ac_cv_member_struct_tcp_info_tcpi_total_retrans" = yes; then + ac_cv_tcpstats=yes + fi + fi + if test "$ac_cv_have_decl_TCP_CONNECTION_INFO" = yes; then + ac_cv_tcpstats=yes + fi + AC_MSG_RESULT($ac_cv_tcpstats) + if test "$ac_cv_tcpstats" = yes; then + AC_DEFINE([HAVE_TCP_STATS], 1, [Define to enable tcp stats support]) + fi +fi + +dnl check for IPv6 +if test "$ac_cv_have_ipv6" != no; then + AC_MSG_CHECKING(for IPv6 headers and structures) + ac_cv_have_ipv6=no + if test "$ac_cv_type_struct_sockaddr_storage" = yes; then + if test "$ac_cv_type_struct_sockaddr_in6" = yes; then + if test "$ac_cv_have_decl_AF_INET6" = yes; then + AC_DEFINE([HAVE_IPV6], 1, [Define to enable IPv6 support]) + ac_cv_have_ipv6=yes + fi + fi + fi + AC_MSG_RESULT($ac_cv_have_ipv6) +fi + +if test "$ac_cv_have_ipv6" = yes; then + if test "$ac_cv_multicast" = yes; then + AC_MSG_CHECKING(for IPv6 multicast support) + ac_cv_have_ipv6_multicast=no + if test "$ac_cv_type_struct_ipv6_mreq" = yes; then + if test "$ac_cv_have_decl_IPV6_ADD_MEMBERSHIP" = yes; then + if test "$ac_cv_have_decl_IPV6_MULTICAST_HOPS" = yes; then + AC_DEFINE([HAVE_IPV6_MULTICAST], 1, [Define to enable IPv6 multicast support]) + ac_cv_have_ipv6_multicast=yes + fi + fi + fi + AC_MSG_RESULT($ac_cv_have_ipv6_multicast) + fi +fi + + +if test "$enable_thread_debug" = yes; then + AC_DEFINE([HAVE_THREAD_DEBUG], 1, [Define for thread level debugging of the code]) +else + if test "$enable_debuginfo" = yes; then + AC_DEFINE([DBG_MJZ], 1, [Define if debugging info is desired]) + else + AC_DEFINE([NDEBUG], [1], [Define to disable asserts]) + fi +fi + +if test "$enable_web100" != no; then +if test -e "/proc/web100"; then +if test -d "/proc/web100"; then +if test -e "/proc/web100/header"; then +if test -f "/proc/web100/header"; then +if test -r "/proc/web100/header"; then +AM_PATH_WEB100() +if test "$web100_success" = yes; then +AC_DEFINE([HAVE_WEB100], 1, [Define if Web100 is desired and available]) +fi fi fi fi fi fi +fi + +if test "$enable_kalman" != no; then +AC_DEFINE([HAVE_KALMAN], 1, [Define if Kalman tuning is desired and available]) +fi + +if test "$enable_role_reversal_id" != no; then +AC_DEFINE([HAVE_ROLE_REVERSAL_ID], 1, [Define if role reversal ids are desired ]) +fi + +if test "$enable_default_localonly" = yes; then +AC_DEFINE([HAVE_DEFAULT_DONTROUTE_ON], 1, [Define if limiting test traffic to the local-only network (via socket SO_DONTROUTE) should be the default]) +fi + +if test "$enable_seqno64b" != no; then +AC_DEFINE([HAVE_SEQNO64b], 1, [Define if 64 bit sequence numbers are desired and available]) +fi + +if test "$enable_isochronous" != no; then +AC_DEFINE([HAVE_ISOCHRONOUS], 1, [Define if isochronous traffic option is desired and available]) +fi + +if test "$enable_fastsampling" = yes; then +AC_DEFINE([HAVE_FASTSAMPLING], 1, [Define if fast sampling for report intervals is desired]) +fi +if test "$enable_discover_defaultlen" = yes; then +AC_DEFINE([DEFAULT_PAYLOAD_LEN_PER_MTU_DISCOVERY], 1, [Define if default UDP payload length is based on device MTU and socket buffer size]) +fi + +if test "$enable_packet_debug" = yes; then +AC_DEFINE([HAVE_PACKET_DEBUG], 1, [Define if packet level debugging is desired]) +fi + +case "$ac_cv_host" in +*-mingw32) + dnl Static link on MINGW for standalone DOS executable + LIBS="$LIBS -static-libstdc++ -static";; +*-android) + dnl Android requires PIE + CFLAGS="$CFLAGS -fPIE"; LDFLAGS="$LDFLAGS -pie";; +esac + + +dnl GNU make allows us to use the $(strip ...) builtin which eliminates a +dnl large amount of extra whitespace in compile lines. +AC_MSG_CHECKING(whether make is GNU make) +STRIP_BEGIN= +STRIP_END= +if $ac_make --version 2> /dev/null | grep '^GNU Make ' > /dev/null ; then + STRIP_BEGIN='$(strip $(STRIP_DUMMY)' + STRIP_END=')' + AC_MSG_RESULT(yes) +else + AC_MSG_RESULT(no) +fi + +dnl some Make 3.79 $(strip ) versions are broken and require an empty arg +STRIP_DUMMY= +AC_SUBST(STRIP_DUMMY) +AC_SUBST(STRIP_BEGIN) +AC_SUBST(STRIP_END) + +AC_CONFIG_FILES([Makefile + compat/Makefile + doc/Makefile + include/Makefile + src/Makefile + man/Makefile]) +AC_OUTPUT @@ -0,0 +1,529 @@ +#! /bin/sh +# depcomp - compile a program generating dependencies as side-effects + +scriptversion=2005-02-09.22 + +# Copyright (C) 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>. + +case $1 in + '') + echo "$0: No command. Try \`$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: depcomp [--help] [--version] PROGRAM [ARGS] + +Run PROGRAMS ARGS to compile a file, generating dependencies +as side-effects. + +Environment variables: + depmode Dependency tracking mode. + source Source file read by `PROGRAMS ARGS'. + object Object file output by `PROGRAMS ARGS'. + DEPDIR directory where to store dependencies. + depfile Dependency file to output. + tmpdepfile Temporary file to use when outputing dependencies. + libtool Whether libtool is used (yes/no). + +Report bugs to <bug-automake@gnu.org>. +EOF + exit $? + ;; + -v | --v*) + echo "depcomp $scriptversion" + exit $? + ;; +esac + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi + +# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. +depfile=${depfile-`echo "$object" | + sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. + "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz +## The second -e expression handles DOS-style file names with drive letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the `deleted header file' problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. + tr ' ' ' +' < "$tmpdepfile" | +## Some versions of gcc put a space before the `:'. On the theory +## that the space means something, we add a space to the output as +## well. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like `#:fec' to the end of the + # dependency line. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ + tr ' +' ' ' >> $depfile + echo >> $depfile + + # The second pass generates a dummy entry for each header file. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> $depfile + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. In older versions, this file always lives in the + # current directory. Also, the AIX compiler puts `$object:' at the + # start of each line; $object doesn't have directory information. + # Version 6 uses the directory in both cases. + stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'` + tmpdepfile="$stripped.u" + if test "$libtool" = yes; then + "$@" -Wc,-M + else + "$@" -M + fi + stat=$? + + if test -f "$tmpdepfile"; then : + else + stripped=`echo "$stripped" | sed 's,^.*/,,'` + tmpdepfile="$stripped.u" + fi + + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + + if test -f "$tmpdepfile"; then + outname="$stripped.o" + # Each line is of the form `foo.o: dependent.h'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile" + sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile" + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +icc) + # Intel's C compiler understands `-MD -MF file'. However on + # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c + # ICC 7.0 will fill foo.d with something like + # foo.o: sub/foo.c + # foo.o: sub/foo.h + # which is wrong. We want: + # sub/foo.o: sub/foo.c + # sub/foo.o: sub/foo.h + # sub/foo.c: + # sub/foo.h: + # ICC 7.1 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using \ : + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form `foo.o: dependent.h', + # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | + sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +tru64) + # The Tru64 compiler uses -MD to generate dependencies as a side + # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in `foo.d' instead, so we check for that too. + # Subdirectories are respected. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + + if test "$libtool" = yes; then + # With Tru64 cc, shared objects can also be used to make a + # static library. This mecanism is used in libtool 1.4 series to + # handle both shared and static libraries in a single compilation. + # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. + # + # With libtool 1.5 this exception was removed, and libtool now + # generates 2 separate objects for the 2 libraries. These two + # compilations output dependencies in in $dir.libs/$base.o.d and + # in $dir$base.o.d. We have to check for both files, because + # one of the two compilations can be disabled. We should prefer + # $dir$base.o.d over $dir.libs/$base.o.d because the latter is + # automatically cleaned when .libs/ is deleted, while ignoring + # the former would cause a distcleancheck panic. + tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 + tmpdepfile2=$dir$base.o.d # libtool 1.5 + tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 + tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 + "$@" -Wc,-MD + else + tmpdepfile1=$dir$base.o.d + tmpdepfile2=$dir$base.d + tmpdepfile3=$dir$base.d + tmpdepfile4=$dir$base.d + "$@" -MD + fi + + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + # That's a tab and a space in the []. + sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + test -z "$dashmflag" && dashmflag=-M + # Require at least two characters before searching for `:' + # in the target name. This is to cope with DOS-style filenames: + # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. + "$@" $dashmflag | + sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + tr ' ' ' +' < "$tmpdepfile" | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + "$@" || exit $? + # Remove any Libtool call + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + # X makedepend + shift + cleared=no + for arg in "$@"; do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + # Strip any option that makedepend may not understand. Remove + # the object too, otherwise makedepend will parse it as a source file. + -*|$object) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix="`echo $object | sed 's/^.*\././'`" + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + sed '1,2d' "$tmpdepfile" | tr ' ' ' +' | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + "$@" -E | + sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | + sed '$ s: \\$::' > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o, + # because we must use -o when running libtool. + "$@" || exit $? + IFS=" " + for arg + do + case "$arg" in + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" + echo " " >> "$depfile" + . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 0000000..41ae70e --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1 @@ +EXTRA_DIST = index.html ui_license.html dast.gif diff --git a/doc/Makefile.in b/doc/Makefile.in new file mode 100644 index 0000000..18f2dde --- /dev/null +++ b/doc/Makefile.in @@ -0,0 +1,428 @@ +# Makefile.in generated by automake 1.16.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = doc +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/m4/dast.m4 $(top_srcdir)/m4/ax_pthread.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +STRIP_BEGIN = @STRIP_BEGIN@ +STRIP_DUMMY = @STRIP_DUMMY@ +STRIP_END = @STRIP_END@ +VERSION = @VERSION@ +WEB100_CFLAGS = @WEB100_CFLAGS@ +WEB100_CONFIG = @WEB100_CONFIG@ +WEB100_LIBS = @WEB100_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +EXTRA_DIST = index.html ui_license.html dast.gif +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu doc/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic cscopelist-am \ + ctags-am distclean distclean-generic distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ + pdf-am ps ps-am tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/doc/dast.gif b/doc/dast.gif Binary files differnew file mode 100644 index 0000000..58110da --- /dev/null +++ b/doc/dast.gif diff --git a/doc/index.html b/doc/index.html new file mode 100644 index 0000000..438a020 --- /dev/null +++ b/doc/index.html @@ -0,0 +1,758 @@ +<HTML> +<HEAD> +<TITLE>Iperf version 2.0.0</TITLE> +<!-- $Id: index.html,v 1.1.1.1 2004/05/18 01:50:44 kgibbs Exp $ --> +</HEAD> + +<BODY BGCOLOR="#FFFFFF" LINK="#006633" VLINK="#669900" ALINK="#669966"> + +<CENTER> +<P><IMG SRC="dast.gif" + ALT="Distributed Applications Support Team"></P> +</CENTER> + +<H1>Iperf version 2.0.0</H1> + +<H3>May 2004</H3> + +<HR><!-- ----- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --> + +<H3>NLANR applications support +<BR><A HREF="http://dast.nlanr.net/">http://dast.nlanr.net/</A> +<BR><A HREF="mailto:dast@nlanr.net"><dast@nlanr.net></A> +</H3> +<P><FONT face="arial,helvetica"> +<H1>Iperf User Docs</H1> +<H4>Mark Gates<br> + Ajay Tirumala<BR> + Jon Dugan<BR> + Kevin Gibbs<BR> </H4> + +May 2004 +<P></CENTER> +[<a href="#compiling">Compiling</A> | +<A href="#features">Features</A> | +<A href="#tuningtcp">Tuning a TCP connection</A> | +<A href="#tuningudp">Tuning a UDP connection</A> | +<A href="#multicast">Running multicast servers and clients</A> | +<A href="#ipv6">IPv6 Mode</A> | +<A href="#repmode">Representative Streams</A> | +<A href="#daemon"> Running Iperf as a daemon</A> | +<!--<A href="#adaptive">Adaptive Window Sizes</A> | --> +<A href="#service">Running Iperf as a Windows Service</A> ] +<HR> +<!-- ----- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --> +<H2><A name=compiling></A>Compiling</H2> + +Once you have the distribution, on UNIX, +unpack it using gzip and tar. That will create a new directory +'iperf-<version#>' with the source files and documentation. +<P> + +Iperf compiles cleanly on many systems including Linux, SGI IRIX, HP-UX, +Solaris, AIX, and Cray UNICOS. Use '<TT>make</TT>' to configure for your OS and +compile the source code. + +<BLOCKQUOTE><PRE> + +gunzip -c iperf-<version>.tar.gz | tar -xvf - +cd iperf-<version> +./configure +make + +</PRE></BLOCKQUOTE> + +To install iperf, use '<TT>make install</TT>', +which will ask you where to install it. To recompile, the easiest way is to +start over. Do '<TT>make distclean</TT>' then '<TT>./configure; make</TT>'. See the Makefile +for more options. +<P> + +If you have problems, please report them to <A href="mailto:dast@nlanr.net">dast@nlanr.net</A> and +we will try to fix them quickly. <BR> + +<HR> +<!-- ----- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --> + +<H2><A name=features></A>Features</H2> +<UL> + <LI>TCP + <UL> + <LI>Measure bandwidth + <LI>Report MSS/MTU size and observed read sizes. + <LI>Support for TCP window size via socket buffers. + <LI>Multi-threaded if pthreads or Win32 threads are available. Client and + server can have multiple simultaneous connections. + <!-- <LI>Suggest the optimal window size for a connection where the OS allows + setting window sizes in the granularity of bytes. </LI>--></UL> + <LI>UDP + <UL> + <LI>Client can create UDP streams of specified bandwidth. + <LI>Measure packet loss + <LI>Measure delay jitter + <LI>Multicast capable + <LI>Multi-threaded if pthreads are available. Client and server can have + multiple simultaneous connections. (This doesn't work in Windows.) </LI></UL> + <LI>Where appropriate, options can be specified with K (kilo-) and M (mega-) + suffices. So 128K instead of 131072 bytes. + <LI>Can run for specified time, rather than a set amount of data to transfer. + <LI>Picks the best units for the size of data being reported. + <LI>Server handles multiple connections, rather than quitting after a single + test. + <LI>Print periodic, intermediate bandwidth, jitter, and loss reports at + specified intervals. + <LI>Run the server as a daemon (Check out <A + href="http://www-itg.lbl.gov/nettest">Nettest</A> for running it as a secure + daemon). + <LI>Run the server as a Windows NT Service + <LI>Use representative streams to test out how link layer compression affects + your achievable bandwidth. + +<!-- <LI>A library of <A + href="lib.html">useful functions and C++ + classes.</A> </LI> +--> +</UL> +<HR> +<!-- ----- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --><BR> + +<TABLE cellPadding=3 border=1> + <TBODY> + <TR vAlign=top> + <TH align=left>Command line option</TH> + <TH align=left>Environment variable option</TH> + <TH align=left>Description</TH></TR> + <TR> + <TH bgColor=#cccccc colSpan=3>Client and Server options</TH></TR> + <TR vAlign=top> + <TD><A name=format></A><TT>-f, --format <I>[bkmaBKMA]</I></TT></TD> + <TD><TT>$IPERF_FORMAT</TT></TD> + <TD>A letter specifying the format to print bandwidth numbers in. + Supported formats are + <PRE> + 'b' = bits/sec 'B' = Bytes/sec + 'k' = Kbits/sec 'K' = KBytes/sec + 'm' = Mbits/sec 'M' = MBytes/sec + 'g' = Gbits/sec 'G' = GBytes/sec + 'a' = adaptive bits/sec 'A' = adaptive Bytes/sec + </PRE> + The adaptive formats choose between kilo- and mega- as appropriate. Fields + other than bandwidth always print bytes, but otherwise follow the + requested format. Default is 'a'. <BR><I>NOTE:</I> here Kilo = 1024, + Mega = 1024^2 and Giga = 1024^3 when dealing with bytes. Commonly in networking, + Kilo = 1000, Mega = 1000^2, and Giga = 1000^3 so we use this when dealing with + bits. If this really bothers you, use -f b and do the math.</TD></TR> + <TR vAlign=top> + <TD><A name=interval></A><TT>-i, --interval <I>#</I></TT></TD> + <TD><TT>$IPERF_INTERVAL</TT></TD> + <TD>Sets the interval time in seconds between periodic bandwidth, jitter, + and loss reports. If non-zero, a report is made every <I>interval</I> + seconds of the bandwidth since the last report. If zero, no periodic + reports are printed. Default is zero.</TD></TR> + <TR vAlign=top> + <TD><A name=len></A><TT>-l, --len <I>#[KM]</I></TT></TD> + <TD><TT>$IPERF_LEN</TT></TD> + <TD>The length of buffers to read or write. Iperf works by writing an + array of <I>len</I> bytes a number of times. Default is 8 KB for TCP, 1470 + bytes for UDP. Note for UDP, this is the datagram size and needs to be lowered when using + IPv6 addressing to 1450 or less to avoid fragmentation. See also the <A + href="#num">-n</A> + and <A + href="#time">-t</A> + options.</TD></TR> + <TR vAlign=top> + <TD><A name=print_mss></A><TT>-m, --print_mss</TT></TD> + <TD><TT>$IPERF_PRINT_MSS</TT></TD> + <TD>Print the reported TCP MSS size (via the TCP_MAXSEG option) and the + observed read sizes which often correlate with the MSS. The MSS is usually + the MTU - 40 bytes for the TCP/IP header. Often a slightly smaller MSS is + reported because of extra header space from IP options. The interface type + corresponding to the MTU is also printed (ethernet, FDDI, etc.). This + option is not implemented on many OSes, but the read sizes may still + indicate the MSS.</TD></TR> + <TR vAlign=top> + <TD><A name=port></A><TT>-p, --port <I>#</I></TT></TD> + <TD><TT>$IPERF_PORT</TT></TD> + <TD>The server port for the server to listen on and the client to connect + to. This should be the same in both client and server. Default is 5001, + the same as ttcp.</TD></TR> + <TR vAlign=top> + <TD><A name=udp></A><TT>-u, --udp</TT></TD> + <TD><TT>$IPERF_UDP</TT></TD> + <TD>Use UDP rather than TCP. See also the <A + href="#bandwidth">-b</A> + option.</TD></TR> + <TR vAlign=top> + <TD><A name=window></A><TT>-w, --window <I>#[KM]</I></TT></TD> + <TD><TT>$TCP_WINDOW_SIZE</TT></TD> + <TD>Sets the socket buffer sizes to the specified value. For TCP, this + sets the TCP window size. For UDP it is just the buffer which datagrams + are received in, and so limits the largest receivable datagram size.</TD></TR> + <TR vAlign=top> + <TD><A name=bind></A><TT>-B, --bind <I>host</I></TT></TD> + <TD><TT>$IPERF_BIND</TT></TD> + <TD>Bind to <I>host</I>, one of this machine's addresses. For the client + this sets the outbound interface. For a server this sets the incoming + interface. This is only useful on multihomed hosts, which have multiple + network interfaces. + <P>For Iperf in UDP server mode, this is also used to bind and join to a + multicast group. Use addresses in the range 224.0.0.0 to 239.255.255.255 + for multicast. See also the <A + href="#ttl">-T</A> + option.</P></TD></TR> + <TR vAlign=top> + <TD><A name=compatibility></A><TT>-C, --compatibility </TT></TD> + <TD><TT>$IPERF_COMPAT</TT></TD> + <TD>Compatibility mode allows for use with older version of iperf. This mode + is not required for interoperability but it is highly recommended. In + some cases when using representative streaming you could cause a 1.7 server + to crash or cause undesired connection attempts.</P></TD></TR> + <TR vAlign=top> + <TD><A name=mss></A><TT>-M, --mss <I>#[KM}</I></TT></TD> + <TD><TT>$IPERF_MSS</TT></TD> + <TD>Attempt to set the TCP maximum segment size (MSS) via the TCP_MAXSEG + option. The MSS is usually the MTU - 40 bytes for the TCP/IP header. For + ethernet, the MSS is 1460 bytes (1500 byte MTU). This option is not + implemented on many OSes.</TD></TR> + <TR vAlign=top> + <TD><A name=nodelay></A><TT>-N, --nodelay</TT></TD> + <TD><TT>$IPERF_NODELAY</TT></TD> + <TD>Set the TCP no delay option, disabling Nagle's algorithm. Normally + this is only disabled for interactive applications like telnet.</TD></TR> + <TR> + <TD><TT>-V </TT>(from v1.6 or higher)</TD> + <TD>.</TD> + <TD>Bind to an IPv6 address <BR>Server side: <BR>$ iperf -s -V + <P>Client side: <BR>$ iperf -c <Server IPv6 Address> -V + <BR> </P>Note: On version 1.6.3 and later a specific IPv6 Address does + not need to be bound with the <A href="#bind">-B</A> option, previous 1.6 + versions do. Also on most OSes using this option will also respond to IPv4 + clients using IPv4 mapped addresses.</TD></TR> + <TR> + <TH bgColor=#cccccc colSpan=3>Server specific options</TH></TR> + <TR vAlign=top> + <TD><A name=server></A><TT>-s, --server</TT></TD> + <TD><TT>$IPERF_SERVER</TT></TD> + <TD>Run Iperf in server mode.</TD></TR> + <TR> + <TD><TT>-D </TT> (from v1.2 or higher)</TD> + <TD>.</TD> + <TD>Run the server as a daemon (Unix platforms) <BR>On Win32 platforms + where services are available, Iperf will start running as a service.</TD></TR> + <TR> + <TD><TT>-R </TT>(only for Windows, from v1.2 or higher)</TD> + <TD>.</TD> + <TD>Remove the Iperf service (if it's running). </TD></TR><TR> + <TD><TT>-o </TT>(only for Windows, from v1.2 or higher)</TD> + <TD>.</TD> + <TD>Redirect output to given file. </TD></TR> + <TR vAlign=top> + <TD><A name=sclient></A><TT>-c, --client <I>host</I></TT></TD> + <TD><TT>$IPERF_CLIENT</TT></TD> + <TD> If Iperf is in server mode, then specifying a host with -c + will limit the connections that Iperf will accept to the + <I>host</I> specified. Does not work well for UDP.</TD></TR> + <TR vAlign=top> + <TD><A name=sparallel></A><TT>-P, --parallel <I>#</I></TT></TD> + <TD><TT>$IPERF_PARALLEL</TT></TD> + <TD>The number of connections to handle by the server before + closing. Default is 0 (which means to accept connections forever).</TD></TR> + <TR> + <TH bgColor=#cccccc colSpan=3>Client specific options</TH></TR> + <TR vAlign=top> + <TD><A name=bandwidth></A><TT>-b, --bandwidth <I>#[KM]</I></TT></TD> + <TD><TT>$IPERF_BANDWIDTH</TT></TD> + <TD>The UDP bandwidth to send at, in bits/sec. This implies the -u option. + Default is 1 Mbit/sec.</TD></TR> + <TR vAlign=top> + <TD><A name=client></A><TT>-c, --client <I>host</I></TT></TD> + <TD><TT>$IPERF_CLIENT</TT></TD> + <TD>Run Iperf in client mode, connecting to an Iperf server running on + <I>host</I>.</TD></TR> + <TR vAlign=top> + <TD><A name=dualtest></A><TT>-d, --dualtest </TT></TD> + <TD><TT>$IPERF_DUALTEST</TT></TD> + <TD>Run Iperf in dual testing mode. This will cause the server to connect + back to the client on the port specified in the + <A href="#listenport">-L</A> option (or defaults + to the port the client connected to the server on). This is done immediately + therefore running the tests simultaneously. If you want an alternating + test try <A href="#tradeoff">-r.</A></TD></TR> + <TR vAlign=top> + <TD><A name=num></A><TT>-n, --num <I>#[KM]</I></TT></TD> + <TD><TT>$IPERF_NUM</TT></TD> + <TD>The number of buffers to transmit. Normally, Iperf sends for 10 + seconds. The -n option overrides this and sends an array of <I>len</I> + bytes <I>num</I> times, no matter how long that takes. See also the <A + href="#len">-l</A> + and <A + href="#time">-t</A> + options.</TD></TR> + <TR vAlign=top> + <TD><A name=tradeoff></A><TT>-r, --tradeoff </TT></TD> + <TD><TT>$IPERF_TRADEOFF</TT></TD> + <TD>Run Iperf in tradeoff testing mode. This will cause the server to connect + back to the client on the port specified in the + <A href="#listenport">-L</A> option (or defaults + to the port the client connected to the server on). This is done following + the client connection termination, therefore running the tests + alternating. If you want an simultaneous test try + <A href="#dualtest">-d.</A></TD></TR> + <TR vAlign=top> + <TD><A name=time></A><TT>-t, --time <I>#</I></TT></TD> + <TD><TT>$IPERF_TIME</TT></TD> + <TD>The time in seconds to transmit for. Iperf normally works by + repeatedly sending an array of <I>len</I> bytes for <I>time</I> seconds. + Default is 10 seconds. See also the <A + href="#len">-l</A> + and <A + href="#num">-n</A> + options.</TD></TR> + <TR vAlign=top> + <TD><A name=listenport></A><TT>-L, --listenport <I>#</I></TT></TD> + <TD><TT>$IPERF_LISTENPORT</TT></TD> + <TD>This specifies the port that the server will connect back to the + client on. It defaults to the port used to connect to the server + from the client.</TD></TR> + <TR vAlign=top> + <TD><A name=parallel></A><TT>-P, --parallel <I>#</I></TT></TD> + <TD><TT>$IPERF_PARALLEL</TT></TD> + <TD>The number of simultaneous connections to make to the server. Default + is 1. Requires thread support on both the client and server.</TD></TR> + <TR vAlign=top> + <TD><A name=tos></A><TT>-S, --tos <I>#</I></TT></TD> + <TD><TT>$IPERF_TOS</TT></TD> + <TD>The type-of-service for outgoing packets. (Many routers ignore the TOS + field.) You may specify the value in hex with a '0x' prefix, in octal with + a '0' prefix, or in decimal. For example, '0x10' hex = '020' octal = '16' + decimal. The TOS numbers specified in RFC 1349 are: + <PRE> + IPTOS_LOWDELAY minimize delay 0x10 + IPTOS_THROUGHPUT maximize throughput 0x08 + IPTOS_RELIABILITY maximize reliability 0x04 + IPTOS_LOWCOST minimize cost 0x02 + + </PRE> + </TD></TR> + <TR vAlign=top> + <TD><A name=ttl></A><TT>-T, --ttl <I>#</I></TT></TD> + <TD><TT>$IPERF_TTL</TT></TD> + <TD>The time-to-live for outgoing multicast packets. This is essentially + the number of router hops to go through, and is also used for scoping. + Default is 1, link-local.</TD></TR> + <TR> + <TD><TT>-F</TT> (from v1.2 or higher)</TD> + <TD>.</TD> + <TD>Use a representative stream to measure bandwidth, e.g. :- <BR>$ + iperf -c <server address> -F <file-name></TD></TR> + <TR> + <TD><TT>-I </TT>(from v1.2 or higher)</TD> + <TD>.</TD> + <TD>Same as -F, input from stdin.</TD></TR> + <!-- <TR> + <TD><TT>-W </TT>(from v1.2 or higher)</TD> + <TD>.</TD> + <TD>Adaptive Window Sizes. + <BR>Use Iperf to suggest the best Window size for a connection. Iperf will start from a default window size and try to perform a search for the optimal window size</TD></TR> +--> <TR> + <TH bgColor=#cccccc colSpan=3>Miscellaneous options</TH></TR> + <TR vAlign=top> + <TD><A name=help></A><TT>-h, --help</TT></TD> + <TD> </TD> + <TD>Print out a summary of commands and quit.</TD></TR> + <TR vAlign=top> + <TD><A name=version></A><TT>-v, --version</TT></TD> + <TD> </TD> + <TD>Print version information and quit. Prints 'pthreads' if compiled with + POSIX threads, 'win32 threads' if compiled with Microsoft Win32 threads, + or 'single threaded' if compiled without threads.</TD></TR></TBODY></TABLE> +<P> +<HR> +<!-- ----- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --> +<H2><A name=tuningtcp></A>Tuning a TCP connection</H2> + +The primary goal of Iperf +is to help in tuning TCP connections over a particular path. The most +fundamental tuning issue for TCP is the TCP window size, which controls how much +data can be in the network at any one point. If it is too small, the sender will +be idle at times and get poor performance. The theoretical value to use for the +TCP window size is the <I>bandwidth delay product</I>, +<BLOCKQUOTE>bottleneck bandwidth * round trip time</BLOCKQUOTE>In the below +modi4/cyclops example, the bottleneck link is a 45 Mbit/sec DS3 link and the +round trip time measured with ping is 42 ms. The bandwidth delay product is +<BLOCKQUOTE>45 Mbit/sec * 42 ms <BR>= (45e6) * (42e-3) <BR>= 1890000 bits + <BR>= 230 KByte</BLOCKQUOTE>That is a starting point for figuring the best +window size; setting it higher or lower may produce better results. In our +example, buffer sizes over 130K did not improve the performance, despite the +bandwidth delay product of 230K. +<P>Note that many OSes and hosts have upper limits on the TCP window size. These +may be as low as 64 KB, or as high as several MB. Iperf tries to detect when +these occur and give a warning that the actual and requested window sizes are +not equal (as below, though that is due to rounding in IRIX). PSC has a <A +href="http://www.psc.edu/networking/perf_tune.html">list detailing</A> how to +change the default and maximum window sizes for various OSes. For more +information on TCP window sizes, see the <A +href="http://dast.nlanr.net/Guides/GettingStarted/TCP_window_size.html">User's +Guide to TCP Windows.</A> +<P>Here is an example session, between node1 in Illinois and node2 in North +Carolina. These are connected via the vBNS backbone and a 45 Mbit/sec DS3 link. +Notice we improve bandwidth performance by a factor of 3 using proper TCP window +sizes. Use the adaptive window sizes feature on platforms which allow setting +window sizes in the granularity of bytes. +<BLOCKQUOTE> +<PRE> +<B>node2></B> iperf -s +------------------------------------------------------------ +Server listening on TCP port 5001 +TCP window size: 60.0 KByte (default) +------------------------------------------------------------ +[ 4] local <IP Addr node2> port 5001 connected with <IP Addr node1> port 2357 +[ ID] Interval Transfer Bandwidth +[ 4] 0.0-10.1 sec 6.5 MBytes <B><FONT color=#ff0000>5.2 Mbits/sec + +</FONT>node1></B> iperf -c node2 +------------------------------------------------------------ +Client connecting to node1, TCP port 5001 +TCP window size: 59.9 KByte (default) +------------------------------------------------------------ +[ 3] local <IP Addr node1> port 2357 connected with <IP Addr node2> port 5001 +[ ID] Interval Transfer Bandwidth +[ 3] 0.0-10.0 sec 6.5 MBytes 5.2 Mbits/sec</PRE> + <HR> +<PRE><B>node2></B> iperf -s -w 130k +------------------------------------------------------------ +Server listening on TCP port 5001 +TCP window size: 130 KByte +------------------------------------------------------------ +[ 4] local <IP Addr node 2> port 5001 connected with <IP Addr node 1> port 2530 +[ ID] Interval Transfer Bandwidth +[ 4] 0.0-10.1 sec 19.7 MBytes <B><FONT color=#ff0000>15.7 Mbits/sec + +</FONT>node1></B> iperf -c node2 -w 130k +------------------------------------------------------------ +Client connecting to node2, TCP port 5001 +TCP window size: 129 KByte (WARNING: requested 130 KByte) +------------------------------------------------------------ +[ 3] local <IP Addr node1> port 2530 connected with <IP Addr node2> port 5001 +[ ID] Interval Transfer Bandwidth +[ 3] 0.0-10.0 sec 19.7 MBytes 15.8 Mbits/sec</PRE></BLOCKQUOTE>Another +test to do is run parallel TCP streams. If the total aggregate bandwidth is more +than what an individual stream gets, something is wrong. Either the TCP window +size is too small, or the OS's TCP implementation has bugs, or the network +itself has deficiencies. See above for TCP window sizes; otherwise diagnosing +which is somewhat difficult. If Iperf is compiled with pthreads, a single client +and server can test this, otherwise setup multiple clients and servers on +different ports. Here's an example where a single stream gets 16.5 Mbit/sec, but +two parallel streams together get 16.7 + 9.4 = 26.1 Mbit/sec, even when using +large TCP window sizes: +<BLOCKQUOTE><PRE><B>node2></B> iperf -s -w 300k +------------------------------------------------------------ +Server listening on TCP port 5001 +TCP window size: 300 KByte +------------------------------------------------------------ +[ 4] local <IP Addr node2> port 5001 connected with <IP Addr node1> port 6902 +[ ID] Interval Transfer Bandwidth +[ 4] 0.0-10.2 sec 20.9 MBytes <B><FONT color=#ff0000>16.5 Mbits/sec + +</FONT></B>[ 4] local <IP Addr node2> port 5001 connected with <IP Addr node1> port 6911 +[ 5] local <IP Addr node2> port 5001 connected with <IP Addr node2> port 6912 +[ ID] Interval Transfer Bandwidth +[ 5] 0.0-10.1 sec 21.0 MBytes <B><FONT color=#ff0000>16.7 Mbits/sec +</FONT></B>[ 4] 0.0-10.3 sec 12.0 MBytes <B><FONT color=#ff0000> 9.4 Mbits/sec + +</FONT>node1></B> ./iperf -c node2 -w 300k +------------------------------------------------------------ +Client connecting to node2, TCP port 5001 +TCP window size: 299 KByte (WARNING: requested 300 KByte) +------------------------------------------------------------ +[ 3] local <IP Addr node2> port 6902 connected with <IP Addr node1> port 5001 +[ ID] Interval Transfer Bandwidth +[ 3] 0.0-10.2 sec 20.9 MBytes 16.4 Mbits/sec + +<B>node1></B> iperf -c node2 -w 300k -P 2 +------------------------------------------------------------ +Client connecting to node2, TCP port 5001 +TCP window size: 299 KByte (WARNING: requested 300 KByte) +------------------------------------------------------------ +[ 4] local <IP Addr node2> port 6912 connected with <IP Addr node1> port 5001 +[ 3] local <IP Addr node2> port 6911 connected with <IP Addr node1> port 5001 +[ ID] Interval Transfer Bandwidth +[ 4] 0.0-10.1 sec 21.0 MBytes 16.6 Mbits/sec +[ 3] 0.0-10.2 sec 12.0 MBytes 9.4 Mbits/sec</PRE></BLOCKQUOTE>A +secondary tuning issue for TCP is the maximum transmission unit (MTU). To be +most effective, both hosts should support Path MTU Discovery. PSC has a <A +href="http://www.psc.edu/networking/perf_tune.html">list detailing</A> what OSes +support Path MTU Discovery. Hosts without Path MTU Discovery often use 536 as +the MSS, which wastes bandwidth and processing time. Use the -m option to +display what MSS is being used, and see if this matches what you expect. Often +it is around 1460 bytes for ethernet. +<BLOCKQUOTE><PRE><B>node3></B> iperf -s -m +------------------------------------------------------------ +Server listening on TCP port 5001 +TCP window size: 60.0 KByte (default) +------------------------------------------------------------ +[ 4] local <IP Addr node3> port 5001 connected with <IP Addr node4> port 1096 +[ ID] Interval Transfer Bandwidth +[ 4] 0.0- 2.0 sec 1.8 MBytes 6.9 Mbits/sec +[ 4] <B><FONT color=#ff0000>MSS size 1448 bytes (MTU 1500 bytes, ethernet) +</FONT></B>[ 4] Read lengths occurring in more than 5% of reads: +[ 4] 952 bytes read 219 times (16.2%) +[ 4] 1448 bytes read 1128 times (83.6%)</PRE></BLOCKQUOTE>Here +is a host that doesn't support Path MTU Discovery. It will only send and receive +small 576 byte packets. +<BLOCKQUOTE><PRE><B>node4></B> iperf -s -m +------------------------------------------------------------ +Server listening on TCP port 5001 +TCP window size: 32.0 KByte (default) +------------------------------------------------------------ +[ 4] local <IP Addr node4> port 5001 connected with <IP Addr node3> port 13914 +[ ID] Interval Transfer Bandwidth +[ 4] 0.0- 2.3 sec 632 KBytes 2.1 Mbits/sec +<B><FONT color=#ff0000>WARNING: Path MTU Discovery may not be enabled. +</FONT></B>[ 4] <B><FONT color=#ff0000>MSS size 536 bytes (MTU 576 bytes, minimum) +</FONT></B>[ 4] Read lengths occurring in more than 5% of reads: +[ 4] 536 bytes read 308 times (58.4%) +[ 4] 1072 bytes read 91 times (17.3%) +[ 4] 1608 bytes read 29 times (5.5%)</PRE></BLOCKQUOTE>Iperf +supports other tuning options, which were added for exceptional network +situations like HIPPI-to-HIPPI over ATM. <BR> +<HR> +<!-- ----- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --> + +<H2><A name=tuningudp></A>Tuning a UDP connection</H2> + +Iperf creates a constant bit rate UDP stream. This is a very artificial +stream, similar to voice communication but not much else. +<P> + +You will want to adjust the datagram size (-l) to the size your application +uses. +<P> + +The server detects UDP datagram loss by ID numbers in the datagrams. Usually +a UDP datagram becomes several IP packets. Losing a single IP packet will lose +the entire datagram. To measure packet loss instead of datagram loss, make the +datagrams small enough to fit into a single packet, using the -l option. The +default size of 1470 bytes works for ethernet. Out-of-order packets are also +detected. (Out-of-order packets cause some ambiguity in the lost packet count; +Iperf assumes they are not duplicate packets, so they are excluded from the lost +packet count.) Since TCP does not report loss to the user, I find UDP tests +helpful to see packet loss along a path. +<P> + +Jitter calculations are continuously computed by the server, as specified by +RTP in RFC 1889. The client records a 64 bit second/microsecond timestamp in the +packet. The server computes the relative transit time as (server's receive time +- client's send time). The client's and server's clocks do not need to be +synchronized; any difference is subtracted out in the jitter calculation. Jitter +is the smoothed mean of differences between consecutive transit times. +<BLOCKQUOTE><PRE><B>node2></B> iperf -s -u -i 1 +------------------------------------------------------------ +Server listening on UDP port 5001 +Receiving 1470 byte datagrams +UDP buffer size: 60.0 KByte (default) +------------------------------------------------------------ +[ 4] local <IP Addr node2> port 5001 connected with <IP Addr node1> port 9726 +[ ID] Interval Transfer Bandwidth Jitter Lost/Total Datagrams +[ 4] 0.0- 1.0 sec 1.3 MBytes 10.0 Mbits/sec 0.209 ms 1/ 894 (0.11%) +[ 4] 1.0- 2.0 sec 1.3 MBytes 10.0 Mbits/sec 0.221 ms 0/ 892 (0%) +[ 4] 2.0- 3.0 sec 1.3 MBytes 10.0 Mbits/sec 0.277 ms 0/ 892 (0%) +[ 4] 3.0- 4.0 sec 1.3 MBytes 10.0 Mbits/sec 0.359 ms 0/ 893 (0%) +[ 4] 4.0- 5.0 sec 1.3 MBytes 10.0 Mbits/sec 0.251 ms 0/ 892 (0%) +[ 4] 5.0- 6.0 sec 1.3 MBytes 10.0 Mbits/sec 0.215 ms 0/ 892 (0%) +[ 4] 6.0- 7.0 sec 1.3 MBytes 10.0 Mbits/sec 0.325 ms 0/ 892 (0%) +[ 4] 7.0- 8.0 sec 1.3 MBytes 10.0 Mbits/sec 0.254 ms 0/ 892 (0%) +[ 4] 8.0- 9.0 sec 1.3 MBytes 10.0 Mbits/sec 0.282 ms 0/ 892 (0%) +[ 4] 0.0-10.0 sec 12.5 MBytes 10.0 Mbits/sec 0.243 ms 1/ 8922 (0.011%) + +<B>node1></B> iperf -c node2 -u -b 10m +------------------------------------------------------------ +Client connecting to node2, UDP port 5001 +Sending 1470 byte datagrams +UDP buffer size: 60.0 KByte (default) +------------------------------------------------------------ +[ 3] local <IP Addr node1> port 9726 connected with <IP Addr node2> port 5001 +[ ID] Interval Transfer Bandwidth +[ 3] 0.0-10.0 sec 12.5 MBytes 10.0 Mbits/sec +[ 3] Sent 8922 datagrams</PRE></BLOCKQUOTE>Notice the higher jitter due to +datagram reassembly when using larger 32 KB datagrams, each split into 23 +packets of 1500 bytes. The higher datagram loss seen here may be due to the +burstiness of the traffic, which is 23 back-to-back packets and then a long +pause, rather than evenly spaced individual packets. +<BLOCKQUOTE><PRE><B>node2></B> iperf -s -u -l 32k -w 128k -i 1 +------------------------------------------------------------ +Server listening on UDP port 5001 +Receiving 32768 byte datagrams +UDP buffer size: 128 KByte +------------------------------------------------------------ +[ 3] local <IP Addr node2> port 5001 connected with <IP Addr node1> port 11303 +[ ID] Interval Transfer Bandwidth Jitter Lost/Total Datagrams +[ 3] 0.0- 1.0 sec 1.3 MBytes 10.0 Mbits/sec 0.430 ms 0/ 41 (0%) +[ 3] 1.0- 2.0 sec 1.1 MBytes 8.5 Mbits/sec 5.996 ms 6/ 40 (15%) +[ 3] 2.0- 3.0 sec 1.2 MBytes 9.7 Mbits/sec 0.796 ms 1/ 40 (2.5%) +[ 3] 3.0- 4.0 sec 1.2 MBytes 10.0 Mbits/sec 0.403 ms 0/ 40 (0%) +[ 3] 4.0- 5.0 sec 1.2 MBytes 10.0 Mbits/sec 0.448 ms 0/ 40 (0%) +[ 3] 5.0- 6.0 sec 1.2 MBytes 10.0 Mbits/sec 0.464 ms 0/ 40 (0%) +[ 3] 6.0- 7.0 sec 1.2 MBytes 10.0 Mbits/sec 0.442 ms 0/ 40 (0%) +[ 3] 7.0- 8.0 sec 1.2 MBytes 10.0 Mbits/sec 0.342 ms 0/ 40 (0%) +[ 3] 8.0- 9.0 sec 1.2 MBytes 10.0 Mbits/sec 0.431 ms 0/ 40 (0%) +[ 3] 9.0-10.0 sec 1.2 MBytes 10.0 Mbits/sec 0.407 ms 0/ 40 (0%) +[ 3] 0.0-10.0 sec 12.3 MBytes 9.8 Mbits/sec 0.407 ms 7/ 401 (1.7%) + +<B>node1></B> iperf -c node2 -b 10m -l 32k -w 128k +------------------------------------------------------------ +Client connecting to node2, UDP port 5001 +Sending 32768 byte datagrams +UDP buffer size: 128 KByte +------------------------------------------------------------ +[ 3] local <IP Addr node2> port 11303 connected with <IP Addr node1> port 5001 +[ ID] Interval Transfer Bandwidth +[ 3] 0.0-10.0 sec 12.5 MBytes 10.0 Mbits/sec +[ 3] Sent 401 datagrams</PRE><PRE></PRE></BLOCKQUOTE> +<P><A name=multicast></A> +<B><FONT size=+1>Multicast</FONT></B> +<P>To test multicast, run several servers with the bind option (-B, --bind) set +to the multicast group address. Run the client, connecting to the multicast +group address and setting the TTL (-T, --ttl) as needed. Unlike normal TCP and +UDP tests, multicast servers may be started after the client. In that case, +datagrams sent before the server started show up as losses in the first periodic +report (61 datagrams on arno below). +<BLOCKQUOTE><PRE><B>node5></B> iperf -c 224.0.67.67 -u --ttl 5 -t 5 +------------------------------------------------------------ +Client connecting to 224.0.67.67, UDP port 5001 +Sending 1470 byte datagrams +Setting multicast TTL to 5 +UDP buffer size: 32.0 KByte (default) +------------------------------------------------------------ +[ 3] local <IP Addr node5> port 1025 connected with 224.0.67.67 port 5001 +[ ID] Interval Transfer Bandwidth +[ 3] 0.0- 5.0 sec 642 KBytes 1.0 Mbits/sec +[ 3] Sent 447 datagrams + +<B>node5></B> iperf -s -u -B 224.0.67.67 -i 1 +------------------------------------------------------------ +Server listening on UDP port 5001 +Binding to local address 224.0.67.67 +Joining multicast group 224.0.67.67 +Receiving 1470 byte datagrams +UDP buffer size: 32.0 KByte (default) +------------------------------------------------------------ +[ 3] local 224.0.67.67 port 5001 connected with <IP Addr node5> port 1025 +[ ID] Interval Transfer Bandwidth Jitter Lost/Total Datagrams +[ 3] 0.0- 1.0 sec 131 KBytes 1.0 Mbits/sec 0.007 ms 0/ 91 (0%) +[ 3] 1.0- 2.0 sec 128 KBytes 1.0 Mbits/sec 0.008 ms 0/ 89 (0%) +[ 3] 2.0- 3.0 sec 128 KBytes 1.0 Mbits/sec 0.010 ms 0/ 89 (0%) +[ 3] 3.0- 4.0 sec 128 KBytes 1.0 Mbits/sec 0.013 ms 0/ 89 (0%) +[ 3] 4.0- 5.0 sec 128 KBytes 1.0 Mbits/sec 0.008 ms 0/ 89 (0%) +[ 3] 0.0- 5.0 sec 642 KBytes 1.0 Mbits/sec 0.008 ms 0/ 447 (0%) + +<B>node6></B> iperf -s -u -B 224.0.67.67 -i 1 +------------------------------------------------------------ +Server listening on UDP port 5001 +Binding to local address 224.0.67.67 +Joining multicast group 224.0.67.67 +Receiving 1470 byte datagrams +UDP buffer size: 60.0 KByte (default) +------------------------------------------------------------ +[ 3] local 224.0.67.67 port 5001 connected with <IP Addr node5> port 1025 +[ ID] Interval Transfer Bandwidth Jitter Lost/Total Datagrams +[ 3] 0.0- 1.0 sec 129 KBytes 1.0 Mbits/sec 0.778 ms 61/ 151 (40%) +[ 3] 1.0- 2.0 sec 128 KBytes 1.0 Mbits/sec 0.236 ms 0/ 89 (0%) +[ 3] 2.0- 3.0 sec 128 KBytes 1.0 Mbits/sec 0.264 ms 0/ 89 (0%) +[ 3] 3.0- 4.0 sec 128 KBytes 1.0 Mbits/sec 0.248 ms 0/ 89 (0%) +[ 3] 0.0- 4.3 sec 554 KBytes 1.0 Mbits/sec 0.298 ms 61/ 447 (14%)</PRE><PRE><HR width="100%"></PRE></BLOCKQUOTE> +<P><A name=ipv6></A> +<DL> + <DT><B><FONT size=+2>IPv6 Mode</FONT></B> + <DD>Download the IPv6 version of this release.<BR>Get the IPv6 address of the node using the 'ifconfig' command.<BR>Use the <FONT color=#000099>-V</FONT> option to indicate that you are using an IPv6 address Please note that we need to explicitly bind the server address also. + <P>Server side:<BR><FONT color=#000099> $ iperf -s -V</FONT> + <P>Client side:<BR><FONT color=#000099>$ iperf -c <Server IPv6 Address> -V </FONT> + <P>Note: Iperf version 1.6.2 and eariler require a IPv6 address to be explicitly bound + with the <A HREF="#bind">-B</A> option for the server.</P></DD></DL> +<HR> +<P><A name=repmode></A> +<DL> + <DT><B><FONT size=+2>Using Representative Streams to measure + bandwidth</FONT></B> + <DD>Use the -F or -I option. If you want to test how your network performs + with compressed / uncompressed streams, just create representative streams and + use the -F option to test it. This is usually due to the link layer + compressing data. + <P>The -F option is for file input.<BR>The -I option is for input from stdin. + <P>E.g. <BR>Client: $ <FONT color=#000099> iperf -c <server address> -F <file-name><BR></FONT> + <BR>Client: $ <FONT color=#000099> iperf -c <server address> -I </FONT></P></DD></DL> +<P><A name=daemon></A> +<HR> +<DL> + <DT><B><FONT size=+2>Running the server as a daemon</FONT></B> + <DD>Use the -D command line option to run the server as a daemon. Redirect the + output to a file.<BR>E.g. <FONT color=#000099>iperf -s -D > + iperfLog</FONT>. <FONT color=#000000>This will have the Iperf Server running + as a daemon and the server messages will be logged in the file iperfLog. +</DD></DL> +<HR> +<P><A name=service></A> +<DL> + <DT><B><FONT size=+2>Using Iperf as a Service under Win32</FONT></B> + <DD>There are three options for Win32: + <P> + <DL> + <DT>-o outputfilename + <DD>output the messages into the specified file + <DT>-s -D + <DD>install Iperf as a service and run it + <DT>-s -R + <DD>uninstall the Iperf service </DD></DL> + <P>Examples: + <DL> + <DT><FONT color=#3366ff>iperf -s -D -o iperflog.txt</FONT> + <DD>will install the Iperf service and run it. Messages will be reported + into "%windir%\system32\iperflog.txt" + <P></P> + <DT><FONT color=#3366ff>iperf -s -R</FONT> + <DD>will uninstall the Iperf service if it is installed. + <P>Note: If you stop want to restart the Iperf service after having killed + it with the Microsoft Management Console or the Windows Task Manager, make + sure to use the proper OPTION in the service properties dialog. + </P></DD></DL></DD></DL> +<HR> +<!--<P><A name=multicast></A> +<DL> + <DT><B><FONT size=+2>Running the multicast server and client</FONT></B> + <DD>Use the -B option while starting the server to bind it to a multicast + address.<BR>E.g. :-<FONT color=#3366ff>iperf -s -u -B 224.0.55.55</FONT>. + + <P>This will have the Iperf server listening for datagrams (-u) for the + address 224.0.55.55(-B 224.0.55.55). + <P>Now, start a client sending packets to this multicast address. + <P>E.g. : <FONT color=#3366ff>iperf -c 224.0.55.55 -u</FONT>. + This will have a UDP client (-u) sending to the multicast address + 224.0.55.55(-c 224.0.55.55). + <P><FONT color=#000000>Start multiple clients or servers as explained above, + sending data to the same multicast server. (If you have multiple servers + listening on the multicast address, each of the servers will be getting the data) +</P></DD></DL> +<HR>--> +<!--<A name=adaptive></A> +<DL> + <DT><B><FONT size=+2>Adaptive window sizes</FONT></B> + <DD>Use the -W option on the client to run the client with the adaptive window + size. Ensure that the server window size is fairly big for this + option.<BR>E.g.. If the server TCP window size is 8KB, it does not help having + a client TCP window size of 256KB.<BR>256KB Server TCP Window Size should + suffice for most high bandwidth networks. + <P>Client changes the TCP window size using a binary exponential + algorithm. This means that you may notice that TCP window size suggested may + vary according to the traffic in the network, Iperf will suggest the best + window size for the current network scenario. +</DL> +<HR width="100%"> +--><P><!-- ----- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --> +<CENTER> +<P>Copyright 1999,2000,2001,2002,2003,2004 <BR>The Board of Trustees of the University of +Illinois <BR>All rights reserved <BR>See <A +href="ui_license.html">UI License</A> for +complete details.</CENTER> +</BODY> +</HTML> + diff --git a/doc/ui_license.html b/doc/ui_license.html new file mode 100644 index 0000000..c3d8a0c --- /dev/null +++ b/doc/ui_license.html @@ -0,0 +1,90 @@ +<HTML> +<HEAD> +<TITLE>Iperf Copyright</TITLE> +<!-- $Id: ui_license.html,v 1.1.1.1 2004/05/18 01:50:44 kgibbs Exp $ --> +</HEAD> + +<BODY BGCOLOR="#FFFFFF" LINK="#006633" VLINK="#669900" ALINK="#669966"> + +<CENTER> +<P><IMG SRC="dast.gif" + ALT="Distributed Applications Support Team"></P> +</CENTER> + + +<H1 ALIGN=CENTER>Iperf Copyright</H1> + +<HR><!-- ----- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --> + +<CENTER> +Copyright (c) 1999,2000,2001,2002,2003,2004,2005 The Board of Trustees of the University of Illinois<br> +All Rights Reserved. +<P> + +<a href="http://dast.nlanr.net/Projects/Iperf">Iperf performance test</a><BR> +Mark Gates<BR> +Ajay Tirumala<br> +Jim Ferguson<br> +Jon Dugan<br> +Feng Qin<br> +Kevin Gibbs<br> +John Estabrook<BR> +National Laboratory for Applied Network Research <BR> +National Center for Supercomputing Applications <BR> +University of Illinois at Urbana-Champaign <BR> +<a href="http://www.ncsa.uiuc.edu">http://www.ncsa.uiuc.edu</a> +</center> +<P> + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software (Iperf) +and associated documentation files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: +<p> +<ul> +<li>Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimers. +<p> + +<li>Redistributions in binary form must reproduce the above copyright notice, this list + of conditions and the following disclaimers in the documentation and/or other + materials provided with the distribution. +<p> + +<li>Neither the names of the University of Illinois, NCSA, nor the names of its + contributors may be used to endorse or promote products derived from this + Software without specific prior written permission. +</ul> +<p> + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +</pre> + + +<HR><!-- ----- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- --> + +<CENTER> +<P><FONT FACE="helvetica,arial" SIZE="2"> + +<A HREF="mailto:dast@nlanr.net">dast@nlanr.net</A> + +Last modified: Jan 5, 2004<br> + +<A HREF="http://www.nlanr.net">NLANR</a> || +<A HREF="http://dast.nlanr.net">applications support</a> || +<A HREF="http://ncne.nlanr.net">engineering support</a> || +<A HREF="http://moat.nlanr.net">measurement and operations</a> +</FONT></P> +</CENTER> + +</BODY> +</HTML> diff --git a/include/Client.hpp b/include/Client.hpp new file mode 100644 index 0000000..3848e92 --- /dev/null +++ b/include/Client.hpp @@ -0,0 +1,147 @@ +/*--------------------------------------------------------------- + * Copyright (c) 1999,2000,2001,2002,2003 + * The Board of Trustees of the University of Illinois + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software (Iperf) and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the names of the University of Illinois, NCSA, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * National Laboratory for Applied Network Research + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * http://www.ncsa.uiuc.edu + * ________________________________________________________________ + * Client.hpp + * by Mark Gates <mgates@nlanr.net> + * ------------------------------------------------------------------- + * A client thread initiates a connect to the server and handles + * sending and receiving data, then closes the socket. + * ------------------------------------------------------------------- + */ + +#ifndef CLIENT_H +#define CLIENT_H + +#include "Settings.hpp" +#include "Timestamp.hpp" +#include "isochronous.hpp" +#include "Mutex.h" + +/* ------------------------------------------------------------------- */ +class Client { +public: + // stores server hostname, port, UDP/TCP mode, and UDP rate + Client( thread_Settings *inSettings ); + + // destroy the client object + ~Client(); + + // Set up the traffic thread and invokes + // appropriate traffic loop per the protocol + // and type of traffic + void Run( void ); + + // For things like dual tests a server needs to be started by the client, + // The code in src/launch.cpp will invoke this + int StartSynch(void); + void TxDelay(void); + void ConnectPeriodic(void); + bool my_connect(bool close_on_fail); + void mySockInit(void); + bool isConnected(void) const; + int SendFirstPayload(void); + int BarrierClient(struct BarrierMutex *); + void RunBounceBackTCP(void); + struct ReportHeader *myJob; + +private: + inline void WritePacketID(intmax_t); + inline void WriteTcpTxHdr(struct ReportStruct *, int, int); + inline void WriteTcpTxBBHdr(struct ReportStruct *, uint32_t, int); + inline double get_delay_target(void); + void InitTrafficLoop(void); + void SetReportStartTime(void); + inline void SetFullDuplexReportStartTime(void); + void FinishTrafficActions(void); + void AwaitServerFinPacket(void); + bool InProgress(void); + void PostNullEvent(void); + void PostNullEvent(bool isFirst); + void AwaitServerCloseEvent(void); + inline void tcp_shutdown(void); + bool connected; + ReportStruct scratchpad; + ReportStruct *reportstruct; + double delay_lower_bounds; + intmax_t totLen; + bool one_report; + bool apply_first_udppkt_delay; + int udp_payload_minimum; + void myReportPacket(void); + // TCP plain + void RunTCP(void); + // TCP version which supports rate limiting per -b + void RunRateLimitedTCP(void); + void RunNearCongestionTCP(void); +#if HAVE_DECL_TCP_NOTSENT_LOWAT + bool AwaitWriteSelectEventTCP(void); + void RunWriteEventsTCP(void); +#endif + // UDP traffic with isochronous and vbr support + void RunUDPIsochronous(void); + // UDP plain + void RunUDP(void); + // client connect + void PeerXchange(void); + thread_Settings *mSettings; +#if WIN32 + SOCKET mySocket; +#else + int mySocket; +#endif + struct ReporterData *myReport; + Timestamp mEndTime; + Timestamp lastPacketTime; + Timestamp now; + char* readAt; + Timestamp connect_done, connect_start; + Isochronous::FrameCounter *framecounter; + bool isburst; + bool mysock_init_done; + bool peerclose; + Timestamp write_start; +}; // end class Client + +#endif // CLIENT_H diff --git a/include/Condition.h b/include/Condition.h new file mode 100644 index 0000000..6968b29 --- /dev/null +++ b/include/Condition.h @@ -0,0 +1,209 @@ +/*--------------------------------------------------------------- + * Copyright (c) 1999,2000,2001,2002,2003 + * The Board of Trustees of the University of Illinois + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software (Iperf) and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the names of the University of Illinois, NCSA, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * National Laboratory for Applied Network Research + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * http://www.ncsa.uiuc.edu + * ________________________________________________________________ + * + * Condition.h + * by Mark Gates <mgates@nlanr.net> + * ------------------------------------------------------------------- + * An abstract class for waiting on a condition variable. If + * threads are not available, this does nothing. + * ------------------------------------------------------------------- */ + +#ifndef CONDITION_H +#define CONDITION_H + +#include "headers.h" +#include "Mutex.h" +#include "util.h" + +#if defined( HAVE_POSIX_THREAD ) +struct Condition { + pthread_cond_t mCondition; + pthread_mutex_t mMutex; +}; +#elif defined( HAVE_WIN32_THREAD ) +struct Condition { + HANDLE mCondition; + HANDLE mMutex; +}; +#else +struct Condition { + int mCondition; + int mMutex; +}; +#endif + +struct AwaitMutex { + struct Condition await; + int ready; +}; + +struct BarrierMutex { + struct Condition await; + struct timeval release_time; + int count; + int timeout; +}; + +struct ReferenceMutex { + Mutex lock; + int count; + int maxcount; +}; + +#define Condition_Lock( Cond ) Mutex_Lock( &Cond.mMutex ) + +#define Condition_Unlock( Cond ) Mutex_Unlock( &Cond.mMutex ) + + // initialize condition +#if defined( HAVE_POSIX_THREAD ) + #define Condition_Initialize( Cond ) do { \ + Mutex_Initialize( &(Cond)->mMutex ); \ + pthread_cond_init( &(Cond)->mCondition, NULL ); \ + } while ( 0 ) +#elif defined( HAVE_WIN32_THREAD ) + // set all conditions to be broadcast + // unfortunately in Win32 you have to know at creation + // whether the signal is broadcast or not. + #define Condition_Initialize( Cond ) do { \ + Mutex_Initialize( &(Cond)->mMutex ); \ + (Cond)->mCondition = CreateEvent( NULL, 1, 0, NULL ); \ + } while ( 0 ) +#else + #define Condition_Initialize( Cond ) +#endif + + // destroy condition +#if defined( HAVE_POSIX_THREAD ) + #define Condition_Destroy( Cond ) do { \ + pthread_cond_destroy( &(Cond)->mCondition ); \ + Mutex_Destroy( &(Cond)->mMutex ); \ + } while ( 0 ) +#elif defined( HAVE_WIN32_THREAD ) + #define Condition_Destroy( Cond ) do { \ + CloseHandle( (Cond)->mCondition ); \ + Mutex_Destroy( &(Cond)->mMutex ); \ + } while ( 0 ) +#else + #define Condition_Destroy( Cond ) +#endif + +#define Condition_Destroy_Reference(Ref) do { \ + Mutex_Destroy(&(Ref)->lock); \ + } while ( 0 ) + +#if defined (HAVE_CLOCK_GETTIME) + #define SETABSTIME(ts, seconds) do { \ + clock_gettime(CLOCK_REALTIME, &ts); \ + ts.tv_sec += seconds; \ +} while (0) +#else + #define SETABSTIME(ts, seconds) do { \ + struct timeval t1; \ + gettimeofday(&t1, NULL); + ts.tv_sec = t1.tv_sec + inSeconds; \ + ts.tv_nsec = t1.tv_sec * 1000; \ +} while (0) +#endif + + // sleep this thread, waiting for condition signal +#if defined( HAVE_POSIX_THREAD ) + #define Condition_Wait( Cond ) pthread_cond_wait( &(Cond)->mCondition, &(Cond)->mMutex ) +#elif defined( HAVE_WIN32_THREAD ) + // atomically release mutex and wait on condition, + // then re-acquire the mutex + #define Condition_Wait( Cond ) do { \ + SignalObjectAndWait( (Cond)->mMutex, (Cond)->mCondition, INFINITE, 0 ); \ + Mutex_Lock( &(Cond)->mMutex ); \ + } while ( 0 ) +#else + #define Condition_Wait( Cond ) +#endif + + // sleep this thread, waiting for condition signal, + // but bound sleep time by the relative time inSeconds. +#if defined( HAVE_POSIX_THREAD ) + #define Condition_TimedWait( Cond, inSeconds ) do { \ + struct timespec absTimeout; \ + SETABSTIME(absTimeout, inSeconds); \ + pthread_cond_timedwait( &(Cond)->mCondition, &(Cond)->mMutex, &absTimeout ); \ + } while ( 0 ) + #define Condition_TimedLock( Cond, inSeconds ) do { \ + struct timespec absTimeout; \ + SETABSTIME(absTimeout, inSeconds); \ + pthread_mutex_timedlock(&Cond.mMutex, &absTimeout); \ + } while ( 0 ) +#elif defined( HAVE_WIN32_THREAD ) + // atomically release mutex and wait on condition, + // then re-acquire the mutex +#define Condition_TimedWait( Cond, inSeconds ) do { \ + SignalObjectAndWait( (Cond)->mMutex, (Cond)->mCondition, inSeconds*1000, false ); \ + Mutex_Lock( &(Cond)->mMutex ); \ + } while ( 0 ) +#else + #define Condition_TimedWait( Cond, inSeconds ) +#endif + + // send a condition signal to wake one thread waiting on condition + // in Win32, this actually wakes up all threads, same as Broadcast + // use PulseEvent to auto-reset the signal after waking all threads +#if defined( HAVE_POSIX_THREAD ) + #define Condition_Signal( Cond ) pthread_cond_signal( &(Cond)->mCondition ) +#elif defined( HAVE_WIN32_THREAD ) + #define Condition_Signal( Cond ) PulseEvent( (Cond)->mCondition ) +#else + #define Condition_Signal( Cond ) +#endif + + // send a condition signal to wake all threads waiting on condition +#if defined( HAVE_POSIX_THREAD ) + #define Condition_Broadcast( Cond ) pthread_cond_broadcast( &(Cond)->mCondition ) +#elif defined( HAVE_WIN32_THREAD ) + #define Condition_Broadcast( Cond ) PulseEvent( (Cond)->mCondition ) +#else + #define Condition_Broadcast( Cond ) +#endif + +#endif // CONDITION_H diff --git a/include/Extractor.h b/include/Extractor.h new file mode 100644 index 0000000..e017532 --- /dev/null +++ b/include/Extractor.h @@ -0,0 +1,123 @@ +/*--------------------------------------------------------------- + * Copyright (c) 1999,2000,2001,2002,2003 + * The Board of Trustees of the University of Illinois + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software (Iperf) and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the names of the University of Illinois, NCSA, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * National Laboratory for Applied Network Research + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * http://www.ncsa.uiuc.edu + * ________________________________________________________________ + * + * Extractor.h + * by Ajay Tirumala (tirumala@ncsa.uiuc.edu) + * ------------------------------------------------------------------- + * Extract data from a file, used to measure the transfer rates + * for various stream formats. + * + * E.g. Use a gzipped file to measure the transfer rates for + * compressed data + * Use an MPEG file to measure the transfer rates of + * Multimedia data formats + * Use a plain BMP file to measure the transfer rates of + * Uncompressed data + * + * This is beneficial especially in measuring bandwidth across WAN + * links where data compression takes place before data transmission + * ------------------------------------------------------------------- */ + +#ifndef _EXTRACTOR_H +#define _EXTRACTOR_H + +#include <stdlib.h> +#include <stdio.h> +#include "Settings.hpp" + +#ifdef __cplusplus +extern "C" { +#endif + + /** + * Constructor + * @arg fileName Name of the file + * @arg size Block size for reading + */ + void Extractor_Initialize( char *fileName, int size, struct thread_Settings *mSettings ); + + /** + * Constructor + * @arg fp File Pointer + * @arg size Block size for reading + */ + void Extractor_InitializeFile( FILE *fp, int size, struct thread_Settings *mSettings ); + + + /* + * Fetches the next data block from + * the file + * @arg block Pointer to the data read + * @return Number of bytes read + */ + int Extractor_getNextDataBlock( char *data, struct thread_Settings *mSettings ); + + + /** + * Function which determines whether + * the file stream is still readable + * @return true, if readable; false, if not + */ + int Extractor_canRead( struct thread_Settings *mSettings ); + + /** + * This is used to reduce the read size + * Used in UDP transfer to accomodate the + * the header (timestamp) + * @arg delta Size to reduce + */ + void Extractor_reduceReadSize( int delta, struct thread_Settings *mSettings ); + + /** + * Destructor + */ + void Extractor_Destroy( struct thread_Settings *mSettings ); +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif + diff --git a/include/Listener.hpp b/include/Listener.hpp new file mode 100644 index 0000000..92baad7 --- /dev/null +++ b/include/Listener.hpp @@ -0,0 +1,101 @@ +/*--------------------------------------------------------------- + * Copyright (c) 1999,2000,2001,2002,2003 + * The Board of Trustees of the University of Illinois + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software (Iperf) and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the names of the University of Illinois, NCSA, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * National Laboratory for Applied Network Research + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * http://www.ncsa.uiuc.edu + * ________________________________________________________________ + * + * Listener.hpp + * by Mark Gates <mgates@nlanr.net> + * ------------------------------------------------------------------- + * Listener sets up a socket listening on the server host. For each + * connected socket that accept() returns, this creates a Server + * socket and spawns a thread for it. + * ------------------------------------------------------------------- */ + +#ifndef LISTENER_H +#define LISTENER_H + +#include "Thread.h" +#include "Settings.hpp" +#include "Timestamp.hpp" + +class Listener; + +class Listener { +public: + // stores server port and TCP/UDP mode + Listener(thread_Settings *inSettings); + // destroy the server object + ~Listener(); + // accepts connections and starts Servers + void Run(void); + +private: + int mClients; + struct ether_header *eth_hdr; + struct iphdr *ip_hdr; + struct udphdr *udp_hdr; + thread_Settings *mSettings; + thread_Settings *server; + Timestamp mEndTime; + bool apply_client_settings_udp(thread_Settings *server); + bool apply_client_settings_tcp(thread_Settings *server); + bool apply_client_settings(thread_Settings *server); + int client_test_ack(thread_Settings *server); + void my_multicast_join(void); + void my_listen(void); + int my_accept(thread_Settings *server); + int udp_accept(thread_Settings *server); + int tuntap_accept(thread_Settings *server); + bool L2_setup(thread_Settings *server, int sockfd); + bool tap_setup(thread_Settings *server, int sockfd); + void UDPSingleServer(thread_Settings *server); + bool test_permit_key(uint32_t flags, thread_Settings *server, int keyoffset); +#if WIN32 + SOCKET ListenSocket; +#else + int ListenSocket; +#endif +}; // end class Listener + +#endif // LISTENER_H diff --git a/include/Locale.h b/include/Locale.h new file mode 100644 index 0000000..65e547e --- /dev/null +++ b/include/Locale.h @@ -0,0 +1,437 @@ +/*--------------------------------------------------------------- + * Copyright (c) 1999,2000,2001,2002,2003 + * The Board of Trustees of the University of Illinois + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software (Iperf) and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the names of the University of Illinois, NCSA, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * National Laboratory for Applied Network Research + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * http://www.ncsa.uiuc.edu + * ________________________________________________________________ + * + * Locale.h + * by Ajay Tirumala <tirumala@ncsa.uiuc.edu> + * & Mark Gates <mgates@nlanr.net> + * ------------------------------------------------------------------- + * Strings and other stuff that is locale specific. + * ------------------------------------------------------------------- */ + +#ifndef LOCALE_H +#define LOCALE_H + +#ifdef __cplusplus +extern "C" { +#endif + + +#define HEADING_FLAG(HEADING) __ ## HEADING ## _print_done +#define HEADING_HDR(HEADING) HEADING ## _header +#define HEADING_PRINT_COND(HEADING) \ + do { \ + if (!HEADING_FLAG(HEADING)) { \ + printf("%s", HEADING_HDR(HEADING)); \ + HEADING_FLAG(HEADING) = 1; \ + } \ + } while(0) + +/* ------------------------------------------------------------------- + * usage + * ------------------------------------------------------------------- */ + +extern const char usage_short[]; + +extern const char usage_long1[]; +extern const char usage_long2[]; + +extern const char version[]; + +/* ------------------------------------------------------------------- + * settings + * ------------------------------------------------------------------- */ + +extern const char separator_line[]; + +extern const char server_port[]; + +extern const char client_port[]; + +extern const char client_report_epoch_start[]; + +extern const char client_report_epoch_start_current[]; + +extern const char server_pid_port[]; + +extern const char server_pid_portrange[]; + +extern const char client_pid_port[]; + +extern const char client_pid_port_dev[]; + +extern const char bind_address[]; + +extern const char bind_address_iface[]; + +extern const char bind_address_iface_taptun[]; + +extern const char multicast_ttl[]; + +extern const char join_multicast[]; + +extern const char join_multicast_sg[]; + +extern const char join_multicast_sg_dev[]; + +extern const char join_multicast_starg_dev[]; + +extern const char client_datagram_size[]; + +extern const char client_datagram_size_tx_sync[]; + +extern const char client_datagram_size_kalman[]; + +extern const char server_datagram_size[]; + +extern const char tcp_window_size[]; + +extern const char udp_buffer_size[]; + +extern const char window_default[]; + +extern const char wait_server_threads[]; + +extern const char client_isochronous[]; + +extern const char client_burstperiod[]; + +extern const char client_burstperiodcount[]; + +extern const char client_bounceback[]; + +extern const char client_bounceback_noqack[]; + +extern const char server_burstperiod[]; + +extern const char client_fq_pacing[]; +/* ------------------------------------------------------------------- + * Legacy reports + * ------------------------------------------------------------------- */ + +extern const char report_bw_header[]; + +extern const char report_sumcnt_bw_header[]; + +extern const char report_bw_format[]; + +extern const char report_sum_bw_format[]; + +extern const char report_sumcnt_bw_format[]; + +extern const char report_bw_read_format[]; + +extern const char report_bw_jitter_loss_header[]; + +extern const char report_bw_jitter_loss_format[]; + +extern const char report_sum_bw_jitter_loss_format[]; + +extern const char report_sumcnt_bw_jitter_loss_header[]; + +extern const char report_sumcnt_bw_jitter_loss_format[]; + +/* ------------------------------------------------------------------- + * Enhanced reports (per -e) + * ------------------------------------------------------------------- */ + +extern const char client_write_size[]; + +extern const char server_read_size[]; + +extern const char report_bw_enhanced_format[]; + +extern const char report_write_enhanced_isoch_format[]; + +extern const char report_write_enhanced_isoch_header[]; + +extern const char report_write_enhanced_isoch_nocwnd_format[]; + +extern const char report_sum_bw_enhanced_format[]; + +extern const char report_bw_read_enhanced_header[]; + +extern const char report_bw_read_enhanced_netpwr_header[]; + +extern const char report_bw_read_enhanced_netpwr_format[]; + +extern const char report_bw_read_enhanced_format[]; + +extern const char report_sum_bw_read_enhanced_format[]; + +extern const char report_sumcnt_bw_read_enhanced_header[]; + +extern const char report_sumcnt_bw_read_enhanced_format[]; + +extern const char report_sumcnt_bw_read_triptime_header[]; + +extern const char report_sumcnt_bw_read_triptime_format[]; + +extern const char report_sumcnt_bw_pps_enhanced_header[]; + +extern const char report_sumcnt_bw_pps_enhanced_format[]; + +extern const char report_triptime_enhanced_format[]; + +extern const char report_bw_write_enhanced_header[]; + +extern const char report_bw_write_enhanced_header[]; + +extern const char report_sumcnt_write_enhanced_write_header[]; + +extern const char report_bw_write_enhanced_format[]; + +extern const char report_write_enhanced_write_header[]; + +extern const char report_write_enhanced_write_format[]; + +extern const char report_write_enhanced_nocwnd_write_format[]; + +extern const char report_bw_write_enhanced_nocwnd_format[]; + +extern const char report_sum_bw_write_enhanced_format[]; + +extern const char report_sumcnt_bw_write_enhanced_header[]; + +extern const char report_sumcnt_bw_write_enhanced_format[]; + +extern const char report_bw_pps_enhanced_header[]; + +extern const char report_bw_pps_enhanced_format[]; + +extern const char report_bw_pps_enhanced_isoch_header[]; + +extern const char report_bw_pps_enhanced_isoch_format[]; + +extern const char report_sum_bw_pps_enhanced_format[]; + +extern const char report_bw_jitter_loss_pps_header[]; + +extern const char report_bw_jitter_loss_pps_format[]; + +extern const char report_bw_jitter_loss_enhanced_header[]; + +extern const char report_bw_jitter_loss_enhanced_format[]; + +extern const char report_bw_jitter_loss_enhanced_isoch_header[]; + +extern const char report_bw_jitter_loss_enhanced_isoch_format[]; + +extern const char report_bw_jitter_loss_enhanced_triptime_header[]; + +extern const char report_bw_jitter_loss_enhanced_triptime_format[]; + +extern const char report_bw_jitter_loss_enhanced_isoch_triptime_header[]; + +extern const char report_bw_jitter_loss_enhanced_isoch_triptime_format[]; + +extern const char report_bw_jitter_loss_suppress_enhanced_format[]; + +extern const char report_sum_bw_jitter_loss_enhanced_format[]; + +extern const char report_sumcnt_bw_jitter_loss_enhanced_format[]; + +extern const char report_bw_sum_fullduplex_format[]; + +extern const char report_bw_sum_fullduplex_enhanced_format[]; + +extern const char report_frame_jitter_loss_enhanced_header[]; + +extern const char report_frame_jitter_loss_enhanced_format[]; + +extern const char report_frame_jitter_loss_suppress_enhanced_format[]; + +extern const char report_frame_tcp_enhanced_header[]; + +extern const char report_burst_read_tcp_header[]; + +extern const char report_burst_read_tcp_format[]; + +extern const char report_burst_read_tcp_final_format[]; + +extern const char report_burst_write_tcp_header[]; + +extern const char report_burst_write_tcp_format[]; + +extern const char report_burst_write_tcp_nocwnd_format[]; + +extern const char report_burst_write_tcp_final_format[]; + +extern const char report_udp_fullduplex_header[]; + +extern const char report_udp_fullduplex_format[]; + +extern const char report_udp_fullduplex_sum_format[]; + +extern const char report_udp_fullduplex_enhanced_format[]; + +extern const char report_sumcnt_udp_fullduplex_header[]; + +extern const char report_sumcnt_udp_fullduplex_format[]; + +extern const char report_client_bb_bw_header[]; + +extern const char report_client_bb_bw_format[]; + +extern const char report_client_bb_bw_triptime_format[]; + +extern const char report_bw_isoch_enhanced_netpwr_header[]; + +extern const char report_bw_isoch_enhanced_netpwr_format[]; + +extern const char report_sumcnt_udp_enhanced_header[]; + +extern const char report_sumcnt_udp_enhanced_format[]; + +extern const char report_sumcnt_udp_triptime_header[]; + +extern const char report_sumcnt_udp_triptime_format[]; + +/* ------------------------------------------------------------------- + * Misc reports + * ------------------------------------------------------------------- */ + +extern const char report_outoforder[]; + +extern const char report_sumcnt_outoforder[]; + +extern const char report_l2statistics[]; + +extern const char report_sum_outoforder[]; + +extern const char report_peer[]; + +extern const char report_peer_dev[]; + +extern const char report_peer_fail[]; + +extern const char report_mss_unsupported[]; + +extern const char report_mss[]; + +extern const char report_default_mss[]; + +extern const char report_datagrams[]; + +extern const char report_sumcnt_datagrams[]; + +extern const char report_sum_datagrams[]; + +extern const char server_reporting[]; + +extern const char reportCSV_peer[]; + +extern const char reportCSV_bw_format[]; + +extern const char reportCSV_bw_read_enhanced_format[]; + +extern const char reportCSV_bw_write_enhanced_format[]; + +extern const char reportCSV_bw_jitter_loss_format[]; + +extern const char reportCSV_bw_jitter_loss_pps_format[]; + +/* ------------------------------------------------------------------- + * warnings + * ------------------------------------------------------------------- */ + +extern const char warn_window_requested[]; + +extern const char warn_window_small[]; + +extern const char warn_delay_large[]; + +extern const char warn_no_pathmtu[]; + +extern const char warn_no_ack[]; + +extern const char warn_ack_failed[]; + +extern const char warn_fileopen_failed[]; + +extern const char unable_to_change_win[]; + +extern const char opt_estimate[]; + +extern const char report_interval_small[]; + +extern const char warn_invalid_server_option[]; + +extern const char warn_invalid_client_option[]; + +extern const char warn_invalid_compatibility_option[]; + +extern const char warn_implied_udp[]; + +extern const char warn_implied_compatibility[]; + +extern const char warn_buffer_too_small[]; + +extern const char warn_invalid_single_threaded[]; + +extern const char warn_invalid_report_style[]; + +extern const char warn_invalid_report[]; + +extern const char warn_server_old[]; + +extern const char warn_test_exchange_failed[]; + +extern const char warn_len_too_small_peer_exchange[]; + +extern const char warn_compat_and_peer_exchange[]; + +extern const char warn_seqno_wrap[]; + +extern const char warn_start_before_now[]; + +extern const char error_starttime_exceeds[]; + +extern const char error_delaytime_exceeds[]; + +#ifdef __cplusplus +} /* end extern "C" */ +#endif +#endif // LOCALE_H diff --git a/include/Makefile.am b/include/Makefile.am new file mode 100644 index 0000000..033fbd3 --- /dev/null +++ b/include/Makefile.am @@ -0,0 +1,2 @@ +EXTRA_DIST = Client.hpp Condition.h Extractor.h active_hosts.h packet_ring.h Listener.hpp Locale.h Makefile.am Mutex.h PerfSocket.hpp Reporter.h Server.hpp Settings.hpp SocketAddr.h Thread.h Timestamp.hpp config.win32.h delay.h gettimeofday.h gnu_getopt.h headers.h inet_aton.h service.h snprintf.h util.h version.h histogram.h isochronous.hpp pdfs.h checksums.h payloads.h gettcpinfo.h dscp.h iperf_formattime.h +DISTCLEANFILES = $(top_builddir)/include/iperf-int.h diff --git a/include/Makefile.in b/include/Makefile.in new file mode 100644 index 0000000..ae4ef10 --- /dev/null +++ b/include/Makefile.in @@ -0,0 +1,430 @@ +# Makefile.in generated by automake 1.16.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = include +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/m4/dast.m4 $(top_srcdir)/m4/ax_pthread.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +STRIP_BEGIN = @STRIP_BEGIN@ +STRIP_DUMMY = @STRIP_DUMMY@ +STRIP_END = @STRIP_END@ +VERSION = @VERSION@ +WEB100_CFLAGS = @WEB100_CFLAGS@ +WEB100_CONFIG = @WEB100_CONFIG@ +WEB100_LIBS = @WEB100_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +EXTRA_DIST = Client.hpp Condition.h Extractor.h active_hosts.h packet_ring.h Listener.hpp Locale.h Makefile.am Mutex.h PerfSocket.hpp Reporter.h Server.hpp Settings.hpp SocketAddr.h Thread.h Timestamp.hpp config.win32.h delay.h gettimeofday.h gnu_getopt.h headers.h inet_aton.h service.h snprintf.h util.h version.h histogram.h isochronous.hpp pdfs.h checksums.h payloads.h gettcpinfo.h dscp.h iperf_formattime.h +DISTCLEANFILES = $(top_builddir)/include/iperf-int.h +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu include/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu include/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic cscopelist-am \ + ctags-am distclean distclean-generic distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ + pdf-am ps ps-am tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/include/Mutex.h b/include/Mutex.h new file mode 100644 index 0000000..2d22dc3 --- /dev/null +++ b/include/Mutex.h @@ -0,0 +1,112 @@ +/*--------------------------------------------------------------- + * Copyright (c) 1999,2000,2001,2002,2003 + * The Board of Trustees of the University of Illinois + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software (Iperf) and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the names of the University of Illinois, NCSA, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * National Laboratory for Applied Network Research + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * http://www.ncsa.uiuc.edu + * ________________________________________________________________ + * + * Mutex.h + * by Mark Gates <mgates@nlanr.net> + * ------------------------------------------------------------------- + * An abstract class for locking a mutex (mutual exclusion). If + * threads are not available, this does nothing. + * ------------------------------------------------------------------- */ +#ifndef MUTEX_H +#define MUTEX_H + +#include "headers.h" + +#if defined( HAVE_POSIX_THREAD ) + typedef pthread_mutex_t Mutex; +#elif defined( HAVE_WIN32_THREAD ) + typedef HANDLE Mutex; +#else + typedef int Mutex; +#endif + +/* ------------------------------------------------------------------- * +class Mutex { +public:*/ + + // initialize mutex +#if defined( HAVE_POSIX_THREAD ) + #define Mutex_Initialize( MutexPtr ) pthread_mutex_init( MutexPtr, NULL ) +#elif defined( HAVE_WIN32_THREAD ) + #define Mutex_Initialize( MutexPtr ) *MutexPtr = CreateMutex( NULL, 0, NULL ) +#else + #define Mutex_Initialize( MutexPtr ) +#endif + + // lock the mutex variable +#if defined( HAVE_POSIX_THREAD ) + #define Mutex_Lock( MutexPtr ) pthread_mutex_lock( MutexPtr ) +#elif defined( HAVE_WIN32_THREAD ) + #define Mutex_Lock( MutexPtr ) WaitForSingleObject( *MutexPtr, INFINITE ) +#else + #define Mutex_Lock( MutexPtr ) +#endif + + // unlock the mutex variable +#if defined( HAVE_POSIX_THREAD ) + #define Mutex_Unlock( MutexPtr ) pthread_mutex_unlock( MutexPtr ) +#elif defined( HAVE_WIN32_THREAD ) + #define Mutex_Unlock( MutexPtr ) ReleaseMutex( *MutexPtr ) +#else + #define Mutex_Unlock( MutexPtr ) +#endif + + // destroy, making sure mutex is unlocked +#if defined( HAVE_POSIX_THREAD ) + #define Mutex_Destroy( MutexPtr ) do { \ + int rc = pthread_mutex_destroy( MutexPtr ); \ + if ( rc == EBUSY ) { \ + Mutex_Unlock( MutexPtr ); \ + pthread_mutex_destroy( MutexPtr ); \ + } \ + } while ( 0 ) +#elif defined( HAVE_WIN32_THREAD ) + #define Mutex_Destroy( MutexPtr ) CloseHandle( *MutexPtr ) +#else + #define Mutex_Destroy( MutexPtr ) +#endif + +#endif // MUTEX_H diff --git a/include/PerfSocket.hpp b/include/PerfSocket.hpp new file mode 100644 index 0000000..0214c08 --- /dev/null +++ b/include/PerfSocket.hpp @@ -0,0 +1,80 @@ +/*--------------------------------------------------------------- + * Copyright (c) 1999,2000,2001,2002,2003 + * The Board of Trustees of the University of Illinois + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software (Iperf) and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the names of the University of Illinois, NCSA, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * National Laboratory for Applied Network Research + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * http://www.ncsa.uiuc.edu + * ________________________________________________________________ + * + * PerfSocket.hpp + * by Mark Gates <mgates@nlanr.net> + * & Ajay Tirumala <tirumala@ncsa.uiuc.edu> + * ------------------------------------------------------------------- + * Changes in version 1.6 + * Incorporates class declarations for fetching data from files + * ------------------------------------------------------------------- */ + + +#ifndef PERFSOCKET_H +#define PERFSOCKET_H + +#include "Mutex.h" +#include "Settings.hpp" +#ifdef __cplusplus +extern "C" { +#endif + +// int timer units is micorseconds +void SetSocketOptions(struct thread_Settings *inSettings); +void SetSocketOptionsSendTimeout(struct thread_Settings *mSettings, int timer); +void SetSocketOptionsReceiveTimeout(struct thread_Settings *mSettings, int timer); +void SetSocketOptionsIPTos (struct thread_Settings *mSettings, int tos); +void setsock_tcp_mss(int inSock, int inMSS); +int getsock_tcp_mss(int inSock); +#ifdef DEFAULT_PAYLOAD_LEN_PER_MTU_DISCOVERY +void checksock_max_udp_payload (struct thread_Settings *inSettings); +#endif + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif // PERFSOCKET_H diff --git a/include/Reporter.h b/include/Reporter.h new file mode 100644 index 0000000..6f97418 --- /dev/null +++ b/include/Reporter.h @@ -0,0 +1,584 @@ +/*--------------------------------------------------------------- + * Copyright (c) 1999,2000,2001,2002,2003 + * The Board of Trustees of the University of Illinois + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software (Iperf) and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the names of the University of Illinois, NCSA, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * National Laboratory for Applied Network Research + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * http://www.ncsa.uiuc.edu + * ________________________________________________________________ + * + * Reporter.h + * by Kevin Gibbs <kgibbs@nlanr.net> + * + * Since version 2.0 this handles all reporting. + * ________________________________________________________________ */ + +#ifndef REPORTER_H +#define REPORTER_H + +#include "headers.h" +#include "Mutex.h" +#include "histogram.h" +#include "packet_ring.h" +#include "gettcpinfo.h" + +// forward declarations found in Settings.hpp +struct thread_Settings; +struct server_hdr; + +#include "Settings.hpp" + +#define NUM_REPORT_STRUCTS 10000 +#define PEERVERBUFSIZE 256 +#define NETPOWERCONSTANT 1e-6 +#define REPORTTXTMAX 80 +#define MINBARRIERTIMEOUT 3 +#define PARTIALPERCENT 0.25 // used to decide if a final partial report should be displayed +// If the minimum latency exceeds the boundaries below +// assume the clocks are not synched and suppress the +// latency output. Units are seconds +#define UNREALISTIC_LATENCYMINMIN -0.01*1e6 +#define UNREALISTIC_LATENCYMINMAX 60*1e6 +#define JITTER_BINCNT 1000000 // 1 million +#define JITTER_BINWIDTH 100 // 100 usecs +#define JITTER_UNITS 1e6 // usecs +#define JITTER_LCI 5 // 5% +#define JITTER_UCI 95 // 95% + +#ifdef __cplusplus +extern "C" { +#endif + +extern struct Condition ReportCond; +extern struct Condition ReportsPending; +extern Mutex transferid_mutex; + +/* + * + * Used for end/end latency measurements + * + */ + +struct MeanMinMaxStats { + double max; + double min; + double sum; + double last; + double mean; + double m2; + double vd; + intmax_t cnt; + intmax_t err; +}; + +#define TCPREADBINCOUNT 8 +struct ReadStats { + intmax_t cntRead; + intmax_t totcntRead; + int bins[TCPREADBINCOUNT]; + int totbins[TCPREADBINCOUNT]; + int binsize; +}; + +struct WriteStats { + intmax_t WriteCnt; + intmax_t WriteErr; + intmax_t totWriteCnt; + intmax_t totWriteErr; + intmax_t totWriteWarn; + struct iperf_tcpstats tcpstats; +}; + +/* + * This struct contains all important information from the sending or + * recieving thread. + */ +#define L2UNKNOWN 0x01 +#define L2LENERR 0x02 +#define L2CSUMERR 0x04 + +enum WriteErrType { + WriteNoErr = 0, + WriteErrAccount, + WriteErrFatal, + WriteErrNoAccount +}; + +struct L2Stats { + intmax_t cnt; + intmax_t unknown; + intmax_t udpcsumerr; + intmax_t lengtherr; + intmax_t tot_cnt; + intmax_t tot_unknown; + intmax_t tot_udpcsumerr; + intmax_t tot_lengtherr; +}; + +struct RunningMMMStats { + struct MeanMinMaxStats current; + struct MeanMinMaxStats total; +}; +/* + * The type field of ReporterData is a bitmask + * with one or more of the following + */ +enum ReportType { + DATA_REPORT = 1, + SUM_REPORT, + SETTINGS_REPORT, + CONNECTION_REPORT, + SERVER_RELAY_REPORT +}; + +enum ReportSubType { + FULLDUPLEXSUM_REPORT = 1, + HOSTSUM_REPORT, + TOTALSUM_REPORT +}; + +union SendReadStats { + struct ReadStats read; + struct WriteStats write; +}; + +// This attributes are shared by all reports +// deep copies are made when creating a new report +// rather than using references +struct ReportCommon { + enum ThreadMode ThreadMode; + enum ReportMode ReportMode; + bool KeyCheck; + int flags; + int flags_extend; + int flags_extend2; + int threads; + unsigned short Port; + unsigned short PortLast; + unsigned short BindPort; + unsigned short ListenPort; + intmax_t AppRate; // -b or -u + uint32_t BurstSize; + int AppRateUnits; + char Format; + int TTL; + int BufLen; + int MSS; + int TCPWin; + int TOS; + int RTOS; +#if HAVE_DECL_TCP_WINDOW_CLAMP + int ClampSize; +#endif +#if HAVE_DECL_TCP_NOTSENT_LOWAT + int WritePrefetch; +#endif + int winsize_requested; + unsigned int FQPacingRate; + int HistBins; + int HistBinsize; + int HistUnits; + double pktIPG; + iperf_sockaddr peer; + Socklen_t size_peer; + iperf_sockaddr local; + Socklen_t size_local; + char* Host; // -c + char* HideHost; + char* Localhost; // -B + char* Ifrname; + char* Ifrnametx; + char* SSMMulticastStr; + char* Congestion; + char* transferIDStr; + char* PermitKey; + int transferID; + double rtt_weight; + double ListenerTimeout; + double FPS; + int bbsize; + int bbhold; + int bbcount; + int jitter_binwidth; +#if WIN32 + SOCKET socket; +#else + int socket; +#if defined(HAVE_LINUX_FILTER_H) && defined(HAVE_AF_PACKET) + int socketdrop; +#endif +#endif +}; + +struct ConnectionInfo { + struct ReportCommon *common; + struct timeval connect_timestamp; + struct timeval txholdbacktime; + struct timeval epochStartTime; + int winsize; + char peerversion[PEERVERBUFSIZE]; + struct MeanMinMaxStats connect_times; + struct iperf_tcpstats tcpinitstats; +}; + +struct ShiftIntCounter { + intmax_t current; + intmax_t prev; +}; + +struct ShiftUintCounter { + uintmax_t current; + uintmax_t prev; +}; + +struct ShiftCounters { + struct ShiftUintCounter Bytes; + struct ShiftIntCounter Lost; + struct ShiftIntCounter OutofOrder; + struct ShiftIntCounter Datagrams; + struct ShiftIntCounter IPG; +}; + +struct IsochStats { + double mFPS; //frames per second + double mMean; //variable bit rate mean + double mVariance; //vbr variance + int mJitterBufSize; //Server jitter buffer size, units is frames + uintmax_t cntFrames; + uintmax_t cntFramesMissed; + uintmax_t cntSlips; + struct ShiftUintCounter slipcnt; + struct ShiftUintCounter framecnt; + struct ShiftUintCounter framelostcnt; + unsigned int mBurstInterval; + unsigned int mBurstIPG; //IPG of packets within the burst + uint32_t frameID; + struct RunningMMMStats transit; + int newburst; +}; + +struct ReportSettings { + struct ReportCommon *common; + iperf_sockaddr peer; + Socklen_t size_peer; + iperf_sockaddr local; + Socklen_t size_local; + int pid; + int sockmaxseg; + struct IsochStats isochstats; + void (*output_handler) (struct ReportSettings *settings); +}; + +// Timestamps +enum TimeStampType { + INTERVAL = 0, + FINALPARTIAL, + TOTAL, + INTERVALPARTIAL +}; + +struct ReportTimeStamps { + double iStart; + double iEnd; + double significant_partial; + struct timeval startTime; + struct timeval matchTime; + struct timeval packetTime; + struct timeval prevpacketTime; + struct timeval prevsendTime; + struct timeval nextTime; + struct timeval intervalTime; + struct timeval IPGstart; + struct timeval nextTCPSampleTime; +}; + +struct TransferInfo { + struct ReportCommon *common; + struct ReportTimeStamps ts; + void (*output_handler) (struct TransferInfo *stats); + int groupID; + int threadcnt; + bool isMaskOutput; + uintmax_t cntBytes; + intmax_t cntError; + intmax_t cntOutofOrder; + intmax_t cntDatagrams; + intmax_t cntIPG; + intmax_t PacketID; + double jitter; + double IPGsum; + struct ShiftCounters total; // Shift counters used to calculate interval reports and hold totals + union SendReadStats sock_callstats; + struct IsochStats isochstats; + struct histogram *latency_histogram; + struct histogram *jitter_histogram; + struct RunningMMMStats transit; + struct RunningMMMStats inline_jitter; // per RTP inline calc + struct histogram *framelatency_histogram; + struct RunningMMMStats frame; // isochronous frame or msg burst + struct histogram *bbrtt_histogram; + struct RunningMMMStats bbrtt; + struct RunningMMMStats bbowdto; + struct RunningMMMStats bbowdfro; + struct RunningMMMStats bbasym; + struct MeanMinMaxStats schedule_error; + struct L2Stats l2counts; + // Packet and frame state info + uint32_t matchframeID; + uint32_t frameID; + char csv_peer[CSVPEERLIMIT]; + bool final; + bool burstid_transition; + bool isEnableTcpInfo; + struct RunningMMMStats write_mmm; + struct histogram *write_histogram; + double iBBrunning; + double fBBrunning; + double iInP; + double fInP; + double iInPVar; + double fInPVar; +}; + +struct SumReport { + struct ReferenceMutex reference; + int threads; + int threads_cntr_fsum; + struct TransferInfo info; + void (*transfer_protocol_sum_handler) (struct TransferInfo *stats, int final); + struct BarrierMutex fullduplex_barrier; + int sum_fd_set; + bool sum_reverse_set; +}; + +struct ReporterData { + // function pointer for per packet processing + void (*packet_handler_pre_report) (struct ReporterData *data, struct ReportStruct *packet); + void (*packet_handler_post_report) (struct ReporterData *data, struct ReportStruct *packet); + void (*transfer_protocol_handler) (struct ReporterData *data, int final); + int (*transfer_interval_handler) (struct ReporterData *data, struct ReportStruct *packet); + + struct PacketRing *packetring; + int reporter_thread_suspends; // used to detect CPU bound systems + + // group sum and full duplext reports + struct SumReport *GroupSumReport; + struct SumReport *FullDuplexReport; + struct TransferInfo info; +}; + +struct ServerRelay { + struct TransferInfo info; + iperf_sockaddr peer; + Socklen_t size_peer; + iperf_sockaddr local; + Socklen_t size_local; +}; + +struct ReportHeader { + enum ReportType type; + enum ReportMode ReportMode; + void *this_report; + struct ReportHeader *next; +}; + +typedef void* (* report_connection)( struct ConnectionInfo*, int ); +typedef void (* report_settings)( struct ReporterData* ); +typedef void (* report_statistics)( struct TransferInfo* ); +typedef void (* report_serverstatistics)( struct ConnectionInfo *, struct TransferInfo* ); + +void SetSumHandlers (struct thread_Settings *inSettings, struct SumReport* sumreport); +struct SumReport* InitSumReport(struct thread_Settings *inSettings, int inID, int fullduplex); +struct ReportHeader* InitIndividualReport(struct thread_Settings *inSettings); +struct ReportHeader* InitConnectionReport(struct thread_Settings *inSettings); +struct ConnectionInfo* InitConnectOnlyReport(struct thread_Settings *thread); +struct ReportHeader *InitSettingsReport(struct thread_Settings *inSettings); +struct ReportHeader* InitServerRelayUDPReport(struct thread_Settings *inSettings, struct server_hdr *server); +void PostReport(struct ReportHeader *reporthdr); +bool ReportPacket (struct ReporterData* data, struct ReportStruct *packet); +int EndJob(struct ReportHeader *reporthdr, struct ReportStruct *packet); +void FreeReport(struct ReportHeader *reporthdr); +void FreeSumReport (struct SumReport *sumreport); +void FreeConnectionReport(struct ConnectionInfo *reporthdr); +void ReportServerUDP(struct thread_Settings *inSettings, struct server_hdr *server); +void ReportConnections(struct thread_Settings *inSettings ); +void reporter_dump_job_queue(void); +void IncrSumReportRefCounter(struct SumReport *sumreport); +int DecrSumReportRefCounter(struct SumReport *sumreport); + +extern struct AwaitMutex reporter_state; +extern struct AwaitMutex threads_start; + +extern report_connection connection_reports[]; +extern report_settings settings_reports[]; +extern report_statistics statistics_reports[]; +extern report_serverstatistics serverstatistics_reports[]; +extern report_statistics multiple_reports[]; + + +// The packet or read/write accounting routines used by the reporter thread +// They're function vectors called from the reporter loop via +// this_ireport->packet_handler_pre_report or this_ireport->packet_handler_post_report +// The vectors are set during report instantiation in Reports.c +// Note that client packet handling is the same for TCP and UDP +void reporter_handle_packet_null(struct ReporterData *data, struct ReportStruct *packet); +void reporter_handle_packet_client(struct ReporterData *data, struct ReportStruct *packet); +void reporter_handle_packet_server_udp(struct ReporterData *data, struct ReportStruct *packet); +void reporter_handle_packet_server_tcp(struct ReporterData *data, struct ReportStruct *packet); +void reporter_handle_packet_bb_client(struct ReporterData *data, struct ReportStruct *packet); +void reporter_handle_packet_bb_server(struct ReporterData *data, struct ReportStruct *packet); + +// Reporter thread's conditional prints of interval reports +// Invoked from the Reporter thread per function vector this_ireport->transfer_interval_handler +// This is set during Report instantiation (found in Reports.c) +// These conditionally, e.g per a sample interval, invoke the transfer protocol handlers +int reporter_condprint_time_interval_report(struct ReporterData *data, struct ReportStruct *packet); +int reporter_condprint_frame_interval_report_client_udp(struct ReporterData *data, struct ReportStruct *packet); +int reporter_condprint_frame_interval_report_server_udp(struct ReporterData *data, struct ReportStruct *packet); +int reporter_condprint_frame_interval_report_server_tcp(struct ReporterData *data, struct ReportStruct *packet); +int reporter_condprint_frame_interval_report_client_tcp(struct ReporterData *data, struct ReportStruct *packet); +int reporter_condprint_burst_interval_report_client_udp(struct ReporterData *data, struct ReportStruct *packet); +int reporter_condprint_burst_interval_report_server_udp(struct ReporterData *data, struct ReportStruct *packet); +int reporter_condprint_burst_interval_report_server_tcp(struct ReporterData *data, struct ReportStruct *packet); +int reporter_condprint_burst_interval_report_client_tcp(struct ReporterData *data, struct ReportStruct *packet); + +// Each report type needs specialized updating prior to printing its report +// These functions realize that updating. They are called by the transfer protocol handler, +// e.g. (*data->transfer_protocol_handler)(data, 0) found in src/Reporter.c +// These update the TransferInfo stats struct which is used during output (e.g. the output handler) +void reporter_transfer_protocol_null(struct ReporterData *data, int final); +void reporter_transfer_protocol_client_tcp(struct ReporterData *data, int final); +void reporter_transfer_protocol_client_bb_tcp(struct ReporterData *data, int final); +void reporter_transfer_protocol_client_udp(struct ReporterData *data, int final); +void reporter_transfer_protocol_server_tcp(struct ReporterData *data, int final); +void reporter_transfer_protocol_server_bb_tcp(struct ReporterData *data, int final); +void reporter_transfer_protocol_server_udp(struct ReporterData *data, int final); +// Function vectors to suppport sum reports +void reporter_transfer_protocol_sum_client_tcp(struct TransferInfo *stats, int final); +void reporter_transfer_protocol_sum_server_tcp(struct TransferInfo *stats, int final); +void reporter_transfer_protocol_sum_client_udp(struct TransferInfo *stats, int final); +void reporter_transfer_protocol_sum_server_udp(struct TransferInfo *stats, int final); +void reporter_transfer_protocol_fullduplex_tcp(struct TransferInfo *stats, int final); +void reporter_transfer_protocol_fullduplex_udp(struct TransferInfo *stats, int final); + +// Report output print routines invoked by the transfer_protocol handler +// Bound in Report instantiation and invoked by the transfer protocol +// handler, using (*stats->output_handler)(stats) +// TCP server +void tcp_output_read(struct TransferInfo *stats); +void tcp_output_read_enhanced(struct TransferInfo *stats); +void tcp_output_read_triptime(struct TransferInfo *stats); +void tcp_output_sum_read(struct TransferInfo *stats); +void tcp_output_sum_read_enhanced(struct TransferInfo *stats); +void tcp_output_sumcnt_read(struct TransferInfo *stats); +void tcp_output_sumcnt_read_enhanced (struct TransferInfo *stats); +void tcp_output_sumcnt_read_triptime (struct TransferInfo *stats); +void tcp_output_frame_read(struct TransferInfo *stats); +void tcp_output_frame_read_triptime(struct TransferInfo *stats); +void tcp_output_burst_read(struct TransferInfo *stats); +void tcp_output_read_enhanced_isoch(struct TransferInfo *stats); +// TCP client +void tcp_output_write(struct TransferInfo *stats); +void tcp_output_burst_write(struct TransferInfo *stats); +void tcp_output_sum_write(struct TransferInfo *stats); +void tcp_output_sumcnt_write(struct TransferInfo *stats); +void tcp_output_write_enhanced (struct TransferInfo *stats); +void tcp_output_write_enhanced_isoch (struct TransferInfo *stats); +void tcp_output_sum_write_enhanced (struct TransferInfo *stats); +void tcp_output_sumcnt_write_enhanced (struct TransferInfo *stats); +void tcp_output_write_enhanced_write (struct TransferInfo *stats); +void tcp_output_write_bb(struct TransferInfo *stats); +// TCP fullduplex +void tcp_output_fullduplex(struct TransferInfo *stats); +void tcp_output_fullduplex_enhanced(struct TransferInfo *stats); +void tcp_output_fullduplex_sum (struct TransferInfo *stats); +// UDP server +void udp_output_read(struct TransferInfo *stats); +void udp_output_read_enhanced(struct TransferInfo *stats); +void udp_output_read_triptime(struct TransferInfo *stats); +void udp_output_read_triptime_isoch(struct TransferInfo *stats); +void udp_output_sum_read(struct TransferInfo *stats); +void udp_output_sum_read_enhanced (struct TransferInfo *stats); +void udp_output_sumcnt(struct TransferInfo *stats); +void udp_output_sumcnt_read_enhanced (struct TransferInfo *stats); +//UDP client +void udp_output_write(struct TransferInfo *stats); +void udp_output_sum_write(struct TransferInfo *stats); +void udp_output_write_enhanced(struct TransferInfo *stats); +void udp_output_write_enhanced_isoch(struct TransferInfo *stats); +void udp_output_sum_write_enhanced (struct TransferInfo *stats); +void udp_output_sumcnt_write(struct TransferInfo *stats); +void udp_output_sumcnt_write_enhanced (struct TransferInfo *stats); +void udp_output_sumcnt_enhanced(struct TransferInfo *stats); +void udp_output_sumcnt_read_triptime(struct TransferInfo *stats); +// UDP full duplex +void udp_output_fullduplex(struct TransferInfo *stats); +void udp_output_fullduplex_enhanced(struct TransferInfo *stats); +void udp_output_fullduplex_sum(struct TransferInfo *stats); + +// CSV output +void udp_output_basic_csv(struct TransferInfo *stats); +void udp_output_enhanced_csv(struct TransferInfo *stats); +void tcp_output_basic_csv(struct TransferInfo *stats); +void tcp_output_read_enhanced_csv(struct TransferInfo *stats); +void tcp_output_write_enhanced_csv(struct TransferInfo *stats); + +// The report output routines that are simpler and aren't related to stats +void reporter_print_connection_report(struct ConnectionInfo *report); +void reporter_print_settings_report(struct ReportSettings *report); +void reporter_print_server_relay_report(struct ServerRelay *report); +void reporter_peerversion (struct ConnectionInfo *report, uint32_t upper, uint32_t lower); +void PrintMSS(struct ReporterData *data); +void reporter_default_heading_flags(int); +void reporter_connect_printf_tcp_final(struct ConnectionInfo *report); + +void write_UDP_AckFIN(struct TransferInfo *stats, int len); + +int reporter_process_transfer_report (struct ReporterData *this_ireport); +int reporter_process_report (struct ReportHeader *reporthdr); + +void setTransferID(struct thread_Settings *inSettings, int role_reversal); +void format_ips_port_string (struct TransferInfo *stats, bool sum); + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif // REPORTER_H diff --git a/include/Server.hpp b/include/Server.hpp new file mode 100644 index 0000000..cca386a --- /dev/null +++ b/include/Server.hpp @@ -0,0 +1,127 @@ +/*--------------------------------------------------------------- + * Copyright (c) 1999,2000,2001,2002,2003 + * The Board of Trustees of the University of Illinois + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software (Iperf) and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the names of the University of Illinois, NCSA, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * National Laboratory for Applied Network Research + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * http://www.ncsa.uiuc.edu + * ________________________________________________________________ + * + * Server.hpp + * by Mark Gates <mgates@nlanr.net> + * ------------------------------------------------------------------- + * A server thread is initiated for each connection accept() returns. + * Handles sending and receiving data, and then closes socket. + * ------------------------------------------------------------------- */ + +#ifndef SERVER_H +#define SERVER_H + + +#include "Settings.hpp" +#include "util.h" +#include "Timestamp.hpp" + +/* ------------------------------------------------------------------- */ +class Server { +public: + // stores server socket, port and TCP/UDP mode + Server(thread_Settings *inSettings); + + // destroy the server object + ~Server(); + + // accepts connection and receives data + void RunUDP(void); + void RunTCP(void); + void RunBounceBackTCP(void); + static void Sig_Int(int inSigno); + +private: + thread_Settings *mSettings; + Timestamp mEndTime; + Timestamp now; + ReportStruct scratchpad; + ReportStruct *reportstruct; + + void InitKernelTimeStamping(void); + bool InitTrafficLoop(void); + inline void SetFullDuplexReportStartTime(void); + inline void SetReportStartTime(); + bool ReadBBWithRXTimestamp (); + int ReadWithRxTimestamp(void); + bool ReadPacketID(int); + void L2_processing(void); + int L2_quintuple_filter(void); + void udp_isoch_processing(int); + bool InProgress(void); + int SkipFirstPayload(void); + void ClientReverseFirstRead(void); + void PostNullEvent(void); + Timestamp connect_done; + bool peerclose; + bool isburst; +#if WIN32 + SOCKET mySocket; + SOCKET myDropSocket; +#else + int mySocket; + int myDropSocket; +#endif + struct ReportHeader *myJob; + struct ReporterData *myReport; + +#if HAVE_DECL_SO_TIMESTAMP + // Structures needed for recvmsg + // Use to get kernel timestamps of packets + struct sockaddr_storage srcaddr; + struct iovec iov[1]; + struct msghdr message; + char ctrl[CMSG_SPACE(sizeof(struct timeval))]; + struct cmsghdr *cmsg; +#endif +#if defined(HAVE_LINUX_FILTER_H) && defined(HAVE_AF_PACKET) + struct ether_header *eth_hdr; + struct iphdr *ip_hdr; + struct udphdr *udp_hdr; +#endif +}; // end class Server + +#endif // SERVER_H diff --git a/include/Settings.hpp b/include/Settings.hpp new file mode 100644 index 0000000..250d3a7 --- /dev/null +++ b/include/Settings.hpp @@ -0,0 +1,665 @@ +/*--------------------------------------------------------------- + * Copyright (c) 1999,2000,2001,2002,2003 + * The Board of Trustees of the University of Illinois + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software (Iperf) and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the names of the University of Illinois, NCSA, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * National Laboratory for Applied Network Research + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * http://www.ncsa.uiuc.edu + * ________________________________________________________________ + * + * Settings.hpp + * by Mark Gates <mgates@nlanr.net> + * & Ajay Tirumala <tirumala@ncsa.uiuc.edu> + * ------------------------------------------------------------------- + * Stores and parses the initial values for all the global variables. + * ------------------------------------------------------------------- + * headers + * uses + * <stdlib.h> + * <assert.h> + * ------------------------------------------------------------------- */ + +#ifndef SETTINGS_H +#define SETTINGS_H + +#include "headers.h" +#include "Thread.h" +#include "Condition.h" +#include "packet_ring.h" + +/* ------------------------------------------------------------------- + * constants + * ------------------------------------------------------------------- */ +#ifdef __cplusplus +extern "C" { +#endif + +/* Smallest report interval supported. Units is microseconds */ +#ifndef HAVE_FASTSAMPLING +#define SMALLEST_INTERVAL 5000 // 5ms +#define SMALLEST_INTERVAL_SEC 0.005 // 5ms +#else +#define SMALLEST_INTERVAL 100 // 100 usec +#define SMALLEST_INTERVAL_SEC 0.0001 // 5ms +#endif + +#define SLOPSECS 2 +// maximum difference allowed between the tx (client) start time and the +// the first receive time (units seconds, requires --trip-times on client) +#define MAXDIFFTIMESTAMPSECS 600 +// maximum difference in seconds to bound --txstart-time +#define MAXDIFFTXSTART 3600 +// maximum difference in seconds to bound --txdelay-time, +// if this is too large and w/o keep-alives the connect may drop +#define MAXDIFFTXDELAY 3600 +// maximum inter packet gap (or write delay) for UDP packets +#define MAXIPGSECS 60 +#define CSVPEERLIMIT ((REPORT_ADDRLEN * 2) + 40) +#define NEARCONGEST_DEFAULT 0.5 +#define DEFAULT_PERMITKEY_LIFE 20.0 // units is seconds +#define TESTEXCHANGETIMEOUT (4 * 1000000) // 4 secs, units is microseconds +#ifndef MAXTTL +#define MAXTTL 255 +#endif +#define DEFAULT_BOUNCEBACK_BYTES 100 +#define SMALL_WRITE_PREFETCH (1024 * 16) + +#define SHALLOW_COPY 1 +#define DEEP_COPY 1 +// server/client mode +enum ThreadMode { + kMode_Unknown = 0, + kMode_Server, + kMode_Client, + kMode_Reporter, + kMode_ReporterClient, + kMode_WriteAckServer, + kMode_WriteAckClient, + kMode_Listener +}; + +// report mode +enum ReportMode { + kReport_Default = 0, + kReport_CSV +}; + +// test mode +enum TestMode { + kTest_Normal = 0, + kTest_DualTest, + kTest_TradeOff, + kTest_Unknown +}; + +// interval reporting mode +enum IntervalMode { + kInterval_None = 0, + kInterval_Time, + kInterval_Frames +}; + +// rate request units +enum RateUnits { + kRate_BW = 0, + kRate_PPS +}; + +#include "Reporter.h" +#include "payloads.h" + +/* + * The thread_Settings is a structure that holds all + * options for a given execution of either a client + * or server. By using this structure rather than + * a global structure or class we can have multiple + * clients or servers running with different settings. + * In version 2.0 and above this structure contains + * all the information needed for a thread to execute + * and contains only C elements so it can be manipulated + * by either C or C++. + */ +struct thread_Settings { + // Pointers + char* mFileName; // -F + char* mHost; // -c + char* mHideHost; + char* mLocalhost; // -B + char* mOutputFileName; // -o + char* mIfrname; // %<device> name (for rx) + char* mIfrnametx; // %<device> name (for tx) + char* mSSMMulticastStr; // --ssm-host + char* mIsochronousStr; // --isochronous + char* mHistogramStr; // --histograms (packets) + char* mTransferIDStr; // + char* mBuf; + FILE* Extractor_file; + + struct ReportHeader* reporthdr; + struct SumReport* mSumReport; + struct SumReport* mFullDuplexReport; + struct thread_Settings *runNow; + struct thread_Settings *runNext; + // int's + int mThreads; // -P + int mTOS; // -S + int mRTOS; // reflected TOS + int mTransferID; + int mConnectRetries; +#if WIN32 + SOCKET mSock; +#else + int mSock; +#endif +#if defined(HAVE_LINUX_FILTER_H) && defined(HAVE_AF_PACKET) + int mSockDrop; +#endif + int Extractor_size; + int mBufLen; // -l + int mWriteAckLen; // --write-ack + int mMSS; // -M + int mTCPWin; // -w + /* flags is a BitMask of old bools + bool mBufLenSet; // -l + bool mCompat; // -C + bool mDaemon; // -D + bool mDomain; // -V + bool mFileInput; // -F or -I + bool mNodelay; // -N + bool mPrintMSS; // -m + bool mRemoveService; // -R + bool mStdin; // -I + bool mStdout; // -o + bool mSuggestWin; // -W + bool mUDP; // -u + bool mMode_time; + bool mReportSettings; + bool mMulticast; + bool mNoSettingsReport; // -x s + bool mNoConnectionReport; // -x c + bool mNoDataReport; // -x d + bool mNoServerReport; // -x + bool mNoMultReport; // -x m + bool mSinlgeClient; // -1 */ + int flags; + int flags_extend; + int flags_extend2; + // enums (which should be special int's) + enum ThreadMode mThreadMode; // -s or -c + enum ReportMode mReportMode; + enum TestMode mMode; // -r or -d + bool clientListener; // set to True if client mode listener per -r or -d + // Hopefully int64_t's + uintmax_t mAppRate; // -b or -u + char mAppRateUnits; // -b is either bw or pps + uintmax_t mAmount; // -n or -t time unit is 10 ms + unsigned int mInterval; // -i integer time units is usec + enum IntervalMode mIntervalMode; + // shorts + unsigned short mListenPort; // -L + unsigned short mPort; // -p + unsigned short mPortLast; // -p last port, e.g. when -p 6001-6010 + unsigned short mBindPort; // -B + // chars + char mFormat; // -f + int mTTL; // -T + char pad1[2]; + // structs or miscellaneous + iperf_sockaddr peer; + Socklen_t size_peer; + iperf_sockaddr local; + Socklen_t size_local; + nthread_t mTID; + int incrdstip; + int incrsrcip; + int incrsrcport; + int connectonly_count; + char* mCongestion; + int mHistBins; + int mHistBinsize; + int mHistUnits; + double mHistci_lower; + double mHistci_upper; +#if defined(HAVE_WIN32_THREAD) + HANDLE mHandle; +#endif + double mFPS; //frames per second + double mMean; //variable bit rate mean + uint32_t mBurstSize; //number of bytes in a burst + int mJitterBufSize; //Server jitter buffer size, units is frames + double mBurstIPG; //Interpacket gap + int l4offset; // used in l2 mode to offset the raw packet + int l4payloadoffset; + int recvflags; // used to set recv flags,e.g. MSG_TRUNC with L + double mVariance; //vbr variance + uintmax_t mFQPacingRate; + struct timeval txholdback_timer; + struct timeval txstart_epoch; + struct timeval accept_time; + struct timeval sent_time; + struct Condition awake_me; + struct PacketRing *ackring; + struct BarrierMutex *connects_done; + int numreportstructs; + int32_t peer_version_u; + int32_t peer_version_l; + double connecttime; + double rtt_nearcongest_weight_factor; + char mPermitKey[MAX_PERMITKEY_LEN + 1]; //add some space for timestamp + struct timeval mPermitKeyTime; + bool mKeyCheck; + double mListenerTimeout; + int tuntapdev; + int firstreadbytes; + int mBounceBackBytes; + int mBounceBackBurst; + int mWorkingLoadThreads; // number of congest threads + uint32_t mBounceBackHold; // units of usecs + struct iperf_tcpstats tcpinitstats; +#if HAVE_DECL_TCP_WINDOW_CLAMP + int mClampSize; +#endif +#if HAVE_DECL_TCP_NOTSENT_LOWAT + int mWritePrefetch; +#endif + int jitter_binwidth; +}; + +/* + * Thread based flags + * + * Due to the use of thread_Settings in C and C++ + * we are unable to use bool values. To provide + * the functionality of bools we use the following + * bitmask over an assumed 32 bit int. This will + * work fine on 64bit machines we will just be ignoring + * the upper 32bits. + * + * To add a flag simply define it as the next bit then + * add the 3 support functions below. + */ +#define FLAG_BUFLENSET 0x00000001 +#define FLAG_COMPAT 0x00000002 +#define FLAG_DAEMON 0x00000004 +#define FLAG_DOMAINV6 0x00000008 +#define FLAG_FILEINPUT 0x00000010 +#define FLAG_NODELAY 0x00000020 +#define FLAG_PRINTMSS 0x00000040 +#define FLAG_REMOVESERVICE 0x00000080 +#define FLAG_STDIN 0x00000100 +#define FLAG_STDOUT 0x00000200 +#define FLAG_SUGGESTWIN 0x00000400 +#define FLAG_UDP 0x00000800 +#define FLAG_MODETIME 0x00001000 +#define FLAG_REPORTSETTINGS 0x00002000 +#define FLAG_MULTICAST 0x00004000 +#define FLAG_NOSETTREPORT 0x00008000 +#define FLAG_NOCONNREPORT 0x00010000 +#define FLAG_NODATAREPORT 0x00020000 +#define FLAG_NOSERVREPORT 0x00040000 +#define FLAG_NOMULTREPORT 0x00080000 +#define FLAG_SINGLECLIENT 0x00100000 +#define FLAG_SINGLEUDP 0x00200000 +#define FLAG_CONGESTION 0x00400000 +#define FLAG_REALTIME 0x00800000 +#define FLAG_BWSET 0x01000000 +#define FLAG_ENHANCEDREPORT 0x02000000 +#define FLAG_SERVERMODETIME 0x04000000 +#define FLAG_SSM_MULTICAST 0x08000000 +/* + * Extended flags + */ +#define FLAG_PEERVER 0x00000001 +#define FLAG_SEQNO64 0x00000002 +#define FLAG_REVERSE 0x00000004 +#define FLAG_ISOCHRONOUS 0x00000008 +#define FLAG_UDPUNUSED 0x00000010 +#define FLAG_HISTOGRAM 0x00000020 +#define FLAG_L2LENGTHCHECK 0x00000100 +#define FLAG_TXSTARTTIME 0x00000200 +#define FLAG_INCRDSTIP 0x00000400 +#define FLAG_VARYLOAD 0x00000800 +#define FLAG_FQPACING 0x00001000 +#define FLAG_TRIPTIME 0x00002000 +#define FLAG_TXHOLDBACK 0x00004000 +#define FLAG_UNUSED 0x00008000 +#define FLAG_MODEINFINITE 0x00010000 +#define FLAG_CONNECTONLY 0x00020000 +#define FLAG_SERVERREVERSE 0x00040000 +#define FLAG_FULLDUPLEX 0x00080000 +#define FLAG_WRITEACK 0x00100000 +#define FLAG_NOUDPFIN 0x00200000 +#define FLAG_NOCONNECTSYNC 0x00400000 +#define FLAG_SUMONLY 0x00800000 +#define FLAG_FRAMEINTERVAL 0x01000000 +#define FLAG_IPG 0x02000000 +#define FLAG_DONTROUTE 0x04000000 +#define FLAG_NEARCONGEST 0x08000000 +#define FLAG_PERMITKEY 0x10000000 +#define FLAG_SETTCPMSS 0x20000000 +#define FLAG_INCRDSTPORT 0x40000000 +#define FLAG_INCRSRCIP 0x80000000 + +/* + * More extended flags + */ +#define FLAG_PERIODICBURST 0x00000001 +#define FLAG_SUMDSTIP 0x00000002 +#define FLAG_SMALLTRIPTIME 0x00000004 +#define FLAG_RXCLAMP 0x00000008 +#define FLAG_WRITEPREFETCH 0x00000010 +#define FLAG_TUNDEV 0x00000020 +#define FLAG_TAPDEV 0x00000040 +#define FLAG_HIDEIPS 0x00000080 +#define FLAG_BOUNCEBACK 0x00000100 +#define FLAG_TCPWRITETIMES 0x00000200 +#define FLAG_INCRSRCPORT 0x00000400 +#define FLAG_OVERRIDETOS 0x00000800 +#define FLAG_TCPQUICKACK 0x00001000 +#define FLAG_WORKING_LOAD_DOWN 0x00002000 +#define FLAG_WORKING_LOAD_UP 0x00004000 +#define FLAG_DOMAINV4 0x00008000 +#define FLAG_JITTER_HISTOGRAM 0x00010000 +#define FLAG_UTC 0x00020000 + +#define isBuflenSet(settings) ((settings->flags & FLAG_BUFLENSET) != 0) +#define isCompat(settings) ((settings->flags & FLAG_COMPAT) != 0) +#define isDaemon(settings) ((settings->flags & FLAG_DAEMON) != 0) +#define isIPV6(settings) ((settings->flags & FLAG_DOMAINV6) != 0) +#define isIPV4(settings) ((settings->flags_extend2 & FLAG_DOMAINV4) != 0) +#define isFileInput(settings) ((settings->flags & FLAG_FILEINPUT) != 0) +#define isNoDelay(settings) ((settings->flags & FLAG_NODELAY) != 0) +#define isPrintMSS(settings) ((settings->flags & FLAG_PRINTMSS) != 0) +#define isRemoveService(settings) ((settings->flags & FLAG_REMOVESERVICE) != 0) +#define isSTDIN(settings) ((settings->flags & FLAG_STDIN) != 0) +#define isSTDOUT(settings) ((settings->flags & FLAG_STDOUT) != 0) +#define isSuggestWin(settings) ((settings->flags & FLAG_SUGGESTWIN) != 0) +#define isUDP(settings) ((settings->flags & FLAG_UDP) != 0) +#define isModeTime(settings) ((settings->flags & FLAG_MODETIME) != 0) +#define isReport(settings) ((settings->flags & FLAG_REPORTSETTINGS) != 0) +#define isMulticast(settings) ((settings->flags & FLAG_MULTICAST) != 0) +#define isSSMMulticast(settings) ((settings->flags & FLAG_SSM_MULTICAST) != 0) +// Active Low for Reports +#define isSettingsReport(settings) ((settings->flags & FLAG_NOSETTREPORT) == 0) +#define isConnectionReport(settings) ((settings->flags & FLAG_NOCONNREPORT) == 0) +#define isDataReport(settings) ((settings->flags & FLAG_NODATAREPORT) == 0) +#define isServerReport(settings) ((settings->flags & FLAG_NOSERVREPORT) == 0) +#define isMultipleReport(settings) ((settings->flags & FLAG_NOMULTREPORT) == 0) +// end Active Low +#define isSingleClient(settings) ((settings->flags & FLAG_SINGLECLIENT) != 0) +#define isSingleUDP(settings) ((settings->flags & FLAG_SINGLEUDP) != 0) +#define isCongestionControl(settings) ((settings->flags & FLAG_CONGESTION) != 0) +#define isRealtime(settings) ((settings->flags & FLAG_REALTIME) != 0) +#define isBWSet(settings) ((settings->flags & FLAG_BWSET) != 0) +#define isEnhanced(settings) ((settings->flags & FLAG_ENHANCEDREPORT) != 0) +#define isServerModeTime(settings) ((settings->flags & FLAG_SERVERMODETIME) != 0) +#define isPeerVerDetect(settings) ((settings->flags_extend & FLAG_PEERVER) != 0) +#define isSeqNo64b(settings) ((settings->flags_extend & FLAG_SEQNO64) != 0) +#define isReverse(settings) ((settings->flags_extend & FLAG_REVERSE) != 0) +#define isFullDuplex(settings) ((settings->flags_extend & FLAG_FULLDUPLEX) != 0) +#define isServerReverse(settings) ((settings->flags_extend & FLAG_SERVERREVERSE) != 0) +#define isIsochronous(settings) ((settings->flags_extend & FLAG_ISOCHRONOUS) != 0) +#define isHistogram(settings) ((settings->flags_extend & FLAG_HISTOGRAM) != 0) +#define isL2LengthCheck(settings) ((settings->flags_extend & FLAG_L2LENGTHCHECK) != 0) +#define isIncrDstIP(settings) ((settings->flags_extend & FLAG_INCRDSTIP) != 0) +#define isIncrSrcIP(settings) ((settings->flags_extend & FLAG_INCRSRCIP) != 0) +#define isIncrDstPort(settings) ((settings->flags_extend & FLAG_INCRDSTPORT) != 0) +#define isIncrSrcPort(settings) ((settings->flags_extend2 & FLAG_INCRSRCPORT) != 0) +#define isTxStartTime(settings) ((settings->flags_extend & FLAG_TXSTARTTIME) != 0) +#define isTxHoldback(settings) ((settings->flags_extend & FLAG_TXHOLDBACK) != 0) +#define isVaryLoad(settings) ((settings->flags_extend & FLAG_VARYLOAD) != 0) +#define isFQPacing(settings) ((settings->flags_extend & FLAG_FQPACING) != 0) +#define isTripTime(settings) ((settings->flags_extend & FLAG_TRIPTIME) != 0) +#define isSmallTripTime(settings) ((settings->flags_extend2 & FLAG_SMALLTRIPTIME) != 0) +#define isModeInfinite(settings) ((settings->flags_extend & FLAG_MODEINFINITE) != 0) +#define isModeAmount(settings) (!isModeTime(settings) && !isModeInfinite(settings)) +#define isConnectOnly(settings) ((settings->flags_extend & FLAG_CONNECTONLY) != 0) +#define isWriteAck(settings) ((settings->flags_extend & FLAG_WRITEACK) != 0) +#define isNoUDPfin(settings) ((settings->flags_extend & FLAG_NOUDPFIN) != 0) +#define isNoConnectSync(settings) ((settings->flags_extend & FLAG_NOCONNECTSYNC) != 0) +#define isSumOnly(settings) ((settings->flags_extend & FLAG_SUMONLY) != 0) +#define isFrameInterval(settings) ((settings->flags_extend & FLAG_FRAMEINTERVAL) != 0) +#define isIPG(settings) ((settings->flags_extend & FLAG_IPG) != 0) +#define isDontRoute(settings) ((settings->flags_extend & FLAG_DONTROUTE) != 0) +#define isNearCongest(settings) ((settings->flags_extend & FLAG_NEARCONGEST) != 0) +#define isPermitKey(settings) ((settings->flags_extend & FLAG_PERMITKEY) != 0) +#define isTCPMSS(settings) ((settings->flags_extend & FLAG_SETTCPMSS) != 0) +#define isPeriodicBurst(settings) ((settings->flags_extend2 & FLAG_PERIODICBURST) != 0) +#define isSumServerDstIP(settings) ((settings->flags_extend2 & FLAG_SUMDSTIP) != 0) +#define isRxClamp(settings) ((settings->flags_extend2 & FLAG_RXCLAMP) != 0) +#define isWritePrefetch(settings) ((settings->flags_extend2 & FLAG_WRITEPREFETCH) != 0) +#define isTapDev(settings) ((settings->flags_extend2 & FLAG_TAPDEV) != 0) +#define isTunDev(settings) ((settings->flags_extend2 & FLAG_TUNDEV) != 0) +#define isHideIPs(settings) ((settings->flags_extend2 & FLAG_HIDEIPS) != 0) +#define isBounceBack(settings) ((settings->flags_extend2 & FLAG_BOUNCEBACK) != 0) +#define isTcpWriteTimes(settings) ((settings->flags_extend2 & FLAG_TCPWRITETIMES) != 0) +#define isOverrideTOS(settings) ((settings->flags_extend2 & FLAG_OVERRIDETOS) != 0) +#define isTcpQuickAck(settings) ((settings->flags_extend2 & FLAG_TCPQUICKACK) != 0) +#define isWorkingLoadUp(settings) ((settings->flags_extend2 & FLAG_WORKING_LOAD_UP) != 0) +#define isWorkingLoadDown(settings) ((settings->flags_extend2 & FLAG_WORKING_LOAD_DOWN) != 0) +#define isJitterHistogram(settings) ((settings->flags_extend2 & FLAG_JITTER_HISTOGRAM) != 0) +#define isUTC(settings) ((settings->flags_extend2 & FLAG_UTC) != 0) + +#define setBuflenSet(settings) settings->flags |= FLAG_BUFLENSET +#define setCompat(settings) settings->flags |= FLAG_COMPAT +#define setDaemon(settings) settings->flags |= FLAG_DAEMON +#define setIPV6(settings) settings->flags |= FLAG_DOMAINV6 +#define setIPV4(settings) settings->flags_extend2 |= FLAG_DOMAINV4 +#define setFileInput(settings) settings->flags |= FLAG_FILEINPUT +#define setNoDelay(settings) settings->flags |= FLAG_NODELAY +#define setPrintMSS(settings) settings->flags |= FLAG_PRINTMSS +#define setRemoveService(settings) settings->flags |= FLAG_REMOVESERVICE +#define setSTDIN(settings) settings->flags |= FLAG_STDIN +#define setSTDOUT(settings) settings->flags |= FLAG_STDOUT +#define setSuggestWin(settings) settings->flags |= FLAG_SUGGESTWIN +#define setUDP(settings) settings->flags |= FLAG_UDP +#define setModeTime(settings) settings->flags |= FLAG_MODETIME +#define setReport(settings) settings->flags |= FLAG_REPORTSETTINGS +#define setMulticast(settings) settings->flags |= FLAG_MULTICAST +#define setSSMMulticast(settings) settings->flags |= FLAG_SSM_MULTICAST +#define setNoSettReport(settings) settings->flags |= FLAG_NOSETTREPORT +#define setNoConnReport(settings) settings->flags |= FLAG_NOCONNREPORT +#define setNoDataReport(settings) settings->flags |= FLAG_NODATAREPORT +#define setNoServReport(settings) settings->flags |= FLAG_NOSERVREPORT +#define setNoMultReport(settings) settings->flags |= FLAG_NOMULTREPORT +#define setSingleClient(settings) settings->flags |= FLAG_SINGLECLIENT +#define setSingleUDP(settings) settings->flags |= FLAG_SINGLEUDP +#define setCongestionControl(settings) settings->flags |= FLAG_CONGESTION +#define setRealtime(settings) settings->flags |= FLAG_REALTIME +#define setBWSet(settings) settings->flags |= FLAG_BWSET +#define setEnhanced(settings) settings->flags |= FLAG_ENHANCEDREPORT +#define setServerModeTime(settings) settings->flags |= FLAG_SERVERMODETIME +#define setPeerVerDetect(settings) settings->flags_extend |= FLAG_PEERVER +#define setSeqNo64b(settings) settings->flags_extend |= FLAG_SEQNO64 +#define setReverse(settings) settings->flags_extend |= FLAG_REVERSE +#define setFullDuplex(settings) settings->flags_extend |= FLAG_FULLDUPLEX +#define setServerReverse(settings) settings->flags_extend |= FLAG_SERVERREVERSE +#define setIsochronous(settings) settings->flags_extend |= FLAG_ISOCHRONOUS +#define setHistogram(settings) settings->flags_extend |= FLAG_HISTOGRAM +#define setL2LengthCheck(settings) settings->flags_extend |= FLAG_L2LENGTHCHECK +#define setIncrDstIP(settings) settings->flags_extend |= FLAG_INCRDSTIP +#define setIncrSrcIP(settings) settings->flags_extend |= FLAG_INCRSRCIP +#define setIncrDstPort(settings) settings->flags_extend |= FLAG_INCRDSTPORT +#define setIncrSrcPort(settings) settings->flags_extend2 |= FLAG_INCRSRCPORT +#define setTxStartTime(settings) settings->flags_extend |= FLAG_TXSTARTTIME +#define setTxHoldback(settings) settings->flags_extend |= FLAG_TXHOLDBACK +#define setVaryLoad(settings) settings->flags_extend |= FLAG_VARYLOAD +#define setFQPacing(settings) settings->flags_extend |= FLAG_FQPACING +#define setTripTime(settings) settings->flags_extend |= FLAG_TRIPTIME +#define setSmallTripTime(settings) settings->flags_extend2 |= FLAG_SMALLTRIPTIME +#define setModeInfinite(settings) settings->flags_extend |= FLAG_MODEINFINITE +#define setConnectOnly(settings) settings->flags_extend |= FLAG_CONNECTONLY +#define setWriteAck(settings) settings->flags_extend |= FLAG_WRITEACK +#define setNoUDPfin(settings) settings->flags_extend |= FLAG_NOUDPFIN +#define setNoConnectSync(settings) settings->flags_extend |= FLAG_NOCONNECTSYNC +#define setSumOnly(settings) settings->flags_extend |= FLAG_SUMONLY +#define setFrameInterval(settings) settings->flags_extend |= FLAG_FRAMEINTERVAL +#define setIPG(settings) settings->flags_extend |= FLAG_IPG +#define setDontRoute(settings) settings->flags_extend |= FLAG_DONTROUTE +#define setNearCongest(settings) settings->flags_extend |= FLAG_NEARCONGEST +#define setPermitKey(settings) settings->flags_extend |= FLAG_PERMITKEY +#define setTCPMSS(settings) settings->flags_extend |= FLAG_SETTCPMSS +#define setPeriodicBurst(settings) settings->flags_extend2 |= FLAG_PERIODICBURST +#define setSumServerDstIP(settings) settings->flags_extend2 |= FLAG_SUMDSTIP +#define setRxClamp(settings) settings->flags_extend2 |= FLAG_RXCLAMP +#define setWritePrefetch(settings) settings->flags_extend2 |= FLAG_WRITEPREFETCH +#define setTapDev(settings) settings->flags_extend2 |= FLAG_TAPDEV +#define setTunDev(settings) settings->flags_extend2 |= FLAG_TUNDEV +#define setHideIPs(settings) settings->flags_extend2 |= FLAG_HIDEIPS +#define setBounceBack(settings) settings->flags_extend2 |= FLAG_BOUNCEBACK +#define setTcpWriteTimes(settings) settings->flags_extend2 |= FLAG_TCPWRITETIMES +#define setOverrideTOS(settings) settings->flags_extend2 |= FLAG_OVERRIDETOS +#define setTcpQuickAck(settings) settings->flags_extend2 |= FLAG_TCPQUICKACK +#define setWorkingLoadUp(settings) settings->flags_extend2 |= FLAG_WORKING_LOAD_UP +#define setWorkingLoadDown(settings) settings->flags_extend2 |= FLAG_WORKING_LOAD_DOWN +#define setJitterHistogram(settings) settings->flags_extend2 |= FLAG_JITTER_HISTOGRAM +#define setUTC(settings) settings->flags_extend2 |= FLAG_UTC + +#define unsetBuflenSet(settings) settings->flags &= ~FLAG_BUFLENSET +#define unsetCompat(settings) settings->flags &= ~FLAG_COMPAT +#define unsetDaemon(settings) settings->flags &= ~FLAG_DAEMON +#define unsetIPV6(settings) settings->flags &= ~FLAG_DOMAINV6 +#define unsetIPV4(settings) settings->flags_extend2 &= ~FLAG_DOMAINV4 +#define unsetFileInput(settings) settings->flags &= ~FLAG_FILEINPUT +#define unsetNoDelay(settings) settings->flags &= ~FLAG_NODELAY +#define unsetPrintMSS(settings) settings->flags &= ~FLAG_PRINTMSS +#define unsetRemoveService(settings) settings->flags &= ~FLAG_REMOVESERVICE +#define unsetSTDIN(settings) settings->flags &= ~FLAG_STDIN +#define unsetSTDOUT(settings) settings->flags &= ~FLAG_STDOUT +#define unsetSuggestWin(settings) settings->flags &= ~FLAG_SUGGESTWIN +#define unsetUDP(settings) settings->flags &= ~FLAG_UDP +#define unsetModeTime(settings) settings->flags &= ~FLAG_MODETIME +#define unsetReport(settings) settings->flags &= ~FLAG_REPORTSETTINGS +#define unsetMulticast(settings) settings->flags &= ~FLAG_MULTICAST +#define unsetSSMMulticast(settings) settings->flags &= ~FLAG_SSM_MULTICAST +#define unsetNoSettReport(settings) settings->flags &= ~FLAG_NOSETTREPORT +#define unsetNoConnReport(settings) settings->flags &= ~FLAG_NOCONNREPORT +#define unsetNoDataReport(settings) settings->flags &= ~FLAG_NODATAREPORT +#define unsetNoServReport(settings) settings->flags &= ~FLAG_NOSERVREPORT +#define unsetNoMultReport(settings) settings->flags &= ~FLAG_NOMULTREPORT +#define unsetSingleClient(settings) settings->flags &= ~FLAG_SINGLECLIENT +#define unsetSingleUDP(settings) settings->flags &= ~FLAG_SINGLEUDP +#define unsetCongestionControl(settings) settings->flags &= ~FLAG_CONGESTION +#define unsetRealtime(settings) settings->flags &= ~FLAG_REALTIME +#define unsetBWSet(settings) settings->flags &= ~FLAG_BWSET +#define unsetEnhanced(settings) settings->flags &= ~FLAG_ENHANCEDREPORT +#define unsetServerModeTime(settings) settings->flags &= ~FLAG_SERVERMODETIME +#define unsetPeerVerDetect(settings) settings->flags_extend &= ~FLAG_PEERVER +#define unsetSeqNo64b(settings) settings->flags_extend &= ~FLAG_SEQNO64 +#define unsetReverse(settings) settings->flags_extend &= ~FLAG_REVERSE +#define unsetFullDuplex(settings) settings->flags_extend &= ~FLAG_FULLDUPLEX +#define unsetServerReverse(settings) settings->flags_extend &= ~FLAG_SERVERREVERSE +#define unsetIsochronous(settings) settings->flags_extend &= ~FLAG_ISOCHRONOUS +#define unsetHistogram(settings) settings->flags_extend &= ~FLAG_HISTOGRAM +#define unsetL2LengthCheck(settings) settings->flags_extend &= ~FLAG_L2LENGTHCHECK +#define unsetIncrDstIP(settings) settings->flags_extend &= ~FLAG_INCRDSTIP +#define unsetIncrSrcIP(settings) settings->flags_extend &= ~FLAG_INCRSRCIP +#define unsetIncrDstPort(settings) settings->flags_extend &= ~FLAG_INCRDSTPORT +#define unsetIncrSrcPort(settings) settings->flags_extend2 &= ~FLAG_INCRSRCPORT +#define unsetTxStartTime(settings) settings->flags_extend &= ~FLAG_TXSTARTTIME +#define unsetTxHoldback(settings) settings->flags_extend &= ~FLAG_TXHOLDBACK +#define unsetVaryLoad(settings) settings->flags_extend &= ~FLAG_VARYLOAD +#define unsetFQPacing(settings) settings->flags_extend &= ~FLAG_FQPACING +#define unsetTripTime(settings) settings->flags_extend &= ~FLAG_TRIPTIME +#define unsetSmallTripTime(settings) settings->flags_extend2 &= ~FLAG_SMALLTRIPTIME +#define unsetModeInfinite(settings) settings->flags_extend &= ~FLAG_MODEINFINITE +#define unsetConnectOnly(settings) settings->flags_extend &= ~FLAG_CONNECTONLY +#define unsetWriteAck(settings) settings->flags_extend &= ~FLAG_WRITEACK +#define unsetNoUDPfin(settings) settings->flags_extend &= ~FLAG_NOUDPFIN +#define unsetNoConnectSync(settings) settings->flags_extend &= ~FLAG_NOCONNECTSYNC +#define unsetSumOnly(settings) settings->flags_extend &= ~FLAG_SUMONLY +#define unsetFrameInterval(settings) settings->flags_extend &= ~FLAG_FRAMEINTERVAL +#define unsetIPG(settings) settings->flags_extend &= ~FLAG_IPG +#define unsetDontRoute(settings) settings->flags_extend &= ~FLAG_DONTROUTE +#define unsetPermitKey(settings) settings->flags_extend &= ~FLAG_PERMITKEY +#define unsetTCPMSS(settings) settings->flags_extend &= ~FLAG_SETTCPMSS +#define unsetPeriodicBurst(settings) settings->flags_extend2 &= ~FLAG_PERIODICBURST +#define unsetSumServerDstIP(settings) settings->flags_extend2 &= ~FLAG_SUMDSTIP +#define unsetRxClamp(settings) settings->flags_extend2 &= ~FLAG_RXCLAMP +#define unsetWritePrefetch(settings) settings->flags_extend2 &= ~FLAG_WRITEPREFETCH +#define unsetTapDev(settings) settings->flags_extend2 &= ~FLAG_TAPDEV +#define unsetTunDev(settings) settings->flags_extend2 &= ~FLAG_TUNDEV +#define unsetHideIPs(settings) settings->flags_extend2 &= ~FLAG_HIDEIPS +#define unsetBounceBack(settings) settings->flags_extend2 &= ~FLAG_BOUNCEBACK +#define unsetTcpWriteTimes(settings) settings->flags_extend2 &= ~FLAG_TCPWRITETIMES +#define unsetOverrideTOS(settings) settings->flags_extend2 &= ~FLAG_OVERRIDETOS +#define unsetTcpQuickAck(settings) settings->flags_extend2 &= ~FLAG_TCPQUICKACK +#define unsetWorkingLoadUp(settings) settings->flags_extend2 &= ~FLAG_WORKING_LOAD_UP +#define unsetWorkingLoadDown(settings) settings->flags_extend2 &= ~FLAG_WORKING_LOAD_DOWN +#define unsetJitterHistogram(settings) settings->flags_extend2 &= ~FLAG_JITTER_HISTOGRAM +#define unsetUTC(settings) settings->flags_extend2 &= ~FLAG_UTC + +// set to defaults +void Settings_Initialize(struct thread_Settings* main); + +// copy structure +void Settings_Copy(struct thread_Settings* from, struct thread_Settings** into, int copyall); + +// free associated memory +void Settings_Destroy(struct thread_Settings *mSettings); + +// parse settings from user's environment variables +void Settings_ParseEnvironment(struct thread_Settings *mSettings); + +// parse settings from app's command line +void Settings_ParseCommandLine(int argc, char **argv, struct thread_Settings *mSettings); + +// convert to lower case for [KMG]bits/sec +void Settings_GetLowerCaseArg(const char *,char *); + +// convert to upper case for [KMG]bytes/sec +void Settings_GetUpperCaseArg(const char *,char *); + +// generate settings for listener instance +void Settings_GenerateListenerSettings(struct thread_Settings *client, struct thread_Settings **listener); + +// generate settings for speaker instance +void Settings_GenerateClientSettings(struct thread_Settings *server, struct thread_Settings **client, void * mBuf); + +// generate client header for server +int Settings_GenerateClientHdr(struct thread_Settings *client, void * hdr, struct timeval startTime); + +int Settings_ClientTestHdrLen(uint32_t flags, struct thread_Settings *inSettings); + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif // SETTINGS_H diff --git a/include/SocketAddr.h b/include/SocketAddr.h new file mode 100644 index 0000000..be391a8 --- /dev/null +++ b/include/SocketAddr.h @@ -0,0 +1,119 @@ +/*--------------------------------------------------------------- + * Copyright (c) 1999,2000,2001,2002,2003 + * The Board of Trustees of the University of Illinois + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software (Iperf) and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the names of the University of Illinois, NCSA, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * National Laboratory for Applied Network Research + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * http://www.ncsa.uiuc.edu + * ________________________________________________________________ + * + * Socket.cpp + * by Ajay Tirumala <tirumala@ncsa.uiuc.edu> + * and Mark Gates <mgates@nlanr.net> + * ------------------------------------------------------------------- */ + + +#ifndef SOCKET_ADDR_H +#define SOCKET_ADDR_H + +#include "headers.h" +#include "Settings.hpp" + +#ifdef __cplusplus +extern "C" { +#endif +/* ------------------------------------------------------------------- */ +void SockAddr_localAddr(struct thread_Settings *inSettings); +void SockAddr_remoteAddr(struct thread_Settings *inSettings); + +void SockAddr_setHostname(const char* inHostname, + iperf_sockaddr *inSockAddr, + int isIPv6); // DNS lookup +void SockAddr_getHostname(iperf_sockaddr *inSockAddr, + char* outHostname, + size_t len); // reverse DNS lookup +void SockAddr_getHostAddress(iperf_sockaddr *inSockAddr, + char* outAddress, + size_t len); // dotted decimal + +void SockAddr_setPort(iperf_sockaddr *inSockAddr, unsigned short inPort); +void SockAddr_setPortAny(iperf_sockaddr *inSockAddr); +unsigned short SockAddr_getPort(iperf_sockaddr *inSockAddr); + +void SockAddr_setAddressAny(iperf_sockaddr *inSockAddr); + +// return pointer to the struct in_addr +struct in_addr* SockAddr_get_in_addr(iperf_sockaddr *inSockAddr); +#if HAVE_IPV6 +// return pointer to the struct in_addr +struct in6_addr* SockAddr_get_in6_addr(iperf_sockaddr *inSockAddr); +#endif +// return the sizeof the addess structure (struct sockaddr_in) +Socklen_t SockAddr_get_sizeof_sockaddr(iperf_sockaddr *inSockAddr); + +int SockAddr_isMulticast(iperf_sockaddr *inSockAddr); +int SockAddr_isLinklocal(iperf_sockaddr *inSockAddr); + +int SockAddr_isIPv6(iperf_sockaddr *inSockAddr); + +int SockAddr_are_Equal(iperf_sockaddr *first, iperf_sockaddr *second); +int SockAddr_Hostare_Equal(iperf_sockaddr *first, iperf_sockaddr *second); + +void SockAddr_zeroAddress(iperf_sockaddr *inSockAddr); +int SockAddr_isZeroAddress(iperf_sockaddr *inSockAddr); +void SockAddr_incrAddress(iperf_sockaddr *inSockAddr, int value); +int SockAddr_Ifrname(struct thread_Settings *inSettings); +#ifdef HAVE_LINUX_FILTER_H +int SockAddr_v4_Accept_BPF(int socket, uint16_t port); +int SockAddr_Accept_v4_TAP_BPF(int socket, uint32_t dstip, uint16_t port); +int SockAddr_Drop_All_BPF(int socket); +int SockAddr_v4_Connect_BPF(int socket, uint32_t dstip, uint32_t srcip, uint16_t dstport, uint16_t srcport); +int SockAddr_v4_Connect_TAP_BPF(int socket, uint32_t dstip, uint32_t srcip, uint16_t dstport, uint16_t srcport); +int SockAddr_v4_Connect_BPF_Drop(int socket, uint32_t dstip, uint32_t srcip, uint16_t dstport, uint16_t srcport); +# if HAVE_IPV6 +int SockAddr_v6_Connect_BPF (int sock, struct in6_addr *dst, struct in6_addr *src, uint16_t dstport, uint16_t srcport); +# endif // v6 +#endif // linux_filter + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif /* SOCKET_ADDR_H */ diff --git a/include/Thread.h b/include/Thread.h new file mode 100644 index 0000000..f439a6a --- /dev/null +++ b/include/Thread.h @@ -0,0 +1,176 @@ +/*--------------------------------------------------------------- + * Copyright (c) 1999,2000,2001,2002,2003 + * The Board of Trustees of the University of Illinois + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software (Iperf) and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the names of the University of Illinois, NCSA, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * National Laboratory for Applied Network Research + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * http://www.ncsa.uiuc.edu + * ________________________________________________________________ + * + * Thread.h + * by Kevin Gibbs <kgibbs@nlanr.net> + * + * Based on: + * Thread.hpp + * by Mark Gates <mgates@nlanr.net> + * ------------------------------------------------------------------- + * The thread subsystem is responsible for all thread functions. It + * provides a thread implementation agnostic interface to Iperf. If + * threads are not available (HAVE_THREAD is undefined), thread_start + * does not start a new thread but just launches the specified object + * in the current thread. Everything that defines a thread of + * execution in Iperf is contained in an thread_Settings structure. To + * start a thread simply pass one such structure into thread_start. + * ------------------------------------------------------------------- */ + +#ifndef THREAD_H +#define THREAD_H + +#ifdef __cplusplus +extern "C" { +#endif + + +#if defined(HAVE_POSIX_THREAD) + +/* Definitions for Posix Threads (pthreads) */ +#include <pthread.h> + +typedef pthread_t nthread_t; + +#define HAVE_THREAD 1 + +#elif defined(HAVE_WIN32_THREAD) + +/* Definitions for Win32 NT Threads */ +typedef DWORD nthread_t; + +#define HAVE_THREAD 1 + +#else + +/* Definitions for no threads */ +typedef int nthread_t; + +#undef HAVE_THREAD + +#endif + +// Forward declaration +struct thread_Settings; + +#include "Condition.h" +#include "Settings.hpp" + +#if HAVE_THREAD_DEBUG +struct ReportHeader; +void reporttype_text(struct ReportHeader *reporthdr, char *rs); +void thread_debug(const char *format, ...); +extern Mutex thread_debug_mutex; +extern Mutex packetringdebug_mutex; +#endif +// initialize or destroy the thread subsystem +void thread_init(); +void thread_destroy(); + +// start or stop a thread executing +void thread_start_all(struct thread_Settings* thread); +void thread_start(struct thread_Settings* thread); +void thread_stop(struct thread_Settings* thread); + +/* wait for this or all threads to complete */ +void thread_joinall(void); +int thread_numuserthreads(void); +int thread_numtrafficthreads(void); + +// set a thread to be ignorable, so joinall won't wait on it +void thread_setignore(void); +void thread_unsetignore(void); + +// Used for threads that may never terminate (ie Listener Thread) +void thread_register_nonterm(void); +void thread_unregister_nonterm(void); +int thread_release_nonterm(int interrupt); + +/* ------------------------------------------------------------------- + * Return the current thread's ID. + * ------------------------------------------------------------------- */ +#if defined(HAVE_POSIX_THREAD) +#define thread_getid() pthread_self() +#elif defined(HAVE_WIN32_THREAD) +#define thread_getid() GetCurrentThreadId() +#else +#define thread_getid() 0 +#endif + +int thread_equalid(nthread_t inLeft, nthread_t inRight); + +nthread_t thread_zeroid(void); + +#if defined(HAVE_WIN32_THREAD) +DWORD WINAPI thread_run_wrapper(void* paramPtr); +#else +void*thread_run_wrapper(void* paramPtr); +#endif + +#if HAVE_SCHED_SETSCHEDULER +void thread_setscheduler(struct thread_Settings *thread); +#endif + +void thread_rest (void); + +// defined in launch.cpp +void server_spawn(struct thread_Settings* thread); +void client_spawn(struct thread_Settings* thread); +void client_init(struct thread_Settings* clients); +void listener_spawn(struct thread_Settings* thread); +void listeners_init(struct thread_Settings* listeners); +void writeack_server_spawn(struct thread_Settings* thread); +void writeack_client_spawn(struct thread_Settings* thread); +int fullduplex_start_barrier(struct BarrierMutex *barrier); +int fullduplex_stop_barrier(struct BarrierMutex *barrier); + +// defined in reporter.c +void reporter_spawn(struct thread_Settings* thread); + +#ifdef __cplusplus +} /* end extern "C" */ +#endif +#endif // THREAD_H diff --git a/include/Timestamp.hpp b/include/Timestamp.hpp new file mode 100644 index 0000000..e0c9f29 --- /dev/null +++ b/include/Timestamp.hpp @@ -0,0 +1,308 @@ +/*--------------------------------------------------------------- + * Copyright (c) 1999,2000,2001,2002,2003 + * The Board of Trustees of the University of Illinois + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software (Iperf) and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the names of the University of Illinois, NCSA, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * National Laboratory for Applied Network Research + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * http://www.ncsa.uiuc.edu + * ________________________________________________________________ + * + * Timestamp.hpp + * by Mark Gates <mgates@nlanr.net> + * ------------------------------------------------------------------- + * A generic interface to a timestamp. + * This implementation uses the unix gettimeofday(). + * ------------------------------------------------------------------- + * headers + * uses + * <sys/types.h> + * <sys/time.h> + * <unistd.h> + * ------------------------------------------------------------------- */ + +#ifndef TIMESTAMP_H +#define TIMESTAMP_H + +#include "headers.h" + +/* ------------------------------------------------------------------- */ +class Timestamp { +public: + /* ------------------------------------------------------------------- + * Create a timestamp, with the current time in it. + * ------------------------------------------------------------------- */ + Timestamp(void) { + setnow(); + } + + /* ------------------------------------------------------------------- + * Copy construcutor + * ------------------------------------------------------------------- */ + Timestamp(const Timestamp &t2) { + mTime.tv_sec = t2.mTime.tv_sec; + mTime.tv_usec = t2.mTime.tv_usec; + } + + /* ------------------------------------------------------------------- + * Create a timestamp, with the given seconds/microseconds + * ------------------------------------------------------------------- */ + Timestamp(long sec, long usec) { + set(sec, usec); + } + + /* ------------------------------------------------------------------- + * Create a timestamp, with the given seconds + * ------------------------------------------------------------------- */ + Timestamp(double sec) { + set(sec); + } + + /* ------------------------------------------------------------------- + * Set timestamp to current time. + * ------------------------------------------------------------------- */ + void inline setnow(void) { +#ifdef HAVE_CLOCK_GETTIME + struct timespec t1; + clock_gettime(CLOCK_REALTIME, &t1); + mTime.tv_sec = t1.tv_sec; + mTime.tv_usec = t1.tv_nsec / 1000; +#else + gettimeofday(&mTime, NULL); +#endif + } + + /* ------------------------------------------------------------------- + * Set timestamp to the given seconds/microseconds + * ------------------------------------------------------------------- */ + void set(long sec, long usec) { + assert(sec >= 0); + assert(usec >= 0 && usec < kMillion); + + mTime.tv_sec = sec; + mTime.tv_usec = usec; + } + + /* ------------------------------------------------------------------- + * Set timestamp to the given seconds + * ------------------------------------------------------------------- */ + void set(double sec) { + mTime.tv_sec = (long) sec; + mTime.tv_usec = (long) ((sec - mTime.tv_sec) * kMillion); + } + + /* ------------------------------------------------------------------- + * return seconds portion of timestamp + * ------------------------------------------------------------------- */ + long inline getSecs(void) { + return mTime.tv_sec; + } + + /* ------------------------------------------------------------------- + * return microseconds portion of timestamp + * ------------------------------------------------------------------- */ + long inline getUsecs(void) { + return mTime.tv_usec; + } + + /* ------------------------------------------------------------------- + * return timestamp as a floating point seconds + * ------------------------------------------------------------------- */ + double get(void) { + return mTime.tv_sec + mTime.tv_usec / ((double) kMillion); + } + + /* ------------------------------------------------------------------- + * subtract the right timestamp from my timestamp. + * return the difference in microseconds. + * ------------------------------------------------------------------- */ + long subUsec(Timestamp right) { + return(mTime.tv_sec - right.mTime.tv_sec) * kMillion + + (mTime.tv_usec - right.mTime.tv_usec); + } + + /* ------------------------------------------------------------------- + * subtract the right timestamp from my timestamp. + * return the difference in microseconds. + * ------------------------------------------------------------------- */ + long subUsec(timeval right) { + return(mTime.tv_sec - right.tv_sec) * kMillion + + (mTime.tv_usec - right.tv_usec); + } + + /* ------------------------------------------------------------------- + * subtract my timestamp from the right timestamp + * return the difference in microseconds. + * ------------------------------------------------------------------- */ + long mysubUsec(timeval right) { + return(right.tv_sec - mTime.tv_sec) * kMillion + + (right.tv_usec - mTime.tv_usec); + } + + /* ------------------------------------------------------------------- + * Return the number of microseconds from now to last time of setting. + * ------------------------------------------------------------------- */ + long delta_usec(void) { + struct timeval previous = mTime; + setnow(); + return subUsec(previous); + } + + /* ------------------------------------------------------------------- + * subtract the right timestamp from my timestamp. + * return the difference in seconds as a floating point. + * ------------------------------------------------------------------- */ + double subSec(Timestamp right) { + return(mTime.tv_sec - right.mTime.tv_sec) + + (mTime.tv_usec - right.mTime.tv_usec) / ((double) kMillion); + } + + /* ------------------------------------------------------------------- + * add the right timestamp to my timestamp. + * ------------------------------------------------------------------- */ + void add(Timestamp right) { + mTime.tv_sec += right.mTime.tv_sec; + mTime.tv_usec += right.mTime.tv_usec; + + // watch for under- and overflow + if (mTime.tv_usec < 0) { + mTime.tv_usec += kMillion; + mTime.tv_sec--; + } + if (mTime.tv_usec >= kMillion) { + mTime.tv_usec -= kMillion; + mTime.tv_sec++; + } + + assert(mTime.tv_usec >= 0 && + mTime.tv_usec < kMillion); + } + + /* ------------------------------------------------------------------- + * add the right timestamp to my timestamp. + * ------------------------------------------------------------------- */ + void add (struct timeval *right) { + mTime.tv_sec += right->tv_sec; + mTime.tv_usec += right->tv_usec; + + // watch for under- and overflow + if (mTime.tv_usec < 0) { + mTime.tv_usec += kMillion; + mTime.tv_sec--; + } + if (mTime.tv_usec >= kMillion) { + mTime.tv_usec -= kMillion; + mTime.tv_sec++; + } + + assert(mTime.tv_usec >= 0 && + mTime.tv_usec < kMillion); + } + + /* ------------------------------------------------------------------- + * add the seconds to my timestamp. + * TODO optimize? + * ------------------------------------------------------------------- */ + void add(double sec) { + mTime.tv_sec += (long) sec; + mTime.tv_usec += (long) ((sec - ((long) sec)) * kMillion); + + // watch for overflow + if (mTime.tv_usec >= kMillion) { + mTime.tv_usec -= kMillion; + mTime.tv_sec++; + } + + assert(mTime.tv_usec >= 0 && + mTime.tv_usec < kMillion); + } + + /* ------------------------------------------------------------------- + * add micro seconds to my timestamp. + * ------------------------------------------------------------------- */ + void add(unsigned int usec) { + mTime.tv_usec += usec; + mTime.tv_sec += mTime.tv_usec / kMillion; + mTime.tv_usec = mTime.tv_usec % kMillion; + // assert((mTime.tv_usec >= 0) && (mTime.tv_usec < kMillion)); + } + + /* ------------------------------------------------------------------- + * return true if my timestamp is before the right timestamp. + * ------------------------------------------------------------------- */ + bool before(timeval right) { + return mTime.tv_sec < right.tv_sec || + (mTime.tv_sec == right.tv_sec && + mTime.tv_usec < right.tv_usec); + } + bool before(Timestamp right) { return before(right.mTime); } + + /* ------------------------------------------------------------------- + * return true if my timestamp is after the right timestamp. + * ------------------------------------------------------------------- */ + bool after(timeval right) { + return mTime.tv_sec > right.tv_sec || + (mTime.tv_sec == right.tv_sec && + mTime.tv_usec > right.tv_usec); + } + bool after(Timestamp right) { return after(right.mTime); } + + /** + * This function returns the fraction of time elapsed after the beginning + * till the end + */ + double fraction(Timestamp currentTime, Timestamp endTime) { + if ((currentTime.after(*this)) && (endTime.after(currentTime))) { + return(((double)currentTime.subUsec(*this)) / + ((double)endTime.subUsec(*this))); + } else { + return -1.0; + } + } + +protected: + enum { + kMillion = 1000000 + }; + + struct timeval mTime; + +}; // end class Timestamp + +#endif // TIMESTAMP_H diff --git a/include/active_hosts.h b/include/active_hosts.h new file mode 100644 index 0000000..9635032 --- /dev/null +++ b/include/active_hosts.h @@ -0,0 +1,95 @@ +/*--------------------------------------------------------------- + * Copyright (c) 1999,2000,2001,2002,2003 + * The Board of Trustees of the University of Illinois + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software (Iperf) and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the names of the University of Illinois, NCSA, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * National Laboratory for Applied Network Research + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * http://www.ncsa.uiuc.edu + * ________________________________________________________________ + * + * List.h + * by Kevin Gibbs <kgibbs@ncsa.uiuc.edu> + * + * renamed to active_hosts.h + * ------------------------------------------------------------------- + */ + +#ifndef Iperf_LIST_H +#define Iperf_LIST_H + +#include "headers.h" +#include "Settings.hpp" +#include "Mutex.h" + +/* + * A List entry that consists of a sockaddr + * a pointer to the Audience that sockaddr is + * associated with and a pointer to the next + * entry + */ +struct Iperf_ListEntry { + iperf_sockaddr host; + struct SumReport *sum_report; + int thread_count; +#if WIN32 + SOCKET socket; +#else + int socket; +#endif + struct Iperf_ListEntry *next; +}; + +struct Iperf_Table { + Mutex my_mutex; + struct Iperf_ListEntry *root; + int count; + int total_count; + int groupid; +}; + +/* + * Functions to modify or search the list + */ +void Iperf_initialize_active_table (void); +void Iperf_destroy_active_table (void); +int Iperf_push_host (struct thread_Settings *agent); +int Iperf_push_host_port_conditional (struct thread_Settings *agent); +void Iperf_remove_host (struct thread_Settings *agent); +#endif diff --git a/include/checksums.h b/include/checksums.h new file mode 100644 index 0000000..2b3e594 --- /dev/null +++ b/include/checksums.h @@ -0,0 +1,62 @@ +/*--------------------------------------------------------------- + * Copyright (c) 2018 + * Broadcom Corporation + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the name of Broadcom Coporation, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * + * + * UDP checksums v4 and v6 + * + * The checksum calculation is defined in RFC 768 + * hints as to how to calculate it efficiently are in RFC 1071 + * + * by Robert J. McMahon (rjmcmahon@rjmcmahon.com, bob.mcmahon@broadcom.com) + * ------------------------------------------------------------------- + */ + +#ifndef CHECKSUMS_H +#define CHECKSUMS_H +#ifdef __cplusplus +extern "C" { +#endif +uint32_t udpchecksum(const void *l3pdu, const void *udp_hdr, int udplen, int v6); +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif /* CHEKCSUMS_H */ diff --git a/include/config.win32.h b/include/config.win32.h new file mode 100644 index 0000000..d648bf9 --- /dev/null +++ b/include/config.win32.h @@ -0,0 +1,82 @@ +/* config.h. Generated by hand for Windows. */ +#ifndef CONFIG_H +#define CONFIG_H + +/* =================================================================== + * config.h + * + * config.h is derived from config.h.in -- do not edit config.h + * + * This contains variables that the configure script checks and + * then defines or undefines. The source code checks for these + * variables to know if certain features are present. + * + * by Mark Gates <mgates@nlanr.net> + * + * Copyright 1999 The Board of Trustees of the University of Illinois + * All rights reserved. See doc/license.txt for complete text. + * + * $Id: config.win32.h,v 1.1.1.1 2004/05/18 01:50:44 kgibbs Exp $ + * =================================================================== */ + +/* Define if threads exist (using pthreads or Win32 threads) */ +/* #undef HAVE_POSIX_THREAD */ +#define HAVE_WIN32_THREAD 1 +/* #undef _REENTRANT */ + +/* Define if on OSF1 and need special extern "C" around some header files */ +/* #undef SPECIAL_OSF1_EXTERN */ + +/* Define if the strings.h header file exists */ +/* #undef HAVE_STRINGS_H */ + +/* Define the intXX_t, u_intXX_t, size_t, ssize_t, and socklen_t types */ +/* On the Cray J90 there is no 4 byte integer, so we define int32_t + * but it is 8 bytes, and we leave HAVE_INT32_T undefined. */ +#define SIZEOF_INT 4 +#define HAVE_U_INT16_T 1 +#define HAVE_INT32_T 1 +#define HAVE_INT64_T 1 +#define HAVE_U_INT32_T 1 + +#define int32_t LONG32 +#define u_int16_t UINT16 +#define u_int32_t ULONG32 +/* #undef size_t */ +#define ssize_t int + +/* socklen_t usually defined in <sys/socket.h>. Unfortunately it doesn't + * work on some systems (like DEC OSF/1), so we'll use our own Socklen_t */ +#define Socklen_t int + +/* Define if you have these functions. */ +#define HAVE_SNPRINTF 1 +/* #undef HAVE_INET_PTON */ +/* #undef HAVE_INET_NTOP */ +/* #undef HAVE_GETTIMEOFDAY */ +/* #undef HAVE_PTHREAD_CANCEL */ +#define HAVE_USLEEP 1 +/* #undef HAVE_QUAD_SUPPORT */ +/* #undef HAVE_PRINTF_QD */ + +/* standard C++, which isn't always... */ +/* #undef bool */ +#define true 1 +#define false 0 + +/* Define if the host is Big Endian (network byte order) */ +/* #undef WORDS_BIGENDIAN */ + +/* Define if multicast support exists */ +#define HAVE_MULTICAST 1 + +/* Define if all IPv6 headers/structures are present */ +#define HAVE_IPV6 1 + +/* Define if IPv6 multicast support exists */ +#define HAVE_IPV6_MULTICAST 1 + +/* Define if Debugging of sockets is desired */ +/* #undef DBG_MJZ */ + +#endif /* CONFIG_H */ diff --git a/include/delay.h b/include/delay.h new file mode 100644 index 0000000..fee44c0 --- /dev/null +++ b/include/delay.h @@ -0,0 +1,78 @@ +/*--------------------------------------------------------------- + * Copyright (c) 1999,2000,2001,2002,2003 + * The Board of Trustees of the University of Illinois + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software (Iperf) and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the names of the University of Illinois, NCSA, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * National Laboratory for Applied Network Research + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * http://www.ncsa.uiuc.edu + * ________________________________________________________________ + * + * delay.h + * by Mark Gates <mgates@nlanr.net> + * ------------------------------------------------------------------- + * accurate microsecond delay + * ------------------------------------------------------------------- */ +#ifndef DELAY_H +#define DELAY_H +#ifdef __cplusplus +extern "C" { +#endif +#include <time.h> +void delay_loop( unsigned long usecs ); +void delay_busyloop(unsigned long usecs); +void delay_nanosleep(unsigned long usecs); +int clock_usleep(struct timeval *request); +int clock_usleep_abstime(struct timeval *request); +#ifdef HAVE_KALMAN +// Kalman filter states +struct kalman_state { + double q; //process noise covariance + double r; //measurement noise covariance + double x; //value + double p; //estimation error covariance + double k; //kalman gain +}; +void delay_kalman(unsigned long usecs); +#endif +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif /* DELAY_H */ diff --git a/include/dscp.h b/include/dscp.h new file mode 100644 index 0000000..fe5486e --- /dev/null +++ b/include/dscp.h @@ -0,0 +1,58 @@ +/*--------------------------------------------------------------- + * Copyright (c) 2022 + * Broadcom Corporation + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the name of Broadcom Coporation, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * + * Header file for dscp parsing + * + * by Robert J. McMahon (rjmcmahon@rjmcmahon.com, bob.mcmahon@broadcom.com) + * ------------------------------------------------------------------- */ + +#ifndef DSCP_H +#define DSCP_H +#ifdef __cplusplus +extern "C" { +#endif +int parse_ipqos(const char *cp); +const char * iptos2str(int iptos); +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif /* DSCP_H */ diff --git a/include/gettcpinfo.h b/include/gettcpinfo.h new file mode 100644 index 0000000..995ee20 --- /dev/null +++ b/include/gettcpinfo.h @@ -0,0 +1,82 @@ +/*--------------------------------------------------------------- + * Copyright (c) 2021 + * Broadcom Corporation + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the name of Broadcom Coporation, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * + * gettcpinfo.c + * Suppport for tcp info in a portable way + * + * by Robert J. McMahon (rjmcmahon@rjmcmahon.com, bob.mcmahon@broadcom.com) + * ------------------------------------------------------------------- + */ +#ifndef GETTCPINFO_H +#define GETTCPINFO_H + +#include "headers.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct iperf_tcpstats { + bool isValid; + int rtt; + double connecttime; +#if HAVE_TCP_STATS + int cwnd; + int rttvar; + intmax_t retry; + intmax_t retry_prev; + intmax_t retry_tot; + int mss_negotiated; +#endif +}; + +#if WIN32 +void gettcpinfo(SOCKET sock, struct iperf_tcpstats *sample); +#else +void gettcpinfo(int sock, struct iperf_tcpstats *sample); +#endif +void tcpstats_copy (struct iperf_tcpstats *stats_dst, struct iperf_tcpstats *stats_src); + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif diff --git a/include/gettimeofday.h b/include/gettimeofday.h new file mode 100644 index 0000000..56b0d89 --- /dev/null +++ b/include/gettimeofday.h @@ -0,0 +1,83 @@ +/*--------------------------------------------------------------- + * Copyright (c) 1999,2000,2001,2002,2003 + * The Board of Trustees of the University of Illinois + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software (Iperf) and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the names of the University of Illinois, NCSA, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * National Laboratory for Applied Network Research + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * http://www.ncsa.uiuc.edu + * ________________________________________________________________ + * + * gettimeofday.h + * + * Mark Gates <mgates@nlanr.net> + * ------------------------------------------------------------------- + * An implementation of gettimeofday for Windows. + * ------------------------------------------------------------------- */ + +#ifndef GETTIMEOFDAY_H +#define GETTIMEOFDAY_H + +#ifndef HAVE_GETTIMEOFDAY + + #ifdef __cplusplus +extern "C" { +#endif + +int gettimeofday( struct timeval* tv, void* timezone ); + +#ifdef __cplusplus +} /* end extern "C" */ + #endif + +#else +#include <sys/time.h> +#endif /* HAVE_GETTIMEOFDAY */ +#endif /* GETTIMEOFDAY_H */ + + + + + + + + + + + diff --git a/include/gnu_getopt.h b/include/gnu_getopt.h new file mode 100644 index 0000000..de8ba9f --- /dev/null +++ b/include/gnu_getopt.h @@ -0,0 +1,136 @@ +/* Declarations for gnu_getopt. + Copyright (C) 1989,90,91,92,93,94,96,97 Free Software Foundation, Inc. + + This file is part of the GNU C Library. Its master source is NOT part of + the C library, however. The master source lives in /gd/gnu/lib. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* + * modified July 9, 1999 by mark gates <mgates@nlanr.net> + * Dec 17, 1999 + * + * renamed all functions and variables by prepending "gnu_" + * removed/redid a bunch of stuff under the assumption we're + * using a modern standard C compiler. + * + * $Id: gnu_getopt.h,v 1.1.1.1 2004/05/18 01:50:44 kgibbs Exp $ + */ + +#ifndef _GETOPT_H + #define _GETOPT_H 1 + + #ifdef __cplusplus +extern "C" { +#endif + +/* For communication from `gnu_getopt' to the caller. + When `gnu_getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +extern char *gnu_optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `gnu_getopt'. + + On entry to `gnu_getopt', zero means this is the first call; initialize. + + When `gnu_getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `gnu_optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +extern int gnu_optind; + +/* Callers store zero here to inhibit the error message `gnu_getopt' prints + for unrecognized options. */ + +extern int gnu_opterr; + +/* Set to an option character which was unrecognized. */ + +extern int gnu_optopt; + +/* Describe the long-named options requested by the application. + The LONG_OPTIONS argument to gnu_getopt_long or getopt_long_only is a vector + of `struct option' terminated by an element containing a name which is + zero. + + The field `has_arg' is: + no_argument (or 0) if the option does not take an argument, + required_argument (or 1) if the option requires an argument, + optional_argument (or 2) if the option takes an optional argument. + + If the field `flag' is not NULL, it points to a variable that is set + to the value given in the field `val' when the option is found, but + left unchanged if the option is not found. + + To have a long-named option do something other than set an `int' to + a compiled-in constant, such as set a value from `gnu_optarg', set the + option's `flag' field to zero and its `val' field to a nonzero + value (the equivalent single-letter option character, if there is + one). For long options that have a zero `flag' field, `gnu_getopt' + returns the contents of the `val' field. */ + +/* has_arg can't be an enum because some compilers complain about + type mismatches in all the code that assumes it is an int. */ + +struct option { + const char *name; + int has_arg; + int *flag; + int val; +}; + +/* Names for the values of the `has_arg' field of `struct option'. */ + +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +int gnu_getopt( int argc, + char *const *argv, + const char *optstring ); + +int gnu_getopt_long( int argc, + char *const *argv, + const char *options, + const struct option *long_options, + int *opt_index ); + +int gnu_getopt_long_only( int argc, + char *const *argv, + const char *options, + const struct option *long_options, + int *opt_index ); + +/* Internal only. Users should not call this directly. */ +int _gnu_getopt_internal( int argc, + char *const *argv, + const char *optstring, + const struct option *longopts, + int *longind, + int long_only ); + +#ifdef __cplusplus +} /* end extern "C" */ + #endif + +#endif /* _GETOPT_H */ diff --git a/include/headers.h b/include/headers.h new file mode 100644 index 0000000..6fb499d --- /dev/null +++ b/include/headers.h @@ -0,0 +1,302 @@ +/*--------------------------------------------------------------- + * Copyright (c) 1999,2000,2001,2002,2003 + * The Board of Trustees of the University of Illinois + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software (Iperf) and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the names of the University of Illinois, NCSA, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * National Laboratory for Applied Network Research + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * http://www.ncsa.uiuc.edu + * ________________________________________________________________ + * + * headers.h + * by Mark Gates <mgates@nlanr.net> + * ------------------------------------------------------------------- + * All system headers required by iperf. + * This could be processed to form a single precompiled header, + * to avoid overhead of compiling it multiple times. + * This also verifies a few things are defined, for portability. + * ------------------------------------------------------------------- */ + +#ifndef HEADERS_H +#define HEADERS_H + + +#ifdef HAVE_CONFIG_H + #include "config.h" + +/* OSF1 (at least the system I use) needs extern C + * around the <netdb.h> and <arpa/inet.h> files. */ + #if defined( SPECIAL_OSF1_EXTERN ) && defined( __cplusplus ) + #define SPECIAL_OSF1_EXTERN_C_START extern "C" { + #define SPECIAL_OSF1_EXTERN_C_STOP } + #else + #define SPECIAL_OSF1_EXTERN_C_START + #define SPECIAL_OSF1_EXTERN_C_STOP + #endif +#endif /* HAVE_CONFIG_H */ + +/* standard C headers */ +#include <stdlib.h> +#include <stdio.h> +#include <assert.h> +#include <ctype.h> +#include <errno.h> +#include <string.h> +#include <time.h> +#include <float.h> +#include <sys/types.h> +#include <fcntl.h> +#include <inttypes.h> +#include <limits.h> + +#ifdef HAVE_STDBOOL_H +# include <stdbool.h> +#else +# ifndef HAVE__BOOL +# ifdef __cplusplus +typedef bool _Bool; +# else +# define _Bool signed char +# endif +# endif +# define bool _Bool +# define false 0 +# define true 1 +# define __bool_true_false_are_defined 1 +#endif + + +// v4: 1470 bytes UDP payload will fill one and only one ethernet datagram (IPv4 overhead is 20 bytes) +#define kDefault_UDPBufLen 1470 +// v6: 1450 bytes UDP payload will fill one and only one ethernet datagram (IPv6 overhead is 40 bytes) +#define kDefault_UDPBufLenV6 1450 +#define IPV4HDRLEN 20 +#define IPV6HDRLEN 40 +#define UDPHDRLEN 8 + +#if ((defined HAVE_SSM_MULTICAST) || (defined HAVE_DECL_SO_BINDTODEVICE)) && (defined HAVE_NET_IF_H) +#include <net/if.h> +#endif +#ifdef HAVE_SYS_IOCTL_H +#include <sys/ioctl.h> +#endif +#ifdef HAVE_SYS_SOCKIO_H +#include <sys/sockio.h> +#endif +#ifdef HAVE_LINUX_SOCKIOS_H +#include <linux/sockios.h> +#endif +#if defined(HAVE_LINUX_FILTER_H) && defined(HAVE_AF_PACKET) +#include <net/ethernet.h> +#endif +#if ((HAVE_TUNTAP_TAP) || (HAVE_TUNTAP_TUN)) +#include <linux/if_tun.h> +#endif + +// AF_PACKET HEADERS +#if defined(HAVE_LINUX_FILTER_H) && defined(HAVE_AF_PACKET) +// Bummer, AF_PACKET requires kernel headers as <netpacket/packet.h> isn't sufficient +#include <linux/filter.h> +#include <linux/if_packet.h> +#include <linux/ip.h> +#include <linux/udp.h> +// In older linux kernels, the kernel headers and glibc headers are in conflict, +// specificially <linux/in6.h> and <netinit/in.h> +// preventing the following include: +// #include <linux/ipv6.h> (which includes <linux/in6.h>) +// and the use of sizeof(struct ipv6hdr) +// +// See https://patchwork.ozlabs.org/patch/631400/ +// +// "In upstream kernel 56c176c9 the _UAPI prefix was stripped and +// this broke our synchronized headers again. We now need to check +// for _LINUX_IN6_H and _IPV6_H, and keep checking the old versions +// of the header guard checks for maximum backwards compatibility +// with older Linux headers (the history is actually a bit muddled +// here and it appears upstream linus kernel broke this 10 months +// *before* our fix was ever applied to glibc, but without glibc +// testing we didn't notice and distro kernels have their own +// testing to fix this)." +// +// The use cases fixed by this patch are: +// #include <linux/in6.h> +// #include <netinet/in.h> +// +// force the ipv6hdr length to 40 vs use of sizeof(struct ipv6hdr) + +#endif // HAVE_AF_PACKET + +#ifdef WIN32 + +/* Windows config file */ +// #include "config.win32.h" + +/* Windows headers */ +#ifdef _WIN32_WINNT +#undef _WIN32_WINNT +#endif + #define _WIN32_WINNT 0x0501 /* use (at least) WinXP API */ + #define WIN32_LEAN_AND_MEAN /* exclude unnecesary headers */ + #include <windows.h> + #include <winsock2.h> + #include <ws2tcpip.h> + #include <process.h> + +/* define EINTR, just to help compile; it isn't useful */ + #ifndef EINTR + #define EINTR WSAEINTR + #endif // EINTR + +/* Visual C++ has INT64, but not 'long long'. + * Metrowerks has 'long long', but INT64 doesn't work. */ + #ifdef __MWERKS__ + #define int64_t long long + #else + #define int64_t INT64 + #endif // __MWERKS__ + +/* Visual C++ has _snprintf instead of snprintf */ + #ifndef __MWERKS__ + #define snprintf _snprintf + #endif // __MWERKS__ + +/* close, read, and write only work on files in Windows. + * I get away with #defining them because I don't read files. */ + #define close( s ) closesocket( s ) + #define read( s, b, l ) recv( s, (char*) b, l, 0 ) + #define write( s, b, l ) send( s, (char*) b, l, 0 ) + +/* usleep is in unistd.h, but that would conflict with the +close/read/write redefinitin above */ +int usleep(useconds_t usec); + +#else /* not defined WIN32 */ + +/* used in Win32 for error checking, + * rather than checking rc < 0 as unix usually does */ +#define SOCKET_ERROR -1 +#define INVALID_SOCKET -1 + +#include <unistd.h> + +#endif /* not defined WIN32 */ + +/* required on AIX for FD_SET (requires bzero). + * often this is the same as <string.h> */ + #ifdef HAVE_STRINGS_H + #include <strings.h> + #endif // HAVE_STRINGS_H + +/* unix headers */ +#ifdef HAVE_SYS_SOCKET_H + #include <sys/socket.h> +#endif + #include <sys/time.h> +#ifdef HAVE_SIGNAL_H + #include <signal.h> +#endif + +#ifdef HAVE_SYSLOG_H +/** Added for daemonizing the process */ + #include <syslog.h> +#endif + +#ifdef HAVE_NETDB_H +SPECIAL_OSF1_EXTERN_C_START + #include <netdb.h> +SPECIAL_OSF1_EXTERN_C_STOP +#endif +#if HAVE_NETINET_IN_H +#include <netinet/in.h> +SPECIAL_OSF1_EXTERN_C_START + #include <arpa/inet.h> /* netinet/in.h must be before this on SunOS */ +SPECIAL_OSF1_EXTERN_C_STOP +#endif +#if HAVE_NETINET_TCP_H +#include <netinet/tcp.h> +#endif + +#ifdef HAVE_POSIX_THREAD +#include <pthread.h> +#endif // HAVE_POSIX_THREAD + +#ifndef INET6_ADDRSTRLEN + #define INET6_ADDRSTRLEN 40 +#endif +#ifndef INET_ADDRSTRLEN + #define INET_ADDRSTRLEN 15 +#endif + +//#ifdef __cplusplus + #if HAVE_IPV6 + #define REPORT_ADDRLEN (INET6_ADDRSTRLEN + 1) +typedef struct sockaddr_storage iperf_sockaddr; + #else + #define REPORT_ADDRLEN (INET_ADDRSTRLEN + 1) +typedef struct sockaddr_in iperf_sockaddr; + #endif +//#endif + +// inttypes.h is already included + +#ifdef HAVE_FASTSAMPLING +#define IPERFTimeFrmt "%4.4f-%4.4f" +#define IPERFTimeSpace " " +#else +#define IPERFTimeFrmt "%4.2f-%4.2f" +#define IPERFTimeSpace " " +#endif + +/* in case the OS doesn't have these, we provide our own implementations */ +#include "gettimeofday.h" +#include "inet_aton.h" +#include "snprintf.h" + +#ifndef SHUT_RD + #define SHUT_RD 0 + #define SHUT_WR 1 + #define SHUT_RDWR 2 +#endif // SHUT_RD + + +/* Internal debug */ +//#define INITIAL_PACKETID 0x7FFFFF00LL +//#define SHOW_PACKETID + +#endif /* HEADERS_H */ diff --git a/include/histogram.h b/include/histogram.h new file mode 100644 index 0000000..2cd7b3b --- /dev/null +++ b/include/histogram.h @@ -0,0 +1,82 @@ +/*--------------------------------------------------------------- + * Copyrighta (c) 2017 + * Broadcom Corporation + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the name of Broadcom Coporation, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * + * histogram.h + * Suppport for isochonronous traffic testing + * + * by Robert J. McMahon (rjmcmahon@rjmcmahon.com, bob.mcmahon@broadcom.com) + * ------------------------------------------------------------------- + */ +#ifndef HISTOGRAMC_H +#define HISTOGRAMC_H + +struct histogram { + unsigned int id; + unsigned int *mybins; + unsigned int bincount; + unsigned int binwidth; + unsigned int populationcnt; + int final; + int maxbin; + int fmaxbin; + double maxval; + double fmaxval; + struct timeval maxts; + struct timeval fmaxts; + float offset; + unsigned int cntloweroutofbounds; + unsigned int cntupperoutofbounds; + char *myname; + char *outbuf; + float units; + double ci_lower; + double ci_upper; + struct histogram *prev; +}; + +extern struct histogram *histogram_init(unsigned int bincount, unsigned int binwidth, float offset,\ + float units, double ci_lower, double ci_upper, unsigned int id, char *name); +extern void histogram_delete(struct histogram *h); +extern int histogram_insert(struct histogram *h, float value, struct timeval *ts); +extern void histogram_clear(struct histogram *h); +extern void histogram_add(struct histogram *to, struct histogram *from); +extern void histogram_print(struct histogram *h, double, double); +#endif // HISTOGRAMC_H diff --git a/include/inet_aton.h b/include/inet_aton.h new file mode 100644 index 0000000..08b9750 --- /dev/null +++ b/include/inet_aton.h @@ -0,0 +1,108 @@ +/*--------------------------------------------------------------- + * Copyright (c) 1999,2000,2001,2002,2003 + * The Board of Trustees of the University of Illinois + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software (Iperf) and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the names of the University of Illinois, NCSA, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * National Laboratory for Applied Network Research + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * http://www.ncsa.uiuc.edu + * ________________________________________________________________ + * + * inet_aton.h + * + * Mark Gates <mgates@nlanr.net> + * Kevin Gibbs <kgibbs@ncsa.uiuc.edu> Sept. 2002 + * to use this prototype, make sure HAVE_INET_PTON is not defined + * to use this prototype, make sure HAVE_INET_NTOP is not defined + * + * =================================================================== */ + +#ifndef INET_ATON_H +#define INET_ATON_H + + +#include "headers.h" + +/* + * inet_pton is the new, better version of inet_aton. + * inet_aton is not IP version agnostic. + * inet_aton is the new, better version of inet_addr. + * inet_addr is incorrect in that it returns -1 as an error value, + * while -1 (0xFFFFFFFF) is a valid IP address (255.255.255.255). + */ + +const char* inet_ntop_hide(int af, const void *src, char *dst, socklen_t size); +const char* inet_ntop4_hide(const unsigned char *src, char *dst, socklen_t size); + +#ifndef HAVE_INET_NTOP + +#ifdef __cplusplus +extern "C" { +#endif +const char* inet_ntop(int af, const void *src, char *dst, socklen_t size); +const char* inet_ntop4(const unsigned char *src, char *dst, socklen_t size); + +#if HAVE_IPV6 +const char* inet_ntop6(const unsigned char *src, char *dst, + socklen_t size); +#endif + + +#ifdef __cplusplus +} /* end extern "C" */ + #endif + +#endif /* HAVE_INET_NTOP */ +#ifndef HAVE_INET_PTON + + #ifdef __cplusplus +extern "C" { +#endif +int inet_pton(int af, const char *src, void *dst); +int inet_pton4(const char *src, unsigned char *dst); +#if HAVE_IPV6 +int inet_pton6(const char *src, unsigned char *dst); +#endif + +#ifdef __cplusplus +} /* end extern "C" */ + #endif + +#endif /* HAVE_INET_PTON */ +#endif /* INET_ATON_H */ diff --git a/include/iperf_formattime.h b/include/iperf_formattime.h new file mode 100644 index 0000000..d331550 --- /dev/null +++ b/include/iperf_formattime.h @@ -0,0 +1,69 @@ +/*--------------------------------------------------------------- + * Copyright (c) 2023 + * Broadcom Corporation + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the name of Broadcom Coporation, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * + * iperf_formattime + * wrapper around strftime.c for iperf supported formatting + * + * by Robert J. McMahon (rjmcmahon@rjmcmahon.com, bob.mcmahon@broadcom.com) + * ------------------------------------------------------------------- + */ +#ifndef IPERFFORMATTIME_H +#define IPERFFORMATTIME_H + +#include "headers.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum TimeFormatType { + YearThruSec = 0, + YearThruSecTZ, + CSV, + CSVTZ +}; +void iperf_formattime (char *timestr, int buflen, struct timeval timestamp, bool prec_ms, bool utc_time, enum TimeFormatType ftype); + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif diff --git a/include/isochronous.hpp b/include/isochronous.hpp new file mode 100644 index 0000000..7fb5a92 --- /dev/null +++ b/include/isochronous.hpp @@ -0,0 +1,88 @@ +/*--------------------------------------------------------------- + * Copyright (c) 2017 + * Broadcom Corporation + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the name of Broadcom Coporation, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * + * isochronous.hpp + * Suppport for isochonronous traffic testing + * + * by Robert J. McMahon (rjmcmahon@rjmcmahon.com, bob.mcmahon@broadcom.com) + * ------------------------------------------------------------------- + */ +#ifndef ISOCHRONOUS_H +#define ISOCHRONOUS_H + +#include <time.h> +#include "Settings.hpp" +#include "Timestamp.hpp" + +/* ------------------------------------------------------------------- */ +namespace Isochronous { + class FrameCounter { + public : + FrameCounter(double, const Timestamp& start); + FrameCounter(double); + ~FrameCounter(); + unsigned int get(void) const; + unsigned int get(long *); + unsigned int get(const Timestamp&) const; + unsigned int period_us(void); + unsigned int wait_tick(long *sched_err); + unsigned int wait_sync(long sec, long usec); + long getSecs(void); + long getUsecs(void); + void reset(void); + Timestamp next_slot(void); + unsigned int slip; + private : + double frequency; + Timestamp startTime; + Timestamp nextslotTime; + unsigned int period; // units microseconds or 100 ns + unsigned int lastcounter; + unsigned int slot_counter; +#ifdef WIN32 + int mySetWaitableTimer (long delay_time); + HANDLE my_timer; // Timer handle + LARGE_INTEGER delay; // units is 100 nanoseconds +#endif + + }; // end class FrameCounter +} +#endif // ISOCHRONOUS_H diff --git a/include/packet_ring.h b/include/packet_ring.h new file mode 100644 index 0000000..3ac6b91 --- /dev/null +++ b/include/packet_ring.h @@ -0,0 +1,127 @@ +/*--------------------------------------------------------------- + * Copyright (c) 2019 + * Broadcom Corporation + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the name of Broadcom Coporation, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * + * packet_ring.h + * Suppport for packet rings between threads + * + * by Robert J. McMahon (rjmcmahon@rjmcmahon.com, bob.mcmahon@broadcom.com) + * ------------------------------------------------------------------- + */ +#ifndef PACKETRINGC_H +#define PACKETRINGC_H + +#include "Condition.h" +#include "gettcpinfo.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ACKRING_DEFAULTSIZE 100 + +struct ReportStruct { + intmax_t packetID; + intmax_t packetLen; + struct timeval packetTime; + struct timeval prevPacketTime; + struct timeval sentTime; + struct timeval prevSentTime; + int errwrite; + int emptyreport; + int l2errors; + int l2len; + int expected_l2len; + // isochStartTime is overloaded: first write timestamp of the frame or burst w/trip-times or very first read w/o trip-times + // reporter calculation will compute latency accordingly + struct timeval isochStartTime; + uint32_t prevframeID; + uint32_t frameID; + uint32_t burstsize; + uint32_t burstperiod; + uint32_t remaining; + int transit_ready; + int writecnt; + long write_time; + bool scheduled; + long sched_err; + struct timeval sentTimeRX; + struct timeval sentTimeTX; + struct iperf_tcpstats tcpstats; +}; + +struct PacketRing { + // producer and consumer + // must be an atomic type, e.g. int + // otherwise reads/write can be torn + int producer; + int consumer; + int maxcount; + int consumerdone; + int awaitcounter; + int mutex_enable; + int bytes; + + // Use a condition variables + // o) awake_producer - producer waits for the consumer thread to + // make space or end (signaled by the consumer) + // o) awake_consumer - signal the consumer thread to to run + // (signaled by the producer) + struct Condition *awake_producer; + struct Condition *awake_consumer; + struct ReportStruct *data; +}; + +extern struct PacketRing * packetring_init(int count, struct Condition *awake_consumer, struct Condition *awake_producer); +extern void packetring_enqueue(struct PacketRing *pr, struct ReportStruct *metapacket); +extern struct ReportStruct *packetring_dequeue(struct PacketRing * pr); +extern void enqueue_ackring(struct PacketRing *pr, struct ReportStruct *metapacket); +extern struct ReportStruct *dequeue_ackring(struct PacketRing * pr); +extern void packetring_free(struct PacketRing *pr); +extern void free_ackring(struct PacketRing *pr); +#ifdef HAVE_THREAD_DEBUG +extern int packetring_getcount(struct PacketRing *pr); +#endif + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif // PACKETRINGC_H diff --git a/include/payloads.h b/include/payloads.h new file mode 100644 index 0000000..30080d9 --- /dev/null +++ b/include/payloads.h @@ -0,0 +1,622 @@ +/*--------------------------------------------------------------- + * Copyrighta (c) 2019 + * Broadcom Corporation + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the name of Broadcom Coporation, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * + * payloads.h + * Iperf 2 packet or socket payloads/protocols + * + * by Robert J. McMahon (rjmcmahon@rjmcmahon.com, bob.mcmahon@broadcom.com) + * ------------------------------------------------------------------- + */ +#ifndef PAYLOADSC_H +#define PAYLOADSC_H + +#ifdef __cplusplus +extern "C" { +#endif +/* + * Message header flags + */ + +#define TAPBYTESSLOP 512 + +/* key for permit */ +#define HEADER_KEYCHECK 0x10000000 +#define HEADER_KEYL1 0x01000000 +#define HEADER_KEYL2 0x02000000 +#define HEADER_KEYLEN_MASK 0x0000FFFE // Lower bit used by V1 hdr +#define DEFAULT_PERMITKEY_LEN 16 +#define MIN_PERMITKEY_LEN 4 +#define MAX_PERMITKEY_LEN 128 + +/* + * base flags, keep compatible with older versions + */ +#define HEADER_VERSION1 0x80000000 +#define HEADER_EXTEND 0x40000000 +#define HEADER_UDPTESTS 0x20000000 +// reserved for keycheck flag 0x10000000 +#define HEADER_SEQNO64B 0x08000000 +#define HEADER_VERSION2 0x04000000 +#define HEADER_V2PEERDETECT 0x02000000 +#define HEADER_UDPAVOID2 0x02000000 +#define HEADER_UDPAVOID1 0x01000000 +#define HEADER_BOUNCEBACK 0x00800000 + +#define HEADER32_SMALL_TRIPTIMES 0x00020000 +#define HEADER_LEN_BIT 0x00010000 +#define HEADER_LEN_MASK 0x000001FE +#define MAX_HEADER_LEN 256 +#define SERVER_HEADER_EXTEND 0x40000000 +#define RUN_NOW 0x00000001 +#define HEADER16_SMALL_TRIPTIMES 0x0002 // use is 16 bits and not 32 bits + +// Bounceback flag +#define HEADER_BBQUICKACK 0x8000 +#define HEADER_BBCLOCKSYNCED 0x4000 // used in the bb header only +#define HEADER_BBTOS 0x2000 +#define HEADER_BBSTOP 0x1000 + +// newer flags available per HEADER_EXTEND +// Below flags are used to pass test settings in *every* UDP packet +// and not just during the header exchange +#define HEADER_ISOCH 0x0001 +#define HEADER_L2ETHPIPV6 0x0002 +#define HEADER_L2LENCHECK 0x0004 +#define HEADER_NOUDPFIN 0x0008 +#define HEADER_TRIPTIME 0x0010 +#define HEADER_UNUSED2 0x0020 +#define HEADER_ISOCH_SETTINGS 0x0040 +#define HEADER_UNITS_PPS 0x0080 +#define HEADER_BWSET 0x0100 +#define HEADER_FQRATESET 0x0200 +#define HEADER_REVERSE 0x0400 +#define HEADER_FULLDUPLEX 0x0800 +#define HEADER_EPOCH_START 0x1000 +#define HEADER_PERIODICBURST 0x2000 +#define HEADER_WRITEPREFETCH 0x4000 +#define HEADER_TCPQUICKACK 0x8000 + +// later features +#define HDRXACKMAX 2500000 // default 2.5 seconds, units microseconds +#define HDRXACKMIN 10000 // default 10 ms, units microsecond +/* + * Structures used for test messages which + * are exchanged between the client and the Server/Listener + */ +enum MsgType { + CLIENTHDR = 0x1, + CLIENTHDRACK, + CLIENTTCPHDR, + SERVERHDR, + SERVERHDRACK +}; + +#define MINIPERFPAYLOAD 18 +// Minimum IPv4 frame size = 18 (Ethernet) + 20 (IPv4) + 8 (UDP) + 18 (payload) = 64 bytes +// Minimum IPv6 frame size = 18 (Ethernet) + 40 (IPv6) + 8 (UDP) + 18 (payload) = 84 bytes + +/* + * Structures below will be passed as network i/o + * between the client, listener and server + * and must be packed by the compilers + * Align on 32 bits (4 bytes) + */ +#pragma pack(push,4) +struct UDP_datagram { +// used to reference the 4 byte ID number we place in UDP datagrams +// Support 64 bit seqno on machines that support them + uint32_t id; + uint32_t tv_sec; + uint32_t tv_usec; + uint32_t id2; +}; + +struct hdr_typelen { + int32_t type; + int32_t length; +}; + +struct TCP_datagram { +// used to reference write ids and timestamps in TCP payloads + struct hdr_typelen typelen; + uint32_t id; + uint32_t id2; + uint32_t tv_sec; + uint32_t tv_usec; + uint32_t reserved1; + uint32_t reserved2; +}; + +/* + * The client_hdr structure is sent from clients + * to servers to alert them of things that need + * to happen. Order must be perserved in all + * future releases for backward compatibility. + * 1.7 has flags, numThreads, mPort, and bufferlen + */ +struct client_hdr_v1 { + /* + * flags is a bitmap for different options + * the most significant bits are for determining + * which information is available. So 1.7 uses + * 0x80000000 and the next time information is added + * the 1.7 bit will be set and 0x40000000 will be + * set signifying additional information. If no + * information bits are set then the header is ignored. + * The lowest order diferentiates between dualtest and + * tradeoff modes, wheither the speaker needs to start + * immediately or after the audience finishes. + */ + int32_t flags; + int32_t numThreads; + int32_t mPort; + int32_t mBufLen; + int32_t mWinBand; + int32_t mAmount; +}; + +// +// Payload used for the bounce back feature +// +// Notes: +// o) flags is standard iperf 2 flags for test exchange info +// o) burst size is the payload size and size of bounce back write +// o) burst id is a running seq no +// o) send is the write timestamp +// o) bb_r2w_hold is an optional delay value between the read and bb write, typically expected as zero +// o) triptimes will support OWD measurements in each direction (useful for asymmetry testing) +// o) min payload +// - seven 32b or 28 bytes with round trip only, +// - eleven 32b or 44 bytes when including trip-times support +// o) no need for a bb read timestamp to be passed in the payload +// o) OWD calculations require e2e clock sync and --trip-times cli option +// o) no need to copy bb payload as rx buffer with be used for bounce back write +// o) single threaded design +// o) these are packed, be careful that the union doesn't break this +// + +struct bb_ts { + uint32_t sec; + uint32_t usec; +}; +struct bounceback_hdr { + uint32_t flags; + uint32_t bbsize; + uint32_t bbid; + uint16_t bbflags; + uint16_t tos; + uint32_t bbRunTime; //units 10 ms + struct bb_ts bbclientTx_ts; + struct bb_ts bbserverRx_ts; + struct bb_ts bbserverTx_ts; + uint32_t bbhold; // up to here is mandatory + uint32_t bbrtt; + struct bb_ts bbread_ts; +}; + +struct client_hdrext_isoch_settings { + int32_t FPSl; + int32_t FPSu; + int32_t Meanl; + int32_t Meanu; + int32_t Variancel; + int32_t Varianceu; + int32_t BurstIPGl; + int32_t BurstIPGu; +}; + +struct client_hdrext { + int32_t type; + int32_t length; + int16_t upperflags; + int16_t lowerflags; + uint32_t version_u; + uint32_t version_l; + uint16_t reserved; + uint16_t tos; + uint32_t lRate; + uint32_t uRate; + uint32_t TCPWritePrefetch; +}; + +struct client_hdrext_starttime_fq { + uint32_t reserved; + uint32_t start_tv_sec; + uint32_t start_tv_usec; + uint32_t fqratel; + uint32_t fqrateu; +}; + +/* + * TCP Isoch/burst payload structure + * + * 0 7 8 15 16 23 24 31 + * +--------+--------+--------+--------+ + * 1 | type | + * +--------+--------+--------+--------+ + * 2 | len | + * +--------+--------+--------+--------+ + * 3 | flags | + * +--------+--------+--------+--------+ + * 4 | reserved | + * +--------+--------+--------+--------+ + * 5 | isoch burst period (us) | + * +--------+--------+--------+--------+ + * 6 | isoch start timestamp (s) | + * +--------+--------+--------+--------+ + * 7 | isoch start timestamp (us) | + * +--------+--------+--------+--------+ + * 8 | burst id | + * +--------+--------+--------+--------+ + * 9 | burtsize | + * +--------+--------+--------+--------+ + * 10 | burst bytes remaining | + * +--------+--------+--------+--------+ + * 11 | seqno lower | + * +--------+--------+--------+--------+ + * 12 | seqno upper | + * +--------+--------+--------+--------+ + * 13 | tv_sec (write) | + * +--------+--------+--------+--------+ + * 14 | tv_usec (write) | + * +--------+--------+--------+--------+ + * 15 | tv_sec (read) | + * +--------+--------+--------+--------+ + * 16 | tv_usec (read) | + * +--------+--------+--------+--------+ + * 17 | tv_sec (write-ack) | + * +--------+--------+--------+--------+ + * 18 | tv_usec (write-ack) | + * +--------+--------+--------+--------+ + * 19 | tv_sec (read-ack) | + * +--------+--------+--------+--------+ + * 20 | tv_usec (read-ack) | + * +--------+--------+--------+--------+ + * 21 | reserved | + * +--------+--------+--------+--------+ + * 22 | reserved | + * +--------+--------+--------+--------+ + * 23 | reserved | + * +--------+--------+--------+--------+ + * 24 | reserved | + * +--------+--------+--------+--------+ + * + */ +struct TCP_oneway_triptime { + uint32_t write_tv_sec; + uint32_t write_tv_usec; + uint32_t read_tv_sec; + uint32_t read_tv_usec; +}; + +struct TCP_burst_payload { + uint32_t flags; + struct hdr_typelen typelen; + uint32_t start_tv_sec; + uint32_t start_tv_usec; + struct TCP_oneway_triptime send_tt; + uint32_t reserved0; + uint32_t burst_period_us; + uint32_t burst_id; + uint32_t burst_size; + uint32_t seqno_lower; + uint32_t seqno_upper; + struct TCP_oneway_triptime writeacktt; + uint32_t reserved1; + uint32_t reserved2; + uint32_t reserved3; + uint32_t reserved4; +}; + +/* + * UDP Full Isoch payload structure + * + * 0 7 8 15 16 23 24 31 + * +--------+--------+--------+--------+ + * 0x00 1 | seqno lower | + * +--------+--------+--------+--------+ + * 0x04 2 | tv_sec | + * +--------+--------+--------+--------+ + * 0x08 3 | tv_usec | + * +--------+--------+--------+--------+ + * 4 | seqno upper | + * +--------+--------+--------+--------+ + * 5 | flags (v1) | + * +--------+--------+--------+--------+ + * 6 | numThreads (v1) | + * +--------+--------+--------+--------+ + * 7 | mPort (v1) | + * +--------+--------+--------+--------+ + * 8 | bufferLen (v1) | + * +--------+--------+--------+--------+ + * 9 | mWinBand (v1) | + * +--------+--------+--------+--------+ + * 10 | mAmount (v1) | + * +--------+--------+--------+--------+ + * 11 | up flags | low flags | + * +--------+--------+--------+--------+ + * 12 | iperf version major | + * +--------+--------+--------+--------+ + * 13 | iperf version minor | + * +--------+--------+--------+--------+ + * 14 | reserved | TOS | + * +--------+--------+--------+--------+ + * 15 | rate | + * +--------+--------+--------+--------+ + * 16 | rate units | + * +--------+--------+--------+--------+ + * 17 | realtime (0.13) | + * +--------+--------+--------+--------+ + * 18 | isoch burst period (us) | + * +--------+--------+--------+--------+ + * 19 | isoch start timestamp (s) | + * +--------+--------+--------+--------+ + * 20 | isoch start timestamp (us) | + * +--------+--------+--------+--------+ + * 21 | isoch prev frameid | + * +--------+--------+--------+--------+ + * 22 | isoch frameid | + * +--------+--------+--------+--------+ + * 23 | isoch burtsize | + * +--------+--------+--------+--------+ + * 24 | isoch bytes remaining | + * +--------+--------+--------+--------+ + * 25 | isoch reserved | + * +--------+--------+--------+--------+ + * 26 | reserved (0.14 start) | + * +--------+--------+--------+--------+ + * 28 | start tv_sec (0.14) | + * +--------+--------+--------+--------+ + * 29 | start tv_usec | + * +--------+--------+--------+--------+ + * 27 | fqratel | + * +--------+--------+--------+--------+ + * 28 | fqrateu | + * +--------+--------+--------+--------+ + * 29 | FPSl | + * +--------+--------+--------+--------+ + * 30 | FPSu | + * +--------+--------+--------+--------+ + * 31 | Meanl | + * +--------+--------+--------+--------+ + * 32 | Meanu | + * +--------+--------+--------+--------+ + * 33 | Variancel | + * +--------+--------+--------+--------+ + * 34 | Varianceu | + * +--------+--------+--------+--------+ + * 35 | BurstIPGl | + * +--------+--------+--------+--------+ + * 36 | BurstIPG | + * +--------+--------+--------+--------+ + * + */ +struct isoch_payload { + uint32_t burstperiod; //period units microseconds + uint32_t start_tv_sec; + uint32_t start_tv_usec; + uint32_t prevframeid; + uint32_t frameid; + uint32_t burstsize; + uint32_t remaining; + uint32_t reserved; +}; + +struct permitKey { + uint16_t length; + char value[MAX_PERMITKEY_LEN]; +}; + +struct client_udp_testhdr { + struct UDP_datagram seqno_ts; + struct client_hdr_v1 base; + struct client_hdrext extend; + struct isoch_payload isoch; + struct client_hdrext_starttime_fq start_fq; + struct client_hdrext_isoch_settings isoch_settings; +}; + +struct client_udpsmall_testhdr { + struct UDP_datagram seqno_ts; + uint16_t flags; +}; + +struct client_hdr_ack_ts { + uint32_t sent_tv_sec; + uint32_t sent_tv_usec; + uint32_t sentrx_tv_sec; + uint32_t sentrx_tv_usec; + uint32_t ack_tv_sec; + uint32_t ack_tv_usec; +}; + +struct client_hdr_ack { + struct hdr_typelen typelen; + uint32_t flags; + uint32_t version_u; + uint32_t version_l; + uint32_t reserved1; + uint32_t reserved2; + struct client_hdr_ack_ts ts; +}; + +/* + * TCP first payload structure + * + * 0 7 8 15 16 23 24 31 + * +--------+--------+--------+--------+ + * 0x00 1 | flags (v1) | + * +--------+--------+--------+--------+ + * 2 | numThreads (v1) | + * +--------+--------+--------+--------+ + * 3 | mPort (v1) | + * +--------+--------+--------+--------+ + * 4 | bufferLen (v1) | + * +--------+--------+--------+--------+ + * 5 | mWinBand (v1) | + * +--------+--------+--------+--------+ + * 6 | mAmount (v1) | + * +--------+--------+--------+--------+ + * 7 | type (0.13) | + * +--------+--------+--------+--------+ + * 8 | len (0.13) | + * +--------+--------+--------+--------+ + * 9 | flags (0.13) | + * +--------+--------+--------+--------+ + * 10 | iperf version major | + * +--------+--------+--------+--------+ + * 11 | iperf version minor | + * +--------+--------+--------+--------+ + * 12 | reserved | TOS | + * +--------+--------+--------+--------+ + * 13 | rate | + * +--------+--------+--------+--------+ + * 14 | rate units | + * +--------+--------+--------+--------+ + * 15 | write prefetch (0.13) | + * +--------+--------+--------+--------+ + * 16 | reserved (0.14 start) | + * +--------+--------+--------+--------+ + * 17 | start tv_sec (0.14) | + * +--------+--------+--------+--------+ + * 18 | start tv_usec | + * +--------+--------+--------+--------+ + * 19 | fqratel | + * +--------+--------+--------+--------+ + * 20 | fqrateu | + * +--------+--------+--------+--------+ + * 21 | FPSl | + * +--------+--------+--------+--------+ + * 22 | FPSu | + * +--------+--------+--------+--------+ + * 23 | Meanl | + * +--------+--------+--------+--------+ + * 24 | Meanu | + * +--------+--------+--------+--------+ + * 25 | Variancel | + * +--------+--------+--------+--------+ + * 26 | Varianceu | + * +--------+--------+--------+--------+ + * 27 | BurstIPGl | + * +--------+--------+--------+--------+ + * 28 | BurstIPG | + * +--------+--------+--------+--------+ + */ +struct client_tcp_testhdr { + struct client_hdr_v1 base; + struct client_hdrext extend; + struct client_hdrext_starttime_fq start_fq; + struct client_hdrext_isoch_settings isoch_settings; + struct permitKey permitkey; +}; + +/* + * The server_hdr structure facilitates the server + * report of jitter and loss on the client side. + * It piggy_backs on the existing clear to close + * packet. + */ +struct server_hdr_v1 { + /* + * flags is a bitmap for different options + * the most significant bits are for determining + * which information is available. So 1.7 uses + * 0x80000000 and the next time information is added + * the 1.7 bit will be set and 0x40000000 will be + * set signifying additional information. If no + * information bits are set then the header is ignored. + */ + int32_t flags; + int32_t total_len1; + int32_t total_len2; + int32_t stop_sec; + int32_t stop_usec; + int32_t error_cnt; + int32_t outorder_cnt; + int32_t datagrams; + int32_t jitter1; + int32_t jitter2; +}; + +struct server_hdr_extension { + int32_t minTransit1; + int32_t minTransit2; + int32_t maxTransit1; + int32_t maxTransit2; + int32_t sumTransit1; + int32_t sumTransit2; + int32_t meanTransit1; + int32_t meanTransit2; + int32_t m2Transit1; + int32_t m2Transit2; + int32_t vdTransit1; + int32_t vdTransit2; + int32_t cntTransit; + int32_t cntIPG; + int32_t IPGsum; +}; + +// Extension for 64bit datagram counts +struct server_hdr_extension2 { + int32_t error_cnt2; + int32_t outorder_cnt2; + int32_t datagrams2; +}; + +struct server_hdr { + struct server_hdr_v1 base; + struct server_hdr_extension extend; + struct server_hdr_extension2 extend2; +}; + +#pragma pack(pop) + +#define SIZEOF_UDPHDRMSG_V1 (sizeof(struct client_hdrv1) + sizeof(struct UDP_datagram)) +#define SIZEOF_UDPHDRMSG_EXT (sizeof(struct client_udp_testhdr)) +#define SIZEOF_TCPHDRMSG_V1 (sizeof(struct client_hdr_v1)) +#define SIZEOF_TCPHDRMSG_EXT (sizeof(struct client_tcp_testhdr)) +#define MINMBUFALLOCSIZE (int) (sizeof(struct client_tcp_testhdr)) + TAPBYTESSLOP +#define MINTRIPTIMEPLAYOAD (int) (sizeof(struct client_udp_testhdr) - sizeof(struct client_hdrext_isoch_settings)) +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif // PAYLOADS diff --git a/include/pdfs.h b/include/pdfs.h new file mode 100644 index 0000000..1a3a47d --- /dev/null +++ b/include/pdfs.h @@ -0,0 +1,60 @@ +/*--------------------------------------------------------------- + * Copyright (c) 2017 + * Broadcom Corporation + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the name of Broadcom Coporation, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * + * Produce probability distribution functions, expected to be used + * for iperf client traffic emulations + * + * by Robert J. McMahon (rjmcmahon@rjmcmahon.com, bob.mcmahon@broadcom.com) + * ------------------------------------------------------------------- */ + +#ifndef PDFS_H +#define PDFS_H +#ifdef __cplusplus +extern "C" { +#endif +float normal(float mean, float variance); +float lognormal(float mu, float sigma); +float box_muller(void); +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif /* PDFS_H */ diff --git a/include/snprintf.h b/include/snprintf.h new file mode 100644 index 0000000..26e870f --- /dev/null +++ b/include/snprintf.h @@ -0,0 +1,40 @@ +#ifndef SNPRINTF_H +#define SNPRINTF_H + +/* =================================================================== + * snprintf.h + * + * This is from + * W. Richard Stevens, 'UNIX Network Programming', Vol 1, 2nd Edition, + * Prentice Hall, 1998. + * + * Mark Gates <mgates@nlanr.net> + * July 1998 + * + * to use this prototype, make sure HAVE_SNPRINTF is not defined + * + * =================================================================== */ + +/* + * Throughout the book I use snprintf() because it's safer than sprintf(). + * But as of the time of this writing, not all systems provide this + * function. The function below should only be built on those systems + * that do not provide a real snprintf(). + * The function below just acts like sprintf(); it is not safe, but it + * tries to detect overflow. + */ + +#ifndef HAVE_SNPRINTF + + #ifdef __cplusplus +extern "C" { +#endif + +int snprintf(char *buf, size_t size, const char *fmt, ...); + +#ifdef __cplusplus +} /* end extern "C" */ + #endif + +#endif /* HAVE_SNPRINTF */ +#endif /* SNPRINTF_H */ diff --git a/include/util.h b/include/util.h new file mode 100644 index 0000000..0f28ce4 --- /dev/null +++ b/include/util.h @@ -0,0 +1,281 @@ +/*--------------------------------------------------------------- + * Copyright (c) 1999,2000,2001,2002,2003 + * The Board of Trustees of the University of Illinois + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software (Iperf) and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the names of the University of Illinois, NCSA, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * National Laboratory for Applied Network Research + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * http://www.ncsa.uiuc.edu + * ________________________________________________________________ + * + * util.h + * by Mark Gates <mgates@nlanr.net> + * ------------------------------------------------------------------- + * various C utility functions. + * ------------------------------------------------------------------- */ + +#ifndef UTIL_H +#define UTIL_H + +#ifdef HAVE_CONFIG_H + #include "config.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +extern int sInterupted; + +/* ------------------------------------------------------------------- + * set/getsockopt wrappers for SO_RCVBUF and SO_SNDBUF; TCP_MAXSEG + * socket.c + * ------------------------------------------------------------------- */ +int setsock_tcp_windowsize(int inSock, int inTCPWin, int inSend); +int getsock_tcp_windowsize(int inSock, int inSend); + +bool setsock_blocking(int fd, bool blocking); +#if HAVE_DECL_TCP_WINDOW_CLAMP +int getsock_tcp_windowclamp(int inSock); +int setsock_tcp_windowclamp(int inSock, int clampsize); +#endif +#if HAVE_DECL_TCP_NOTSENT_LOWAT +int getsock_tcp_notsent_low_watermark(int inSock); +int setsock_tcp_notsent_low_watermark(int inSock, int clampsize); +#endif +int recvn(int inSock, char *outBuf, int inLen, int flags); +int writen(int inSock, const void *inBuf, int inLen, int *count); + +void disarm_itimer(void); +int set_itimer(uintmax_t); +/* ------------------------------------------------------------------- + * signal handlers + * signal.c + * ------------------------------------------------------------------- */ +typedef void Sigfunc(int); +void sig_exit(int inSigno); + +typedef Sigfunc *SigfuncPtr; + +SigfuncPtr my_signal(int inSigno, SigfuncPtr inFunc); + +#ifdef WIN32 + +#ifdef HAVE_SIGNAL_H + #define _NSIG NSIG +#else +/* under windows, emulate unix signals */ +enum { + SIGINT, + SIGTERM, + SIGPIPE, + _NSIG +}; +#endif + +BOOL WINAPI sig_dispatcher(DWORD type); + +#endif + +/* ------------------------------------------------------------------- + * error handlers + * error.c + * ------------------------------------------------------------------- */ +void warn (const char *inMessage, const char *inFile, int inLine); +void warn_errno(const char *inMessage, const char *inFile, int inLine); + +#define FAIL_exit(cond, msg) \ + do { \ + if (cond) { \ + warn(msg, __FILE__, __LINE__); \ + exit(1); \ + } \ + } while(0) + +#if defined(HAVE_POSIX_THREAD) || defined(HAVE_WIN32_THREAD) +#define FAIL(cond, msg, settings) \ + do { \ + if (cond) { \ + warn(msg, __FILE__, __LINE__); \ + thread_stop(settings); \ + } \ + } while(0) +#else +#define FAIL(cond, msg, settings) \ + do { \ + if (cond) { \ + warn(msg, __FILE__, __LINE__); \ + exit(1); \ + } \ + } while(0) +#endif + +#define WARN(cond, msg) \ + do { \ + if (cond) { \ + warn(msg, __FILE__, __LINE__); \ + } \ + } while(0) + +#if defined(HAVE_POSIX_THREAD) || defined(HAVE_WIN32_THREAD) +#define FAIL_errno(cond, msg, settings) \ + do { \ + if (cond) { \ + warn_errno(msg, __FILE__, __LINE__); \ + thread_stop(settings); \ + } \ + } while(0) +#else +#define FAIL_errno(cond, msg, settings) \ + do { \ + if (cond) { \ + warn_errno(msg, __FILE__, __LINE__); \ + exit(1); \ + } \ + } while(0) +#endif + +#define WARN_errno(cond, msg) \ + do { \ + if (cond) { \ + warn_errno(msg, __FILE__, __LINE__); \ + } \ + } while(0) + +/* ------------------------------------------------------------------- + * initialize buffer to a pattern + * ------------------------------------------------------------------- */ +void pattern(char *outBuf, int inBytes); + +/* ------------------------------------------------------------------- + * input and output numbers, converting with kilo, mega, giga + * stdio.c + * ------------------------------------------------------------------- */ +double byte_atof(const char *inString); +double bitorbyte_atof(const char *inString); +intmax_t byte_atoi(const char *inString); +uintmax_t bitorbyte_atoi(const char *inString); +void byte_snprintf(char* outString, int inLen, double inNum, char inFormat); + +/* + * Time macros for C-code (not the include Timestamp.hpp) + */ +#define rMillion 1000000 + +#define TimeZero(timeval) ((timeval.tv_sec == 0) && (timeval.tv_usec == 0)) + +#define TimeDifference(left, right) ((left.tv_sec - right.tv_sec) + \ + (left.tv_usec - right.tv_usec) / ((double) rMillion)) + +#define TimeDifferenceUsec(left, right) ((1e6 * (left.tv_sec - right.tv_sec)) + \ + (double) (left.tv_usec - right.tv_usec)) + +#define TimeDouble(timeval) (timeval.tv_sec + timeval.tv_usec / ((double) rMillion)) + +#define TimeAdd(left, right) do { \ + left.tv_usec += right.tv_usec; \ + if (left.tv_usec > rMillion) { \ + left.tv_usec -= rMillion; \ + left.tv_sec++; \ + } \ + left.tv_sec += right.tv_sec; \ + } while (0) + +/* ------------------------------------------------------------------- + * redirect the stdout to a specified file + * stdio.c + * ------------------------------------------------------------------- */ +void redirect(const char *inOutputFileName); + +/* ------------------------------------------------------------------- + * delete macro + * ------------------------------------------------------------------- */ +#define DELETE_PTR(ptr) \ + do { \ + if (ptr != NULL) { \ + delete ptr; \ + ptr = NULL; \ + } \ + } while(false) + +#define DELETE_ARRAY(ptr) \ + do { \ + if (ptr != NULL) { \ + delete [] ptr; \ + ptr = NULL; \ + } \ + } while(false) + +#define FREE_ARRAY(ptr) \ + do { \ + if (ptr != NULL) { \ + free(ptr); \ + ptr = NULL; \ + } \ + } while(false) + + +// Readn and write error macros +// Define fatal and nonfatal write errors +#ifdef WIN32 +#define FATALTCPREADERR(errno) (WSAGetLastError() != WSAEWOULDBLOCK) +#define FATALUDPREADERR(errno) (((errno = WSAGetLastError()) != WSAEWOULDBLOCK)) +#define FATALTCPWRITERR(errno) ((errno = WSAGetLastError()) != WSAETIMEDOUT) +#define NONFATALTCPWRITERR(errno) ((errno = WSAGetLastError()) == WSAETIMEDOUT) +#define FATALUDPWRITERR(errno) (((errno = WSAGetLastError()) != WSAETIMEDOUT) \ + && (errno != WSAECONNREFUSED)) +#else +#define FATALTCPREADERR(errno) ((errno != EAGAIN) && (errno != EWOULDBLOCK) && (errno != EINTR)) +#define FATALUDPREADERR(errno) ((errno != EAGAIN) && (errno != EWOULDBLOCK) && \ + (errno != EINTR)) +#define FATALTCPWRITERR(errno) (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) +#define NONFATALTCPWRITERR(errno) (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) +#define FATALUDPWRITERR(errno) ((errno != EAGAIN) && (errno != EWOULDBLOCK) && (errno != EINTR) \ + && (errno != ECONNREFUSED) && (errno != ENOBUFS)) +#endif + +#ifdef WIN32 +#else +#endif + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif /* UTIL_H */ diff --git a/include/version.h b/include/version.h new file mode 100644 index 0000000..d28d4b0 --- /dev/null +++ b/include/version.h @@ -0,0 +1,27 @@ +#include "config.h" +#define IPERF_VERSION VERSION +#define IPERF_VERSION_DATE "14 March 2023" +#define IPERF_VERSION_MAJORHEX 0x00020001 +#define IPERF_VERSION_MINORHEX 0x00090003 + +/* + * case 0: + * sprintf(report->peerversion + strlen(report->peerversion) - 1,"-dev)"); + * break; + * case 1: + * sprintf(report->peerversion + strlen(report->peerversion) - 1,"-rc)"); + * break; + * case 2: + * sprintf(report->peerversion + strlen(report->peerversion) - 1,"-rc2)"); + * break; + * case 3: + * break; + * case 4: + * sprintf(report->peerversion + strlen(report->peerversion) - 1,"-private)"); + * break; + * case 5: + * sprintf(report->peerversion + strlen(report->peerversion) - 1,"-master)"); + * break; + * default: + * sprintf(report->peerversion + strlen(report->peerversion) - 1, "-unk)"); + */ diff --git a/install-sh b/install-sh new file mode 100755 index 0000000..1a83534 --- /dev/null +++ b/install-sh @@ -0,0 +1,323 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2005-02-02.21 + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +chmodcmd="$chmodprog 0755" +chowncmd= +chgrpcmd= +stripcmd= +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src= +dst= +dir_arg= +dstarg= +no_target_directory= + +usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: +-c (ignored) +-d create directories instead of installing files. +-g GROUP $chgrpprog installed files to GROUP. +-m MODE $chmodprog installed files to MODE. +-o USER $chownprog installed files to USER. +-s $stripprog installed files. +-t DIRECTORY install into DIRECTORY. +-T report an error if DSTFILE is a directory. +--help display this help and exit. +--version display version info and exit. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG +" + +while test -n "$1"; do + case $1 in + -c) shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + --help) echo "$usage"; exit $?;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -s) stripcmd=$stripprog + shift + continue;; + + -t) dstarg=$2 + shift + shift + continue;; + + -T) no_target_directory=true + shift + continue;; + + --version) echo "$0 $scriptversion"; exit $?;; + + *) # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + test -n "$dir_arg$dstarg" && break + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dstarg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dstarg" + shift # fnord + fi + shift # arg + dstarg=$arg + done + break;; + esac +done + +if test -z "$1"; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call `install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +for src +do + # Protect names starting with `-'. + case $src in + -*) src=./$src ;; + esac + + if test -n "$dir_arg"; then + dst=$src + src= + + if test -d "$dst"; then + mkdircmd=: + chmodcmd= + else + mkdircmd=$mkdirprog + fi + else + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dstarg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + + dst=$dstarg + # Protect names starting with `-'. + case $dst in + -*) dst=./$dst ;; + esac + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dstarg: Is a directory" >&2 + exit 1 + fi + dst=$dst/`basename "$src"` + fi + fi + + # This sed command emulates the dirname command. + dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` + + # Make sure that the destination directory exists. + + # Skip lots of stat calls in the usual case. + if test ! -d "$dstdir"; then + defaultIFS=' + ' + IFS="${IFS-$defaultIFS}" + + oIFS=$IFS + # Some sh's can't handle IFS=/ for some reason. + IFS='%' + set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` + shift + IFS=$oIFS + + pathcomp= + + while test $# -ne 0 ; do + pathcomp=$pathcomp$1 + shift + if test ! -d "$pathcomp"; then + $mkdirprog "$pathcomp" + # mkdir can fail with a `File exist' error in case several + # install-sh are creating the directory concurrently. This + # is OK. + test -d "$pathcomp" || exit + fi + pathcomp=$pathcomp/ + done + fi + + if test -n "$dir_arg"; then + $doit $mkdircmd "$dst" \ + && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } + + else + dstfile=`basename "$dst"` + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + trap '(exit $?); exit' 1 2 13 15 + + # Copy the file name to the temp name. + $doit $cpprog "$src" "$dsttmp" && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && + + # Now rename the file to the real destination. + { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ + || { + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + if test -f "$dstdir/$dstfile"; then + $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ + || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ + || { + echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 + (exit 1); exit 1 + } + else + : + fi + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" + } + } + fi || { (exit 1); exit 1; } +done + +# The final little trick to "correctly" pass the exit status to the exit trap. +{ + (exit 0); exit 0 +} + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/m4/ax_create_stdint_h.m4 b/m4/ax_create_stdint_h.m4 new file mode 100644 index 0000000..d06329b --- /dev/null +++ b/m4/ax_create_stdint_h.m4 @@ -0,0 +1,685 @@ +dnl @synopsis AX_CREATE_STDINT_H [( HEADER-TO-GENERATE [, HEDERS-TO-CHECK])] +dnl +dnl the "ISO C9X: 7.18 Integer types <stdint.h>" section requires the +dnl existence of an include file <stdint.h> that defines a set of +dnl typedefs, especially uint8_t,int32_t,uintptr_t. Many older +dnl installations will not provide this file, but some will have the +dnl very same definitions in <inttypes.h>. In other enviroments we can +dnl use the inet-types in <sys/types.h> which would define the typedefs +dnl int8_t and u_int8_t respectivly. +dnl +dnl This macros will create a local "_stdint.h" or the headerfile given +dnl as an argument. In many cases that file will just "#include +dnl <stdint.h>" or "#include <inttypes.h>", while in other environments +dnl it will provide the set of basic 'stdint's definitions/typedefs: +dnl +dnl int8_t,uint8_t,int16_t,uint16_t,int32_t,uint32_t,intptr_t,uintptr_t +dnl int_least32_t.. int_fast32_t.. intmax_t +dnl +dnl which may or may not rely on the definitions of other files, or +dnl using the AC_CHECK_SIZEOF macro to determine the actual sizeof each +dnl type. +dnl +dnl if your header files require the stdint-types you will want to +dnl create an installable file mylib-int.h that all your other +dnl installable header may include. So if you have a library package +dnl named "mylib", just use +dnl +dnl AX_CREATE_STDINT_H(mylib-int.h) +dnl +dnl in configure.ac and go to install that very header file in +dnl Makefile.am along with the other headers (mylib.h) - and the +dnl mylib-specific headers can simply use "#include <mylib-int.h>" to +dnl obtain the stdint-types. +dnl +dnl Remember, if the system already had a valid <stdint.h>, the +dnl generated file will include it directly. No need for fuzzy +dnl HAVE_STDINT_H things... +dnl +dnl @category C +dnl @author Guido Draheim <guidod@gmx.de> +dnl @version 2003-12-07 +dnl @license GPLWithACException + +AC_DEFUN([AX_CHECK_DATA_MODEL],[ + AC_CHECK_SIZEOF(char) + AC_CHECK_SIZEOF(short) + AC_CHECK_SIZEOF(int) + AC_CHECK_SIZEOF(long) + AC_CHECK_SIZEOF(void*) + ac_cv_char_data_model="" + ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_char" + ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_short" + ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_int" + ac_cv_long_data_model="" + ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_int" + ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_long" + ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_voidp" + AC_MSG_CHECKING([data model]) + case "$ac_cv_char_data_model/$ac_cv_long_data_model" in + 122/242) ac_cv_data_model="IP16" ; n="standard 16bit machine" ;; + 122/244) ac_cv_data_model="LP32" ; n="standard 32bit machine" ;; + 122/*) ac_cv_data_model="i16" ; n="unusual int16 model" ;; + 124/444) ac_cv_data_model="ILP32" ; n="standard 32bit unixish" ;; + 124/488) ac_cv_data_model="LP64" ; n="standard 64bit unixish" ;; + 124/448) ac_cv_data_model="LLP64" ; n="unusual 64bit unixish" ;; + 124/*) ac_cv_data_model="i32" ; n="unusual int32 model" ;; + 128/888) ac_cv_data_model="ILP64" ; n="unusual 64bit numeric" ;; + 128/*) ac_cv_data_model="i64" ; n="unusual int64 model" ;; + 222/*2) ac_cv_data_model="DSP16" ; n="strict 16bit dsptype" ;; + 333/*3) ac_cv_data_model="DSP24" ; n="strict 24bit dsptype" ;; + 444/*4) ac_cv_data_model="DSP32" ; n="strict 32bit dsptype" ;; + 666/*6) ac_cv_data_model="DSP48" ; n="strict 48bit dsptype" ;; + 888/*8) ac_cv_data_model="DSP64" ; n="strict 64bit dsptype" ;; + 222/*|333/*|444/*|666/*|888/*) : + ac_cv_data_model="iDSP" ; n="unusual dsptype" ;; + *) ac_cv_data_model="none" ; n="very unusual model" ;; + esac + AC_MSG_RESULT([$ac_cv_data_model ($ac_cv_long_data_model, $n)]) +]) + +dnl AX_CHECK_HEADER_STDINT_X([HEADERLIST][,ACTION-IF]) +AC_DEFUN([AX_CHECK_HEADER_STDINT_X],[ +AC_CACHE_CHECK([for stdint uintptr_t], [ac_cv_header_stdint_x],[ + ac_cv_header_stdint_x="" # the 1997 typedefs (inttypes.h) + AC_MSG_RESULT([(..)]) + for i in m4_ifval([$1],[$1],[stdint.h inttypes.h sys/inttypes.h]) ; do + unset ac_cv_type_uintptr_t + unset ac_cv_type_uint64_t + AC_CHECK_TYPE(uintptr_t,[ac_cv_header_stdint_x=$i],continue,[#include <$i>]) + AC_CHECK_TYPE(uint64_t,[and64="/uint64_t"],[and64=""],[#include<$i>]) + m4_ifvaln([$1],[$1]) break + done + AC_MSG_CHECKING([for stdint uintptr_t]) + ]) +]) + +AC_DEFUN([AX_CHECK_HEADER_STDINT_O],[ +AC_CACHE_CHECK([for stdint uint32_t], [ac_cv_header_stdint_o],[ + ac_cv_header_stdint_o="" # the 1995 typedefs (sys/inttypes.h) + AC_MSG_RESULT([(..)]) + for i in m4_ifval([$1],[$1],[inttypes.h sys/inttypes.h stdint.h]) ; do + unset ac_cv_type_uint32_t + unset ac_cv_type_uint64_t + AC_CHECK_TYPE(uint32_t,[ac_cv_header_stdint_o=$i],continue,[#include <$i>]) + AC_CHECK_TYPE(uint64_t,[and64="/uint64_t"],[and64=""],[#include<$i>]) + m4_ifvaln([$1],[$1]) break + break; + done + AC_MSG_CHECKING([for stdint uint32_t]) + ]) +]) + +AC_DEFUN([AX_CHECK_HEADER_STDINT_U],[ +AC_CACHE_CHECK([for stdint u_int32_t], [ac_cv_header_stdint_u],[ + ac_cv_header_stdint_u="" # the BSD typedefs (sys/types.h) + AC_MSG_RESULT([(..)]) + for i in m4_ifval([$1],[$1],[sys/types.h inttypes.h sys/inttypes.h]) ; do + unset ac_cv_type_u_int32_t + unset ac_cv_type_u_int64_t + AC_CHECK_TYPE(u_int32_t,[ac_cv_header_stdint_u=$i],continue,[#include <$i>]) + AC_CHECK_TYPE(u_int64_t,[and64="/u_int64_t"],[and64=""],[#include<$i>]) + m4_ifvaln([$1],[$1]) break + break; + done + AC_MSG_CHECKING([for stdint u_int32_t]) + ]) +]) + +AC_DEFUN([AX_CREATE_STDINT_H], +[# ------ AX CREATE STDINT H ------------------------------------- +AC_MSG_CHECKING([for stdint types]) +ac_stdint_h=`echo ifelse($1, , _stdint.h, $1)` +# try to shortcircuit - if the default include path of the compiler +# can find a "stdint.h" header then we assume that all compilers can. +AC_CACHE_VAL([ac_cv_header_stdint_t],[ +old_CXXFLAGS="$CXXFLAGS" ; CXXFLAGS="" +old_CPPFLAGS="$CPPFLAGS" ; CPPFLAGS="" +old_CFLAGS="$CFLAGS" ; CFLAGS="" +AC_TRY_COMPILE([#include <stdint.h>],[int_least32_t v = 0;], +[ac_cv_stdint_result="(assuming C99 compatible system)" + ac_cv_header_stdint_t="stdint.h"; ], +[ac_cv_header_stdint_t=""]) +CXXFLAGS="$old_CXXFLAGS" +CPPFLAGS="$old_CPPFLAGS" +CFLAGS="$old_CFLAGS" ]) + +v="... $ac_cv_header_stdint_h" +if test "$ac_stdint_h" = "stdint.h" ; then + AC_MSG_RESULT([(are you sure you want them in ./stdint.h?)]) +elif test "$ac_stdint_h" = "inttypes.h" ; then + AC_MSG_RESULT([(are you sure you want them in ./inttypes.h?)]) +elif test "_$ac_cv_header_stdint_t" = "_" ; then + AC_MSG_RESULT([(putting them into $ac_stdint_h)$v]) +else + ac_cv_header_stdint="$ac_cv_header_stdint_t" + AC_MSG_RESULT([$ac_cv_header_stdint (shortcircuit)]) +fi + +if test "_$ac_cv_header_stdint_t" = "_" ; then # can not shortcircuit.. + +dnl .....intro message done, now do a few system checks..... +dnl btw, all old CHECK_TYPE macros do automatically "DEFINE" a type, +dnl therefore we use the autoconf implementation detail CHECK_TYPE_NEW +dnl instead that is triggered with 3 or more arguments (see types.m4) + +inttype_headers=`echo $2 | sed -e 's/,/ /g'` + +ac_cv_stdint_result="(no helpful system typedefs seen)" +AX_CHECK_HEADER_STDINT_X(dnl + stdint.h inttypes.h sys/inttypes.h $inttype_headers, + ac_cv_stdint_result="(seen uintptr_t$and64 in $i)") + +if test "_$ac_cv_header_stdint_x" = "_" ; then +AX_CHECK_HEADER_STDINT_O(dnl, + inttypes.h sys/inttypes.h stdint.h $inttype_headers, + ac_cv_stdint_result="(seen uint32_t$and64 in $i)") +fi + +if test "_$ac_cv_header_stdint_x" = "_" ; then +if test "_$ac_cv_header_stdint_o" = "_" ; then +AX_CHECK_HEADER_STDINT_U(dnl, + sys/types.h inttypes.h sys/inttypes.h $inttype_headers, + ac_cv_stdint_result="(seen u_int32_t$and64 in $i)") +fi fi + +dnl if there was no good C99 header file, do some typedef checks... +if test "_$ac_cv_header_stdint_x" = "_" ; then + AC_MSG_CHECKING([for stdint datatype model]) + AC_MSG_RESULT([(..)]) + AX_CHECK_DATA_MODEL +fi + +if test "_$ac_cv_header_stdint_x" != "_" ; then + ac_cv_header_stdint="$ac_cv_header_stdint_x" +elif test "_$ac_cv_header_stdint_o" != "_" ; then + ac_cv_header_stdint="$ac_cv_header_stdint_o" +elif test "_$ac_cv_header_stdint_u" != "_" ; then + ac_cv_header_stdint="$ac_cv_header_stdint_u" +else + ac_cv_header_stdint="stddef.h" +fi + +AC_MSG_CHECKING([for extra inttypes in chosen header]) +AC_MSG_RESULT([($ac_cv_header_stdint)]) +dnl see if int_least and int_fast types are present in _this_ header. +unset ac_cv_type_int_least32_t +unset ac_cv_type_int_fast32_t +AC_CHECK_TYPE(int_least32_t,,,[#include <$ac_cv_header_stdint>]) +AC_CHECK_TYPE(int_fast32_t,,,[#include<$ac_cv_header_stdint>]) +AC_CHECK_TYPE(intmax_t,,,[#include <$ac_cv_header_stdint>]) + +fi # shortcircut to system "stdint.h" +# ------------------ PREPARE VARIABLES ------------------------------ +if test "$GCC" = "yes" ; then +ac_cv_stdint_message="using gnu compiler "`$CC --version | head -1` +else +ac_cv_stdint_message="using $CC" +fi + +AC_MSG_RESULT([make use of $ac_cv_header_stdint in $ac_stdint_h dnl +$ac_cv_stdint_result]) + +dnl ----------------------------------------------------------------- +# ----------------- DONE inttypes.h checks START header ------------- +AC_CONFIG_COMMANDS([$ac_stdint_h],[ +AC_MSG_NOTICE(creating $ac_stdint_h : $_ac_stdint_h) +ac_stdint=$tmp/_stdint.h + +echo "#ifndef" $_ac_stdint_h >$ac_stdint +echo "#define" $_ac_stdint_h "1" >>$ac_stdint +echo "#ifndef" _GENERATED_STDINT_H >>$ac_stdint +echo "#define" _GENERATED_STDINT_H '"'$PACKAGE $VERSION'"' >>$ac_stdint +echo "/* generated $ac_cv_stdint_message */" >>$ac_stdint +if test "_$ac_cv_header_stdint_t" != "_" ; then +echo "#define _STDINT_HAVE_STDINT_H" "1" >>$ac_stdint +echo "#include <stdint.h>" >>$ac_stdint +echo "#endif" >>$ac_stdint +echo "#endif" >>$ac_stdint +else + +cat >>$ac_stdint <<STDINT_EOF + +/* ................... shortcircuit part ........................... */ + +#if defined HAVE_STDINT_H || defined _STDINT_HAVE_STDINT_H +#include <stdint.h> +#else +#include <stddef.h> + +/* .................... configured part ............................ */ + +STDINT_EOF + +echo "/* whether we have a C99 compatible stdint header file */" >>$ac_stdint +if test "_$ac_cv_header_stdint_x" != "_" ; then + ac_header="$ac_cv_header_stdint_x" + echo "#define _STDINT_HEADER_INTPTR" '"'"$ac_header"'"' >>$ac_stdint +else + echo "/* #undef _STDINT_HEADER_INTPTR */" >>$ac_stdint +fi + +echo "/* whether we have a C96 compatible inttypes header file */" >>$ac_stdint +if test "_$ac_cv_header_stdint_o" != "_" ; then + ac_header="$ac_cv_header_stdint_o" + echo "#define _STDINT_HEADER_UINT32" '"'"$ac_header"'"' >>$ac_stdint +else + echo "/* #undef _STDINT_HEADER_UINT32 */" >>$ac_stdint +fi + +echo "/* whether we have a BSD compatible inet types header */" >>$ac_stdint +if test "_$ac_cv_header_stdint_u" != "_" ; then + ac_header="$ac_cv_header_stdint_u" + echo "#define _STDINT_HEADER_U_INT32" '"'"$ac_header"'"' >>$ac_stdint +else + echo "/* #undef _STDINT_HEADER_U_INT32 */" >>$ac_stdint +fi + +echo "" >>$ac_stdint + +if test "_$ac_header" != "_" ; then if test "$ac_header" != "stddef.h" ; then + echo "#include <$ac_header>" >>$ac_stdint + echo "" >>$ac_stdint +fi fi + +echo "/* which 64bit typedef has been found */" >>$ac_stdint +if test "$ac_cv_type_uint64_t" = "yes" ; then +echo "#define _STDINT_HAVE_UINT64_T" "1" >>$ac_stdint +else +echo "/* #undef _STDINT_HAVE_UINT64_T */" >>$ac_stdint +fi +if test "$ac_cv_type_u_int64_t" = "yes" ; then +echo "#define _STDINT_HAVE_U_INT64_T" "1" >>$ac_stdint +else +echo "/* #undef _STDINT_HAVE_U_INT64_T */" >>$ac_stdint +fi +echo "" >>$ac_stdint + +echo "/* which type model has been detected */" >>$ac_stdint +if test "_$ac_cv_char_data_model" != "_" ; then +echo "#define _STDINT_CHAR_MODEL" "$ac_cv_char_data_model" >>$ac_stdint +echo "#define _STDINT_LONG_MODEL" "$ac_cv_long_data_model" >>$ac_stdint +else +echo "/* #undef _STDINT_CHAR_MODEL // skipped */" >>$ac_stdint +echo "/* #undef _STDINT_LONG_MODEL // skipped */" >>$ac_stdint +fi +echo "" >>$ac_stdint + +echo "/* whether int_least types were detected */" >>$ac_stdint +if test "$ac_cv_type_int_least32_t" = "yes"; then +echo "#define _STDINT_HAVE_INT_LEAST32_T" "1" >>$ac_stdint +else +echo "/* #undef _STDINT_HAVE_INT_LEAST32_T */" >>$ac_stdint +fi +echo "/* whether int_fast types were detected */" >>$ac_stdint +if test "$ac_cv_type_int_fast32_t" = "yes"; then +echo "#define _STDINT_HAVE_INT_FAST32_T" "1" >>$ac_stdint +else +echo "/* #undef _STDINT_HAVE_INT_FAST32_T */" >>$ac_stdint +fi +echo "/* whether intmax_t type was detected */" >>$ac_stdint +if test "$ac_cv_type_intmax_t" = "yes"; then +echo "#define _STDINT_HAVE_INTMAX_T" "1" >>$ac_stdint +else +echo "/* #undef _STDINT_HAVE_INTMAX_T */" >>$ac_stdint +fi +echo "" >>$ac_stdint + + cat >>$ac_stdint <<STDINT_EOF +/* .................... detections part ............................ */ + +/* whether we need to define bitspecific types from compiler base types */ +#ifndef _STDINT_HEADER_INTPTR +#ifndef _STDINT_HEADER_UINT32 +#ifndef _STDINT_HEADER_U_INT32 +#define _STDINT_NEED_INT_MODEL_T +#else +#define _STDINT_HAVE_U_INT_TYPES +#endif +#endif +#endif + +#ifdef _STDINT_HAVE_U_INT_TYPES +#undef _STDINT_NEED_INT_MODEL_T +#endif + +#ifdef _STDINT_CHAR_MODEL +#if _STDINT_CHAR_MODEL+0 == 122 || _STDINT_CHAR_MODEL+0 == 124 +#ifndef _STDINT_BYTE_MODEL +#define _STDINT_BYTE_MODEL 12 +#endif +#endif +#endif + +#ifndef _STDINT_HAVE_INT_LEAST32_T +#define _STDINT_NEED_INT_LEAST_T +#endif + +#ifndef _STDINT_HAVE_INT_FAST32_T +#define _STDINT_NEED_INT_FAST_T +#endif + +#ifndef _STDINT_HEADER_INTPTR +#define _STDINT_NEED_INTPTR_T +#ifndef _STDINT_HAVE_INTMAX_T +#define _STDINT_NEED_INTMAX_T +#endif +#endif + + +/* .................... definition part ............................ */ + +/* some system headers have good uint64_t */ +#ifndef _HAVE_UINT64_T +#if defined _STDINT_HAVE_UINT64_T || defined HAVE_UINT64_T +#define _HAVE_UINT64_T +#elif defined _STDINT_HAVE_U_INT64_T || defined HAVE_U_INT64_T +#define _HAVE_UINT64_T +typedef u_int64_t uint64_t; +#endif +#endif + +#ifndef _HAVE_UINT64_T +/* .. here are some common heuristics using compiler runtime specifics */ +#if defined __STDC_VERSION__ && defined __STDC_VERSION__ >= 199901L +#define _HAVE_UINT64_T +#define _HAVE_LONGLONG_UINT64_T +typedef long long int64_t; +typedef unsigned long long uint64_t; + +#elif !defined __STRICT_ANSI__ +#if defined _MSC_VER || defined __WATCOMC__ || defined __BORLANDC__ +#define _HAVE_UINT64_T +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; + +#elif defined __GNUC__ || defined __MWERKS__ || defined __ELF__ +/* note: all ELF-systems seem to have loff-support which needs 64-bit */ +#if !defined _NO_LONGLONG +#define _HAVE_UINT64_T +#define _HAVE_LONGLONG_UINT64_T +typedef long long int64_t; +typedef unsigned long long uint64_t; +#endif + +#elif defined __alpha || (defined __mips && defined _ABIN32) +#if !defined _NO_LONGLONG +typedef long int64_t; +typedef unsigned long uint64_t; +#endif + /* compiler/cpu type to define int64_t */ +#endif +#endif +#endif + +#if defined _STDINT_HAVE_U_INT_TYPES +/* int8_t int16_t int32_t defined by inet code, redeclare the u_intXX types */ +typedef u_int8_t uint8_t; +typedef u_int16_t uint16_t; +typedef u_int32_t uint32_t; + +/* glibc compatibility */ +#ifndef __int8_t_defined +#define __int8_t_defined +#endif +#endif + +#ifdef _STDINT_NEED_INT_MODEL_T +/* we must guess all the basic types. Apart from byte-adressable system, */ +/* there a few 32-bit-only dsp-systems that we guard with BYTE_MODEL 8-} */ +/* (btw, those nibble-addressable systems are way off, or so we assume) */ + +dnl /* have a look at "64bit and data size neutrality" at */ +dnl /* http://unix.org/version2/whatsnew/login_64bit.html */ +dnl /* (the shorthand "ILP" types always have a "P" part) */ + +#if defined _STDINT_BYTE_MODEL +#if _STDINT_LONG_MODEL+0 == 242 +/* 2:4:2 = IP16 = a normal 16-bit system */ +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned long uint32_t; +#ifndef __int8_t_defined +#define __int8_t_defined +typedef char int8_t; +typedef short int16_t; +typedef long int32_t; +#endif +#elif _STDINT_LONG_MODEL+0 == 244 || _STDINT_LONG_MODEL == 444 +/* 2:4:4 = LP32 = a 32-bit system derived from a 16-bit */ +/* 4:4:4 = ILP32 = a normal 32-bit system */ +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +#ifndef __int8_t_defined +#define __int8_t_defined +typedef char int8_t; +typedef short int16_t; +typedef int int32_t; +#endif +#elif _STDINT_LONG_MODEL+0 == 484 || _STDINT_LONG_MODEL+0 == 488 +/* 4:8:4 = IP32 = a 32-bit system prepared for 64-bit */ +/* 4:8:8 = LP64 = a normal 64-bit system */ +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +#ifndef __int8_t_defined +#define __int8_t_defined +typedef char int8_t; +typedef short int16_t; +typedef int int32_t; +#endif +/* this system has a "long" of 64bit */ +#ifndef _HAVE_UINT64_T +#define _HAVE_UINT64_T +typedef unsigned long uint64_t; +typedef long int64_t; +#endif +#elif _STDINT_LONG_MODEL+0 == 448 +/* LLP64 a 64-bit system derived from a 32-bit system */ +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +#ifndef __int8_t_defined +#define __int8_t_defined +typedef char int8_t; +typedef short int16_t; +typedef int int32_t; +#endif +/* assuming the system has a "long long" */ +#ifndef _HAVE_UINT64_T +#define _HAVE_UINT64_T +#define _HAVE_LONGLONG_UINT64_T +typedef unsigned long long uint64_t; +typedef long long int64_t; +#endif +#else +#define _STDINT_NO_INT32_T +#endif +#else +#define _STDINT_NO_INT8_T +#define _STDINT_NO_INT32_T +#endif +#endif + +/* + * quote from SunOS-5.8 sys/inttypes.h: + * Use at your own risk. As of February 1996, the committee is squarely + * behind the fixed sized types; the "least" and "fast" types are still being + * discussed. The probability that the "fast" types may be removed before + * the standard is finalized is high enough that they are not currently + * implemented. + */ + +#if defined _STDINT_NEED_INT_LEAST_T +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +#ifdef _HAVE_UINT64_T +typedef int64_t int_least64_t; +#endif + +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +#ifdef _HAVE_UINT64_T +typedef uint64_t uint_least64_t; +#endif + /* least types */ +#endif + +#if defined _STDINT_NEED_INT_FAST_T +typedef int8_t int_fast8_t; +typedef int int_fast16_t; +typedef int32_t int_fast32_t; +#ifdef _HAVE_UINT64_T +typedef int64_t int_fast64_t; +#endif + +typedef uint8_t uint_fast8_t; +typedef unsigned uint_fast16_t; +typedef uint32_t uint_fast32_t; +#ifdef _HAVE_UINT64_T +typedef uint64_t uint_fast64_t; +#endif + /* fast types */ +#endif + +#ifdef _STDINT_NEED_INTMAX_T +#ifdef _HAVE_UINT64_T +typedef int64_t intmax_t; +typedef uint64_t uintmax_t; +#else +typedef long intmax_t; +typedef unsigned long uintmax_t; +#endif +#endif + +#ifdef _STDINT_NEED_INTPTR_T +#ifndef __intptr_t_defined +#define __intptr_t_defined +/* we encourage using "long" to store pointer values, never use "int" ! */ +#if _STDINT_LONG_MODEL+0 == 242 || _STDINT_LONG_MODEL+0 == 484 +typedef unsinged int uintptr_t; +typedef int intptr_t; +#elif _STDINT_LONG_MODEL+0 == 244 || _STDINT_LONG_MODEL+0 == 444 +typedef unsigned long uintptr_t; +typedef long intptr_t; +#elif _STDINT_LONG_MODEL+0 == 448 && defined _HAVE_UINT64_T +typedef uint64_t uintptr_t; +typedef int64_t intptr_t; +#else /* matches typical system types ILP32 and LP64 - but not IP16 or LLP64 */ +typedef unsigned long uintptr_t; +typedef long intptr_t; +#endif +#endif +#endif + +/* The ISO C99 standard specifies that in C++ implementations these + should only be defined if explicitly requested. */ +#if !defined __cplusplus || defined __STDC_CONSTANT_MACROS +#ifndef UINT32_C + +/* Signed. */ +# define INT8_C(c) c +# define INT16_C(c) c +# define INT32_C(c) c +# ifdef _HAVE_LONGLONG_UINT64_T +# define INT64_C(c) c ## L +# else +# define INT64_C(c) c ## LL +# endif + +/* Unsigned. */ +# define UINT8_C(c) c ## U +# define UINT16_C(c) c ## U +# define UINT32_C(c) c ## U +# ifdef _HAVE_LONGLONG_UINT64_T +# define UINT64_C(c) c ## UL +# else +# define UINT64_C(c) c ## ULL +# endif + +/* Maximal type. */ +# ifdef _HAVE_LONGLONG_UINT64_T +# define INTMAX_C(c) c ## L +# define UINTMAX_C(c) c ## UL +# else +# define INTMAX_C(c) c ## LL +# define UINTMAX_C(c) c ## ULL +# endif + + /* literalnumbers */ +#endif +#endif + +/* These limits are merily those of a two complement byte-oriented system */ + +/* Minimum of signed integral types. */ +# define INT8_MIN (-128) +# define INT16_MIN (-32767-1) +# define INT32_MIN (-2147483647-1) +# define INT64_MIN (-__INT64_C(9223372036854775807)-1) +/* Maximum of signed integral types. */ +# define INT8_MAX (127) +# define INT16_MAX (32767) +# define INT32_MAX (2147483647) +# define INT64_MAX (__INT64_C(9223372036854775807)) + +/* Maximum of unsigned integral types. */ +# define UINT8_MAX (255) +# define UINT16_MAX (65535) +# define UINT32_MAX (4294967295U) +# define UINT64_MAX (__UINT64_C(18446744073709551615)) + +/* Minimum of signed integral types having a minimum size. */ +# define INT_LEAST8_MIN INT8_MIN +# define INT_LEAST16_MIN INT16_MIN +# define INT_LEAST32_MIN INT32_MIN +# define INT_LEAST64_MIN INT64_MIN +/* Maximum of signed integral types having a minimum size. */ +# define INT_LEAST8_MAX INT8_MAX +# define INT_LEAST16_MAX INT16_MAX +# define INT_LEAST32_MAX INT32_MAX +# define INT_LEAST64_MAX INT64_MAX + +/* Maximum of unsigned integral types having a minimum size. */ +# define UINT_LEAST8_MAX UINT8_MAX +# define UINT_LEAST16_MAX UINT16_MAX +# define UINT_LEAST32_MAX UINT32_MAX +# define UINT_LEAST64_MAX UINT64_MAX + + /* shortcircuit*/ +#endif + /* once */ +#endif +#endif +STDINT_EOF +fi + if cmp -s $ac_stdint_h $ac_stdint 2>/dev/null; then + AC_MSG_NOTICE([$ac_stdint_h is unchanged]) + else + ac_dir=`AS_DIRNAME(["$ac_stdint_h"])` + AS_MKDIR_P(["$ac_dir"]) + rm -f $ac_stdint_h + mv $ac_stdint $ac_stdint_h + fi +],[# variables for create stdint.h replacement +PACKAGE="$PACKAGE" +VERSION="$VERSION" +ac_stdint_h="$ac_stdint_h" +_ac_stdint_h=AS_TR_CPP(_$PACKAGE-$ac_stdint_h) +ac_cv_stdint_message="$ac_cv_stdint_message" +ac_cv_header_stdint_t="$ac_cv_header_stdint_t" +ac_cv_header_stdint_x="$ac_cv_header_stdint_x" +ac_cv_header_stdint_o="$ac_cv_header_stdint_o" +ac_cv_header_stdint_u="$ac_cv_header_stdint_u" +ac_cv_type_uint64_t="$ac_cv_type_uint64_t" +ac_cv_type_u_int64_t="$ac_cv_type_u_int64_t" +ac_cv_char_data_model="$ac_cv_char_data_model" +ac_cv_long_data_model="$ac_cv_long_data_model" +ac_cv_type_int_least32_t="$ac_cv_type_int_least32_t" +ac_cv_type_int_fast32_t="$ac_cv_type_int_fast32_t" +ac_cv_type_intmax_t="$ac_cv_type_intmax_t" +]) +]) diff --git a/m4/ax_pthread.m4 b/m4/ax_pthread.m4 new file mode 100644 index 0000000..0300e4e --- /dev/null +++ b/m4/ax_pthread.m4 @@ -0,0 +1,492 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_pthread.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) +# +# DESCRIPTION +# +# This macro figures out how to build C programs using POSIX threads. It +# sets the PTHREAD_LIBS output variable to the threads library and linker +# flags, and the PTHREAD_CFLAGS output variable to any special C compiler +# flags that are needed. (The user can also force certain compiler +# flags/libs to be tested by setting these environment variables.) +# +# Also sets PTHREAD_CC to any special C compiler that is needed for +# multi-threaded programs (defaults to the value of CC otherwise). (This +# is necessary on AIX to use the special cc_r compiler alias.) +# +# NOTE: You are assumed to not only compile your program with these flags, +# but also to link with them as well. For example, you might link with +# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS +# +# If you are only building threaded programs, you may wish to use these +# variables in your default LIBS, CFLAGS, and CC: +# +# LIBS="$PTHREAD_LIBS $LIBS" +# CFLAGS="$CFLAGS $PTHREAD_CFLAGS" +# CC="$PTHREAD_CC" +# +# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant +# has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to +# that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX). +# +# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the +# PTHREAD_PRIO_INHERIT symbol is defined when compiling with +# PTHREAD_CFLAGS. +# +# ACTION-IF-FOUND is a list of shell commands to run if a threads library +# is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it +# is not found. If ACTION-IF-FOUND is not specified, the default action +# will define HAVE_PTHREAD. +# +# Please let the authors know if this macro fails on any platform, or if +# you have any other suggestions or comments. This macro was based on work +# by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help +# from M. Frigo), as well as ac_pthread and hb_pthread macros posted by +# Alejandro Forero Cuervo to the autoconf macro repository. We are also +# grateful for the helpful feedback of numerous users. +# +# Updated for Autoconf 2.68 by Daniel Richard G. +# +# LICENSE +# +# Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu> +# Copyright (c) 2011 Daniel Richard G. <skunk@iSKUNK.ORG> +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation, either version 3 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see <https://www.gnu.org/licenses/>. +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 26 + +AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD]) +AC_DEFUN([AX_PTHREAD], [ +AC_REQUIRE([AC_CANONICAL_HOST]) +AC_REQUIRE([AC_PROG_CC]) +AC_REQUIRE([AC_PROG_SED]) +AC_LANG_PUSH([C]) +ax_pthread_ok=no + +# We used to check for pthread.h first, but this fails if pthread.h +# requires special compiler flags (e.g. on Tru64 or Sequent). +# It gets checked for in the link test anyway. + +# First of all, check if the user has set any of the PTHREAD_LIBS, +# etcetera environment variables, and if threads linking works using +# them: +if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then + ax_pthread_save_CC="$CC" + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"]) + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS]) + AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes]) + AC_MSG_RESULT([$ax_pthread_ok]) + if test "x$ax_pthread_ok" = "xno"; then + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" + fi + CC="$ax_pthread_save_CC" + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" +fi + +# We must check for the threads library under a number of different +# names; the ordering is very important because some systems +# (e.g. DEC) have both -lpthread and -lpthreads, where one of the +# libraries is broken (non-POSIX). + +# Create a list of thread flags to try. Items starting with a "-" are +# C compiler flags, and other items are library names, except for "none" +# which indicates that we try without any flags at all, and "pthread-config" +# which is a program returning the flags for the Pth emulation library. + +ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" + +# The ordering *is* (sometimes) important. Some notes on the +# individual items follow: + +# pthreads: AIX (must check this before -lpthread) +# none: in case threads are in libc; should be tried before -Kthread and +# other compiler flags to prevent continual compiler warnings +# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) +# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64 +# (Note: HP C rejects this with "bad form for `-t' option") +# -pthreads: Solaris/gcc (Note: HP C also rejects) +# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it +# doesn't hurt to check since this sometimes defines pthreads and +# -D_REENTRANT too), HP C (must be checked before -lpthread, which +# is present but should not be used directly; and before -mthreads, +# because the compiler interprets this as "-mt" + "-hreads") +# -mthreads: Mingw32/gcc, Lynx/gcc +# pthread: Linux, etcetera +# --thread-safe: KAI C++ +# pthread-config: use pthread-config program (for GNU Pth library) + +case $host_os in + + freebsd*) + + # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) + # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) + + ax_pthread_flags="-kthread lthread $ax_pthread_flags" + ;; + + hpux*) + + # From the cc(1) man page: "[-mt] Sets various -D flags to enable + # multi-threading and also sets -lpthread." + + ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags" + ;; + + openedition*) + + # IBM z/OS requires a feature-test macro to be defined in order to + # enable POSIX threads at all, so give the user a hint if this is + # not set. (We don't define these ourselves, as they can affect + # other portions of the system API in unpredictable ways.) + + AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING], + [ +# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS) + AX_PTHREAD_ZOS_MISSING +# endif + ], + [AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])]) + ;; + + solaris*) + + # On Solaris (at least, for some versions), libc contains stubbed + # (non-functional) versions of the pthreads routines, so link-based + # tests will erroneously succeed. (N.B.: The stubs are missing + # pthread_cleanup_push, or rather a function called by this macro, + # so we could check for that, but who knows whether they'll stub + # that too in a future libc.) So we'll check first for the + # standard Solaris way of linking pthreads (-mt -lpthread). + + ax_pthread_flags="-mt,pthread pthread $ax_pthread_flags" + ;; +esac + +# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC) + +AS_IF([test "x$GCC" = "xyes"], + [ax_pthread_flags="-pthread -pthreads $ax_pthread_flags"]) + +# The presence of a feature test macro requesting re-entrant function +# definitions is, on some systems, a strong hint that pthreads support is +# correctly enabled + +case $host_os in + darwin* | hpux* | linux* | osf* | solaris*) + ax_pthread_check_macro="_REENTRANT" + ;; + + aix*) + ax_pthread_check_macro="_THREAD_SAFE" + ;; + + *) + ax_pthread_check_macro="--" + ;; +esac +AS_IF([test "x$ax_pthread_check_macro" = "x--"], + [ax_pthread_check_cond=0], + [ax_pthread_check_cond="!defined($ax_pthread_check_macro)"]) + +# Are we compiling with Clang? + +AC_CACHE_CHECK([whether $CC is Clang], + [ax_cv_PTHREAD_CLANG], + [ax_cv_PTHREAD_CLANG=no + # Note that Autoconf sets GCC=yes for Clang as well as GCC + if test "x$GCC" = "xyes"; then + AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG], + [/* Note: Clang 2.7 lacks __clang_[a-z]+__ */ +# if defined(__clang__) && defined(__llvm__) + AX_PTHREAD_CC_IS_CLANG +# endif + ], + [ax_cv_PTHREAD_CLANG=yes]) + fi + ]) +ax_pthread_clang="$ax_cv_PTHREAD_CLANG" + +ax_pthread_clang_warning=no + +# Clang needs special handling, because older versions handle the -pthread +# option in a rather... idiosyncratic way + +if test "x$ax_pthread_clang" = "xyes"; then + + # Clang takes -pthread; it has never supported any other flag + + # (Note 1: This will need to be revisited if a system that Clang + # supports has POSIX threads in a separate library. This tends not + # to be the way of modern systems, but it's conceivable.) + + # (Note 2: On some systems, notably Darwin, -pthread is not needed + # to get POSIX threads support; the API is always present and + # active. We could reasonably leave PTHREAD_CFLAGS empty. But + # -pthread does define _REENTRANT, and while the Darwin headers + # ignore this macro, third-party headers might not.) + + PTHREAD_CFLAGS="-pthread" + PTHREAD_LIBS= + + ax_pthread_ok=yes + + # However, older versions of Clang make a point of warning the user + # that, in an invocation where only linking and no compilation is + # taking place, the -pthread option has no effect ("argument unused + # during compilation"). They expect -pthread to be passed in only + # when source code is being compiled. + # + # Problem is, this is at odds with the way Automake and most other + # C build frameworks function, which is that the same flags used in + # compilation (CFLAGS) are also used in linking. Many systems + # supported by AX_PTHREAD require exactly this for POSIX threads + # support, and in fact it is often not straightforward to specify a + # flag that is used only in the compilation phase and not in + # linking. Such a scenario is extremely rare in practice. + # + # Even though use of the -pthread flag in linking would only print + # a warning, this can be a nuisance for well-run software projects + # that build with -Werror. So if the active version of Clang has + # this misfeature, we search for an option to squash it. + + AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread], + [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG], + [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown + # Create an alternate version of $ac_link that compiles and + # links in two steps (.c -> .o, .o -> exe) instead of one + # (.c -> exe), because the warning occurs only in the second + # step + ax_pthread_save_ac_link="$ac_link" + ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g' + ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"` + ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)" + ax_pthread_save_CFLAGS="$CFLAGS" + for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do + AS_IF([test "x$ax_pthread_try" = "xunknown"], [break]) + CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS" + ac_link="$ax_pthread_save_ac_link" + AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], + [ac_link="$ax_pthread_2step_ac_link" + AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], + [break]) + ]) + done + ac_link="$ax_pthread_save_ac_link" + CFLAGS="$ax_pthread_save_CFLAGS" + AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no]) + ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try" + ]) + + case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in + no | unknown) ;; + *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;; + esac + +fi # $ax_pthread_clang = yes + +if test "x$ax_pthread_ok" = "xno"; then +for ax_pthread_try_flag in $ax_pthread_flags; do + + case $ax_pthread_try_flag in + none) + AC_MSG_CHECKING([whether pthreads work without any flags]) + ;; + + -mt,pthread) + AC_MSG_CHECKING([whether pthreads work with -mt -lpthread]) + PTHREAD_CFLAGS="-mt" + PTHREAD_LIBS="-lpthread" + ;; + + -*) + AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag]) + PTHREAD_CFLAGS="$ax_pthread_try_flag" + ;; + + pthread-config) + AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no]) + AS_IF([test "x$ax_pthread_config" = "xno"], [continue]) + PTHREAD_CFLAGS="`pthread-config --cflags`" + PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" + ;; + + *) + AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag]) + PTHREAD_LIBS="-l$ax_pthread_try_flag" + ;; + esac + + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + + # Check for various functions. We must include pthread.h, + # since some functions may be macros. (On the Sequent, we + # need a special flag -Kthread to make this header compile.) + # We check for pthread_join because it is in -lpthread on IRIX + # while pthread_create is in libc. We check for pthread_attr_init + # due to DEC craziness with -lpthreads. We check for + # pthread_cleanup_push because it is one of the few pthread + # functions on Solaris that doesn't have a non-functional libc stub. + # We try pthread_create on general principles. + + AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h> +# if $ax_pthread_check_cond +# error "$ax_pthread_check_macro must be defined" +# endif + static void *some_global = NULL; + static void routine(void *a) + { + /* To avoid any unused-parameter or + unused-but-set-parameter warning. */ + some_global = a; + } + static void *start_routine(void *a) { return a; }], + [pthread_t th; pthread_attr_t attr; + pthread_create(&th, 0, start_routine, 0); + pthread_join(th, 0); + pthread_attr_init(&attr); + pthread_cleanup_push(routine, 0); + pthread_cleanup_pop(0) /* ; */])], + [ax_pthread_ok=yes], + []) + + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" + + AC_MSG_RESULT([$ax_pthread_ok]) + AS_IF([test "x$ax_pthread_ok" = "xyes"], [break]) + + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" +done +fi + +# Various other checks: +if test "x$ax_pthread_ok" = "xyes"; then + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + + # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. + AC_CACHE_CHECK([for joinable pthread attribute], + [ax_cv_PTHREAD_JOINABLE_ATTR], + [ax_cv_PTHREAD_JOINABLE_ATTR=unknown + for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do + AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>], + [int attr = $ax_pthread_attr; return attr /* ; */])], + [ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break], + []) + done + ]) + AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \ + test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \ + test "x$ax_pthread_joinable_attr_defined" != "xyes"], + [AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], + [$ax_cv_PTHREAD_JOINABLE_ATTR], + [Define to necessary symbol if this constant + uses a non-standard name on your system.]) + ax_pthread_joinable_attr_defined=yes + ]) + + AC_CACHE_CHECK([whether more special flags are required for pthreads], + [ax_cv_PTHREAD_SPECIAL_FLAGS], + [ax_cv_PTHREAD_SPECIAL_FLAGS=no + case $host_os in + solaris*) + ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS" + ;; + esac + ]) + AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \ + test "x$ax_pthread_special_flags_added" != "xyes"], + [PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS" + ax_pthread_special_flags_added=yes]) + + AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT], + [ax_cv_PTHREAD_PRIO_INHERIT], + [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]], + [[int i = PTHREAD_PRIO_INHERIT; + return i;]])], + [ax_cv_PTHREAD_PRIO_INHERIT=yes], + [ax_cv_PTHREAD_PRIO_INHERIT=no]) + ]) + AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \ + test "x$ax_pthread_prio_inherit_defined" != "xyes"], + [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.]) + ax_pthread_prio_inherit_defined=yes + ]) + + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" + + # More AIX lossage: compile with *_r variant + if test "x$GCC" != "xyes"; then + case $host_os in + aix*) + AS_CASE(["x/$CC"], + [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6], + [#handle absolute path differently from PATH based program lookup + AS_CASE(["x$CC"], + [x/*], + [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])], + [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])]) + ;; + esac + fi +fi + +test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" + +AC_SUBST([PTHREAD_LIBS]) +AC_SUBST([PTHREAD_CFLAGS]) +AC_SUBST([PTHREAD_CC]) + +# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: +if test "x$ax_pthread_ok" = "xyes"; then + ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1]) + : +else + ax_pthread_ok=no + $2 +fi +AC_LANG_POP +])dnl AX_PTHREAD diff --git a/m4/dast.m4 b/m4/dast.m4 new file mode 100644 index 0000000..15ae308 --- /dev/null +++ b/m4/dast.m4 @@ -0,0 +1,148 @@ + +AH_TEMPLATE([HAVE_POSIX_THREAD], []) +AH_TEMPLATE([_REENTRANT], []) +AH_TEMPLATE([ssize_t], [Define to "int" if <sys/types.h> does not define.]) + +dnl =================================================================== +dnl DAST_REPLACE_TYPE( type, sizeof ) +dnl Check for the type as AC_CHECK_TYPE does. Define HAVE_<type> +dnl if type exists; don't define <type> to anything if it doesn't exist. +dnl Useful if there is no well-defined default type, such as int32_t + +AC_DEFUN(DAST_REPLACE_TYPE, [ + +AC_CACHE_CHECK(for $1, ac_cv_type_$1, + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[$ac_includes_default]], + [[$1 foo]])], + ac_cv_type_$1=yes, + ac_cv_type_$1=no) + +if test $ac_cv_type_$1 != yes ; then + if test "$ac_cv_sizeof_char" = $2; then + ac_cv_type_$1="char" + elif test "$ac_cv_sizeof_short" = $2; then + ac_cv_type_$1="short" + elif test "$ac_cv_sizeof_int" = $2; then + ac_cv_type_$1="int" + elif test "$ac_cv_sizeof_long" = $2; then + ac_cv_type_$1="long" + elif test "$ac_cv_sizeof_long_long" = $2; then + ac_cv_type_$1="long long" + fi +fi) + +if test "$ac_cv_type_$1" != no; then + if test "$ac_cv_type_$1" != yes; then + AC_DEFINE_UNQUOTED($1, $ac_cv_type_$1) + fi + AC_DEFINE_UNQUOTED(HAVE_`echo $1 | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`) +fi + +]) + +AC_DEFUN(DAST_REPLACE_TYPE_UNSIGNED, [ + +AC_CACHE_CHECK(for $1, ac_cv_type_$1, + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[$ac_includes_default]], + [[$1 foo]])], + ac_cv_type_$1=yes, + ac_cv_type_$1=no) + +if test $ac_cv_type_$1 != yes ; then + if test "$ac_cv_sizeof_unsigned_char" = $2; then + ac_cv_type_$1="unsigned char" + elif test "$ac_cv_sizeof_unsigned_short" = $2; then + ac_cv_type_$1="unsigned short" + elif test "$ac_cv_sizeof_unsigned_int" = $2; then + ac_cv_type_$1="unsigned int" + elif test "$ac_cv_sizeof_unsigned_long" = $2; then + ac_cv_type_$1="unsigned long" + elif test "$ac_cv_sizeof_unsigned_long_long" = $2; then + ac_cv_type_$1="unsigned long long" + fi +fi) + +if test "$ac_cv_type_$1" != no; then + if test "$ac_cv_type_$1" != yes; then + AC_DEFINE_UNQUOTED($1, $ac_cv_type_$1) + fi + AC_DEFINE_UNQUOTED(HAVE_`echo $1 | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`) +fi + +]) + +dnl DAST_CHECK_ARG +dnl Check for the 3rd arguement to accept + +AC_DEFUN(DAST_ACCEPT_ARG, [ + if test -z "$ac_cv_accept_arg" ; then + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + + AC_COMPILE_IFELSE([AC_LANG_PROGRAM( + [[$ac_includes_default + #include <sys/socket.h>]], + [[$1 length; + accept( 0, 0, &length );]])], + ac_cv_accept_arg=$1) + + AC_LANG_RESTORE + fi +]) + +dnl Configure paths for Web100. Based off of Owen Taylor's gtk.m4 from gtk+-1.2.10 +dnl AM_PATH_WEB100([EXACT-VERSION [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) +dnl Test for Web100, and define WEB100_CFLAGS and WEB100_LIBS +dnl +AC_DEFUN(AM_PATH_WEB100, +[ +web100_success="" + +AC_PATH_PROG([WEB100_CONFIG], [web100-config], [no]) + +AC_MSG_CHECKING(for Web100) + +if test "$WEB100_CONFIG" != "no"; then + WEB100_CFLAGS=`$WEB100_CONFIG --cflags` + WEB100_LIBS=`$WEB100_CONFIG --libs` + AC_MSG_RESULT(yes) +else + AC_MSG_RESULT(no) + echo "*** The web100-config script installed by Web100 could not be found" + echo "*** If Web100 was installed in PREFIX, make sure PREFIX/bin is in" + echo "*** your path, or set the WEB100_CONFIG environment variable to the" + echo "*** full path to web100-config" + web100_success="no" +fi + +if test x$web100_success = x; then + if test "x$1" != "x"; then + AC_MSG_CHECKING(for Web100 - version $1) + + WEB100_VERSION=`$WEB100_CONFIG --version` + if test "$WEB100_VERSION" = "$1"; then + AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no) + echo "*** The requested ($1) and installed ($WEB100_VERSION) versions" + echo "*** of Web100 do not match." + web100_success="no" + fi + fi +fi + +if test x$web100_success = x; then + web100_success="yes" +fi + +if test x$web100_success = xyes; then + m4_if([$2], [], [:], [$2]) +else + WEB100_CFLAGS="" + WEB100_LIBS="" + m4_if([$3], [], [:], [$3]) +fi + +AC_SUBST(WEB100_CFLAGS) +AC_SUBST(WEB100_LIBS) +]) diff --git a/man/Makefile.am b/man/Makefile.am new file mode 100644 index 0000000..728873f --- /dev/null +++ b/man/Makefile.am @@ -0,0 +1 @@ +dist_man_MANS = iperf.1 diff --git a/man/Makefile.in b/man/Makefile.in new file mode 100644 index 0000000..51e1fe5 --- /dev/null +++ b/man/Makefile.in @@ -0,0 +1,508 @@ +# Makefile.in generated by automake 1.16.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = man +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/m4/dast.m4 $(top_srcdir)/m4/ax_pthread.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +man1dir = $(mandir)/man1 +am__installdirs = "$(DESTDIR)$(man1dir)" +NROFF = nroff +MANS = $(dist_man_MANS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(dist_man_MANS) $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +STRIP_BEGIN = @STRIP_BEGIN@ +STRIP_DUMMY = @STRIP_DUMMY@ +STRIP_END = @STRIP_END@ +VERSION = @VERSION@ +WEB100_CFLAGS = @WEB100_CFLAGS@ +WEB100_CONFIG = @WEB100_CONFIG@ +WEB100_LIBS = @WEB100_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +dist_man_MANS = iperf.1 +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu man/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu man/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-man1: $(dist_man_MANS) + @$(NORMAL_INSTALL) + @list1=''; \ + list2='$(dist_man_MANS)'; \ + test -n "$(man1dir)" \ + && test -n "`echo $$list1$$list2`" \ + || exit 0; \ + echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \ + { for i in $$list1; do echo "$$i"; done; \ + if test -n "$$list2"; then \ + for i in $$list2; do echo "$$i"; done \ + | sed -n '/\.1[a-z]*$$/p'; \ + fi; \ + } | while read p; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; echo "$$p"; \ + done | \ + sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ + sed 'N;N;s,\n, ,g' | { \ + list=; while read file base inst; do \ + if test "$$base" = "$$inst"; then list="$$list $$file"; else \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ + fi; \ + done; \ + for i in $$list; do echo "$$i"; done | $(am__base_list) | \ + while read files; do \ + test -z "$$files" || { \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ + done; } + +uninstall-man1: + @$(NORMAL_UNINSTALL) + @list=''; test -n "$(man1dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \ + sed -n '/\.1[a-z]*$$/p'; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir) +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(MANS) +installdirs: + for dir in "$(DESTDIR)$(man1dir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-man + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: install-man1 + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-man + +uninstall-man: uninstall-man1 + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic cscopelist-am \ + ctags-am distclean distclean-generic distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-man1 install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ + pdf-am ps ps-am tags-am uninstall uninstall-am uninstall-man \ + uninstall-man1 + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/man/iperf.1 b/man/iperf.1 new file mode 100644 index 0000000..8ca1343 --- /dev/null +++ b/man/iperf.1 @@ -0,0 +1,1008 @@ +.TH IPERF 1 "February 2023" NLANR/DAST "User Manuals" +.SH NAME +iperf \- perform network traffic tests using network sockets. Metrics include throughput and latency or link capacity and responsiveness. +.SH SYNOPSIS +.BI "iperf -s [" options ] + +.BI "iperf -c " server " [" options ] + +.BI "iperf -u -s [" options ] + +.BI "iperf -u -c " server " [" options ] + +.SH DESCRIPTION +.LP +iperf 2 is a testing tool which performs network traffic measurements using network sockets. The performance +metrics supported include throughput and latency (or link capacity and responsiveness.) Latency measurements include +both one way delay (OWD) and round trip times (RTTs.) Iperf can use both TCP and UDP sockets (or +protocols.) It supports unidirectional, full duplex (same socket) and bidirectional traffic, and supports +multiple, simultaneous traffic streams. It supports multicast traffic including source specific +multicast (SSM) joins. Its multi-threaded design allows for peak performance. Metrics displayed help to +characterize host to host network performance. Setting the enhanced (-e) option provides all +available metrics. Note: the metrics are at the socket level reads and writes. They do +not include the overhead associated with lower level protocol layer headers. +.LP +The user must establish both a server (to receive traffic) +and a client (to generate and send traffic) for a test to occur. +The client and server typically are on different hosts or +computers but need not be. +.SH "GENERAL OPTIONS" +.TP +.BR -b ", " --bandwidth " " +set the target bandwidth and optional standard deviation per +\fI<mean>\fR,\fI[<stdev>]\fR (See NOTES for suffixes) +.TP +.BR -e ", " --enhanced " " +Display enhanced output in reports otherwise use legacy report (ver +2.0.5) formatting (see NOTES) +.TP +.BR -f ", " --format " " [abkmgBKMG] +format to report: adaptive, bits, Bytes, Kbits, Mbits, Gbits, KBytes, +MBytes, GBytes (see NOTES for more) +.TP +.BR -h ", " --help " " +print a help synopsis +.TP +.BR " --hide-ips " +obscure ip addresses in output (useful when wanting to publish results and not display the full ip addresses. v4 only) +.TP +.BR -i ", " --interval " < \fIt\fR | f >" +sample or display interval reports every \fIt\fR seconds (default) or every frame or burst, i.e. if f is used then the interval will be each frame or burst. The frame interval reporting is experimental. Also suggest a compile with fast-sampling, i.e. ./configure --enable-fastsampling +.TP +.BR -l ", " --len " \fIn\fR[kmKM]" +set read/write buffer size (TCP) or length (UDP) to \fIn\fR (TCP default 128K, UDP default 1470) +.TP +.BR " --l2checks " +perform layer 2 length checks on received UDP packets (requires systems that support packet sockets, e.g. Linux) +.TP +.BR -m ", " --print_mss " " +print TCP maximum segment size +.TP +.BR " --NUM_REPORT_STRUCTS " \fI<count>\fR +Override the default shared memory size between the traffic thread(s) and reporter thread in order to mitigate mutex lock contentions. The default value of 5000 should be sufficient for 1Gb/s networks. Increase this upon seeing the Warning message of reporter thread too slow. If the Warning message isn't seen, then increasing this won't have any significant effect (other than to use some additional memory.) +.TP +.BR -o ", " --output " \fIfilename\fR" +output the report or error message to this specified file +.TP +.BR " --permit-key [=" \fI<value>\fR "]" +Set a key value that must match for the server to accept traffic on a connection. If the option is given without a value on the server a key value will be autogenerated and displayed in its initial settings report. The lifetime of the key is set using --permit-key-timeout and defaults to twenty seconds. The value is required on clients. The value will also be used as part of the transfer id in reports. The option set on the client but not the server will also cause the server to reject the client's traffic. TCP only, no UDP support. +.TP +.BR -p ", " --port " \fIm\fR[-\fIn\fR]" +set client or server port(s) to send or listen on per \fIm\fR (default 5001) w/optional port range per m-n (e.g. -p 6002-6008) (see NOTES) +.TP +.BR " --sum-dstip" +sum traffic threads based upon the destination IP address (default is source ip address) +.TP +.BR " --sum-only " +set the output to sum reports only. Useful for -P at large values +.TP +.BR -t ", " --time " \fIn\fR" +time in seconds to listen for new traffic connections, receive traffic or send traffic +.TP +.BR -u ", " --udp " " +use UDP rather than TCP +.TP +.BR " --utc" +use coordinated universal time (UTC) when outputting time (otherwise use local time) +.TP +.BR -w ", " --window " \fIn\fR[kmKM]" +TCP window size (socket buffer size) +.TP +.BR -z ", " --realtime " " +Request real-time scheduler, if supported. +.TP +.BR -B ", " --bind " \fIhost\fR[:\fIport\fR][%\fIdev\fR]" +bind to \fIhost\fR, ip address or multicast address, optional port or device (see NOTES) +.TP +.BR -C ", " --compatibility " " +for use with older versions does not sent extra msgs +.TP +.BR -M ", " --mss " \fIn\fR" +set TCP maximum segment size using TCP_MAXSEG +.TP +.BR -N ", " --nodelay " " +set TCP no delay, disabling Nagle's Algorithm +.TP +.BR -v ", " --version " " +print version information and quit +.TP +.BR -x ", " --reportexclude " [CDMSV]" +exclude C(connection) D(data) M(multicast) S(settings) V(server) reports +.TP +.BR -y ", " --reportstyle " C|c" +if set to C or c report results as CSV (comma separated values) +.TP +.BR -Z ", " --tcp-congestion " " +Set the default congestion-control algorithm to be used for new connections. Platforms must support setsockopt's TCP_CONGESTION. (Notes: See sysctl and tcp_allowed_congestion_control for available options. May require root privileges.) +.SH "SERVER SPECIFIC OPTIONS" +.TP +.BR -1 ", " --singleclient " " +set the server to process only one client at a time +.TP +.BR -b ", " --bandwidth " \fIn\fR[kmgKMG]" +set target read rate to \fIn\fR bits/sec. TCP only for the server. +.TP +.BR -s ", " --server " " +run in server mode +.TP +.BR " --histograms[="\fIbinwidth\fR[u],\fIbincount\fR,[\fIlowerci\fR],[\fIupperci\fR] "]" +enable latency histograms for udp packets (-u), for tcp writes (with --trip-times), or for either udp or tcp with --isochronous clients, or for --bounceback. The binning can be modified. Bin widths (default 1 millisecond, append u for microseconds, m for milliseconds) bincount is total bins (default 1000), ci is confidence interval between 0-100% (default lower 5%, upper 95%, 3 stdev 99.7%) +.TP +.BR " --jitter-histograms[=" \fI<binwidth>\fR "]" +enable jitter histograms for udp packets (-u). Optional value is the bin width where units are microseconds and defaults to 100 usecs +.TP +.BR " --permit-key [=" \fI<value>\fR "]" +Set a key value that must match for the server to accept traffic from a client (also set with --permit-key.) The server will auto-generate a globally unique key when the option is given without a value. This value will be displayed in the server's initial settings report. The lifetime of the key is set using --permit-key-timeout and defaults to twenty seconds. TCP only, no UDP support. +.TP +.BR " --permit-key-timeout " \fI<value>\fR +Set the lifetime of the permit key in seconds. Defaults to 20 seconds if not set. A value of zero will disable the timer. +.TP +.BR " --tap-dev " \fI<dev>\fR +Set the receive interface to the TAP device as specified. +.TP +.BR " --tcp-rx-window-clamp " \fIn\fR[kmKM] +Set the socket option of TCP_WINDOW_CLAMP, units is bytes. +.TP +.BR -t ", " --time " \fIn\fR" +time in seconds to listen for new traffic connections and/or receive traffic (defaults to infinite) +.TP +.BR " --tos-override " \fI<val>\fR +set the socket's IP_TOS value for reverse or full duplex traffic. Supported in versions 2.1.5 or greater. Previous versions won't set IP_TOS on reverse traffic. See NOTES for values. +.TP +.BR -B ", " --bind " \fIip\fR | \fIip\fR%\fIdevice\fR" +bind src ip addr and optional src device for receiving +.TP +.BR -D ", " --daemon " " +run the server as a daemon. On Windows this will run the specified +command-line under the IPerfService, installing the service if +necessary. Note the service is not configured to auto-start or +restart - if you need a self-starting service you will need to create +an init script or use Windows "sc" commands. +.TP +.BR -H ", " --ssm-host " \fIhost\fR" +Set the source host (ip addr) per SSM multicast, i.e. the S of the S,G +.TP +.BR -R ", " --remove " " +remove the IPerfService (Windows only). +.TP +.BR -U ", " --single_udp " " +run in single threaded UDP mode +.TP +.BR -V ", " --ipv6_domain " " +Enable IPv6 reception by setting the domain and socket to AF_INET6 (Can receive on both IPv4 and IPv6) +.SH "CLIENT SPECIFIC OPTIONS" +.TP +.BR -b ", " --bandwidth " \fIn\fR[kmgKMG][,\fIn\fR[kmgKMG]] | \fIn\fR\fR[kmgKMG]pps" +set target bandwidth to \fIn\fR bits/sec (default 1 Mbit/sec) or +\fIn\fR packets per sec. This may be used with TCP or UDP. Optionally, for variable loads, use format of mean,standard deviation +.TP +.BR " --bounceback[=" \fIn\fR "]" +run a TCP bounceback or rps test with optional number writes in a burst per value of n. The default is ten writes every period and the default period is one second (Note: set size with -l or --len which defaults to 100 bytes) +.TP +.BR " --bounceback-hold " \fIn\fR +request the server to insert a delay of n milliseconds between its read and write (default is no delay) +.TP +.BR " --bounceback-period[=" \fIn\fR "]" +request the client schedule its send(s) every n seconds (default is one second, use zero value for immediate or continuous back to back) +.TP +.BR " --bounceback-no-quickack " +request the server not set the TCP_QUICKACK socket option (disabling TCP ACK delays) during a bounceback test (see NOTES) +.TP +.BR " --bounceback-txdelay " \fIn\fR +request the client to delay n seconds between the start of the working load and the bounceback traffic (default is no delay) +.TP +.BR " --burst-period " \fIn\fR +Set the burst period in seconds. Defaults to one second. (Note: assumed use case is low duty cycle traffic bursts) +.TP +.BR " --burst-size " \fIn\fR +Set the burst size in bytes. Defaults to 1M if no value is given. +.BR -c ", " --client " \fI\fIhost\fR | \fIhost\fR%\fIdevice\fR" +run in client mode, connecting to \fIhost\fR where the optional %dev will SO_BINDTODEVICE that output interface (requires root and see NOTES) +.TP +.TP +.BR " --connect-only[=" \fIn\fR "]" +only perform a TCP connect (or 3WHS) without any data transfer, useful to measure TCP connect() times. Optional value of n is the total number of connects to do (zero is run forever.) Note that -i will rate limit the connects where -P will create bursts and -t will end the client and hence end its connect attempts. +.TP +.BR " --connect-retries[= " \fIn\fR "]" +number of times to retry a TCP connect at the application level. See operating system information on the details of TCP connect related settings. +.TP +.BR -d ", " --dualtest " " +Do a bidirectional test simultaneous test using two unidirectional sockets +.TP +.BR " --fq-rate n[kmgKMG]" +Set a rate to be used with fair-queuing based socket-level pacing, in bytes or bits per second. Only available on platforms supporting the SO_MAX_PACING_RATE socket option. (Note: Here the suffixes indicate bytes/sec or bits/sec per use of uppercase or lowercase, respectively) +.TP +.BR " --full-duplex" +run a full duplex test, i.e. traffic in both transmit and receive directions using the \fBsame socket\fR +.TP +.BR " --histograms[="\fIbinwidth\fR[u],\fIbincount\fR,[\fIlowerci\fR],[\fIupperci\fR] "]" +enable select()/write() histograms with --tcp-write-times or --bounceback (these options are mutually exclusive.) The binning can be modified. Bin widths (default 100 microseconds, append u for microseconds, m for milliseconds) bincount is total bins (default 10000), ci is confidence interval between 0-100% (default lower 5%, upper 95%, 3 stdev 99.7%) +.TP +.BR " --incr-dstip" +increment the destination ip address when using the parallel (-P) or port range option +.TP +.BR " --incr-dstport" +increment the destination port when using the parallel (-P) or port range option +.TP +.BR " --incr-srcip" +increment the source ip address when using the parallel (-P) or port range option +.TP +.BR " --incr-srcport" +increment the source ip address when using the parallel (-P) or port range option, requires -B to set the src port +.TP +.BR " --ipg "\fIn\fR +set the inter-packet gap to \fIn\fR (units of seconds) for packets or within a frame/burst when --isochronous is set +.TP +.BR " --isochronous[=" \fIfps\fR:\fImean\fR,\fIstdev\fR "]" +send isochronous traffic with frequency frames per second and load defined by mean and standard deviation using a log normal distribution, defaults to 60:20m,0. (Note: Here the suffixes indicate bytes/sec or bits/sec per use of uppercase or lowercase, respectively. Also the p suffix is supported to set the burst size in packets, e.g. isochronous=2:25p will send two 25 packet bursts every second, or one 25 packet burst every 0.5 seconds.) +.TP +.BR " --local-only[=\fI1\fR|\fI0\fR]" +Set 1 to limit traffic to the local network only (through the use of SO_DONTROUTE) set to zero otherwise with optional override of compile time default (see configure --default-localonly) +.TP +.BR " --near-congestion[=\fIn\fR]" +Enable TCP write rate limiting per the sampled RTT. The delay is applied after the -l number of bytes have completed. The optional value is the multiplier to the RTT and defines the time delay. This value defaults to 0.5 if it is not set. Values less than 1 are supported but the value cannot be negative. This is an experimental feature. It is not likely stable on live networks. Suggested use is over controlled test networks. +.TP +.BR " --no-connect-sync " +By default, parallel traffic threads (per -P greater than 1) will synchronize after their TCP connects and prior to each sending traffic, i.e. all the threads first complete (or error) the TCP 3WHS before any traffic thread will start sending. This option disables that synchronization such that each traffic thread will start sending immediately after completing its successful connect. +.TP +.BR " --no-udp-fin " +Don't perform the UDP final server to client exchange which means there won't be a final server report displayed on the client. All packets per the test will be from the client to the server and no packets should be sent in the other direction. +.B It's highly suggested that -t be set on the server if this option is being used. +This is because there will be +.B only one trigger ending packet +sent from client to server and if it's lost then the server will continue to run. (Requires ver 2.0.14 or better) +.TP +.BR -n ", " --num " \fIn\fR[kmKM]" +number of bytes to transmit (instead of -t) +.TP +.BR " --permit-key [=" \fI<value>\fR "]" +Set a key value that must match the server's value (also set with --permit-key) in order for the server to accept traffic from the client. TCP only, no UDP support. +.TP +.BR -r ", " --tradeoff " " +Do a bidirectional test individually - client-to-server, followed by +a reversed test, server-to-client +.TP +.BR " --tcp-quickack " +Set TCP_QUICKACK on the socket +.TP +.BR " --tcp-write-prefetch " \fIn\fR[kmKM] +Set TCP_NOTSENT_LOWAT on the socket and use event based writes per select() on the socket. +.TP +.BR " --tcp-write-times " +Measure the socket write times +.TP +.BR -t ", " --time " \fIn\fR" | "\fI0\fR" +time in seconds to transmit traffic, use zero for infinite (default is 10 secs) +.TP +.BR " --trip-times " +enable the measurement of end to end write to read latencies (client and server clocks must be synchronized.) See notes about tcp-write-prefetch being enabled. +.TP +.BR " --txdelay-time " +time in seconds to hold back or delay after the TCP connect and prior to the socket writes. For UDP it's the delay between the traffic thread starting and the first write. +.TP +.BR " --txstart-time "\fIn\fR.\fIn\fR +set the txstart-time to \fIn\fR.\fIn\fR using unix or epoch time format (supports microsecond resolution, e.g 1536014418.123456) An example to delay one second using command substitution is iperf -c 192.168.1.10 --txstart-time $(expr $(date +%s) + 1).$(date +%N) +.TP +.BR -B ", " --bind " \fIip\fR | \fIip\fR:\fIport\fR | \fIipv6 -V\fR | \fI[ipv6]\fR:\fIport -V\fR" +bind src ip addr and optional port as the source of traffic (see NOTES) +.TP +.BR -F ", " --fileinput " \fIname\fR" +input the data to be transmitted from a file +.TP +.BR -I ", " --stdin " " +input the data to be transmitted from stdin +.TP +.BR -L ", " --listenport " \fIn\fR" +port to receive bidirectional tests back on +.TP +.BR -P ", " --parallel " \fIn\fR" +number of parallel client threads to run +.TP +.BR -R ", " --reverse " " +reverse the traffic flow (useful for testing through firewalls, see NOTES) +.TP +.BR -S ", " --tos " \fI<val>\fR" +set the socket's IP_TOS value. Versions 2.1.5 or greater will reflect this tos setting back with --reverse or --full-duplex option. (Previous versions won't set tos on the reverse traffic.) Note: use server side --tos-override to override. See NOTES for values. +.TP +.BR -T ", " --ttl " \fIn\fR" +time-to-live, for multicast (default 1) +.TP +.BR " --working-load[="\fBup|down|bidir][\fR,\fIn\fR\fB]\fR +request a concurrent working load, currently TCP stream(s), defaults to full duplex (or bidir) unless the \fBup\fR or \fBdown\fR option is provided. The number of TCP streams defaults to 1 and can be changed via the n value, e.g. \fB--working-load=down,4\fR will use four TCP streams from server to the client as the working load. The IP ToS will be BE (0x0) for working load traffic. +.TP +.BR -V ", " --ipv6_domain " " +Set the domain to IPv6 (send packets over IPv6) +.TP +.BR -X ", " --peerdetect " " +run peer version detection prior to traffic. +.TP +.BR -Z ", " --linux-congestion " \fIalgo\fR" +set TCP congestion control algorithm (Linux only) +.SH EXAMPLES + +.B TCP tests (client) + +.B iperf -c <host> -e -i 1 +.br +------------------------------------------------------------ +.br +Client connecting to <host>, TCP port 5001 with pid 5149 +.br +Write buffer size: 128 KByte +.br +TCP window size: 340 KByte (default) +.br +------------------------------------------------------------ +.br +[ 3] local 45.56.85.133 port 49960 connected with 45.33.58.123 port 5001 (ct=3.23 ms) +.br +[ ID] Interval Transfer Bandwidth Write/Err Rtry Cwnd/RTT NetPwr +.br +[ 3] 0.00-1.00 sec 126 MBytes 1.05 Gbits/sec 1006/0 0 56K/626 us 210636.47 +.br +[ 3] 1.00-2.00 sec 138 MBytes 1.15 Gbits/sec 1100/0 299 483K/3884 us 37121.32 +.br +[ 3] 2.00-3.00 sec 137 MBytes 1.15 Gbits/sec 1093/0 24 657K/5087 us 28162.31 +.br +[ 3] 3.00-4.00 sec 126 MBytes 1.06 Gbits/sec 1010/0 284 294K/2528 us 52366.58 +.br +[ 3] 4.00-5.00 sec 117 MBytes 980 Mbits/sec 935/0 373 487K/2025 us 60519.66 +.br +[ 3] 5.00-6.00 sec 144 MBytes 1.20 Gbits/sec 1149/0 2 644K/3570 us 42185.36 +.br +[ 3] 6.00-7.00 sec 126 MBytes 1.06 Gbits/sec 1011/0 112 582K/5281 us 25092.56 +.br +[ 3] 7.00-8.00 sec 110 MBytes 922 Mbits/sec 879/0 56 279K/1957 us 58871.89 +.br +[ 3] 8.00-9.00 sec 127 MBytes 1.06 Gbits/sec 1014/0 46 483K/3372 us 39414.89 +.br +[ 3] 9.00-10.00 sec 132 MBytes 1.11 Gbits/sec 1054/0 0 654K/3380 us 40872.75 +.br +[ 3] 0.00-10.00 sec 1.25 GBytes 1.07 Gbits/sec 10251/0 1196 -1K/3170 us 42382.03 + +.TP +.B where (per -e,) +.B ct= +TCP connect time (or three way handshake time 3WHS) +.br +.B Write/Err +Total number of successful socket writes. Total number of non-fatal socket write errors +.br +.B Rtry +Total number of TCP retries +.br +.B Cwnd/RTT (*nix only) +TCP congestion window and round trip time (sampled where NA indicates no value) +.br +.B NetPwr (*nix only) +Network power defined as (throughput / RTT) + +.PP + +.B iperf -c host.doamin.com -i 1 --bounceback --permit-key=mytest --hide-ips +.br +------------------------------------------------------------ +.br +Client connecting to (**hidden**), TCP port 5001 +.br +Bursting: 100 Byte writes 10 times every 1.00 second(s) +.br +Bounce-back test (size= 100 Byte) (server hold req=0 usecs) +.br +TCP window size: 16.0 KByte (default) +.br +------------------------------------------------------------ +.br +[mytest(1)] local *.*.*.96 port 38044 connected with *.*.*.123 port 5001 (bb len/hold=100/0) (icwnd/mss/irtt=14/1448/10605) +.br +[ ID] Interval Transfer Bandwidth BB cnt=avg/min/max/stdev Rtry Cwnd/RTT RPS +.br +[mytest(1)] 0.00-1.00 sec 1.95 KBytes 16.0 Kbits/sec 10=11.949/9.662/19.597/3.127 ms 0 14K/10930 us 83 rps +.br +[mytest(1)] 1.00-2.00 sec 1.95 KBytes 16.0 Kbits/sec 10=10.004/9.651/10.322/0.232 ms 0 14K/10244 us 99 rps +.br +[mytest(1)] 2.00-3.00 sec 1.95 KBytes 16.0 Kbits/sec 10=10.582/9.720/14.831/1.573 ms 0 14K/10352 us 94 rps +.br +[mytest(1)] 3.00-4.00 sec 1.95 KBytes 16.0 Kbits/sec 10=11.303/9.940/15.114/2.026 ms 0 14K/10832 us 88 rps +.br +[mytest(1)] 4.00-5.00 sec 1.95 KBytes 16.0 Kbits/sec 10=11.148/9.671/14.803/1.837 ms 0 14K/10858 us 89 rps +.br +[mytest(1)] 5.00-6.00 sec 1.95 KBytes 16.0 Kbits/sec 10=10.207/9.695/10.729/0.356 ms 0 14K/10390 us 97 rps +.br +[mytest(1)] 6.00-7.00 sec 1.95 KBytes 16.0 Kbits/sec 10=10.871/9.770/14.387/1.547 ms 0 14K/10660 us 91 rps +.br +[mytest(1)] 7.00-8.00 sec 1.95 KBytes 16.0 Kbits/sec 10=11.224/9.760/14.993/1.837 ms 0 14K/11027 us 89 rps +.br +[mytest(1)] 8.00-9.00 sec 1.95 KBytes 16.0 Kbits/sec 10=10.719/9.887/14.553/1.455 ms 0 14K/10620 us 93 rps +.br +[mytest(1)] 9.00-10.00 sec 1.95 KBytes 16.0 Kbits/sec 10=10.775/9.689/14.746/1.562 ms 0 14K/10596 us 92 rps +.br +[mytest(1)] 0.00-10.02 sec 19.5 KBytes 16.0 Kbits/sec 100=10.878/9.651/19.597/1.743 ms 0 14K/11676 us 91 rps +.br +[ 1] 0.00-10.02 sec BB8(f)-PDF: bin(w=100us):cnt(100)=97:5,98:8,99:10,100:8,101:12,102:10,103:6,104:7,105:2,106:2,107:3,108:3,109:2,110:1,114:1,115:1,118:1,120:2,121:1,124:1,125:1,128:1,140:1,143:1,144:1,146:2,148:1,149:2,150:1,151:1,152:1,196:1 (5.00/95.00/99.7%=97/149/196,Outliers=0,obl/obu=0/0) +.br + +.TP +.B where +.B BB cnt=avg/min/max/stdev +Count of bouncebacks, average time, minimum time, maximum time, standard deviation units of ms +.br +.B Rtry +Total number of TCP retries +.br +.B Cwnd/RTT (*nix only) +TCP congestion window and round trip time (sampled where NA indicates no value) +.br +.B RPS +Responses per second + +.PP + +.B TCP tests (server) + +.B +iperf -s -e -i 1 -l 8K +.br +------------------------------------------------------------ +.br +Server listening on TCP port 5001 with pid 13430 +.br +Read buffer size: 8.00 KByte +.br +TCP window size: 85.3 KByte (default) +.br +------------------------------------------------------------ +.br +[ 4] local 45.33.58.123 port 5001 connected with 45.56.85.133 port 49960 +.br +[ ID] Interval Transfer Bandwidth Reads Dist(bin=1.0K) +.br +[ 4] 0.00-1.00 sec 124 MBytes 1.04 Gbits/sec 22249 798:2637:2061:767:2165:1563:589:11669 +.br +[ 4] 1.00-2.00 sec 136 MBytes 1.14 Gbits/sec 24780 946:3227:2227:790:2427:1888:641:12634 +.br +[ 4] 2.00-3.00 sec 137 MBytes 1.15 Gbits/sec 24484 1047:2686:2218:810:2195:1819:728:12981 +.br +[ 4] 3.00-4.00 sec 126 MBytes 1.06 Gbits/sec 20812 863:1353:1546:614:1712:1298:547:12879 +.br +[ 4] 4.00-5.00 sec 117 MBytes 984 Mbits/sec 20266 769:1886:1828:589:1866:1350:476:11502 +.br +[ 4] 5.00-6.00 sec 143 MBytes 1.20 Gbits/sec 24603 1066:1925:2139:822:2237:1827:744:13843 +.br +[ 4] 6.00-7.00 sec 126 MBytes 1.06 Gbits/sec 22635 834:2464:2249:724:2269:1646:608:11841 +.br +[ 4] 7.00-8.00 sec 110 MBytes 921 Mbits/sec 21107 842:2437:2747:592:2871:1903:496:9219 +.br +[ 4] 8.00-9.00 sec 126 MBytes 1.06 Gbits/sec 22804 1038:1784:2639:656:2738:1927:573:11449 +.br +[ 4] 9.00-10.00 sec 133 MBytes 1.11 Gbits/sec 23091 1088:1654:2105:710:2333:1928:723:12550 +.br +[ 4] 0.00-10.02 sec 1.25 GBytes 1.07 Gbits/sec 227306 9316:22088:21792:7096:22893:17193:6138:120790 +.br +.TP +.B where (per -e,) +.B Reads +Total number of socket reads +.br +.B Dist(bin=size) +Eight bin histogram of the socket reads returned byte count. Bin +width is set per size. Bins are separated by a colon. In the +example, the bins are 0-1K, 1K-2K, .., 7K-8K. + +.PP + +.B TCP tests (server with --trip-times on client) +.B +iperf -s -i 1 -w 4M +.br +------------------------------------------------------------ +.br +Server listening on TCP port 5001 +.br +TCP window size: 8.00 MByte (WARNING: requested 4.00 MByte) +.br +------------------------------------------------------------ +.br +[ 4] local 192.168.1.4%eth0 port 5001 connected with 192.168.1.7 port 44798 (trip-times) (MSS=1448) (peer 2.0.14-alpha) +.br +[ ID] Interval Transfer Bandwidth Burst Latency avg/min/max/stdev (cnt/size) inP NetPwr Reads=Dist +.br +[ 4] 0.00-1.00 sec 19.0 MBytes 159 Mbits/sec 52.314/10.238/117.155/19.779 ms (151/131717) 1.05 MByte 380.19 781=306:253:129:48:18:15:8:4 +.br +[ 4] 1.00-2.00 sec 20.0 MBytes 168 Mbits/sec 53.863/21.264/79.252/12.277 ms (160/131080) 1.08 MByte 389.38 771=294:236:126:60:18:24:10:3 +.br +[ 4] 2.00-3.00 sec 18.2 MBytes 153 Mbits/sec 58.718/22.000/137.944/20.397 ms (146/130964) 1.06 MByte 325.64 732=299:231:98:52:18:19:10:5 +.br +[ 4] 3.00-4.00 sec 19.7 MBytes 165 Mbits/sec 50.448/ 8.921/82.728/14.627 ms (158/130588) 997 KByte 409.00 780=300:255:121:58:15:18:7:6 +.br +[ 4] 4.00-5.00 sec 18.8 MBytes 158 Mbits/sec 53.826/11.169/115.316/15.541 ms (150/131420) 1.02 MByte 366.24 761=302:226:134:52:22:17:7:1 +.br +[ 4] 5.00-6.00 sec 19.5 MBytes 164 Mbits/sec 50.943/11.922/76.134/14.053 ms (156/131276) 1.03 MByte 402.00 759=273:246:149:45:16:18:4:8 +.br +[ 4] 6.00-7.00 sec 18.5 MBytes 155 Mbits/sec 57.643/10.039/127.850/18.950 ms (148/130926) 1.05 MByte 336.16 710=262:228:133:37:16:20:8:6 +.br +[ 4] 7.00-8.00 sec 19.6 MBytes 165 Mbits/sec 52.498/12.900/77.045/12.979 ms (157/131003) 1.00 MByte 391.78 742=288:200:135:68:16:23:4:8 +.br +[ 4] 8.00-9.00 sec 18.0 MBytes 151 Mbits/sec 58.370/ 8.026/150.243/21.445 ms (144/131255) 1.06 MByte 323.81 716=268:241:108:51:20:17:8:3 +.br +[ 4] 9.00-10.00 sec 18.4 MBytes 154 Mbits/sec 56.112/12.419/79.790/13.668 ms (147/131194) 1.05 MByte 343.70 822=330:303:120:26:16:14:9:4 +.br +[ 4] 10.00-10.06 sec 1.03 MBytes 146 Mbits/sec 69.880/45.175/78.754/10.823 ms (9/119632) 1.74 MByte 260.40 62=26:30:5:1:0:0:0:0 +.br +[ 4] 0.00-10.06 sec 191 MBytes 159 Mbits/sec 54.183/ 8.026/150.243/16.781 ms (1526/131072) 1.03 MByte 366.98 7636=2948:2449:1258:498:175:185:75:48 +.TP +.B where (per -e,) +.B Burst Latency +One way TCP write() to read() latency in mean/minimum/maximum/standard deviation format +(Note: requires the client's and server's system clocks to be +synchronized to a common reference, e.g. using precision time protocol +PTP. A GPS disciplined OCXO is a recommended reference.) +.br +.B cnt +Number of completed bursts received and used for the burst latency calculations +.br +.B size +Average burst size in bytes (computed average and estimate only) +.br +.B inP +inP, short for in progress, is the average number of bytes in progress or in flight. This is taken from the application level write to read perspective. Note this is +a mean value. The parenthesis value is the standard deviation from the mean. (Requires --trip-times on client. See Little's law in NOTES.) +.br +.B NetPwr +Network power defined as (throughput / one way latency) + +.PP + +.B TCP tests (with one way delay sync check -X and --trip-times on the client) + +.B iperf -c 192.168.1.4 -X -e --trip-times -i 1 -t 2 +.br +------------------------------------------------------------ +.br +Client connecting to 192.168.1.4, TCP port 5001 with pid 16762 (1 flows) +.br +Write buffer size: 131072 Byte +.br +TCP window size: 85.0 KByte (default) +.br +------------------------------------------------------------ +.br +.B [ 1] Clock sync check (ms): RTT/Half=(3.361/1.680) OWD-send/ack/asym=(2.246/1.115/1.131) +.br +[ 1] local 192.168.1.1%ap0 port 47466 connected with 192.168.1.4 port 5001 (MSS=1448) (trip-times) (sock=3) (peer 2.1.4-master) +.br +[ ID] Interval Transfer Bandwidth Write/Err Rtry Cwnd/RTT NetPwr +.br +[ 1] 0.00-1.00 sec 9.50 MBytes 79.7 Mbits/sec 77/0 0 2309K/113914 us 87 +.br +[ 1] 1.00-2.00 sec 7.12 MBytes 59.8 Mbits/sec 57/0 0 2492K/126113 us 59 +.br +[ 1] 2.00-2.42 sec 128 KBytes 2.47 Mbits/sec 2/0 0 2492K/126113 us 2 +.br +[ 1] 0.00-2.42 sec 16.8 MBytes 58.0 Mbits/sec 136/0 0 2492K/126113 us 57 +.br + +.PP + +.B UDP tests (client) + +.B iperf -c <host> -e -i 1 -u -b 10m +.br +------------------------------------------------------------ +.br +Client connecting to <host>, UDP port 5001 with pid 5169 +.br +Sending 1470 byte datagrams, IPG target: 1176.00 us (kalman adjust) +.br +UDP buffer size: 208 KByte (default) +.br +------------------------------------------------------------ +.br +[ 3] local 45.56.85.133 port 32943 connected with 45.33.58.123 port 5001 +.br +[ ID] Interval Transfer Bandwidth Write/Err PPS +.br +[ 3] 0.00-1.00 sec 1.19 MBytes 10.0 Mbits/sec 852/0 851 pps +.br +[ 3] 1.00-2.00 sec 1.19 MBytes 10.0 Mbits/sec 850/0 850 pps +.br +[ 3] 2.00-3.00 sec 1.19 MBytes 10.0 Mbits/sec 850/0 850 pps +.br +[ 3] 3.00-4.00 sec 1.19 MBytes 10.0 Mbits/sec 851/0 850 pps +.br +[ 3] 4.00-5.00 sec 1.19 MBytes 10.0 Mbits/sec 850/0 850 pps +.br +[ 3] 5.00-6.00 sec 1.19 MBytes 10.0 Mbits/sec 850/0 850 pps +.br +[ 3] 6.00-7.00 sec 1.19 MBytes 10.0 Mbits/sec 851/0 850 pps +.br +[ 3] 7.00-8.00 sec 1.19 MBytes 10.0 Mbits/sec 850/0 850 pps +.br +[ 3] 8.00-9.00 sec 1.19 MBytes 10.0 Mbits/sec 851/0 850 pps +.br +[ 3] 0.00-10.00 sec 11.9 MBytes 10.0 Mbits/sec 8504/0 850 pps +.br +[ 3] Sent 8504 datagrams +.br +[ 3] Server Report: +.br +[ 3] 0.00-10.00 sec 11.9 MBytes 10.0 Mbits/sec 0.047 ms 0/ 8504 (0%) 0.537/ 0.392/23.657/ 0.497 ms 850 pps 2329.37 +.br +.TP +.B where (per -e,) +.B Write/Err +Total number of successful socket writes. Total number of non-fatal socket write errors +.br +.B PPS +Transmit packet rate in packets per second + +.PP + +.B UDP tests (server) +.B iperf -s -i 1 -w 4M -u +.br +------------------------------------------------------------ +.br +Server listening on UDP port 5001 +.br +Receiving 1470 byte datagrams +.br +UDP buffer size: 8.00 MByte (WARNING: requested 4.00 MByte) +.br +------------------------------------------------------------ +.br +[ 3] local 192.168.1.4 port 5001 connected with 192.168.1.1 port 60027 (WARN: winsize=8.00 MByte req=4.00 MByte) (trip-times) (0.0) (peer 2.0.14-alpha) +.br +[ ID] Interval Transfer Bandwidth Jitter Lost/Total Latency avg/min/max/stdev PPS inP NetPwr +.br +[ 3] 0.00-1.00 sec 44.5 MBytes 373 Mbits/sec 0.071 ms 52198/83938 (62%) 75.185/ 2.367/85.189/14.430 ms 31854 pps 3.64 MByte 620.58 +.br +[ 3] 1.00-2.00 sec 44.8 MBytes 376 Mbits/sec 0.015 ms 59549/143701 (41%) 79.609/75.603/85.757/ 1.454 ms 31954 pps 3.56 MByte 590.04 +.br +[ 3] 2.00-3.00 sec 44.5 MBytes 373 Mbits/sec 0.017 ms 59494/202975 (29%) 80.006/75.951/88.198/ 1.638 ms 31733 pps 3.56 MByte 583.07 +.br +[ 3] 3.00-4.00 sec 44.5 MBytes 373 Mbits/sec 0.019 ms 59586/262562 (23%) 79.939/75.667/83.857/ 1.145 ms 31767 pps 3.56 MByte 583.57 +.br +[ 3] 4.00-5.00 sec 44.5 MBytes 373 Mbits/sec 0.081 ms 59612/322196 (19%) 79.882/75.400/86.618/ 1.666 ms 31755 pps 3.55 MByte 584.40 +.br +[ 3] 5.00-6.00 sec 44.7 MBytes 375 Mbits/sec 0.064 ms 59571/381918 (16%) 79.767/75.571/85.339/ 1.556 ms 31879 pps 3.56 MByte 588.02 +.br +[ 3] 6.00-7.00 sec 44.6 MBytes 374 Mbits/sec 0.041 ms 58990/440820 (13%) 79.722/75.662/85.938/ 1.087 ms 31820 pps 3.58 MByte 586.73 +.br +[ 3] 7.00-8.00 sec 44.7 MBytes 375 Mbits/sec 0.027 ms 59679/500548 (12%) 79.745/75.704/84.731/ 1.094 ms 31869 pps 3.55 MByte 587.46 +.br +[ 3] 8.00-9.00 sec 44.3 MBytes 371 Mbits/sec 0.078 ms 59230/559499 (11%) 80.346/75.514/94.293/ 2.858 ms 31590 pps 3.58 MByte 577.97 +.br +[ 3] 9.00-10.00 sec 44.4 MBytes 373 Mbits/sec 0.073 ms 58782/618394 (9.5%) 79.125/75.511/93.638/ 1.643 ms 31702 pps 3.55 MByte 588.99 +.br +[ 3] 10.00-10.08 sec 3.53 MBytes 367 Mbits/sec 0.129 ms 6026/595236 (1%) 94.967/80.709/99.685/ 3.560 ms 31107 pps 3.58 MByte 483.12 +.br +[ 3] 0.00-10.08 sec 449 MBytes 374 Mbits/sec 0.129 ms 592717/913046 (65%) 79.453/ 2.367/99.685/ 5.200 ms 31776 pps (null) 587.91 +.br + +.TP +.B where (per -e,) +.B Latency +End to end latency in mean/minimum/maximum/standard deviation format +(Note: requires the client's and server's system clocks to be +synchronized to a common reference, e.g. using precision time protocol +PTP. A GPS disciplined OCXO is a recommended reference.) +.br +.B PPS +Received packet rate in packets per second +.br +.B inP +inP, short for in progress, is the average number of bytes in progress or in flight. This is taken from an application write to read perspective. (Requires --trip-times on client. See Little's law in NOTES.) +.br +.B NetPwr +Network power defined as (throughput / latency) + +.PP + +.B Isochronous UDP tests (client) + +.B iperf -c 192.168.100.33 -u -e -i 1 --isochronous=60:100m,10m --realtime +.br +------------------------------------------------------------ +.br +Client connecting to 192.168.100.33, UDP port 5001 with pid 14971 +.br +UDP isochronous: 60 frames/sec mean= 100 Mbit/s, stddev=10.0 Mbit/s, Period/IPG=16.67/0.005 ms +.br +UDP buffer size: 208 KByte (default) +.br +------------------------------------------------------------ +.br +[ 3] local 192.168.100.76 port 42928 connected with 192.168.100.33 port 5001 +.br +[ ID] Interval Transfer Bandwidth Write/Err PPS frames:tx/missed/slips +.br +[ 3] 0.00-1.00 sec 12.0 MBytes 101 Mbits/sec 8615/0 8493 pps 62/0/0 +.br +[ 3] 1.00-2.00 sec 12.0 MBytes 100 Mbits/sec 8556/0 8557 pps 60/0/0 +.br +[ 3] 2.00-3.00 sec 12.0 MBytes 101 Mbits/sec 8586/0 8586 pps 60/0/0 +.br +[ 3] 3.00-4.00 sec 12.1 MBytes 102 Mbits/sec 8687/0 8687 pps 60/0/0 +.br +[ 3] 4.00-5.00 sec 11.8 MBytes 99.2 Mbits/sec 8468/0 8468 pps 60/0/0 +.br +[ 3] 5.00-6.00 sec 11.9 MBytes 99.8 Mbits/sec 8519/0 8520 pps 60/0/0 +.br +[ 3] 6.00-7.00 sec 12.1 MBytes 102 Mbits/sec 8694/0 8694 pps 60/0/0 +.br +[ 3] 7.00-8.00 sec 12.1 MBytes 102 Mbits/sec 8692/0 8692 pps 60/0/0 +.br +[ 3] 8.00-9.00 sec 11.9 MBytes 100 Mbits/sec 8537/0 8537 pps 60/0/0 +.br +[ 3] 9.00-10.00 sec 11.8 MBytes 99.0 Mbits/sec 8450/0 8450 pps 60/0/0 +.br +[ 3] 0.00-10.01 sec 120 MBytes 100 Mbits/sec 85867/0 8574 pps 602/0/0 +.br +[ 3] Sent 85867 datagrams +.br +[ 3] Server Report: +.br +[ 3] 0.00-9.98 sec 120 MBytes 101 Mbits/sec 0.009 ms 196/85867 (0.23%) 0.665/ 0.083/ 1.318/ 0.174 ms 8605 pps 18903.85 +.br +.TP +.B where (per -e,) +.B frames:tx/missed/slips +Total number of isochronous frames or bursts. Total number of frame ids not sent. Total number of frame slips + +.PP + +.B Isochronous UDP tests (server) + +.B iperf -s -e -u --udp-histogram=100u,2000 --realtime +.br +------------------------------------------------------------ +.br +Server listening on UDP port 5001 with pid 5175 +.br +Receiving 1470 byte datagrams +.br +UDP buffer size: 208 KByte (default) +.br +------------------------------------------------------------ +.br +[ 3] local 192.168.100.33 port 5001 connected with 192.168.100.76 port 42928 isoch (peer 2.0.13-alpha) +.br +[ ID] Interval Transfer Bandwidth Jitter Lost/Total Latency avg/min/max/stdev PPS NetPwr Frames/Lost +.br +[ 3] 0.00-9.98 sec 120 MBytes 101 Mbits/sec 0.010 ms 196/85867 (0.23%) 0.665/ 0.083/ 1.318/ 0.284 ms 8585 pps 18903.85 601/1 +.br +[ 3] 0.00-9.98 sec T8(f)-PDF: bin(w=100us):cnt(85671)=1:2,2:844,3:10034,4:8493,5:8967,6:8733,7:8823,8:9023,9:8901,10:8816,11:7730,12:4563,13:741,14:1 (5.00/95.00%=3/12,Outliers=0,obl/obu=0/0) +.br +[ 3] 0.00-9.98 sec F8(f)-PDF: bin(w=100us):cnt(598)=15:2,16:1,17:27,18:68,19:125,20:136,21:103,22:83,23:22,24:23,25:5,26:3 (5.00/95.00%=17/24,Outliers=0,obl/obu=0/0) + +.TP +.B where, +.B Frames/lost +Total number of frames (or bursts) received. Total number of bursts lost or error-ed +.br +.B +T8-PDF(f) +Latency histogram for packets +.br +.B F8-PDF(f) +Latency histogram for frames + + +.SH ENVIRONMENT +.TP +.B +Note: +The environment variable option settings haven't been maintained well. +See the source code if these are of interest. +.RE +.SH NOTES +.B Numeric options: +Some numeric options support format characters per '<value>\fIc\fR' +(e.g. 10M) where the \fIc\fR format characters are k,m,g,K,M,G. +Lowercase format characters are 10^3 based and uppercase are 2^n +based, e.g. 1k = 1000, 1K = 1024, 1m = 1,000,000 and 1M = 1,048,576 +.P +.B Rate limiting: +The -b option supports read and write rate limiting at the application level. The -b option +on the client also supports variable offered loads through the <mean>,<standard deviation> format, e.g. +-b 100m,10m. The distribution used is log normal. Similar for the isochronous +option. The -b on the server rate limits the reads. Socket based pacing is also +supported using the --fq-rate long option. This will work with the --reverse +and --full-duplex options as well. +.P +.B +IP tos: +Specifies the type-of-service or DSCP class for connections. Accepted values are \fBaf11, af12, af13, af21, +af22, af23, af31, af32, af33, af41, af42, af43, cs0, cs1, cs2, cs3, cs4, cs5, cs6, cs7, ef, le, nqb, nqb2, +ac_be, ac_bk, ac_vi, ac_vo, lowdelay, throughput, reliability\fR, a numeric value, or none to use the operating system default. +The ac_xx values are the four access categories defined in WMM for Wi-Fi, and they are aliases for DSCP values that will be mapped +to the corresponding ACs under the assumption that the device uses the DSCP-to-UP mapping table specified in IETF RFC 8325. +.P +.B --trip-times +The --trip-times option enables many one way delay (OWD) metrics. Also note that using --trip-times on a TCP client +will cause --tcp-write-prefetch to be set to a small value if tcp-write-prefetch hasn't hasn't also been set. This is +done to reduce send side bloat latency (which is unrelated to network induced latency.) Set --tcp-write-prefetch +to zero to disable this (which will disable TCP_NOTSENT_LOWAT) and will allow for send side bloat. +.P +.B Synchronized clocks: +The --trip-times option indicates that the client's and server's clocks are synchronized to a common reference. +Network Time Protocol (NTP) or Precision Time Protocol (PTP) are commonly used for +this. The reference clock(s) error and the synchronization protocols will affect +the accuracy of any end to end latency measurements. +.P +.B Histograms and non-parametric statistics: +The --histograms option provides the raw data where nothing is averaged. This is useful for non-parametric +distributions, e.g. latency. The standard output does use the central limit theorem to produce average, +minimum, maximum and variation. This loses information when the underlining distribution is not Gaussian. +Histograms are supported so this information is made available. +.P +.B Histogram output interpretation: +Below is an example bounceback histogram and how to interpret it + +.br +[ 1] 0.00-5.10 sec BB8-PDF: +.br +bin(w=100us):cnt(50)=35:1,37:1,39:1,40:3,41:4,42:1,43:1,52:1,57:1,65:1,68:1,69:1,70:1,72:2,74:1,75:5,78:1,79:2,80:4,81:3,82:1,83:1,88:2,90:2,92:1,94:1,117:1,126:1,369:1,1000:1,1922:1,3710:1 (5.00/95.00/99.7%=39/1000/3710,Outliers=4,obl/obu=0/0) +.TP +.B where, +.B [ 1] +The traffic thread number +.br +.B 0.00-5.10 sec +The time interval of the histogram +.br +.B BB8-PDF +BB8 is the histogram name and the PDF indicates a histogram raw output +.br +.B bin(w=100us) +provides the bin width. The bin width of this histogram is 100 microseconds +.br +.B cnt(50) +provides the total number of samples in the histogram. There are 50 samples in this histogram +.br +.B 35:1 +provides the bin no then the number of samples in that bin. Bin 35 with bin width 100us is 3.4 ms - 3.5 ms and there was one sample that landed there +.br +.B 5.00/95.00/99.7%=39/1000/3710 +provides the bin confidence intervals (per the integrated cumulative distribution function.) 5% landed in 3.9 ms or better (recall bin number multiplies by bin width.) 95% landed in 10 ms or better. 99.7% or 3 standards of deviation landed in 37.1 ms or better +.br +.B Outliers=4 +provides the outlier count, similar to 3IQR (3 times the inter quartile range) but uses 10% and 90% for inner & outer fence post, then 3 times that for outlier detection. +.br +.B obl/obu=0/0 +out of bounds lower and out of bands upper, provides the number of samples that could not be binned because the value landed outside of all possible bins + +.P +.B +Binding +is done at the logical level of port and ip address (or layer 3) using the -B option +and a colon as the separator between port and the ip addr. Binding at the +device (or layer 2) level requires the percent (%) as the delimiter (for both the client and the server.) +An example for src port and ip address is -B 192.168.1.1:6001. To \fBbind the src port only\fR and +let the operating system choose the source ip address use 0.0.0.0, e.g. +\fB-B 0.0.0.0:6001\fR. On the client, the -B option affects the \fBbind\fR(2) +system call, and will set the source ip address and the source port, e.g. iperf -c <host> +-B 192.168.100.2:6002. This controls the packet's source values but not routing. +These can be confusing in that a route or device lookup may not +be that of the device with the configured source IP. +So, for example, if the IP address of eth0 is used for -B and the +routing table for the destination IP address resolves +the output interface to be eth1, then the host will send the packet +out device eth1 while using the source IP address of eth0 in the packet. +To affect the physical output interface (e.g. dual homed systems) either use +-c <host>%<dev> (requires root) which bypasses this host route table lookup, +or configure policy routing per each -B source address and set the +output interface appropriately in the policy routes. On the server or receive, +only packets destined to -B IP address will be received. It's also useful +for multicast. For example, iperf -s -B 224.0.0.1\fB%eth0\fR +will only accept ip multicast packets with dest ip 224.0.0.1 that are +received on the eth0 interface, while iperf -s -B 224.0.0.1 will +receive those packets on any interface, +Finally, the device specifier is required for v6 link-local, +e.g. -c [v6addr]%<dev> -V, to select the output interface. +.P +.B Reverse, full-duplex, dualtest (-d) and tradeoff (-r): +The \fB--reverse\fR (-R) and \fB--full-duplex\fR options can be confusing when compared to the +older options of \fB--dualtest (-d)\fR and \fB--tradeoff (-r)\fR. The newer options of \fB--reverse\fR and \fB--full-duplex\fR only +open one socket and read and write to the \fBsame socket descriptor\fR, i.e. use the socket in full duplex mode. The older -d and -r open +second sockets in the opposite direction and do not use a socket in full duplex mode. Note that full duplex applies to the socket +and not to the network devices and that full duplex sockets are supported by the +operating systems regardless if an underlying network supports full duplex transmission and reception. +It's \fBsuggested to use --reverse\fR if you +want to \fBtest through a NAT firewall\fR (or -R on non-windows systems). This applies +role reversal of the test after opening the full duplex socket. (Note: Firewall piercing may be required to use -d and -r +if a NAT gateway is in the path.) +.P +Also, the --reverse -b <rate> setting behaves differently for TCP and UDP. For +TCP it will rate limit the read side, i.e. the iperf client +(role reversed to act as a server) reading from the full duplex socket. +This will in turn flow control the reverse traffic per standard TCP +congestion control. The --reverse -b <rate> will be applied on +transmit (i.e. the server role reversed to act as a client) for UDP +since there is no flow control with UDP. There is no option to +directly rate limit the writes with TCP testing when using --reverse. +.P +.B Bounceback +The bounceback test allows one to measure network responsiveness (which, in this test, is an inverse of latency.) +The units are responses per second or rps. Latency is merely delay in units of time. Latency metrics require one +to know the delay of what's being measured. For bounceback it's a client write to a server read followed by a server +write and then the client read. The original write is bounce backed. Iperf 2 sets up the socket with TCP_NODELAY +and possibly TCP_QUICKACK (unless disabled). The client sends a small write (which defaults to 100 bytes unless -l is set) +and issues a read waiting for the "bounceback" from the server. The server waits for a read and then +optionally delays before sending the payload back. This repeats until the traffic ends. Results +are shown in units of rps and time delays. +.P +The TCP_QUICKACK socket option will be enabled during bounceback tests when the bounceback-hold +is set to a non-zero value. The socket option is applied after every read() on the server +and before the hold delay call. It's also applied on the client. Use --bounceback-no-quickack +to have TCP run in default mode per the socket (which is most likely TCP_QUICKACK being off.) +.P +.B TCP Connect times: +The TCP connect time (or three way handshake) can be seen on the iperf +client when the -e (--enhanced) option is set. Look for the +ct=<value> in the connected message, e.g.in '[ 3] local 192.168.1.4 +port 48736 connected with 192.168.1.1 port 5001 \fB(ct=1.84 ms)\fR' +shows the 3WHS took 1.84 milliseconds. +.P +.B Port-range +Port ranges are supported using the hyphen notation, e.g. 6001-6009. This will cause multiple threads, one per port, on either the listener/server or the client. The user needs to take care that the ports in the port range are available and not already in use per the operating system. The -P is supported on the client and will apply to each destination port within the port range. +Finally, this can be used for a workaround for Windows UDP and -P > 1 as Windows doesn't dispatch UDP per a server's connect and the quintuple. +.P +.B Packet per second (pps) calculation +The packets per second calculation is done as a derivative, i.e. number of packets divided by +time. The time is taken from the previous last packet to the current last packet. It is not +the sample interval time. The last packet can land at different times within an interval. +This means that pps does not have to match rx bytes divided by the sample interval. +Also, with --trip-times set, the packet time on receive is set by the sender's write +time so pps indicates the end to end pps with --trip-times. The RX pps calculation is receive +side only when -e is set and --trip-times is not set. +.P +\fBLittle's Law\fR in queuing theory is a theorem that determines the average number of items (L) in a stationary queuing system based on the average waiting time (W) of an item within a system and the average number of items arriving at the system per unit of time (lambda). Mathematically, it's L = lambda * W. As used here, the units are bytes. The arrival rate is taken from the writes. +.P +.B Network power: +The network power (NetPwr) metric is \fBexperimental\fR. It's a +convenience function defined as throughput/delay. +For TCP transmits, the delay is the sampled RTT times. +For TCP receives, the delay is the write to read latency. +For UDP the delay is the end/end latency. +Don't confuse this with the physics definition of power (delta +energy/delta time) but more of a measure of a desirable property +divided by an undesirable property. Also note, one must use -i +interval with TCP to get this as that's what sets the RTT sampling +rate. The metric is scaled to assist with human readability. +.P +.B Multicast: +Iperf 2 supports multicast with a couple of caveats. First, multicast streams cannot take advantage of the -P option. The server will serialize multicast streams. Also, it's highly encouraged to use a -t on a server that will be used for multicast clients. That is because the single end of traffic packet sent from client to server may get lost and there are no redundant end of traffic packets. Setting -t on the server will kill the server thread in the event this packet is indeed lost. +.P +.B TCP_QUICKACK: +The TCP_QUICKACK socket option will be applied after every read() on the server such that TCP acks are sent immediately, rather than possibly delayed. +.P +.B Fast Sampling: +Use +.B ./configure --enable-fastsampling +and then compile from source to enable four digit (e.g. 1.0000) precision in reports' timestamps. Useful for sub-millisecond sampling. +.SH DIAGNOSTICS +Use +.B ./configure --enable-thread-debug +and then compile from source to enable both asserts and advanced debugging of the tool itself. +.SH BUGS +See https://sourceforge.net/p/iperf2/tickets/ +.SH AUTHORS +Iperf2, based from iperf (originally written by Mark Gates and Alex +Warshavsky), has a goal of maintenance with some feature enhancement. +Other contributions from Ajay Tirumala, Jim Ferguson, Jon Dugan <jdugan at x1024 dot net>, +Feng Qin, +Kevin Gibbs, +John Estabrook <jestabro at ncsa.uiuc.edu>, +Andrew Gallatin <gallatin at gmail.com>, +Stephen Hemminger <shemminger at linux-foundation.org>, +Tim Auckland <tim.auckland at gmail.com>, +Robert J. McMahon <rjmcmahon at rjmcmahon.com> +.SH "SEE ALSO" +.BR accept (2), bind (2), close (2), connect (2), fcntl (2), getpeername (2), getsockname (2), getsockopt (2), listen (2), read (2), recv (2), select (2), send (2), setsockopt (2), shutdown (2), write (2), ip (7), socket (7), tcp (7), udp (7) +.LP +Source code at http://sourceforge.net/projects/iperf2/ +.LP +"Unix Network Programming, Volume 1: The Sockets Networking API (3rd Edition) 3rd Edition" +by W. Richard Stevens (Author), Bill Fenner (Author), Andrew M. Rudoff (Author) @@ -0,0 +1,215 @@ +#! /bin/sh +# Common wrapper for a few potentially missing GNU programs. + +scriptversion=2012-06-26.16; # UTC + +# Copyright (C) 1996-2013 Free Software Foundation, Inc. +# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try '$0 --help' for more information" + exit 1 +fi + +case $1 in + + --is-lightweight) + # Used by our autoconf macros to check whether the available missing + # script is modern enough. + exit 0 + ;; + + --run) + # Back-compat with the calling convention used by older automake. + shift + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due +to PROGRAM being missing or too old. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + +Supported PROGRAM values: + aclocal autoconf autoheader autom4te automake makeinfo + bison yacc flex lex help2man + +Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and +'g' are ignored when checking the name. + +Send bug reports to <bug-automake@gnu.org>." + exit $? + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit $? + ;; + + -*) + echo 1>&2 "$0: unknown '$1' option" + echo 1>&2 "Try '$0 --help' for more information" + exit 1 + ;; + +esac + +# Run the given program, remember its exit status. +"$@"; st=$? + +# If it succeeded, we are done. +test $st -eq 0 && exit 0 + +# Also exit now if we it failed (or wasn't found), and '--version' was +# passed; such an option is passed most likely to detect whether the +# program is present and works. +case $2 in --version|--help) exit $st;; esac + +# Exit code 63 means version mismatch. This often happens when the user +# tries to use an ancient version of a tool on a file that requires a +# minimum version. +if test $st -eq 63; then + msg="probably too old" +elif test $st -eq 127; then + # Program was missing. + msg="missing on your system" +else + # Program was found and executed, but failed. Give up. + exit $st +fi + +perl_URL=http://www.perl.org/ +flex_URL=http://flex.sourceforge.net/ +gnu_software_URL=http://www.gnu.org/software + +program_details () +{ + case $1 in + aclocal|automake) + echo "The '$1' program is part of the GNU Automake package:" + echo "<$gnu_software_URL/automake>" + echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/autoconf>" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + autoconf|autom4te|autoheader) + echo "The '$1' program is part of the GNU Autoconf package:" + echo "<$gnu_software_URL/autoconf/>" + echo "It also requires GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + esac +} + +give_advice () +{ + # Normalize program name to check for. + normalized_program=`echo "$1" | sed ' + s/^gnu-//; t + s/^gnu//; t + s/^g//; t'` + + printf '%s\n' "'$1' is $msg." + + configure_deps="'configure.ac' or m4 files included by 'configure.ac'" + case $normalized_program in + autoconf*) + echo "You should only need it if you modified 'configure.ac'," + echo "or m4 files included by it." + program_details 'autoconf' + ;; + autoheader*) + echo "You should only need it if you modified 'acconfig.h' or" + echo "$configure_deps." + program_details 'autoheader' + ;; + automake*) + echo "You should only need it if you modified 'Makefile.am' or" + echo "$configure_deps." + program_details 'automake' + ;; + aclocal*) + echo "You should only need it if you modified 'acinclude.m4' or" + echo "$configure_deps." + program_details 'aclocal' + ;; + autom4te*) + echo "You might have modified some maintainer files that require" + echo "the 'automa4te' program to be rebuilt." + program_details 'autom4te' + ;; + bison*|yacc*) + echo "You should only need it if you modified a '.y' file." + echo "You may want to install the GNU Bison package:" + echo "<$gnu_software_URL/bison/>" + ;; + lex*|flex*) + echo "You should only need it if you modified a '.l' file." + echo "You may want to install the Fast Lexical Analyzer package:" + echo "<$flex_URL>" + ;; + help2man*) + echo "You should only need it if you modified a dependency" \ + "of a man page." + echo "You may want to install the GNU Help2man package:" + echo "<$gnu_software_URL/help2man/>" + ;; + makeinfo*) + echo "You should only need it if you modified a '.texi' file, or" + echo "any other file indirectly affecting the aspect of the manual." + echo "You might want to install the Texinfo package:" + echo "<$gnu_software_URL/texinfo/>" + echo "The spurious makeinfo call might also be the consequence of" + echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" + echo "want to install GNU make:" + echo "<$gnu_software_URL/make/>" + ;; + *) + echo "You might have modified some files without having the proper" + echo "tools for further handling them. Check the 'README' file, it" + echo "often tells you about the needed prerequisites for installing" + echo "this package. You may also peek at any GNU archive site, in" + echo "case some other package contains this missing '$1' program." + ;; + esac +} + +give_advice "$1" | sed -e '1s/^/WARNING: /' \ + -e '2,$s/^/ /' >&2 + +# Propagate the correct exit status (expected to be 127 for a program +# not found, 63 for a program that failed due to version mismatch). +exit $st + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/src/Client.cpp b/src/Client.cpp new file mode 100644 index 0000000..89e47e2 --- /dev/null +++ b/src/Client.cpp @@ -0,0 +1,1871 @@ +/*--------------------------------------------------------------- + * Copyright (c) 1999,2000,2001,2002,2003 + * The Board of Trustees of the University of Illinois + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software (Iperf) and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the names of the University of Illinois, NCSA, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * National Laboratory for Applied Network Research + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * http://www.ncsa.uiuc.edu + * ________________________________________________________________ + * + * Client.cpp + * by Mark Gates <mgates@nlanr.net> + * ------------------------------------------------------------------- + * A client thread initiates a connect to the server and handles + * sending and receiving data, then closes the socket. + * ------------------------------------------------------------------- */ +#include <ctime> +#include <cmath> +#include "headers.h" +#include "Client.hpp" +#include "Thread.h" +#include "SocketAddr.h" +#include "PerfSocket.hpp" +#include "Extractor.h" +#include "delay.h" +#include "util.h" +#include "Locale.h" +#include "isochronous.hpp" +#include "pdfs.h" +#include "version.h" +#include "payloads.h" +#include "active_hosts.h" +#include "gettcpinfo.h" + +// const double kSecs_to_usecs = 1e6; +const double kSecs_to_nsecs = 1e9; +const int kBytes_to_Bits = 8; + +#define VARYLOAD_PERIOD 0.1 // recompute the variable load every n seconds +#define MAXUDPBUF 1470 + +Client::Client (thread_Settings *inSettings) { +#ifdef HAVE_THREAD_DEBUG + thread_debug("Client constructor with thread %p sum=%p (flags=%x)", (void *) inSettings, (void *)inSettings->mSumReport, inSettings->flags); +#endif + mSettings = inSettings; + myJob = NULL; + myReport = NULL; + framecounter = NULL; + one_report = false; + udp_payload_minimum = 1; + apply_first_udppkt_delay = false; + + memset(&scratchpad, 0, sizeof(struct ReportStruct)); + reportstruct = &scratchpad; + reportstruct->packetID = 1; + mySocket = isServerReverse(mSettings) ? mSettings->mSock : INVALID_SOCKET; + connected = isServerReverse(mSettings); + if (isCompat(mSettings) && isPeerVerDetect(mSettings)) { + fprintf(stderr, "%s", warn_compat_and_peer_exchange); + unsetPeerVerDetect(mSettings); + } + + pattern(mSettings->mBuf, mSettings->mBufLen); + if (isIsochronous(mSettings)) { + FAIL_errno(!(mSettings->mFPS > 0.0), "Invalid value for frames per second in the isochronous settings\n", mSettings); + } + if (isFileInput(mSettings)) { + if (!isSTDIN(mSettings)) + Extractor_Initialize(mSettings->mFileName, mSettings->mBufLen, mSettings); + else + Extractor_InitializeFile(stdin, mSettings->mBufLen, mSettings); + + if (!Extractor_canRead(mSettings)) { + unsetFileInput(mSettings); + } + } + peerclose = false; + mysock_init_done = false; + isburst = (isIsochronous(mSettings) || isPeriodicBurst(mSettings) || (isTripTime(mSettings) && !isUDP(mSettings))); +} // end Client + +/* ------------------------------------------------------------------- + * Destructor + * ------------------------------------------------------------------- */ +Client::~Client () { +#if HAVE_THREAD_DEBUG + thread_debug("Client destructor sock=%d report=%p server-reverse=%s fullduplex=%s", \ + mySocket, (void *) mSettings->reporthdr, \ + (isServerReverse(mSettings) ? "true" : "false"), (isFullDuplex(mSettings) ? "true" : "false")); +#endif + DELETE_PTR(framecounter); +} // end ~Client + +/* ------------------------------------------------------------------- + * Setup a socket connected to a server. + * If inLocalhost is not null, bind to that address, specifying + * which outgoing interface to use. + * ------------------------------------------------------------------- */ +void Client::mySockInit (void) { + // create an internet socket + int type = (isUDP(mSettings) ? SOCK_DGRAM : SOCK_STREAM); + int domain = (SockAddr_isIPv6(&mSettings->peer) ? +#if HAVE_IPV6 + AF_INET6 +#else + AF_INET +#endif + : AF_INET); + + mySocket = socket(domain, type, 0); + WARN_errno(mySocket == INVALID_SOCKET, "socket"); + // Socket is carried both by the object and the thread + mSettings->mSock=mySocket; + SetSocketOptions(mSettings); + SockAddr_localAddr(mSettings); + SockAddr_remoteAddr(mSettings); + if (mSettings->mLocalhost != NULL) { + // bind socket to local address + int rc = bind(mySocket, reinterpret_cast<sockaddr*>(&mSettings->local), + SockAddr_get_sizeof_sockaddr(&mSettings->local)); + WARN_errno(rc == SOCKET_ERROR, "bind"); + } + mysock_init_done = true; + if (!isUDP(mSettings) && isReport(mSettings) && isSettingsReport(mSettings)) { + struct ReportHeader *tmp = InitSettingsReport(mSettings); + assert(tmp!=NULL); + PostReport(tmp); + setNoSettReport(mSettings); + } +} +/* ------------------------------------------------------------------- + * Setup a socket connected to a server. + * If inLocalhost is not null, bind to that address, specifying + * which outgoing interface to use. + * ------------------------------------------------------------------- */ +bool Client::my_connect (bool close_on_fail) { + int rc; + if (!mysock_init_done) { + mySockInit(); + } + // connect socket + connected = false; + mSettings->tcpinitstats.connecttime = -1; + if (!isUDP(mSettings)) { + int trycnt = mSettings->mConnectRetries + 1; + while (trycnt > 0) { + connect_start.setnow(); + rc = connect(mySocket, reinterpret_cast<sockaddr*>(&mSettings->peer), + SockAddr_get_sizeof_sockaddr(&mSettings->peer)); + WARN_errno((rc == SOCKET_ERROR), "tcp connect"); + if (rc == SOCKET_ERROR) { + if ((--trycnt) <= 0) { + if (close_on_fail) { + close(mySocket); + mySocket = INVALID_SOCKET; + } + } else { + delay_loop(200000); + } + } else { + connect_done.setnow(); + mSettings->tcpinitstats.connecttime = 1e3 * connect_done.subSec(connect_start); + connected = true; + break; + } + } + } else { + rc = connect(mySocket, reinterpret_cast<sockaddr*>(&mSettings->peer), + SockAddr_get_sizeof_sockaddr(&mSettings->peer)); + mSettings->tcpinitstats.connecttime = 0.0; // UDP doesn't have a 3WHS + WARN_errno((rc == SOCKET_ERROR), "udp connect"); + if (rc != SOCKET_ERROR) + connected = true; + } + if (connected) { +#if HAVE_TCP_STATS + assert(reportstruct); + if (!isUDP(mSettings)) { + gettcpinfo(mySocket, &mSettings->tcpinitstats); + } +#endif + // Set the send timeout for the very first write which has the test exchange + int sosndtimer = TESTEXCHANGETIMEOUT; // 4 sec in usecs + SetSocketOptionsSendTimeout(mSettings, sosndtimer); + getsockname(mySocket, reinterpret_cast<sockaddr*>(&mSettings->local), &mSettings->size_local); + getpeername(mySocket, reinterpret_cast<sockaddr*>(&mSettings->peer), &mSettings->size_peer); + SockAddr_Ifrname(mSettings); +#ifdef DEFAULT_PAYLOAD_LEN_PER_MTU_DISCOVERY + if (isUDP(mSettings) && !isBuflenSet(mSettings)) { + checksock_max_udp_payload(mSettings); + } +#endif + if (isUDP(mSettings) && !isIsochronous(mSettings) && !isIPG(mSettings)) { + mSettings->mBurstIPG = get_delay_target() / 1e3; // this is being set for the settings report only + } + if (isReport(mSettings) && isSettingsReport(mSettings)) { + struct ReportHeader *tmp = InitSettingsReport(mSettings); + assert(tmp!=NULL); + PostReport(tmp); + setNoSettReport(mSettings); + } + } else { + if (mySocket != INVALID_SOCKET) { + int rc = close(mySocket); + WARN_errno(rc == SOCKET_ERROR, "client connect close"); + mySocket = INVALID_SOCKET; + } + } + // Post the connect report unless peer version exchange is set + if (isConnectionReport(mSettings) && !isSumOnly(mSettings)) { + if (connected) { + struct ReportHeader *reporthdr = InitConnectionReport(mSettings); + struct ConnectionInfo *cr = static_cast<struct ConnectionInfo *>(reporthdr->this_report); + cr->connect_timestamp.tv_sec = connect_start.getSecs(); + cr->connect_timestamp.tv_usec = connect_start.getUsecs(); + assert(reporthdr); + PostReport(reporthdr); + } else { + PostReport(InitConnectionReport(mSettings)); + } + } + return connected; +} // end Connect + +bool Client::isConnected () const { +#ifdef HAVE_THREAD_DEBUG + // thread_debug("Client is connected %d", connected); +#endif + return connected; +} + +void Client::TxDelay () { + if (isTxHoldback(mSettings)) { + clock_usleep(&mSettings->txholdback_timer); + } +} + +inline void Client::myReportPacket (void) { + ReportPacket(myReport, reportstruct); + reportstruct->packetLen = 0; +} + + +// There are multiple startup synchronizations, this code +// handles them all. The caller decides to apply them +// either before connect() or after connect() and before writes() +int Client::StartSynch () { +#ifdef HAVE_THREAD_DEBUG + thread_debug("Client start sync enterred"); +#endif + bool delay_test_exchange = (isFullDuplex(mSettings) && isUDP(mSettings)); + if (isTxStartTime(mSettings) && delay_test_exchange) { + clock_usleep_abstime(&mSettings->txstart_epoch); + } + myJob = InitIndividualReport(mSettings); + myReport = static_cast<struct ReporterData *>(myJob->this_report); + myReport->info.common->socket=mySocket; + myReport->info.isEnableTcpInfo = false; // default here, set in init traffic actions + if (!isReverse(mSettings) && (mSettings->mReportMode == kReport_CSV)) { + format_ips_port_string(&myReport->info, 0); + } + + // Perform delays, usually between connect() and data xfer though before connect + // Two delays are supported: + // o First is an absolute start time per unix epoch format + // o Second is a holdback, a relative amount of seconds between the connect and data xfers + // check for an epoch based start time + reportstruct->packetLen = 0; + if (!isServerReverse(mSettings)) { + if (!isCompat(mSettings) && !isBounceBack(mSettings)) { + reportstruct->packetLen = SendFirstPayload(); + // Reverse UDP tests need to retry "first sends" a few times + // before going to server or read mode + if (isReverse(mSettings) && isUDP(mSettings)) { + reportstruct->packetLen = 0; + fd_set set; + struct timeval timeout; + int resend_udp = 100; + while (--resend_udp > 0) { + FD_ZERO(&set); + FD_SET(mySocket, &set); + timeout.tv_sec = 0; + timeout.tv_usec = rand() % 20000; // randomize IPG a bit + if (select(mySocket + 1, &set, NULL, NULL, &timeout) == 0) { + reportstruct->packetLen = SendFirstPayload(); + // printf("**** resend sock=%d count=%d\n", mySocket, resend_udp); + } else { + break; + } + } + } + } + if (isTxStartTime(mSettings) && !delay_test_exchange) { + clock_usleep_abstime(&mSettings->txstart_epoch); + } else if (isTxHoldback(mSettings)) { + TxDelay(); + } + // Server side client + } else if (isTripTime(mSettings) || isPeriodicBurst(mSettings)) { + reportstruct->packetLen = SendFirstPayload(); + } + if (isIsochronous(mSettings) || isPeriodicBurst(mSettings)) { + Timestamp tmp; + tmp.set(mSettings->txstart_epoch.tv_sec, mSettings->txstart_epoch.tv_usec); + framecounter = new Isochronous::FrameCounter(mSettings->mFPS, tmp); + // set the mbuf valid for burst period ahead of time. The same value will be set for all burst writes + if (!isUDP(mSettings) && framecounter) { + struct TCP_burst_payload * mBuf_burst = reinterpret_cast<struct TCP_burst_payload *>(mSettings->mBuf); + mBuf_burst->burst_period_us = htonl(framecounter->period_us()); + } + } + int setfullduplexflag = 0; + if (isFullDuplex(mSettings) && !isServerReverse(mSettings)) { + assert(mSettings->mFullDuplexReport != NULL); + if ((setfullduplexflag = fullduplex_start_barrier(&mSettings->mFullDuplexReport->fullduplex_barrier)) < 0) + return -1; + } + SetReportStartTime(); +#if HAVE_TCP_STATS + if (!isUDP(mSettings)) { + // Near congestion and peridiodic need sampling on every report packet + if (isNearCongest(mSettings) || isPeriodicBurst(mSettings)) { + myReport->info.isEnableTcpInfo = true; + myReport->info.ts.nextTCPSampleTime.tv_sec = 0; + myReport->info.ts.nextTCPSampleTime.tv_usec = 0; + } else if (isEnhanced(mSettings) || isBounceBack(mSettings)) { + myReport->info.isEnableTcpInfo = true; + myReport->info.ts.nextTCPSampleTime = myReport->info.ts.nextTime; + } + } +#endif + + if (reportstruct->packetLen > 0) { + reportstruct->packetTime = myReport->info.ts.startTime; + reportstruct->sentTime = reportstruct->packetTime; + reportstruct->prevSentTime = reportstruct->packetTime; + reportstruct->prevPacketTime = myReport->info.ts.prevpacketTime; + if (isModeAmount(mSettings)) { + mSettings->mAmount -= reportstruct->packetLen; + } + myReportPacket(); + myReport->info.ts.prevpacketTime = reportstruct->packetTime; + reportstruct->packetID++; + } + if (setfullduplexflag) { + SetFullDuplexReportStartTime(); + } + // Full duplex sockets need to be syncronized +#ifdef HAVE_THREAD_DEBUG + thread_debug("Client start sync exited"); +#endif + return 0; +} + +inline void Client::SetFullDuplexReportStartTime () { + assert(myReport->FullDuplexReport != NULL); + struct TransferInfo *fullduplexstats = &myReport->FullDuplexReport->info; + assert(fullduplexstats != NULL); + if (TimeZero(fullduplexstats->ts.startTime)) { + fullduplexstats->ts.startTime = myReport->info.ts.startTime; + if (isModeTime(mSettings)) { + fullduplexstats->ts.nextTime = myReport->info.ts.nextTime; + } + } +#ifdef HAVE_THREAD_DEBUG + thread_debug("Client fullduplex report start=%ld.%ld next=%ld.%ld", fullduplexstats->ts.startTime.tv_sec, fullduplexstats->ts.startTime.tv_usec, fullduplexstats->ts.nextTime.tv_sec, fullduplexstats->ts.nextTime.tv_usec); +#endif +} +inline void Client::SetReportStartTime () { + assert(myReport!=NULL); + now.setnow(); + myReport->info.ts.startTime.tv_sec = now.getSecs(); + myReport->info.ts.startTime.tv_usec = now.getUsecs(); + myReport->info.ts.IPGstart = myReport->info.ts.startTime; + myReport->info.ts.prevpacketTime = myReport->info.ts.startTime; + if (!TimeZero(myReport->info.ts.intervalTime)) { + myReport->info.ts.nextTime = myReport->info.ts.startTime; + TimeAdd(myReport->info.ts.nextTime, myReport->info.ts.intervalTime); + } + if (myReport->GroupSumReport) { + struct TransferInfo *sumstats = &myReport->GroupSumReport->info; + assert(sumstats != NULL); + Mutex_Lock(&myReport->GroupSumReport->reference.lock); + if (TimeZero(sumstats->ts.startTime)) { + sumstats->ts.startTime = myReport->info.ts.startTime; + if (isModeTime(mSettings) || isModeInfinite(mSettings)) { + sumstats->ts.nextTime = myReport->info.ts.nextTime; + } +#ifdef HAVE_THREAD_DEBUG + thread_debug("Client group sum report start=%ld.%ld next=%ld.%ld", sumstats->ts.startTime.tv_sec, sumstats->ts.startTime.tv_usec, sumstats->ts.nextTime.tv_sec, sumstats->ts.nextTime.tv_usec); +#endif + } + Mutex_Unlock(&myReport->GroupSumReport->reference.lock); + } +#ifdef HAVE_THREAD_DEBUG + thread_debug("Client(%d) report start/ipg=%ld.%ld next=%ld.%ld", mSettings->mSock, myReport->info.ts.startTime.tv_sec, myReport->info.ts.startTime.tv_usec, myReport->info.ts.nextTime.tv_sec, myReport->info.ts.nextTime.tv_usec); +#endif +} + +void Client::ConnectPeriodic () { + Timestamp end; + Timestamp next; + unsigned int amount_usec = 1000000; + if (isModeTime(mSettings)) { + amount_usec = (mSettings->mAmount * 10000); + end.add(amount_usec); // add in micro seconds + } + setNoConnectSync(mSettings); + int num_connects = -1; + if (!(mSettings->mInterval > 0)) { + if (mSettings->connectonly_count < 0) + num_connects = 10; + else if (mSettings->connectonly_count > 0) + num_connects = mSettings->connectonly_count; + } + + do { + if (my_connect(false)){ + int rc = close(mySocket); + WARN_errno(rc == SOCKET_ERROR, "client close"); + mySocket = INVALID_SOCKET; + mysock_init_done = false; + } + if (mSettings->mInterval > 0) { + now.setnow(); + do { + next.add(mSettings->mInterval); + } while (next.before(now)); + if (next.before(end)) { + struct timeval tmp; + tmp.tv_sec = next.getSecs(); + tmp.tv_usec = next.getUsecs(); + clock_usleep_abstime(&tmp); + } + } + if (num_connects > 0) { + --num_connects; + } + } while (num_connects && !sInterupted && (next.before(end) || (isModeTime(mSettings) && !(mSettings->mInterval > 0)))); +} +/* ------------------------------------------------------------------- + * Common traffic loop intializations + * ------------------------------------------------------------------- */ +void Client::InitTrafficLoop () { + // Enable socket write timeouts for responsive reporting + // Do this after the connection establishment + // and after Client::InitiateServer as during these + // default socket timeouts are preferred. + int sosndtimer = 0; + // sosndtimer units microseconds + // mInterval units are microseconds, mAmount units is 10 ms + // SetSocketOptionsSendTimeout takes microseconds + // Set the timeout value to 1/2 the interval (per -i) or 1/2 the -t value + if (isPeriodicBurst(mSettings) && (mSettings->mFPS > 0.0)) { + sosndtimer = static_cast<int>(round(250000.0 / mSettings->mFPS)); + } else if (mSettings->mInterval > 0) { + sosndtimer = static_cast<int>(round(0.5 * mSettings->mInterval)); + } else { + sosndtimer = static_cast<int>(mSettings->mAmount * 5e3); + } + SetSocketOptionsSendTimeout(mSettings, sosndtimer); + // set the lower bounds delay based of the socket timeout timer + // units needs to be in nanoseconds + delay_lower_bounds = static_cast<double>(sosndtimer) * -1e3; + + if (isIsochronous(mSettings)) + myReport->info.matchframeID = 1; + + // set the total bytes sent to zero + totLen = 0; + if (isModeTime(mSettings)) { + mEndTime.setnow(); + mEndTime.add(mSettings->mAmount / 100.0); + // now.setnow(); fprintf(stderr, "DEBUG: end time set to %ld.%ld now is %ld.%ld\n", mEndTime.getSecs(), mEndTime.getUsecs(), now.getSecs(), now.getUsecs()); + } + readAt = mSettings->mBuf; + lastPacketTime.set(myReport->info.ts.startTime.tv_sec, myReport->info.ts.startTime.tv_usec); + reportstruct->errwrite=WriteNoErr; + reportstruct->emptyreport=0; + reportstruct->packetLen = 0; + // Finally, post this thread's "job report" which the reporter thread + // will continuously process as long as there are packets flowing + // right now the ring is empty + if (!isReverse(mSettings) && !isSingleUDP(mSettings) && isDataReport(mSettings)) { + assert(myJob!=NULL); + assert(myReport!=NULL); + PostReport(myJob); + } + one_report = (!isUDP(mSettings) && !isEnhanced(mSettings) && (mSettings->mIntervalMode != kInterval_Time) \ + && !isIsochronous(mSettings) && !isPeriodicBurst(mSettings) && !isTripTime(mSettings) && !isReverse(mSettings)); +} + +/* ------------------------------------------------------------------- + * Run the appropriate send loop between + * + * 1) TCP without rate limiting + * 2) TCP with rate limiting + * 3) UDP + * 4) UDP isochronous w/vbr + * + * ------------------------------------------------------------------- */ +void Client::Run () { + // Initialize the report struct scratch pad + // Peform common traffic setup + InitTrafficLoop(); + /* + * UDP + */ + if (isUDP(mSettings)) { + if (isFileInput(mSettings)) { + // Due to the UDP timestamps etc, included + // reduce the read size by an amount + // equal to the header size + Extractor_reduceReadSize(sizeof(struct UDP_datagram), mSettings); + readAt += sizeof(struct UDP_datagram); + } + // Launch the approprate UDP traffic loop + if (isIsochronous(mSettings)) { + RunUDPIsochronous(); + } else { + RunUDP(); + } + } else { + // Launch the approprate TCP traffic loop + if (isBounceBack(mSettings)) { + RunBounceBackTCP(); + } else if (mSettings->mAppRate > 0) { + RunRateLimitedTCP(); + } else if (isNearCongest(mSettings)) { + RunNearCongestionTCP(); +#if HAVE_DECL_TCP_NOTSENT_LOWAT + } else if (isWritePrefetch(mSettings) && \ + !isIsochronous(mSettings) && !isPeriodicBurst(mSettings)) { + RunWriteEventsTCP(); +#endif + } else { + RunTCP(); + } + } +} + +/* + * TCP send loop + */ +void Client::RunTCP () { + int burst_remaining = 0; + uint32_t burst_id = 1; + int writelen = mSettings->mBufLen; + + now.setnow(); + reportstruct->packetTime.tv_sec = now.getSecs(); + reportstruct->packetTime.tv_usec = now.getUsecs(); + reportstruct->write_time = 0; + while (InProgress()) { + reportstruct->writecnt = 0; + reportstruct->scheduled = false; + if (isModeAmount(mSettings)) { + writelen = ((mSettings->mAmount < static_cast<unsigned>(mSettings->mBufLen)) ? mSettings->mAmount : mSettings->mBufLen); + } + if (isburst && !(burst_remaining > 0)) { + if (isIsochronous(mSettings)) { + assert(mSettings->mMean); + burst_remaining = static_cast<int>(lognormal(mSettings->mMean,mSettings->mVariance)) / (mSettings->mFPS * 8); + } else if (isPeriodicBurst(mSettings)){ + assert(mSettings->mBurstSize); + burst_remaining = mSettings->mBurstSize; + } else { + burst_remaining = mSettings->mBufLen; + } + // check for TCP minimum payload + if (burst_remaining < static_cast<int>(sizeof(struct TCP_burst_payload))) + burst_remaining = static_cast<int>(sizeof(struct TCP_burst_payload)); + // apply scheduling if needed + if (framecounter) { + burst_id = framecounter->wait_tick(&reportstruct->sched_err); + reportstruct->scheduled = true; + if (isPeriodicBurst(mSettings)) { + // low duty cycle traffic needs special event handling + now.setnow(); + myReport->info.ts.prevsendTime = reportstruct->packetTime; + reportstruct->packetTime.tv_sec = now.getSecs(); + reportstruct->packetTime.tv_usec = now.getUsecs(); + if (!InProgress()) { + reportstruct->packetLen = 0; + reportstruct->emptyreport = 1; + // wait may have crossed the termination boundry + break; + } else { + //time interval crossings may have occurred during the wait + //post a null event to cause the report to flush the packet ring + PostNullEvent(); + } + } +#if HAVE_DECL_TCP_NOTSENT_LOWAT + if (isWritePrefetch(mSettings)) { + AwaitWriteSelectEventTCP(); + } +#endif + } + now.setnow(); + reportstruct->packetTime.tv_sec = now.getSecs(); + reportstruct->packetTime.tv_usec = now.getUsecs(); + WriteTcpTxHdr(reportstruct, burst_remaining, burst_id++); + reportstruct->sentTime = reportstruct->packetTime; + myReport->info.ts.prevsendTime = reportstruct->packetTime; + writelen = (mSettings->mBufLen > burst_remaining) ? burst_remaining : mSettings->mBufLen; + // perform write, full header must succeed + if (isTcpWriteTimes(mSettings)) { + write_start.setnow(); + } + reportstruct->packetLen = writen(mySocket, mSettings->mBuf, writelen, &reportstruct->writecnt); + FAIL_errno(reportstruct->packetLen < (intmax_t) sizeof(struct TCP_burst_payload), "burst written", mSettings); + if (isTcpWriteTimes(mSettings)) { + now.setnow(); + reportstruct->write_time = now.subUsec(write_start); + } + } else { + // printf("pl=%ld\n",reportstruct->packetLen); + // perform write + if (isburst) + writelen = (mSettings->mBufLen > burst_remaining) ? burst_remaining : mSettings->mBufLen; + if (isTcpWriteTimes(mSettings)) { + write_start.setnow(); + } +#if HAVE_DECL_TCP_NOTSENT_LOWAT + if (isWritePrefetch(mSettings)) { + AwaitWriteSelectEventTCP(); + } +#endif + reportstruct->packetLen = write(mySocket, mSettings->mBuf, writelen); + now.setnow(); + reportstruct->writecnt++; + reportstruct->packetTime.tv_sec = now.getSecs(); + reportstruct->packetTime.tv_usec = now.getUsecs(); + if (isTcpWriteTimes(mSettings)) { + reportstruct->write_time = now.subUsec(write_start); + } + reportstruct->sentTime = reportstruct->packetTime; + } + if (reportstruct->packetLen <= 0) { + if (reportstruct->packetLen == 0) { + peerclose = true; + } else if (NONFATALTCPWRITERR(errno)) { + reportstruct->errwrite=WriteErrAccount; + } else if (FATALTCPWRITERR(errno)) { + reportstruct->errwrite=WriteErrFatal; + WARN_errno(1, "tcp write"); + break; + } else { + reportstruct->errwrite=WriteErrNoAccount; + } + reportstruct->packetLen = 0; + reportstruct->emptyreport = 1; + } else { + reportstruct->emptyreport = 0; + totLen += reportstruct->packetLen; + reportstruct->errwrite=WriteNoErr; + if (isburst) { + burst_remaining -= reportstruct->packetLen; + if (burst_remaining > 0) { + reportstruct->transit_ready = 0; + } else { + reportstruct->transit_ready = 1; + reportstruct->prevSentTime = myReport->info.ts.prevsendTime; + } + } + } + if (isModeAmount(mSettings) && !reportstruct->emptyreport) { + /* mAmount may be unsigned, so don't let it underflow! */ + if (mSettings->mAmount >= static_cast<unsigned long>(reportstruct->packetLen)) { + mSettings->mAmount -= static_cast<unsigned long>(reportstruct->packetLen); + } else { + mSettings->mAmount = 0; + } + } + if (!one_report) { + myReportPacket(); + } + } + FinishTrafficActions(); +} + +/* + * TCP send loop + */ +void Client::RunNearCongestionTCP () { + int burst_remaining = 0; + int burst_id = 1; + now.setnow(); + reportstruct->packetTime.tv_sec = now.getSecs(); + reportstruct->packetTime.tv_usec = now.getUsecs(); + while (InProgress()) { + reportstruct->writecnt = 0; + if (isModeAmount(mSettings)) { + reportstruct->packetLen = ((mSettings->mAmount < static_cast<unsigned>(mSettings->mBufLen)) ? mSettings->mAmount : mSettings->mBufLen); + } else { + reportstruct->packetLen = mSettings->mBufLen; + } + if (!burst_remaining) { + burst_remaining = mSettings->mBufLen; + // mAmount check + now.setnow(); + reportstruct->packetTime.tv_sec = now.getSecs(); + reportstruct->packetTime.tv_usec = now.getUsecs(); + WriteTcpTxHdr(reportstruct, burst_remaining, burst_id++); + reportstruct->sentTime = reportstruct->packetTime; + myReport->info.ts.prevsendTime = reportstruct->packetTime; + // perform write + int writelen = (mSettings->mBufLen > burst_remaining) ? burst_remaining : mSettings->mBufLen; + reportstruct->packetLen = write(mySocket, mSettings->mBuf, writelen); + reportstruct->writecnt++; + assert(reportstruct->packetLen >= (intmax_t) sizeof(struct TCP_burst_payload)); + goto ReportNow; + } + if (reportstruct->packetLen > burst_remaining) { + reportstruct->packetLen = burst_remaining; + } + // printf("pl=%ld\n",reportstruct->packetLen); + // perform write + reportstruct->packetLen = write(mySocket, mSettings->mBuf, reportstruct->packetLen); + now.setnow(); + reportstruct->writecnt++; + reportstruct->packetTime.tv_sec = now.getSecs(); + reportstruct->packetTime.tv_usec = now.getUsecs(); + reportstruct->sentTime = reportstruct->packetTime; + ReportNow: + reportstruct->transit_ready = 0; + if (reportstruct->packetLen < 0) { + if (NONFATALTCPWRITERR(errno)) { + reportstruct->errwrite=WriteErrAccount; + } else if (FATALTCPWRITERR(errno)) { + reportstruct->errwrite=WriteErrFatal; + WARN_errno(1, "tcp write"); + break; + } else { + reportstruct->errwrite=WriteErrNoAccount; + } + reportstruct->packetLen = 0; + reportstruct->emptyreport = 1; + } else { + reportstruct->emptyreport = 0; + totLen += reportstruct->packetLen; + reportstruct->errwrite=WriteNoErr; + burst_remaining -= reportstruct->packetLen; + if (burst_remaining <= 0) { + reportstruct->transit_ready = 1; + } + } + if (isModeAmount(mSettings) && !reportstruct->emptyreport) { + /* mAmount may be unsigned, so don't let it underflow! */ + if (mSettings->mAmount >= static_cast<unsigned long>(reportstruct->packetLen)) { + mSettings->mAmount -= static_cast<unsigned long>(reportstruct->packetLen); + } else { + mSettings->mAmount = 0; + } + } + // apply placing after write burst completes + if (reportstruct->transit_ready) { + myReportPacket(); // this will set the tcpstats in the report struct + // pacing timer is weighted by the RTT (set to 1 when RTT is not supported) + int pacing_timer = 0; +#if HAVE_TCP_STATS + pacing_timer = static_cast<int>(std::ceil(static_cast<double>(reportstruct->tcpstats.rtt) * mSettings->rtt_nearcongest_weight_factor)); +#else + pacing_timer = static_cast<int>(100 * mSettings->rtt_nearcongest_weight_factor); +#endif + if (pacing_timer) + delay_loop(pacing_timer); + } + } + FinishTrafficActions(); +} + +/* + * A version of the transmit loop that supports TCP rate limiting using a token bucket + */ +void Client::RunRateLimitedTCP () { + double tokens = 0; + Timestamp time1, time2; + int burst_size = mSettings->mBufLen; + int burst_remaining = 0; + int burst_id = 1; + + long var_rate = mSettings->mAppRate; + int fatalwrite_err = 0; + + now.setnow(); + reportstruct->packetTime.tv_sec = now.getSecs(); + reportstruct->packetTime.tv_usec = now.getUsecs(); + while (InProgress() && !fatalwrite_err) { + reportstruct->writecnt = 0; + // Add tokens per the loop time + time2.setnow(); + if (isVaryLoad(mSettings)) { + static Timestamp time3; + if (time2.subSec(time3) >= VARYLOAD_PERIOD) { + var_rate = lognormal(mSettings->mAppRate,mSettings->mVariance); + time3 = time2; + if (var_rate < 0) + var_rate = 0; + } + } + tokens += time2.subSec(time1) * (var_rate / 8.0); + time1 = time2; + if (tokens >= 0.0) { + if (isModeAmount(mSettings)) { + reportstruct->packetLen = ((mSettings->mAmount < static_cast<unsigned>(mSettings->mBufLen)) ? mSettings->mAmount : mSettings->mBufLen); + } else { + reportstruct->packetLen = mSettings->mBufLen; + } + // perform write + int len = 0; + int len2 = 0; + if (burst_remaining == 0) { + burst_remaining = mSettings->mBufLen; + now.setnow(); + reportstruct->packetTime.tv_sec = now.getSecs(); + reportstruct->packetTime.tv_usec = now.getUsecs(); + reportstruct->sentTime = reportstruct->packetTime; + WriteTcpTxHdr(reportstruct, burst_size, burst_id++); + // perform write + if (isTripTime(mSettings)) { + len = writen(mySocket, mSettings->mBuf, mSettings->mBufLen, &reportstruct->writecnt); + WARN(len != mSettings->mBufLen, "burst write failed"); + } else { + len = writen(mySocket, mSettings->mBuf, sizeof(struct TCP_burst_payload), &reportstruct->writecnt); + WARN(len != sizeof(struct TCP_burst_payload), "burst hdr write failed"); + } + if (len < 0) { + len = 0; + if (NONFATALTCPWRITERR(errno)) { + reportstruct->errwrite=WriteErrAccount; + } else if (FATALTCPWRITERR(errno)) { + reportstruct->errwrite=WriteErrFatal; + WARN_errno(1, "write"); + fatalwrite_err = 1; + break; + } else { + reportstruct->errwrite=WriteErrNoAccount; + } + } else { + burst_remaining -= len; + } + // thread_debug("***write burst header %d id=%d", burst_size, (burst_id - 1)); + } else if (reportstruct->packetLen > burst_remaining) { + reportstruct->packetLen = burst_remaining; + } + if (burst_remaining > 0) { + len2 = write(mySocket, mSettings->mBuf, reportstruct->packetLen); + reportstruct->writecnt++; + } + if (len2 < 0) { + len2 = 0; + if (NONFATALTCPWRITERR(errno)) { + reportstruct->errwrite=WriteErrAccount; + } else if (FATALTCPWRITERR(errno)) { + reportstruct->errwrite=WriteErrFatal; + WARN_errno(1, "write"); + fatalwrite_err = 1; + break; + } else { + reportstruct->errwrite=WriteErrNoAccount; + } + } else { + // Consume tokens per the transmit + tokens -= (len + len2); + totLen += (len + len2);; + reportstruct->errwrite=WriteNoErr; + } + time2.setnow(); + reportstruct->packetLen = len + len2; + reportstruct->packetTime.tv_sec = time2.getSecs(); + reportstruct->packetTime.tv_usec = time2.getUsecs(); + reportstruct->sentTime = reportstruct->packetTime; + if (isModeAmount(mSettings)) { + /* mAmount may be unsigned, so don't let it underflow! */ + if (mSettings->mAmount >= static_cast<unsigned long>(reportstruct->packetLen)) { + mSettings->mAmount -= static_cast<unsigned long>(reportstruct->packetLen); + } else { + mSettings->mAmount = 0; + } + } + if (!one_report) { + myReportPacket(); + } + } else { + // Use a 4 usec delay to fill tokens +#if HAVE_DECL_TCP_NOTSENT_LOWAT + if (isWritePrefetch(mSettings)) { + AwaitWriteSelectEventTCP(); + } else +#endif + { + delay_loop(4); + } + } + } + FinishTrafficActions(); +} + +#if HAVE_DECL_TCP_NOTSENT_LOWAT +inline bool Client::AwaitWriteSelectEventTCP (void) { + int rc; + struct timeval timeout; + fd_set writeset; + FD_ZERO(&writeset); + FD_SET(mySocket, &writeset); + if (isModeTime(mSettings)) { + Timestamp write_event_timeout(0,0); + if (mSettings->mInterval && (mSettings->mIntervalMode == kInterval_Time)) { + write_event_timeout.add((double) mSettings->mInterval / 1e6 * 2.0); + } else { + write_event_timeout.add((double) mSettings->mAmount / 1e2 * 4.0); + } + timeout.tv_sec = write_event_timeout.getSecs(); + timeout.tv_usec = write_event_timeout.getUsecs(); + } else { + timeout.tv_sec = 10; // longest is 10 seconds + timeout.tv_usec = 0; + } + + if ((rc = select(mySocket + 1, NULL, &writeset, NULL, &timeout)) <= 0) { + WARN_errno((rc < 0), "select"); +#ifdef HAVE_THREAD_DEBUG + if (rc == 0) + thread_debug("AwaitWrite timeout"); +#endif + return false; + } + return true; +} + +void Client::RunWriteEventsTCP () { + int burst_id = 0; + int writelen = mSettings->mBufLen; + Timestamp write_end; + + now.setnow(); + reportstruct->packetTime.tv_sec = now.getSecs(); + reportstruct->packetTime.tv_usec = now.getUsecs(); + while (InProgress()) { + if (isModeAmount(mSettings)) { + writelen = ((mSettings->mAmount < static_cast<unsigned>(mSettings->mBufLen)) ? mSettings->mAmount : mSettings->mBufLen); + } + now.setnow(); + reportstruct->write_time = 0; + if (isTcpWriteTimes(mSettings)) { + write_start = now; + } + bool rc = AwaitWriteSelectEventTCP(); + reportstruct->emptyreport = (rc == false) ? 1 : 0; + if (rc) { + now.setnow(); + reportstruct->packetTime.tv_sec = now.getSecs(); + reportstruct->packetTime.tv_usec = now.getUsecs(); + WriteTcpTxHdr(reportstruct, writelen, ++burst_id); + reportstruct->sentTime = reportstruct->packetTime; + reportstruct->packetLen = writen(mySocket, mSettings->mBuf, writelen, &reportstruct->writecnt); + if (reportstruct->packetLen <= 0) { + WARN_errno((reportstruct->packetLen < 0), "event writen()"); + if (reportstruct->packetLen == 0) { + peerclose = true; + } + reportstruct->packetLen = 0; + reportstruct->emptyreport = 1; + } else if (isTcpWriteTimes(mSettings)) { + write_end.setnow(); + reportstruct->write_time = write_end.subUsec(write_start); + } + } + if (isModeAmount(mSettings) && !reportstruct->emptyreport) { + /* mAmount may be unsigned, so don't let it underflow! */ + if (mSettings->mAmount >= static_cast<unsigned long>(reportstruct->packetLen)) { + mSettings->mAmount -= static_cast<unsigned long>(reportstruct->packetLen); + } else { + mSettings->mAmount = 0; + } + } + if (!one_report) { + myReportPacket(); + } + } + FinishTrafficActions(); +} +#endif +void Client::RunBounceBackTCP () { + int burst_id = 0; + int writelen = mSettings->mBufLen; + memset(mSettings->mBuf, 0x5A, sizeof(struct bounceback_hdr)); + if (mSettings->mInterval && (mSettings->mIntervalMode == kInterval_Time)) { + int sotimer = static_cast<int>(round(mSettings->mInterval / 2.0)); + SetSocketOptionsReceiveTimeout(mSettings, sotimer); + SetSocketOptionsSendTimeout(mSettings, sotimer); + } else if (isModeTime(mSettings)) { + int sotimer = static_cast<int>(round(mSettings->mAmount * 10000) / 2); + SetSocketOptionsReceiveTimeout(mSettings, sotimer); + SetSocketOptionsSendTimeout(mSettings, sotimer); + } + if (isModeTime(mSettings)) { + uintmax_t end_usecs = (mSettings->mAmount * 10000); + if (int err = set_itimer(end_usecs)) { + FAIL_errno(err != 0, "setitimer", mSettings); + } + } + now.setnow(); + reportstruct->packetTime.tv_sec = now.getSecs(); + reportstruct->packetTime.tv_usec = now.getUsecs(); + while (InProgress()) { + int n; + reportstruct->writecnt = 0; + bool isFirst; + if (framecounter) { + burst_id = framecounter->wait_tick(&reportstruct->sched_err); + PostNullEvent(true); // this will set the now timestamp + reportstruct->sentTime.tv_sec = now.getSecs(); + reportstruct->sentTime.tv_usec = now.getUsecs(); + isFirst = true; + } else { + burst_id++; + isFirst = false; + } + int bb_burst = (mSettings->mBounceBackBurst > 0) ? mSettings->mBounceBackBurst : 1; + while (bb_burst > 0) { + bb_burst--; + if (isFirst) { + isFirst = false; + } else { + now.setnow(); + reportstruct->sentTime.tv_sec = now.getSecs(); + reportstruct->sentTime.tv_usec = now.getUsecs(); + } + WriteTcpTxBBHdr(reportstruct, burst_id, 0); + reportstruct->packetLen = writen(mySocket, mSettings->mBuf, writelen, &reportstruct->writecnt); + if (reportstruct->packetLen <= 0) { + if ((reportstruct->packetLen < 0) && FATALTCPWRITERR(errno)) { + reportstruct->errwrite=WriteErrFatal; + WARN_errno(1, "tcp bounceback write fatal error"); + peerclose = true; + } else if (reportstruct->packetLen == 0) { + peerclose = true; + } else if (reportstruct->packetLen != writelen) { + WARN_errno(1, "tcp bounceback writen incomplete"); + peerclose = true; + } else { + // retry the write + bb_burst++; + continue; + } + break; + } + if (reportstruct->packetLen == writelen) { + reportstruct->emptyreport = 0; + totLen += reportstruct->packetLen; + reportstruct->errwrite=WriteNoErr; +#if HAVE_DECL_TCP_QUICKACK + if (isTcpQuickAck(mSettings)) { + int opt = 1; + Socklen_t len = sizeof(opt); + int rc = setsockopt(mySocket, IPPROTO_TCP, TCP_QUICKACK, + reinterpret_cast<char*>(&opt), len); + WARN_errno(rc == SOCKET_ERROR, "setsockopt TCP_QUICKACK"); + } +#endif + if ((n = recvn(mySocket, mSettings->mBuf, mSettings->mBounceBackBytes, 0)) == mSettings->mBounceBackBytes) { + struct bounceback_hdr *bbhdr = reinterpret_cast<struct bounceback_hdr *>(mSettings->mBuf); + now.setnow(); + reportstruct->sentTimeRX.tv_sec = ntohl(bbhdr->bbserverRx_ts.sec); + reportstruct->sentTimeRX.tv_usec = ntohl(bbhdr->bbserverRx_ts.usec); + reportstruct->sentTimeTX.tv_sec = ntohl(bbhdr->bbserverTx_ts.sec); + reportstruct->sentTimeTX.tv_usec = ntohl(bbhdr->bbserverTx_ts.usec); + reportstruct->packetTime.tv_sec = now.getSecs(); + reportstruct->packetTime.tv_usec = now.getUsecs(); + reportstruct->packetLen += n; + reportstruct->emptyreport = 0; + myReportPacket(); + } else if (n == 0) { + peerclose = true; + } else if (n < 0) { + if (FATALTCPREADERR(errno)) { + WARN_errno(1, "bounceback read"); + peerclose = true; + n = 0; + } else { + WARN(1, "timeout: bounceback read"); + } + } + } else if ((reportstruct->packetLen < 0 ) && NONFATALTCPWRITERR(errno)) { + reportstruct->packetLen = 0; + reportstruct->emptyreport = 1; + reportstruct->errwrite=WriteErrNoAccount; + myReportPacket(); + } else { + reportstruct->errwrite=WriteErrFatal; + reportstruct->packetLen = -1; + FAIL_errno(1, "tcp bounce-back write", mSettings); + } + } + } + WriteTcpTxBBHdr(reportstruct, 0x0, 1); + disarm_itimer(); + FinishTrafficActions(); +} +/* + * UDP send loop + */ +double Client::get_delay_target () { + double delay_target; + if (isIPG(mSettings)) { + delay_target = mSettings->mBurstIPG * 1000000; // convert from milliseconds to nanoseconds + } else { + // compute delay target in units of nanoseconds + if (mSettings->mAppRateUnits == kRate_BW) { + // compute delay for bandwidth restriction, constrained to [0,1] seconds + delay_target = (mSettings->mBufLen * ((kSecs_to_nsecs * kBytes_to_Bits) + / mSettings->mAppRate)); + } else { + delay_target = 1e9 / mSettings->mAppRate; + } + } + return delay_target; +} + +void Client::RunUDP () { + struct UDP_datagram* mBuf_UDP = reinterpret_cast<struct UDP_datagram*>(mSettings->mBuf); + int currLen; + + double delay_target = get_delay_target(); + double delay = 0; + double adjust = 0; + + // Set this to > 0 so first loop iteration will delay the IPG + currLen = 1; + double variance = mSettings->mVariance; + if (apply_first_udppkt_delay && (delay_target > 100000)) { + //the case when a UDP first packet went out in SendFirstPayload + delay_loop(static_cast<unsigned long>(delay_target / 1000)); + } + + while (InProgress()) { + // Test case: drop 17 packets and send 2 out-of-order: + // sequence 51, 52, 70, 53, 54, 71, 72 + //switch(datagramID) { + // case 53: datagramID = 70; break; + // case 71: datagramID = 53; break; + // case 55: datagramID = 71; break; + // default: break; + //} + now.setnow(); + reportstruct->writecnt = 1; + reportstruct->packetTime.tv_sec = now.getSecs(); + reportstruct->packetTime.tv_usec = now.getUsecs(); + reportstruct->sentTime = reportstruct->packetTime; + if (isVaryLoad(mSettings) && mSettings->mAppRateUnits == kRate_BW) { + static Timestamp time3; + if (now.subSec(time3) >= VARYLOAD_PERIOD) { + long var_rate = lognormal(mSettings->mAppRate,variance); + if (var_rate < 0) + var_rate = 0; + delay_target = (mSettings->mBufLen * ((kSecs_to_nsecs * kBytes_to_Bits) / var_rate)); + time3 = now; + } + } + // store datagram ID into buffer + WritePacketID(reportstruct->packetID); + mBuf_UDP->tv_sec = htonl(reportstruct->packetTime.tv_sec); + mBuf_UDP->tv_usec = htonl(reportstruct->packetTime.tv_usec); + + // Adjustment for the running delay + // o measure how long the last loop iteration took + // o calculate the delay adjust + // - If write succeeded, adjust = target IPG - the loop time + // - If write failed, adjust = the loop time + // o then adjust the overall running delay + // Note: adjust units are nanoseconds, + // packet timestamps are microseconds + if (currLen > 0) + adjust = delay_target + \ + (1000.0 * lastPacketTime.subUsec(reportstruct->packetTime)); + else + adjust = 1000.0 * lastPacketTime.subUsec(reportstruct->packetTime); + + lastPacketTime.set(reportstruct->packetTime.tv_sec, reportstruct->packetTime.tv_usec); + // Since linux nanosleep/busyloop can exceed delay + // there are two possible equilibriums + // 1) Try to perserve inter packet gap + // 2) Try to perserve requested transmit rate + // The latter seems preferred, hence use a running delay + // that spans the life of the thread and constantly adjust. + // A negative delay means the iperf app is behind. + delay += adjust; + // Don't let delay grow unbounded + if (delay < delay_lower_bounds) { + delay = delay_target; + } + + reportstruct->errwrite = WriteNoErr; + reportstruct->emptyreport = 0; + // perform write + if (isModeAmount(mSettings)) { + currLen = write(mySocket, mSettings->mBuf, (mSettings->mAmount < static_cast<unsigned>(mSettings->mBufLen)) ? mSettings->mAmount : mSettings->mBufLen); + } else { + currLen = write(mySocket, mSettings->mBuf, mSettings->mBufLen); + } + if (currLen < 0) { + reportstruct->packetID--; + if (FATALUDPWRITERR(errno)) { + reportstruct->errwrite = WriteErrFatal; + WARN_errno(1, "write"); + break; + } else { + reportstruct->errwrite = WriteErrAccount; + currLen = 0; + } + reportstruct->emptyreport = 1; + } + + if (isModeAmount(mSettings)) { + /* mAmount may be unsigned, so don't let it underflow! */ + if (mSettings->mAmount >= static_cast<unsigned long>(currLen)) { + mSettings->mAmount -= static_cast<unsigned long>(currLen); + } else { + mSettings->mAmount = 0; + } + } + + // report packets + reportstruct->packetLen = static_cast<unsigned long>(currLen); + reportstruct->prevPacketTime = myReport->info.ts.prevpacketTime; + myReportPacket(); + reportstruct->packetID++; + myReport->info.ts.prevpacketTime = reportstruct->packetTime; + // Insert delay here only if the running delay is greater than 100 usec, + // otherwise don't delay and immediately continue with the next tx. + if (delay >= 100000) { + // Convert from nanoseconds to microseconds + // and invoke the microsecond delay + delay_loop(static_cast<unsigned long>(delay / 1000)); + } + } + FinishTrafficActions(); +} + +/* + * UDP isochronous send loop + */ +void Client::RunUDPIsochronous () { + struct UDP_datagram* mBuf_UDP = reinterpret_cast<struct UDP_datagram*>(mSettings->mBuf); + // skip over the UDP datagram (seq no, timestamp) to reach the isoch fields + struct client_udp_testhdr *udp_payload = reinterpret_cast<client_udp_testhdr *>(mSettings->mBuf); + + double delay_target = mSettings->mBurstIPG * 1000000; // convert from milliseconds to nanoseconds + double delay = 0; + double adjust = 0; + int currLen = 1; + int frameid=0; + Timestamp t1; + + // make sure the packet can carry the isoch payload + if (!framecounter) { + framecounter = new Isochronous::FrameCounter(mSettings->mFPS); + } + udp_payload->isoch.burstperiod = htonl(framecounter->period_us()); + + int initdone = 0; + int fatalwrite_err = 0; + while (InProgress() && !fatalwrite_err) { + int bytecnt = static_cast<int>(lognormal(mSettings->mMean,mSettings->mVariance)) / (mSettings->mFPS * 8); + if (bytecnt < udp_payload_minimum) + bytecnt = udp_payload_minimum; + delay = 0; + + // printf("bits=%d\n", (int) (mSettings->mFPS * bytecnt * 8)); + udp_payload->isoch.burstsize = htonl(bytecnt); + udp_payload->isoch.prevframeid = htonl(frameid); + reportstruct->burstsize=bytecnt; + frameid = framecounter->wait_tick(&reportstruct->sched_err); + reportstruct->scheduled = true; + udp_payload->isoch.frameid = htonl(frameid); + lastPacketTime.setnow(); + if (!initdone) { + initdone = 1; + udp_payload->isoch.start_tv_sec = htonl(lastPacketTime.getSecs()); + udp_payload->isoch.start_tv_usec = htonl(lastPacketTime.getUsecs()); + } + while ((bytecnt > 0) && InProgress()) { + t1.setnow(); + reportstruct->packetTime.tv_sec = t1.getSecs(); + reportstruct->packetTime.tv_usec = t1.getUsecs(); + reportstruct->sentTime = reportstruct->packetTime; + mBuf_UDP->tv_sec = htonl(reportstruct->packetTime.tv_sec); + mBuf_UDP->tv_usec = htonl(reportstruct->packetTime.tv_usec); + WritePacketID(reportstruct->packetID); + + // Adjustment for the running delay + // o measure how long the last loop iteration took + // o calculate the delay adjust + // - If write succeeded, adjust = target IPG - the loop time + // - If write failed, adjust = the loop time + // o then adjust the overall running delay + // Note: adjust units are nanoseconds, + // packet timestamps are microseconds + if (currLen > 0) + adjust = delay_target + \ + (1000.0 * lastPacketTime.subUsec(reportstruct->packetTime)); + else + adjust = 1000.0 * lastPacketTime.subUsec(reportstruct->packetTime); + + lastPacketTime.set(reportstruct->packetTime.tv_sec, reportstruct->packetTime.tv_usec); + // Since linux nanosleep/busyloop can exceed delay + // there are two possible equilibriums + // 1) Try to perserve inter packet gap + // 2) Try to perserve requested transmit rate + // The latter seems preferred, hence use a running delay + // that spans the life of the thread and constantly adjust. + // A negative delay means the iperf app is behind. + delay += adjust; + // Don't let delay grow unbounded + // if (delay < delay_lower_bounds) { + // delay = delay_target; + // } + + reportstruct->errwrite = WriteNoErr; + reportstruct->emptyreport = 0; + reportstruct->writecnt = 1; + + // perform write + if (isModeAmount(mSettings) && (mSettings->mAmount < static_cast<unsigned>(mSettings->mBufLen))) { + udp_payload->isoch.remaining = htonl(mSettings->mAmount); + reportstruct->remaining=mSettings->mAmount; + currLen = write(mySocket, mSettings->mBuf, mSettings->mAmount); + } else { + udp_payload->isoch.remaining = htonl(bytecnt); + reportstruct->remaining=bytecnt; + currLen = write(mySocket, mSettings->mBuf, (bytecnt < mSettings->mBufLen) ? bytecnt : mSettings->mBufLen); + } + + if (currLen < 0) { + reportstruct->packetID--; + reportstruct->emptyreport = 1; + currLen = 0; + if (FATALUDPWRITERR(errno)) { + reportstruct->errwrite = WriteErrFatal; + WARN_errno(1, "write"); + fatalwrite_err = 1; + } else { + reportstruct->errwrite = WriteErrAccount; + } + } else { + bytecnt -= currLen; + if (!bytecnt) + reportstruct->transit_ready = 1; + else + reportstruct->transit_ready = 0; + // adjust bytecnt so last packet of burst is greater or equal to min packet + if ((bytecnt > 0) && (bytecnt < udp_payload_minimum)) { + bytecnt = udp_payload_minimum; + udp_payload->isoch.burstsize = htonl(bytecnt); + reportstruct->burstsize=bytecnt; + } + } + if (isModeAmount(mSettings)) { + /* mAmount may be unsigned, so don't let it underflow! */ + if (mSettings->mAmount >= static_cast<unsigned long>(currLen)) { + mSettings->mAmount -= static_cast<unsigned long>(currLen); + } else { + mSettings->mAmount = 0; + } + } + // report packets + + reportstruct->frameID=frameid; + reportstruct->packetLen = static_cast<unsigned long>(currLen); + reportstruct->prevPacketTime = myReport->info.ts.prevpacketTime; + myReportPacket(); + reportstruct->scheduled = false; // reset to false after the report + reportstruct->packetID++; + myReport->info.ts.prevpacketTime = reportstruct->packetTime; + // Insert delay here only if the running delay is greater than 1 usec, + // otherwise don't delay and immediately continue with the next tx. + if (delay >= 1000) { + // Convert from nanoseconds to microseconds + // and invoke the microsecond delay + delay_loop(static_cast<unsigned long>(delay / 1000)); + } + } + } + FinishTrafficActions(); +} +// end RunUDPIsoch + +inline void Client::WritePacketID (intmax_t packetID) { + struct UDP_datagram * mBuf_UDP = reinterpret_cast<struct UDP_datagram *>(mSettings->mBuf); + // store datagram ID into buffer +#ifdef HAVE_INT64_T + // Pack signed 64bit packetID into unsigned 32bit id1 + unsigned + // 32bit id2. A legacy server reading only id1 will still be able + // to reconstruct a valid signed packet ID number up to 2^31. + uint32_t id1, id2; + id1 = packetID & 0xFFFFFFFFLL; + id2 = (packetID & 0xFFFFFFFF00000000LL) >> 32; + + mBuf_UDP->id = htonl(id1); + mBuf_UDP->id2 = htonl(id2); + +#ifdef HAVE_PACKET_DEBUG + printf("id %" PRIdMAX " (0x%" PRIxMAX ") -> 0x%x, 0x%x\n", + packetID, packetID, id1, id2); +#endif +#else + mBuf_UDP->id = htonl((reportstruct->packetID)); +#endif +} + +inline void Client::WriteTcpTxHdr (struct ReportStruct *reportstruct, int burst_size, int burst_id) { + struct TCP_burst_payload * mBuf_burst = reinterpret_cast<struct TCP_burst_payload *>(mSettings->mBuf); + // store packet ID into buffer + reportstruct->packetID += burst_size; + mBuf_burst->start_tv_sec = htonl(myReport->info.ts.startTime.tv_sec); + mBuf_burst->start_tv_usec = htonl(myReport->info.ts.startTime.tv_usec); + +#ifdef HAVE_INT64_T + // Pack signed 64bit packetID into unsigned 32bit id1 + unsigned + // 32bit id2. A legacy server reading only id1 will still be able + // to reconstruct a valid signed packet ID number up to 2^31. + uint32_t id1, id2; + id1 = reportstruct->packetID & 0xFFFFFFFFLL; + id2 = (reportstruct->packetID & 0xFFFFFFFF00000000LL) >> 32; + + mBuf_burst->seqno_lower = htonl(id1); + mBuf_burst->seqno_upper = htonl(id2); + +#ifdef HAVE_PACKET_DEBUG + printf("id %" PRIdMAX " (0x%" PRIxMAX ") -> 0x%x, 0x%x\n", + reportstruct->packetID, reportstruct->packetID, id1, id2); +#endif +#else + mBuf_burst->seqno_lower = htonl((reportstruct->packetID)); + mBuf_burst->seqno_upper = htonl(0x0); +#endif + mBuf_burst->send_tt.write_tv_sec = htonl(reportstruct->packetTime.tv_sec); + mBuf_burst->send_tt.write_tv_usec = htonl(reportstruct->packetTime.tv_usec); + mBuf_burst->burst_id = htonl((uint32_t)burst_id); + mBuf_burst->burst_size = htonl((uint32_t)burst_size); + reportstruct->frameID=burst_id; + reportstruct->burstsize=burst_size; +// printf("**** Write tcp burst header size= %d id = %d\n", burst_size, burst_id); +} + +// See payloads.h +void Client::WriteTcpTxBBHdr (struct ReportStruct *reportstruct, uint32_t bbid, int final) { + struct bounceback_hdr * mBuf_bb = reinterpret_cast<struct bounceback_hdr *>(mSettings->mBuf); + // store packet ID into buffer + uint32_t flags = HEADER_BOUNCEBACK; + uint32_t bbflags = 0x0; + mBuf_bb->flags = htonl(flags); + if (isTripTime(mSettings)) { + bbflags |= HEADER_BBCLOCKSYNCED; + } + if (mSettings->mTOS) { + bbflags |= HEADER_BBTOS; + mBuf_bb->tos = htons((mSettings->mTOS & 0xFF)); + } + if (isTcpQuickAck(mSettings)) { + bbflags |= HEADER_BBQUICKACK; + } + mBuf_bb->bbRunTime = 0x0; + if (final) { + bbflags |= HEADER_BBSTOP; + } + mBuf_bb->bbflags = htons(bbflags); + mBuf_bb->bbsize = htonl(mSettings->mBufLen); + mBuf_bb->bbid = htonl(bbid); + mBuf_bb->bbclientTx_ts.sec = htonl(reportstruct->packetTime.tv_sec); + mBuf_bb->bbclientTx_ts.usec = htonl(reportstruct->packetTime.tv_usec); + mBuf_bb->bbserverRx_ts.sec = -1; + mBuf_bb->bbserverRx_ts.usec = -1; + mBuf_bb->bbserverTx_ts.sec = -1; + mBuf_bb->bbserverTx_ts.usec = -1; + mBuf_bb->bbhold = htonl(mSettings->mBounceBackHold); +} + +inline bool Client::InProgress (void) { + // Read the next data block from + // the file if it's file input + if (isFileInput(mSettings)) { + Extractor_getNextDataBlock(readAt, mSettings); + return Extractor_canRead(mSettings) != 0; + } + // fprintf(stderr, "DEBUG: SI=%d PC=%d T=%d A=%d\n", sInterupted, peerclose, (isModeTime(mSettings) && mEndTime.before(reportstruct->packetTime)), (isModeAmount(mSettings) && (mSettings->mAmount <= 0))); + return !(sInterupted || peerclose || \ + (isModeTime(mSettings) && mEndTime.before(reportstruct->packetTime)) || + (isModeAmount(mSettings) && (mSettings->mAmount <= 0))); +} + +inline void Client::tcp_shutdown (void) { + if ((mySocket != INVALID_SOCKET) && isConnected()) { + int rc = shutdown(mySocket, SHUT_WR); +#ifdef HAVE_THREAD_DEBUG + thread_debug("Client calls shutdown() SHUTW_WR on tcp socket %d", mySocket); +#endif + WARN_errno(rc == SOCKET_ERROR, "shutdown"); + if (!rc && !isFullDuplex(mSettings)) + AwaitServerCloseEvent(); + } +} + +/* + * Common things to do to finish a traffic thread + * + * Notes on the negative packet count or seq no: + * A negative packet id is used to tell the server + * this UDP stream is terminating. The server will remove + * the sign. So a decrement will be seen as increments by + * the server (e.g, -1000, -1001, -1002 as 1000, 1001, 1002) + * If the retries weren't decrement here the server can get out + * of order packets per these retries actually being received + * by the server (e.g. -1000, -1000, -1000) + */ +void Client::FinishTrafficActions () { + disarm_itimer(); + // Shutdown the TCP socket's writes as the event for the server to end its traffic loop + if (!isUDP(mSettings)) { + tcp_shutdown(); + now.setnow(); + reportstruct->packetTime.tv_sec = now.getSecs(); + reportstruct->packetTime.tv_usec = now.getUsecs(); + if (one_report) { + /* + * For TCP and if not doing interval or enhanced reporting (needed for write accounting), + * then report the entire transfer as one big packet + * + */ + reportstruct->packetLen = totLen; + } + } else { + // stop timing + now.setnow(); + reportstruct->packetTime.tv_sec = now.getSecs(); + reportstruct->packetTime.tv_usec = now.getUsecs(); + reportstruct->sentTime = reportstruct->packetTime; + // send a final terminating datagram + // Don't count in the mTotalLen. The server counts this one, + // but didn't count our first datagram, so we're even now. + // The negative datagram ID signifies termination to the server. + WritePacketID(-reportstruct->packetID); + struct UDP_datagram * mBuf_UDP = reinterpret_cast<struct UDP_datagram *>(mSettings->mBuf); + mBuf_UDP->tv_sec = htonl(reportstruct->packetTime.tv_sec); + mBuf_UDP->tv_usec = htonl(reportstruct->packetTime.tv_usec); + int len = write(mySocket, mSettings->mBuf, mSettings->mBufLen); +#ifdef HAVE_THREAD_DEBUG + thread_debug("UDP client sent final packet per negative seqno %ld", -reportstruct->packetID); +#endif + if (len > 0) { + reportstruct->packetLen = len; + myReportPacket(); + } + reportstruct->packetLen = 0; + } + int do_close = EndJob(myJob, reportstruct); + if (isIsochronous(mSettings) && (myReport->info.schedule_error.cnt > 2)) { + fprintf(stderr,"%sIsoch schedule errors (mean/min/max/stdev) = %0.3f/%0.3f/%0.3f/%0.3f ms\n",mSettings->mTransferIDStr, \ + ((myReport->info.schedule_error.sum / myReport->info.schedule_error.cnt) * 1e-3), (myReport->info.schedule_error.min * 1e-3), \ + (myReport->info.schedule_error.max * 1e-3), (1e-3 * (sqrt(myReport->info.schedule_error.m2 / (myReport->info.schedule_error.cnt - 1))))); + } + if (isUDP(mSettings) && !isMulticast(mSettings) && !isNoUDPfin(mSettings)) { + /* + * For UDP, there is a final handshake between the client and the server, + * do that now (unless requested no to) + */ + AwaitServerFinPacket(); + } + if (do_close) { +#if HAVE_THREAD_DEBUG + thread_debug("client close sock=%d", mySocket); +#endif + int rc = close(mySocket); + WARN_errno(rc == SOCKET_ERROR, "client close"); + } + Iperf_remove_host(mSettings); + FreeReport(myJob); + if (framecounter) + DELETE_PTR(framecounter); +} + +/* ------------------------------------------------------------------- + * Await for the server's fin packet which also has the server + * stats to displayed on the client. Attempt to re-transmit + * until the fin is received + * ------------------------------------------------------------------- */ +#define RETRYTIMER 10000 //units of us +#define RETRYCOUNT (2 * 1000000 / RETRYTIMER) // 2 seconds worth of retries +void Client::AwaitServerFinPacket () { + int rc; + fd_set readSet; + struct timeval timeout; + int ack_success = 0; + int count = RETRYCOUNT; + while (--count >= 0) { + // wait until the socket is readable, or our timeout expires + FD_ZERO(&readSet); + FD_SET(mySocket, &readSet); + timeout.tv_sec = 0; + timeout.tv_usec = RETRYTIMER; + rc = select(mySocket+1, &readSet, NULL, NULL, &timeout); + FAIL_errno(rc == SOCKET_ERROR, "select", mSettings); + // rc= zero means select's read timed out + if (rc == 0) { + // try to trigger another FIN by resending a negative seq no + WritePacketID(-(++reportstruct->packetID)); + // write data + rc = write(mySocket, mSettings->mBuf, mSettings->mBufLen); + WARN_errno(rc < 0, "write-fin"); +#ifdef HAVE_THREAD_DEBUG + thread_debug("UDP client retransmit final packet per negative seqno %ld", -reportstruct->packetID); +#endif + } else { + // socket ready to read, this packet size + // is set by the server. Assume it's large enough + // to contain the final server packet + rc = read(mySocket, mSettings->mBuf, MAXUDPBUF); + + // dump any 2.0.13 client acks sent at the start of traffic + if (rc == sizeof(client_hdr_ack)) { + struct client_hdr_ack *ack = reinterpret_cast<struct client_hdr_ack *>(mSettings->mBuf); + if (ntohl(ack->typelen.type) == CLIENTHDRACK) { + // printf("**** dump stale ack \n"); + continue; + } + } + + WARN_errno(rc < 0, "read"); + if (rc > 0) { + ack_success = 1; +#ifdef HAVE_THREAD_DEBUG + thread_debug("UDP client received server relay report ack (%d)", -reportstruct->packetID); +#endif + if (mSettings->mReportMode != kReport_CSV) { + PostReport(InitServerRelayUDPReport(mSettings, reinterpret_cast<server_hdr*>(reinterpret_cast<UDP_datagram*>(mSettings->mBuf) + 1))); + } + break; + } + } + } + if ((!ack_success) && (mSettings->mReportMode != kReport_CSV)) + fprintf(stderr, warn_no_ack, mySocket, (isModeTime(mSettings) ? 10 : 1)); +} + + +void Client::PostNullEvent (void) { + assert(myReport!=NULL); + // push a nonevent into the packet ring + // this will cause the reporter to process + // up to this event + memset(reportstruct, 0, sizeof(struct ReportStruct)); + now.setnow(); + reportstruct->packetTime.tv_sec = now.getSecs(); + reportstruct->packetTime.tv_usec = now.getUsecs(); + reportstruct->emptyreport=1; + myReportPacket(); +} + +void Client::PostNullEvent (bool isFirst) { + assert(myReport!=NULL); + // push a nonevent into the packet ring + // this will cause the reporter to process + // up to this event + memset(reportstruct, 0, sizeof(struct ReportStruct)); + now.setnow(); + reportstruct->packetTime.tv_sec = now.getSecs(); + reportstruct->packetTime.tv_usec = now.getUsecs(); + reportstruct->emptyreport=1; + reportstruct->scheduled = isFirst; + myReportPacket(); +} + +// The client end timer is based upon the final fin, fin-ack w/the server +// A way to detect this is to hang a recv and wait for the zero byte +// return indicating the socket is closed for recv per the server +// closing it's socket +#define MINAWAITCLOSEUSECS 2000000 +void Client::AwaitServerCloseEvent () { + // the await detection can take awhile so post a non event ahead of it + PostNullEvent(); + unsigned int amount_usec = \ + (isModeTime(mSettings) ? static_cast<int>(mSettings->mAmount * 10000) : MINAWAITCLOSEUSECS); + if (amount_usec < MINAWAITCLOSEUSECS) + amount_usec = MINAWAITCLOSEUSECS; + SetSocketOptionsReceiveTimeout(mSettings, amount_usec); + int rc; + while ((rc = recv(mySocket, mSettings->mBuf, mSettings->mBufLen, 0) > 0)) {}; + if (rc < 0) + WARN_errno(1, "client await server close"); + + if (rc==0) { + connected = false; +#ifdef HAVE_THREAD_DEBUG + thread_debug("Client detected server close %d", mySocket); +#endif + } +} + +int Client::SendFirstPayload () { + int pktlen = 0; + if (!isConnectOnly(mSettings)) { + if (myReport && !TimeZero(myReport->info.ts.startTime) && !(mSettings->mMode == kTest_TradeOff)) { + reportstruct->packetTime = myReport->info.ts.startTime; + } else { + now.setnow(); + reportstruct->packetTime.tv_sec = now.getSecs(); + reportstruct->packetTime.tv_usec = now.getUsecs(); + } + pattern(mSettings->mBuf, mSettings->mBufLen); + if (isTxStartTime(mSettings)) { + pktlen = Settings_GenerateClientHdr(mSettings, (void *) mSettings->mBuf, mSettings->txstart_epoch); + } else { + pktlen = Settings_GenerateClientHdr(mSettings, (void *) mSettings->mBuf, reportstruct->packetTime); + } + if (pktlen > 0) { + if (isUDP(mSettings)) { + struct client_udp_testhdr *tmphdr = reinterpret_cast<struct client_udp_testhdr *>(mSettings->mBuf); + WritePacketID(reportstruct->packetID); + tmphdr->seqno_ts.tv_sec = htonl(reportstruct->packetTime.tv_sec); + tmphdr->seqno_ts.tv_usec = htonl(reportstruct->packetTime.tv_usec); + udp_payload_minimum = pktlen; +#if HAVE_DECL_MSG_DONTWAIT + pktlen = send(mySocket, mSettings->mBuf, (pktlen > mSettings->mBufLen) ? pktlen : mSettings->mBufLen, MSG_DONTWAIT); +#else + pktlen = send(mySocket, mSettings->mBuf, (pktlen > mSettings->mBufLen) ? pktlen : mSettings->mBufLen, 0); +#endif + apply_first_udppkt_delay = true; + } else { +#if HAVE_DECL_TCP_NODELAY + if (!isNoDelay(mSettings) && isPeerVerDetect(mSettings) && isTripTime(mSettings)) { + int optflag=1; + int rc; + // Disable Nagle to reduce latency of this intial message + if ((rc = setsockopt(mSettings->mSock, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char *>(&optflag), sizeof(int))) < 0) { + WARN_errno(rc < 0, "tcpnodelay"); + } + } +#endif +#if HAVE_DECL_MSG_DONTWAIT + pktlen = send(mySocket, mSettings->mBuf, pktlen, MSG_DONTWAIT); +#else + pktlen = send(mySocket, mSettings->mBuf, pktlen, 0); +#endif + if (isPeerVerDetect(mSettings) && !isServerReverse(mSettings)) { + PeerXchange(); + } +#if HAVE_DECL_TCP_NODELAY + if (!isNoDelay(mSettings) && isPeerVerDetect(mSettings) && isTripTime(mSettings)) { + int optflag=0; + int rc; + // Disable Nagle to reduce latency of this intial message + if ((rc = setsockopt(mSettings->mSock, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char *>(&optflag), sizeof(int))) < 0) { + WARN_errno(rc < 0, "tcpnodelay"); + } + } +#endif + } + WARN_errno(pktlen < 0, "send_hdr"); + } + } + return pktlen; +} + +void Client::PeerXchange () { + int n; + client_hdr_ack ack; + /* + * Hang read and see if this is a header ack message + */ + int readlen = isTripTime(mSettings) ? sizeof(struct client_hdr_ack) : (sizeof(struct client_hdr_ack) - sizeof(struct client_hdr_ack_ts)); + if ((n = recvn(mySocket, reinterpret_cast<char *>(&ack), readlen, 0)) == readlen) { + if (ntohl(ack.typelen.type) == CLIENTHDRACK) { + mSettings->peer_version_u = ntohl(ack.version_u); + mSettings->peer_version_l = ntohl(ack.version_l); + if (isTripTime(mSettings)) { + Timestamp now; + Timestamp senttx(ntohl(ack.ts.sent_tv_sec), ntohl(ack.ts.sent_tv_usec)); + Timestamp sentrx(ntohl(ack.ts.sentrx_tv_sec), ntohl(ack.ts.sentrx_tv_usec)); + Timestamp acktx(ntohl(ack.ts.ack_tv_sec), ntohl(ack.ts.ack_tv_usec)); + Timestamp ackrx(now.getSecs(), now.getUsecs()); + double str = (sentrx.get() - senttx.get()) * 1e3; + double atr = (now.get() - acktx.get()) * 1e3; + double rtt = str + atr; + double halfrtt = rtt / 2.0; + fprintf(stderr,"%sClock sync check (ms): RTT/Half=(%0.3f/%0.3f) OWD-send/ack/asym=(%0.3f/%0.3f/%0.3f)\n",mSettings->mTransferIDStr, rtt, halfrtt, str, atr, (str-atr)); + } + } + } else { + WARN_errno(1, "recvack"); + } +} + +/* + * BarrierClient allows for multiple stream clients to be syncronized + */ +int Client::BarrierClient (struct BarrierMutex *barrier) { + int last = 0; +#ifdef HAVE_THREAD + assert(barrier != NULL); + Condition_Lock(barrier->await); + if (--barrier->count <= 0) { + // store the barrier release timer +#ifdef HAVE_CLOCK_GETTIME + struct timespec t1; + clock_gettime(CLOCK_REALTIME, &t1); + barrier->release_time.tv_sec = t1.tv_sec; + barrier->release_time.tv_usec = t1.tv_nsec / 1000; +#else + gettimeofday(&barrier->release_time, NULL); +#endif + last = 1; + // last one wake's up everyone else + Condition_Broadcast(&barrier->await); +#ifdef HAVE_THREAD_DEBUG + thread_debug("Barrier BROADCAST on condition %p", (void *)&barrier->await); +#endif + } else { +#ifdef HAVE_THREAD_DEBUG + thread_debug("Barrier WAIT on condition %p count=%d", (void *)&barrier->await, barrier->count); +#endif + Condition_Wait(&barrier->await); + } + Condition_Unlock(barrier->await); +#ifdef HAVE_THREAD_DEBUG + thread_debug("Barrier EXIT on condition %p", (void *)&barrier->await); +#endif +#else + last = 1; +#endif // HAVE_THREAD + return last; +} diff --git a/src/Extractor.c b/src/Extractor.c new file mode 100644 index 0000000..4678018 --- /dev/null +++ b/src/Extractor.c @@ -0,0 +1,188 @@ +/*--------------------------------------------------------------- + * Copyright (c) 1999,2000,2001,2002,2003 + * The Board of Trustees of the University of Illinois + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software (Iperf) and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the names of the University of Illinois, NCSA, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * National Laboratory for Applied Network Research + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * http://www.ncsa.uiuc.edu + * ________________________________________________________________ + * Extractor.cpp + * by Ajay Tirumala (tirumala@ncsa.uiuc.edu) + * ------------------------------------------------------------------- + * Extract data from a file, used to measure the transfer rates + * for various stream formats. + * + * E.g. Use a gzipped file to measure the transfer rates for + * compressed data + * Use an MPEG file to measure the transfer rates of + * Multimedia data formats + * Use a plain BMP file to measure the transfer rates of + * Uncompressed data + * + * This is beneficial especially in measuring bandwidth across WAN + * links where data compression takes place before data transmission + * ------------------------------------------------------------------- + */ + +#include "Extractor.h" + + +/** + * Constructor + * @arg fileName Name of the file + * @arg size Block size for reading + * Open the file and set the block size + */ +void Extractor_Initialize ( char *fileName, int inSize, struct thread_Settings *mSettings ) { + + if ( (mSettings->Extractor_file = fopen (fileName, "rb")) == NULL ) { + fprintf( stderr, "Unable to open the file stream\n"); + fprintf( stderr, "Will use the default data stream\n"); + return; + } + mSettings->Extractor_size = inSize; +} + + +/** + * Constructor + * @arg fp File Pointer + * @arg size Block size for reading + * Set the block size,file pointer + */ +void Extractor_InitializeFile ( FILE *fp, int inSize, struct thread_Settings *mSettings ) { + mSettings->Extractor_file = fp; + mSettings->Extractor_size = inSize; +} + + +/** + * Destructor - Close the file + */ +void Extractor_Destroy ( struct thread_Settings *mSettings ) { + if ( mSettings->Extractor_file != NULL ) + fclose( mSettings->Extractor_file ); +} + + +/* + * Fetches the next data block from + * the file + * @arg block Pointer to the data read + * @return Number of bytes read + */ +int Extractor_getNextDataBlock ( char *data, struct thread_Settings *mSettings ) { + if ( Extractor_canRead( mSettings ) ) { + return(fread( data, 1, mSettings->Extractor_size, + mSettings->Extractor_file )); + } + return 0; +} + +/** + * Function which determines whether + * the file stream is still readable + * @return boolean true, if readable; false, if not + */ +int Extractor_canRead ( struct thread_Settings *mSettings ) { + return(( mSettings->Extractor_file != NULL ) + && !(feof( mSettings->Extractor_file ))); +} + +/** + * This is used to reduce the read size + * Used in UDP transfer to accomodate the + * the header (timestamp) + * @arg delta Size to reduce + */ +void Extractor_reduceReadSize ( int delta, struct thread_Settings *mSettings ) { + mSettings->Extractor_size -= delta; +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Launch.cpp b/src/Launch.cpp new file mode 100644 index 0000000..9f0c633 --- /dev/null +++ b/src/Launch.cpp @@ -0,0 +1,478 @@ +/*--------------------------------------------------------------- + * Copyright (c) 1999,2000,2001,2002,2003 + * The Board of Trustees of the University of Illinois + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software (Iperf) and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the names of the University of Illinois, NCSA, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * National Laboratory for Applied Network Research + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * http://www.ncsa.uiuc.edu + * ________________________________________________________________ + * + * Launch.cpp + * by Kevin Gibbs <kgibbs@nlanr.net> + * ------------------------------------------------------------------- + * Functions to launch new server and client threads from C while + * the server and client are in C++. + * The launch function for reporters is in Reporter.c since it is + * in C and does not need a special launching function. + * ------------------------------------------------------------------- */ + +#include "headers.h" +#include "Thread.h" +#include "Settings.hpp" +#include "Client.hpp" +#include "Listener.hpp" +#include "Server.hpp" +#include "PerfSocket.hpp" +#include "active_hosts.h" +#include "SocketAddr.h" +#include "delay.h" + +static int fullduplex_startstop_barrier (struct BarrierMutex *barrier) { + int rc = 0; + assert(barrier != NULL); + Condition_Lock(barrier->await); + ++barrier->count; +#ifdef HAVE_THREAD_DEBUG + thread_debug("Fullduplex barrier incr to %d %p ", barrier->count, (void *)&barrier->await, rc); +#endif + if (barrier->count == 2) { + rc = 1; + // last one wake's up everyone else' +#ifdef HAVE_THREAD_DEBUG + thread_debug("Fullduplex startstop broadcast on condition %p ", (void *)&barrier->await, rc); +#endif + Condition_Broadcast(&barrier->await); + } else { + int timeout = barrier->timeout; + while ((barrier->count != 2) && (timeout > 0)) { +#ifdef HAVE_THREAD_DEBUG + thread_debug("Fullduplex startstop barrier wait %p %d/2 (%d)", (void *)&barrier->await, barrier->count, timeout); +#endif + Condition_TimedWait(&barrier->await, 1); + timeout--; + if ((timeout == 0) && (barrier->count != 2)) { + fprintf(stdout, "Barrier timeout per full duplex traffic\n"); + Condition_Unlock(barrier->await); + return -1; + } + } + barrier->count=0; + } + Condition_Unlock(barrier->await); + return rc; +} +int fullduplex_start_barrier (struct BarrierMutex *barrier) { + int rc = fullduplex_startstop_barrier(barrier); +#ifdef HAVE_THREAD_DEBUG + thread_debug("Fullduplex start barrier done on condition %p rc=%d", (void *)&barrier->await, rc); +#endif + return rc; +} +int fullduplex_stop_barrier (struct BarrierMutex *barrier) { + int rc = fullduplex_startstop_barrier(barrier); +#ifdef HAVE_THREAD_DEBUG + thread_debug("Fullduplex stop barrier done on condition %p rc=%d", (void *)&barrier->await, rc); +#endif + return rc; +} + +/* + * listener_spawn is responsible for creating a Listener class + * and launching the listener. It is provided as a means for + * the C thread subsystem to launch the listener C++ object. + */ +void listener_spawn(struct thread_Settings *thread) { + Listener *theListener = NULL; + // the Listener need to trigger a settings report + setReport(thread); + // start up a listener + theListener = new Listener(thread); + // Start listening + theListener->Run(); + DELETE_PTR(theListener); +} + +/* + * server_spawn is responsible for creating a Server class + * and launching the server. It is provided as a means for + * the C thread subsystem to launch the server C++ object. + */ +void server_spawn(struct thread_Settings *thread) { + Server *theServer = NULL; +#ifdef HAVE_THREAD_DEBUG + if (isBounceBack(thread)) { + thread_debug("spawn server bounce-back"); + } else { + thread_debug("spawn server settings=%p GroupSumReport=%p sock=%d", \ + (void *) thread, (void *)thread->mSumReport, thread->mSock); + } +#endif + // set traffic thread to realtime if needed +#if HAVE_SCHED_SETSCHEDULER + thread_setscheduler(thread); +#endif + // Start up the server + theServer = new Server(thread); + if (isTxStartTime(thread)) { + clock_usleep_abstime(&thread->txstart_epoch); + } + // Run the test + if (isUDP(thread)) { + theServer->RunUDP(); + } else { + if (isBounceBack(thread)) { + theServer->RunBounceBackTCP(); + } else { + theServer->RunTCP(); + } + } + DELETE_PTR(theServer); +} + +static void clientside_client_basic (struct thread_Settings *thread, Client *theClient) { + setTransferID(thread, 0); +#ifdef HAVE_THREAD_DEBUG + if (isBounceBack(thread)) { + thread_debug("Launch: spawn client bounce-back mode, size = %d", thread->mBurstSize); + } else { + thread_debug("Launch: client spawn thread basic (sock=%d)", thread->mSock); + } +#endif + SockAddr_remoteAddr(thread); + // Bounceback start delays the connect too + if (isBounceBack(thread)) { + if (isTxStartTime(thread)) { + theClient->mySockInit(); + clock_usleep_abstime(&thread->txstart_epoch); + } else if (isTxHoldback(thread)) { + unsetTxHoldback(thread); + theClient->mySockInit(); + clock_usleep(&thread->txholdback_timer); + } + } + theClient->my_connect(true); + if ((thread->mThreads > 1) && !isNoConnectSync(thread) && !isCompat(thread)) + // When -P > 1 then all threads finish connect before starting traffic + theClient->BarrierClient(thread->connects_done); + if (theClient->isConnected()) { + if ((thread->mThreads > 1) || isSumOnly(thread)) + Iperf_push_host(thread); + theClient->StartSynch(); + theClient->Run(); + } +} + +static void clientside_client_reverse (struct thread_Settings *thread, \ + struct thread_Settings *reverse_client, Client *theClient) { + setTransferID(thread, 0); + SockAddr_remoteAddr(thread); + theClient->my_connect(true); +#ifdef HAVE_THREAD_DEBUG + thread_debug("Launch: client spawn thread reverse (sock=%d)", thread->mSock); +#endif + if ((thread->mThreads > 1) && !isNoConnectSync(thread)) + // When -P > 1 then all threads finish connect before starting traffic + theClient->BarrierClient(thread->connects_done); + if (theClient->isConnected()) { + FAIL((!reverse_client || !(thread->mSock > 0)), "Reverse test failed to start per thread settings or socket problem", thread); + setTransferID(reverse_client, 1); + theClient->StartSynch(); + reverse_client->mSock = thread->mSock; // use the same socket for both directions + reverse_client->mThreadMode = kMode_Server; + setReverse(reverse_client); + setNoUDPfin(reverse_client); // disable the fin report - no need + reverse_client->size_local = sizeof(iperf_sockaddr); + getsockname(reverse_client->mSock, reinterpret_cast<sockaddr*>(&reverse_client->local), &reverse_client->size_local); + if ((thread->mThreads > 1) || isSumOnly(thread)) + Iperf_push_host(reverse_client); + thread_start(reverse_client); + if (theClient->myJob) + FreeReport(theClient->myJob); + } +} + +static void clientside_client_fullduplex (struct thread_Settings *thread, \ + struct thread_Settings *reverse_client, Client *theClient) { + setTransferID(thread, 0); + SockAddr_remoteAddr(thread); + if (!isBounceBack(thread)) { + thread->mFullDuplexReport = InitSumReport(thread, -1, 1); + } + Settings_Copy(thread, &reverse_client, SHALLOW_COPY); + if ((thread->mThreads > 1) || isSumOnly(thread) || \ + (!(thread->mThreads > 1) && !isEnhanced(thread))) { + Iperf_push_host(thread); + Iperf_push_host(reverse_client); + } + assert(reverse_client != NULL); + setTransferID(reverse_client, 1); + theClient->my_connect(true); +#ifdef HAVE_THREAD_DEBUG + thread_debug("Launch: client spawn thread fullduplex (sock=%d)", thread->mSock); +#endif + if ((thread->mThreads > 1) && !isNoConnectSync(thread)) + // When -P > 1 then all threads finish connect before starting traffic + theClient->BarrierClient(thread->connects_done); + if (theClient->isConnected()) { + thread->mFullDuplexReport->info.common->socket = thread->mSock; + FAIL((!reverse_client || !(thread->mSock > 0)), "Reverse test failed to start per thread settings or socket problem", thread); + reverse_client->mSock = thread->mSock; // use the same socket for both directions + reverse_client->mThreadMode = kMode_Server; + setReverse(reverse_client); + if (isModeTime(reverse_client)) { + reverse_client->mAmount += (SLOPSECS * 100); // add 2 sec for slop on reverse, units are 10 ms + } + thread_start(reverse_client); + if (theClient->StartSynch() != -1) { + theClient->Run(); + } + } +} + +static void serverside_client_fullduplex (struct thread_Settings *thread, Client *theClient) { +#ifdef HAVE_THREAD_DEBUG + thread_debug("Launch: Listener spawn client thread (fd sock=%d)", thread->mSock); +#endif + setTransferID(thread, 1); + if (theClient->StartSynch() != -1) { + theClient->Run(); + } +} + +static void serverside_client_bidir (struct thread_Settings *thread, Client *theClient) { +#ifdef HAVE_THREAD_DEBUG + thread_debug("Launch: Listener spawn client thread (bidir sock=%d)", thread->mSock); +#endif + setTransferID(thread, 1); + SockAddr_zeroAddress(&thread->peer); + SockAddr_remoteAddr(thread); + if (thread->mReportMode == kReport_CSV) { + setNoSettReport(thread); + setNoConnReport(thread); + } else { + unsetNoSettReport(thread); + unsetNoConnReport(thread); + } + setReport(thread); + theClient->my_connect(false); + if (theClient->isConnected()) { + Iperf_push_host(thread); + if (theClient->StartSynch() != -1) { + theClient->Run(); + } + } +} + +/* + * client_spawn is responsible for creating a Client class + * and launching the client. It is provided as a means for + * the C thread subsystem to launch the client C++ object. + * + * There are a few different client startup modes + * o) Normal + * o) Dual (-d or -r) (legacy) + * o) Reverse (Client side) (client acts like server) + * o) FullDuplex (Client side) client starts server + * o) ServerReverse (Server side) (listener starts a client) + * o) FullDuplex (Server side) (listener starts server & client) + * o) WriteAck + * + * Note: This runs in client thread context + */ +void client_spawn (struct thread_Settings *thread) { + Client *theClient = NULL; + + // set traffic thread to realtime if needed +#if HAVE_SCHED_SETSCHEDULER + thread_setscheduler(thread); +#endif + // start up the client + setTransferID(thread, 0); + theClient = new Client(thread); + // let the reporter thread go first in the case of -P greater than 1 + Condition_Lock(reporter_state.await); + while (!reporter_state.ready) { + Condition_TimedWait(&reporter_state.await, 1); + } + Condition_Unlock(reporter_state.await); + + if (isConnectOnly(thread)) { + theClient->ConnectPeriodic(); + } else if (!isServerReverse(thread)) { + // These are the client side spawning of clients + if (!isReverse(thread) && !isFullDuplex(thread)) { + clientside_client_basic(thread, theClient); + } else if (isReverse(thread) && !isFullDuplex(thread)) { + struct thread_Settings *reverse_thread = NULL; + Settings_Copy(thread, &reverse_thread, DEEP_COPY); + FAIL((reverse_thread == NULL), "Reverse thread alloc failed", thread); + clientside_client_reverse(thread, reverse_thread, theClient); + } else if (isFullDuplex(thread)) { + struct thread_Settings *reverse_thread = NULL; + Settings_Copy(thread, &reverse_thread, DEEP_COPY); + FAIL((reverse_thread == NULL), "Reverse in full-duplex thread alloc failed", thread); + clientside_client_fullduplex(thread, reverse_thread, theClient); + } else { + fprintf(stdout, "Program error in client side client_spawn"); + _exit(-1); + } + } else { + if (thread->mMode != kTest_Normal) { + setCompat(thread); + // These are the server or listener side spawning of clients + serverside_client_bidir(thread, theClient); + } else { + serverside_client_fullduplex(thread, theClient); + } + } + // Call the client's destructor + DELETE_PTR(theClient); +} + +/* + * client_init handles multiple threaded connects. It creates + * a listener object if either the dual test or tradeoff were + * specified. It also creates settings structures for all the + * threads and arranges them so they can be managed and started + * via the one settings structure that was passed in. + * + * Note: This runs in main thread context + */ +void client_init(struct thread_Settings *clients) { + struct thread_Settings *itr = NULL; + struct thread_Settings *next = NULL; + + itr = clients; + setReport(clients); + // See if we need to start a listener as well + Settings_GenerateListenerSettings(clients, &next); +#ifdef HAVE_THREAD + if (next != NULL) { + // We have threads and we need to start a listener so + // have it ran before the client is launched + itr->runNow = next; + itr = next; + } + // For each of the needed threads create a copy of the + // provided settings, unsetting the report flag and add + // to the list of threads to start + for (int i = 1; i < clients->mThreads; i++) { + Settings_Copy(clients, &next, DEEP_COPY); + // printf("*****port/thread = %d/%d\n", next->mPort + i, i); + if (next) { + if (isIncrSrcIP(clients) && (clients->mLocalhost != NULL)) { + next->incrsrcip = i; + } + if (isIncrDstIP(clients)) { + next->incrdstip = i; + // force a setHostname + SockAddr_zeroAddress(&next->peer); + } else if (clients->mBindPort) { + // Increment the source port of none of the quintuple is being change or the user requests it + if ((!isIncrDstPort(clients) && !isIncrDstIP(clients) && !isIncrSrcIP(clients)) || isIncrSrcPort(clients)) { + // case -B with src port and -P > 1 + next->incrsrcport = i; + } + } + if (isIncrDstPort(clients)) { + next->mPort += i; + SockAddr_zeroAddress(&next->peer); + } + } + itr->runNow = next; + itr = next; + } + if ((isBounceBack(clients) || isConnectOnly(clients) || isPeriodicBurst(clients)) \ + && (isWorkingLoadUp(clients) || isWorkingLoadDown(clients))) { + int working_load_threads = (clients->mWorkingLoadThreads == 0) ? 1 : clients->mWorkingLoadThreads; + while (working_load_threads--) { + Settings_Copy(clients, &next, DEEP_COPY); + if (next != NULL) { + unsetBounceBack(next); + unsetConnectOnly(next); + unsetPeriodicBurst(next); + unsetTxHoldback(next); // don't delay working load threads + next->mTOS = 0; // disable any QoS on the congestion stream +#if HAVE_DECL_TCP_NOTSENT_LOWAT + next->mWritePrefetch = SMALL_WRITE_PREFETCH; + setWritePrefetch(next); +#endif + if (isWorkingLoadUp(clients) && isWorkingLoadDown(clients)) { + setFullDuplex(next); + } else if (isWorkingLoadDown(clients)) { + setReverse(next); + } + if (isBounceBack(clients) && (clients->mWorkingLoadThreads > 1)) { + Iperf_push_host(clients); + } + // Bump the bounceback time to include the delay time + if (next->txholdback_timer.tv_sec || next->txholdback_timer.tv_usec) { + // mAmount units are 10 ms + next->mAmount += (next->txholdback_timer.tv_sec * 100); + next->mAmount += (next->txholdback_timer.tv_usec / 10000); + } + itr->runNow = next; + itr = next; + } + } + } +#else + if (next != NULL) { + // We don't have threads and we need to start a listener so + // have it ran after the client is finished + itr->runNext = next; + } +#endif +} + +void listeners_init(struct thread_Settings *listener) { + struct thread_Settings *itr = listener; + struct thread_Settings *next = NULL; + for (int ix = 1; ix < (listener->mPortLast - listener->mPort + 1); ix++) { + Settings_Copy(listener, &next, DEEP_COPY); + if (next != NULL) { + setNoSettReport(next); + next->mPort = listener->mPort + ix; + next->mThreadMode = kMode_Listener; + itr->runNow = next; + itr = next; + } + } +} diff --git a/src/Listener.cpp b/src/Listener.cpp new file mode 100644 index 0000000..a517cbc --- /dev/null +++ b/src/Listener.cpp @@ -0,0 +1,1447 @@ +/*--------------------------------------------------------------- + * Copyright (c) 1999,2000,2001,2002,2003 + * The Board of Trustees of the University of Illinois + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software (Iperf) and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the names of the University of Illinois, NCSA, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * National Laboratory for Applied Network Research + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * http://www.ncsa.uiuc.edu + * ________________________________________________________________ + * + * Listener.cpp + * by Mark Gates <mgates@nlanr.net> + * & Ajay Tirumala <tirumala@ncsa.uiuc.edu> + * rewritten by Robert McMahon + * ------------------------------------------------------------------- + * Listener sets up a socket listening on the server host. For each + * connected socket that accept() returns, this creates a Server + * socket and spawns a thread for it. + * + * Changes to the latest version. Listener will run as a daemon + * Multicast Server is now Multi-threaded + * ------------------------------------------------------------------- + * headers + * uses + * <stdlib.h> + * <stdio.h> + * <string.h> + * <errno.h> + * + * <sys/types.h> + * <unistd.h> + * + * <netdb.h> + * <netinet/in.h> + * <sys/socket.h> + * ------------------------------------------------------------------- */ +#define HEADERS() + +#include "headers.h" +#include "Listener.hpp" +#include "SocketAddr.h" +#include "PerfSocket.hpp" +#include "active_hosts.h" +#include "util.h" +#include "version.h" +#include "Locale.h" +#include "SocketAddr.h" +#include "payloads.h" +#include "delay.h" + +/* ------------------------------------------------------------------- + + * Stores local hostname and socket info. + * ------------------------------------------------------------------- */ + +Listener::Listener (thread_Settings *inSettings) { + mClients = inSettings->mThreads; + ListenSocket = INVALID_SOCKET; + /* + * These thread settings are stored in three places + * + * 1) Listener thread + * 2) Reporter Thread (per the ReportSettings()) + * 3) Server thread + */ + mSettings = inSettings; +} // end Listener + +/* ------------------------------------------------------------------- + * Delete memory (buffer). + * ------------------------------------------------------------------- */ +Listener::~Listener () { +#if HAVE_THREAD_DEBUG + thread_debug("Listener destructor close sock=%d", ListenSocket); +#endif + if (ListenSocket != INVALID_SOCKET) { + int rc = close(ListenSocket); + WARN_errno(rc == SOCKET_ERROR, "listener close"); + } +} // end ~Listener + +/* ------------------------------------------------------------------- + * This is the main Listener thread loop, listens and accept new + * connections and starts traffic threads + * + * Flow is + * o) suspend on traffic done for single client case + * o) hang a select() then accept() on the listener socket + * o) read or, more accurately, peak the socket for initial messages + * o) determine and set server's settings flags + * o) instantiate new settings for listener's clients if needed + * o) instantiate and bind sum and bidir report objects as needed + * o) start the threads needed + * + * ------------------------------------------------------------------- */ +void Listener::Run () { + // mCount is set True if -P was passed to the server + int mCount = ((mSettings->mThreads != 0) ? mSettings->mThreads : -1); + + // This is a listener launched by the client per -r or -d + if (mSettings->clientListener) { + SockAddr_remoteAddr(mSettings); + } + if (!isUDP(mSettings)) { + // TCP needs just one listen + my_listen(); // This will set ListenSocket to a new sock fd + } + bool mMode_Time = isServerModeTime(mSettings) && !isDaemon(mSettings); + if (mMode_Time) { + mEndTime.setnow(); + mEndTime.add(mSettings->mAmount / 100.0); + } else if (isPermitKey(mSettings) && (mSettings->mListenerTimeout > 0)) { + mEndTime.setnow(); + mEndTime.add(mSettings->mListenerTimeout); + } + Timestamp now; +#define SINGLECLIENTDELAY_DURATION 50000 // units is microseconds + while (!sInterupted && mCount) { +#ifdef HAVE_THREAD_DEBUG + thread_debug("Listener main loop port %d ", mSettings->mPort); +#endif + now.setnow(); + if ((mMode_Time || (mSettings->mListenerTimeout > 0)) && mEndTime.before(now)) { +#ifdef HAVE_THREAD_DEBUG + thread_debug("Listener port %d (loop timer expired)", mSettings->mPort); +#endif + break; + } + // Serialize in the event the -1 option or --singleclient is set + int tc; + if ((isSingleClient(mSettings) || isMulticast(mSettings)) && \ + mCount && (tc = (thread_numtrafficthreads()) > 0)) { + // Start with a delay in the event some traffic + // threads are pending to be scheduled and haven't + // had a chance to update the traffic thread count. + // An event system between listener thread and traffic threads + // might better but also more complex. This delay + // really should be good enough unless the os scheduler sucks + delay_loop(SINGLECLIENTDELAY_DURATION); +#ifdef HAVE_THREAD_DEBUG + thread_debug("Listener single client loop mc/t/mcast/sc %d/%d/%d/%d",mCount, tc, isMulticast(mSettings), isSingleClient(mSettings)); +#endif + continue; + } + if (isUDP(mSettings)) { + // UDP needs a new listen per every new socket + my_listen(); // This will set ListenSocket to a new sock fd + } + // Use a select() with a timeout if -t is set or if this is a v1 -r or -d test + fd_set set; + if (((mMode_Time || isCompat(mSettings)) && (!isPermitKey(mSettings) && (mSettings->mAmount != 0))) \ + || (isPermitKey(mSettings) && (mSettings->mListenerTimeout != 0))) { + // Hang a select w/timeout on the listener socket + struct timeval timeout; + if (!isPermitKey(mSettings)) { + timeout.tv_sec = mSettings->mAmount / 100; + timeout.tv_usec = (mSettings->mAmount % 100) * 10000; + } else { + timeout.tv_sec = static_cast<long>(mSettings->mListenerTimeout); + timeout.tv_usec = (static_cast<long>(mSettings->mListenerTimeout) * 1000000) % 1000000; + } + if (isTxStartTime(mSettings)) { + now.setnow(); + long adjsecs = (mSettings->txstart_epoch.tv_sec - now.getSecs()); + if (adjsecs > 0) + timeout.tv_sec += adjsecs + 1; + } + FD_ZERO(&set); + FD_SET(ListenSocket, &set); + if (!(select(ListenSocket + 1, &set, NULL, NULL, &timeout) > 0)) { +#ifdef HAVE_THREAD_DEBUG + thread_debug("Listener select timeout"); +#endif + if (isCompat(mSettings)) { + fprintf(stderr, "ERROR: expected reverse connect did not occur\n"); + break; + } else + continue; + } + } + if (!setsock_blocking(mSettings->mSock, true)) { + WARN(1, "Failed setting socket to blocking mode"); + } + // Instantiate another settings object to be used by the server thread + Settings_Copy(mSettings, &server, DEEP_COPY); + FAIL(!server, "Failed memory allocation for server settings", mSettings); + server->mThreadMode = kMode_Server; + if (!isDataReport(mSettings)) + setNoDataReport(server); + + // accept a new socket and assign it to the server thread + int accept_sock = my_accept(server); + if (!(accept_sock > 0)) { + assert(server != mSettings); +#ifdef HAVE_THREAD_DEBUG + thread_debug("Listener thread accept fail %d", accept_sock); +#endif + Settings_Destroy(server); + continue; + } + +#ifdef HAVE_THREAD_DEBUG + thread_debug("Listener thread accepted server sock=%d transferID", server->mSock, server->mTransferID); +#endif + // Decrement the -P counter, commonly usd to kill the listener + // after one test, i.e. -s -P 1 + if (mCount > 0) { + mCount--; + } + // These are some exception cases where the accepted socket shouldn't have been + // accepted but the accept() was first required to figure this out + // + // 1) When a client started the listener per -d or -r (but not --reverse.) + // What's done here is to see if the server peer opening the + // socket matches the expected peer per a compare of the ip addresses + // For the case of a *client Listener* the server and host must match + // Note: it's a good idea to prefer --reverse and full duplex socket vs this + // -d,-r legacy approach. Still support it though in the name of legacy usage + // + // 2) The peer is using a V6 address but the listener/server didn't get -V (for v6) on + // it's command line + // + if ((mSettings->clientListener && SockAddr_Hostare_Equal(&mSettings->peer, &server->peer)) || \ + (!isIPV6(mSettings) && SockAddr_isIPv6(&server->peer))) { + // Not allowed, reset things and restart the loop + // Don't forget to delete the UDP entry (inserted in my_accept) + Iperf_remove_host(server); + if (!isUDP(server)) + close(server->mSock); + assert(server != mSettings); + Settings_Destroy(server); + continue; + } + // isCompat is a version 1.7 test, basically it indicates there is nothing + // in the first messages so don't try to process them. Later iperf versions use + // the first message to convey test request and test settings information. This flag + // is also used for threads that are children so-to-speak, e.g. a -d or -r client, + // which cannot have test flags otherwise there would be "test setup recursion" + // Time to read the very first packet received (per UDP) or the test flags (TCP) + // to get the client's requested test information. + // Note 1: It's important to know that this will also populate mBuf with + // enough information for the listener to perform test info exchange later in the code + // Note 2: The mBuf read is a peek so the server's traffic thread started later + // will also process the first message from an accounting perspective. + // This is required for accurate traffic statistics + if (!isCompat(server) && (isConnectOnly(server) || !apply_client_settings(server))) { + if (isConnectionReport(server) && !isSumOnly(server)) { + struct ReportHeader *reporthdr = InitConnectionReport(server); + struct ConnectionInfo *cr = static_cast<struct ConnectionInfo *>(reporthdr->this_report); + cr->connect_timestamp.tv_sec = server->accept_time.tv_sec; + cr->connect_timestamp.tv_usec = server->accept_time.tv_usec; + assert(reporthdr); + PostReport(reporthdr); + } + Iperf_remove_host(server); + close(server->mSock); + assert(server != mSettings); + Settings_Destroy(server); + continue; + } + // server settings flags should now be set per the client's first message exchange + // so the server setting's flags per the client can now be checked + if (isUDP(server)){ + if (!isCompat(mSettings) && !isTapDev(mSettings) && (isL2LengthCheck(mSettings) || isL2LengthCheck(server)) && !L2_setup(server, server->mSock)) { + // Requested L2 testing but L2 setup failed + Iperf_remove_host(server); + assert(server != mSettings); + Settings_Destroy(server); + continue; + } + } + // Force compat mode to use 64 bit seq numbers + if (isUDP(server) && isCompat(mSettings)) { + setSeqNo64b(server); + } + setTransferID(server, 0); + if ((mSettings->mReportMode == kReport_CSV) && server->mSumReport && !server->mSumReport->sum_reverse_set) { + format_ips_port_string(&server->mSumReport->info, 1); + server->mSumReport->sum_reverse_set = true; + } else if (isTripTime(server) && server->mSumReport) { + SetSumHandlers(server, server->mSumReport); // this needs to be done again after first read + } + + // Read any more test settings and test values (not just the flags) and instantiate + // any settings objects for client threads (e.g. bidir or full duplex) + // This will set the listener_client_settings to NULL if + // there is no need for the Listener to start a client + // + // Note: the packet payload pointer for this information has different + // offsets per TCP or UDP. Basically, TCP starts at byte 0 but UDP + // has to skip over the UDP seq no, etc. + // + if (!isCompat(server) && !isCompat(mSettings) && \ + (isFullDuplex(server) || isServerReverse(server) || (server->mMode != kTest_Normal))) { + thread_Settings *listener_client_settings = NULL; + // read client header for reverse settings + Settings_GenerateClientSettings(server, &listener_client_settings, server->mBuf); + if (listener_client_settings) { + if (server->mMode != kTest_Normal) + listener_client_settings->mTransferID = 0; + setTransferID(listener_client_settings, 1); + if (isFullDuplex(listener_client_settings) || isReverse(listener_client_settings)) + Iperf_push_host(listener_client_settings); + if (isFullDuplex(server)) { + assert(server->mSumReport != NULL); + if (!server->mSumReport->sum_fd_set) { + // Reset the sum output routine for the server sum report + // now that it's know to be full duplex. This wasn't known + // during accept() + SetSumHandlers(server, server->mSumReport); + server->mSumReport->sum_fd_set = 1; + } + server->mFullDuplexReport = InitSumReport(server, server->mSock, 1); + listener_client_settings->mFullDuplexReport = server->mFullDuplexReport; +#if HAVE_THREAD_DEBUG + thread_debug("FullDuplex report client=%p/%p server=%p/%p", (void *) listener_client_settings, (void *) listener_client_settings->mFullDuplexReport, (void *) server, (void *) server->mFullDuplexReport); +#endif + server->runNow = listener_client_settings; + } else if (server->mMode != kTest_Normal) { +#if HAVE_THREAD_DEBUG + thread_debug("V1 test (-d or -r) sum report client=%p/%p server=%p/%p", (void *) listener_client_settings, (void *) listener_client_settings->mFullDuplexReport, (void *) server, (void *) server->mFullDuplexReport); +#endif + if (listener_client_settings->mMode == kTest_DualTest) { +#ifdef HAVE_THREAD + server->runNow = listener_client_settings; +#else + server->runNext = listener_client_settings; +#endif + } else { + server->runNext = listener_client_settings; + } + } + } + } + setTransferID(server, 0); + if (isConnectionReport(server) && !isSumOnly(server)) { + struct ReportHeader *reporthdr = InitConnectionReport(server); + struct ConnectionInfo *cr = static_cast<struct ConnectionInfo *>(reporthdr->this_report); + cr->connect_timestamp.tv_sec = server->accept_time.tv_sec; + cr->connect_timestamp.tv_usec = server->accept_time.tv_usec; + assert(reporthdr); + PostReport(reporthdr); + } + // Now start the server side traffic threads + thread_start_all(server); + } +#ifdef HAVE_THREAD_DEBUG + thread_debug("Listener exiting port/sig/threads %d/%d/%d", mSettings->mPort, sInterupted, mCount); +#endif +} // end Run + +/* ------------------------------------------------------------------- + * Setup a socket listening on a port. + * For TCP, this calls bind() and listen(). + * For UDP, this just calls bind(). + * If inLocalhost is not null, bind to that address rather than the + * wildcard server address, specifying what incoming interface to + * accept connections on. + * ------------------------------------------------------------------- */ +void Listener::my_listen () { + int rc; + int type; + int domain; + SockAddr_localAddr(mSettings); + +#if (((HAVE_TUNTAP_TUN) || (HAVE_TUNTAP_TAP)) && (AF_PACKET)) + if (isTapDev(mSettings)) { + ListenSocket = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); + FAIL_errno(ListenSocket == SOCKET_ERROR, "tuntap socket()", mSettings); + mSettings->mSock = ListenSocket; + rc = SockAddr_v4_Accept_BPF(ListenSocket, mSettings->mPort); + WARN_errno((rc == SOCKET_ERROR), "tap accept bpf"); + SetSocketOptions(mSettings); + } else +#endif + { + // create an AF_INET socket for the accepts + // for the case of L2 testing and UDP, a new AF_PACKET + // will be created to supercede this one + type = (isUDP(mSettings) ? SOCK_DGRAM : SOCK_STREAM); + domain = (SockAddr_isIPv6(&mSettings->local) ? +#if HAVE_IPV6 + AF_INET6 +#else + AF_INET +#endif + : AF_INET); + +#ifdef WIN32 + if (SockAddr_isMulticast(&mSettings->local)) { + // Multicast on Win32 requires special handling + ListenSocket = WSASocket(domain, type, 0, 0, 0, WSA_FLAG_MULTIPOINT_C_LEAF | WSA_FLAG_MULTIPOINT_D_LEAF); + WARN_errno(ListenSocket == INVALID_SOCKET, "socket"); + + } else +#endif + { + ListenSocket = socket(domain, type, 0); + WARN_errno(ListenSocket == INVALID_SOCKET, "socket"); + } + mSettings->mSock = ListenSocket; + SetSocketOptions(mSettings); + // reuse the address, so we can run if a former server was killed off + int boolean = 1; + Socklen_t len = sizeof(boolean); + rc = setsockopt(ListenSocket, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<char*>(&boolean), len); + // bind socket to server address +#ifdef WIN32 + if (SockAddr_isMulticast(&mSettings->local)) { + // Multicast on Win32 requires special handling + rc = WSAJoinLeaf(ListenSocket, (sockaddr*) &mSettings->local, mSettings->size_local,0,0,0,0,JL_BOTH); + WARN_errno(rc == SOCKET_ERROR, "WSAJoinLeaf (aka bind)"); + } else +#endif + { + rc = bind(ListenSocket, reinterpret_cast<sockaddr*>(&mSettings->local), mSettings->size_local); + FAIL_errno(rc == SOCKET_ERROR, "listener bind", mSettings); + } + } + + // update the reporter thread + if (isReport(mSettings) && isSettingsReport(mSettings)) { + struct ReportHeader *report_settings = InitSettingsReport(mSettings); + assert(report_settings != NULL); + // disable future settings reports, listener should only do it once + unsetReport(mSettings); + PostReport(report_settings); + } + + // listen for connections (TCP only). + // use large (INT_MAX) backlog allowing multiple simultaneous connections + if (!isUDP(mSettings)) { + if (isSingleClient(mSettings)) { + rc = listen(ListenSocket, 0 + mSettings->mThreads); + } else { + rc = listen(ListenSocket, INT_MAX); + } + WARN_errno(rc == SOCKET_ERROR, "listen"); + } else { +#ifndef WIN32 + // if UDP and multicast, join the group + if (SockAddr_isMulticast(&mSettings->local)) { +#ifdef HAVE_MULTICAST + my_multicast_join(); +#else + fprintf(stderr, "Multicast not supported"); +#endif // HAVE_MULTICAST + } +#endif + } +} // end my_listen() + +/* ------------------------------------------------------------------- + * Joins the multicast group or source and group (SSM S,G) + * + * taken from: https://www.ibm.com/support/knowledgecenter/en/SSLTBW_2.1.0/com.ibm.zos.v2r1.hale001/ipv6d0141001708.htm + * + * Multicast function IPv4 IPv6 Protocol-independent + * ================== ==== ==== ==================== + * Level of specified option on setsockopt()/getsockopt() IPPROTO_IP IPPROTO_IPV6 IPPROTO_IP or IPPROTO_IPV6 + * Join a multicast group IP_ADD_MEMBERSHIP IPV6_JOIN_GROUP MCAST_JOIN_GROUP + * Leave a multicast group or leave all sources of that + * multicast group IP_DROP_MEMBERSHIP IPV6_LEAVE_GROUP MCAST_LEAVE_GROUP + * Select outbound interface for sending multicast datagrams IP_MULTICAST_IF IPV6_MULTICAST_IF NA + * Set maximum hop count IP_MULTICAST_TTL IPV6_MULTICAST_HOPS NA + * Enable multicast loopback IP_MULTICAST_LOOP IPV6_MULTICAST_LOOP NA + * Join a source multicast group IP_ADD_SOURCE_MEMBERSHIP NA MCAST_JOIN_SOURCE_GROUP + * Leave a source multicast group IP_DROP_SOURCE_MEMBERSHIP NA MCAST_LEAVE_SOURCE_GROUP + * Block data from a source to a multicast group IP_BLOCK_SOURCE NA MCAST_BLOCK_SOURCE + * Unblock a previously blocked source for a multicast group IP_UNBLOCK_SOURCE NA MCAST_UNBLOCK_SOURCE + * + * + * Reminder: The os will decide which version of IGMP or MLD to use. This may be controlled by system settings, e.g.: + * + * [rmcmahon@lvnvdb0987:~/Code/ssm/iperf2-code] $ sysctl -a | grep mld | grep force + * net.ipv6.conf.all.force_mld_version = 0 + * net.ipv6.conf.default.force_mld_version = 0 + * net.ipv6.conf.lo.force_mld_version = 0 + * net.ipv6.conf.eth0.force_mld_version = 0 + * + * [rmcmahon@lvnvdb0987:~/Code/ssm/iperf2-code] $ sysctl -a | grep igmp | grep force + * net.ipv4.conf.all.force_igmp_version = 0 + * net.ipv4.conf.default.force_igmp_version = 0 + * net.ipv4.conf.lo.force_igmp_version = 0 + * net.ipv4.conf.eth0.force_igmp_version = 0 + * + * ------------------------------------------------------------------- */ +void Listener::my_multicast_join () { + // This is the older mulitcast join code. Both SSM and binding the + // an interface requires the newer socket options. Using the older + // code here will maintain compatiblity with previous iperf versions + if (!isSSMMulticast(mSettings) && !mSettings->mIfrname) { + if (!SockAddr_isIPv6(&mSettings->local)) { + struct ip_mreq mreq; + memcpy(&mreq.imr_multiaddr, SockAddr_get_in_addr(&mSettings->local), \ + sizeof(mreq.imr_multiaddr)); + mreq.imr_interface.s_addr = htonl(INADDR_ANY); + int rc = setsockopt(ListenSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP, + reinterpret_cast<char*>(&mreq), sizeof(mreq)); + WARN_errno(rc == SOCKET_ERROR, "multicast join"); +#if HAVE_DECL_IP_MULTICAST_ALL + int mc_all = 0; + rc = setsockopt(ListenSocket, IPPROTO_IP, IP_MULTICAST_ALL, (void*) &mc_all, sizeof(mc_all)); + WARN_errno(rc == SOCKET_ERROR, "ip_multicast_all"); +#endif + } else { +#if (HAVE_IPV6 && HAVE_IPV6_MULTICAST && (HAVE_DECL_IPV6_JOIN_GROUP || HAVE_DECL_IPV6_ADD_MEMBERSHIP)) + struct ipv6_mreq mreq; + memcpy(&mreq.ipv6mr_multiaddr, SockAddr_get_in6_addr(&mSettings->local), sizeof(mreq.ipv6mr_multiaddr)); + mreq.ipv6mr_interface = 0; +#if HAVE_DECL_IPV6_JOIN_GROUP + int rc = setsockopt(ListenSocket, IPPROTO_IPV6, IPV6_JOIN_GROUP, \ + reinterpret_cast<char*>(&mreq), sizeof(mreq)); +#else + int rc = setsockopt(ListenSocket, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, \ + reinterpret_cast<char*>(&mreq), sizeof(mreq)); +#endif + FAIL_errno(rc == SOCKET_ERROR, "multicast v6 join", mSettings); +#else + fprintf(stderr, "IPv6 multicast is not supported on this platform\n"); +#endif + } + } else { + int rc; +#ifdef HAVE_SSM_MULTICAST + // Here it's either an SSM S,G multicast join or a *,G with an interface specifier + // Use the newer socket options when these are specified + socklen_t socklen = sizeof(struct sockaddr_storage); + int iface=0; +#ifdef HAVE_NET_IF_H + /* Set the interface or any */ + if (mSettings->mIfrname) { + iface = if_nametoindex(mSettings->mIfrname); + FAIL_errno(!iface, "mcast if_nametoindex",mSettings); + } else { + iface = 0; + } +#endif + + if (isIPV6(mSettings)) { +#if HAVE_IPV6_MULTICAST + if (mSettings->mSSMMulticastStr) { + struct group_source_req group_source_req; + struct sockaddr_in6 *group; + struct sockaddr_in6 *source; + + memset(&group_source_req, 0, sizeof(struct group_source_req)); + + group_source_req.gsr_interface = iface; + group=reinterpret_cast<struct sockaddr_in6*>(&group_source_req.gsr_group); + source=reinterpret_cast<struct sockaddr_in6*>(&group_source_req.gsr_source); + source->sin6_family = AF_INET6; + group->sin6_family = AF_INET6; + /* Set the group */ + rc=getsockname(ListenSocket,reinterpret_cast<struct sockaddr *>(group), &socklen); + FAIL_errno(rc == SOCKET_ERROR, "mcast join source group getsockname",mSettings); + group->sin6_port = 0; /* Ignored */ + + /* Set the source, apply the S,G */ + rc=inet_pton(AF_INET6, mSettings->mSSMMulticastStr,&source->sin6_addr); + FAIL_errno(rc != 1, "mcast v6 join source group pton",mSettings); + source->sin6_port = 0; /* Ignored */ +#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN + source->sin6_len = group->sin6_len; +#endif + rc = -1; +#if HAVE_DECL_MCAST_JOIN_SOURCE_GROUP + rc = setsockopt(ListenSocket,IPPROTO_IPV6,MCAST_JOIN_SOURCE_GROUP, reinterpret_cast<const char *>(&group_source_req), + sizeof(group_source_req)); +#endif + FAIL_errno(rc == SOCKET_ERROR, "mcast v6 join source group",mSettings); + } else { + struct group_req group_req; + struct sockaddr_in6 *group; + + memset(&group_req, 0, sizeof(struct group_req)); + + group_req.gr_interface = iface; + group=reinterpret_cast<struct sockaddr_in6*>(&group_req.gr_group); + group->sin6_family = AF_INET6; + /* Set the group */ + rc=getsockname(ListenSocket,reinterpret_cast<struct sockaddr *>(group), &socklen); + FAIL_errno(rc == SOCKET_ERROR, "mcast v6 join group getsockname",mSettings); + group->sin6_port = 0; /* Ignored */ + rc = -1; +#if HAVE_DECL_MCAST_JOIN_GROUP + rc = setsockopt(ListenSocket,IPPROTO_IPV6,MCAST_JOIN_GROUP, reinterpret_cast<const char *>(&group_req), + sizeof(group_source_req)); +#endif + FAIL_errno(rc == SOCKET_ERROR, "mcast v6 join group",mSettings); + } +#else + fprintf(stderr, "Unfortunately, IPv6 multicast is not supported on this platform\n"); +#endif + } else { + if (mSettings->mSSMMulticastStr) { + struct sockaddr_in *group; + struct sockaddr_in *source; + + // Fill out both structures because we don't which one will succeed + // and both may need to be tried +#ifdef HAVE_STRUCT_IP_MREQ_SOURCE + struct ip_mreq_source imr; + memset (&imr, 0, sizeof (imr)); +#endif +#ifdef HAVE_STRUCT_GROUP_SOURCE_REQ + struct group_source_req group_source_req; + memset(&group_source_req, 0, sizeof(struct group_source_req)); + group_source_req.gsr_interface = iface; + group=reinterpret_cast<struct sockaddr_in*>(&group_source_req.gsr_group); + source=reinterpret_cast<struct sockaddr_in*>(&group_source_req.gsr_source); +#else + struct sockaddr_in imrgroup; + struct sockaddr_in imrsource; + group = &imrgroup; + source = &imrsource; +#endif + source->sin_family = AF_INET; + group->sin_family = AF_INET; + /* Set the group */ + rc=getsockname(ListenSocket,reinterpret_cast<struct sockaddr *>(group), &socklen); + FAIL_errno(rc == SOCKET_ERROR, "mcast join source group getsockname",mSettings); + group->sin_port = 0; /* Ignored */ + + /* Set the source, apply the S,G */ + rc=inet_pton(AF_INET,mSettings->mSSMMulticastStr,&source->sin_addr); + FAIL_errno(rc != 1, "mcast join source pton",mSettings); +#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN + source->sin_len = group->sin_len; +#endif + source->sin_port = 0; /* Ignored */ + rc = -1; + +#if HAVE_DECL_MCAST_JOIN_SOURCE_GROUP + rc = setsockopt(ListenSocket,IPPROTO_IP,MCAST_JOIN_SOURCE_GROUP, reinterpret_cast<const char *>(&group_source_req), + sizeof(group_source_req)); +#endif + +#if HAVE_DECL_IP_ADD_SOURCE_MEMBERSHIP +#ifdef HAVE_STRUCT_IP_MREQ_SOURCE + // Some operating systems will have MCAST_JOIN_SOURCE_GROUP but still fail + // In those cases try the IP_ADD_SOURCE_MEMBERSHIP + if (rc < 0) { +#ifdef HAVE_STRUCT_IP_MREQ_SOURCE_IMR_MULTIADDR_S_ADDR + imr.imr_multiaddr = ((const struct sockaddr_in *)group)->sin_addr; + imr.imr_sourceaddr = ((const struct sockaddr_in *)source)->sin_addr; +#else + // Some Android versions declare mreq_source without an s_addr + imr.imr_multiaddr = ((const struct sockaddr_in *)group)->sin_addr.s_addr; + imr.imr_sourceaddr = ((const struct sockaddr_in *)source)->sin_addr.s_addr; +#endif + rc = setsockopt (ListenSocket, IPPROTO_IP, IP_ADD_SOURCE_MEMBERSHIP, reinterpret_cast<char*>(&imr), sizeof (imr)); + } +#endif +#endif + FAIL_errno(rc == SOCKET_ERROR, "mcast join source group",mSettings); + } else { + struct group_req group_req; + struct sockaddr_in *group; + + memset(&group_req, 0, sizeof(struct group_req)); + + group_req.gr_interface = iface; + group=reinterpret_cast<struct sockaddr_in*>(&group_req.gr_group); + group->sin_family = AF_INET; + /* Set the group */ + rc=getsockname(ListenSocket,reinterpret_cast<struct sockaddr *>(group), &socklen); + FAIL_errno(rc == SOCKET_ERROR, "mcast join group getsockname",mSettings); + group->sin_port = 0; /* Ignored */ + rc = -1; +#if HAVE_DECL_MCAST_JOIN_GROUP + rc = setsockopt(ListenSocket,IPPROTO_IP,MCAST_JOIN_GROUP, reinterpret_cast<const char *>(&group_req), + sizeof(group_source_req)); +#endif + FAIL_errno(rc == SOCKET_ERROR, "mcast join group",mSettings); + } + } + +#else + fprintf(stderr, "Unfortunately, SSM is not supported on this platform\n"); + exit(-1); +#endif + } +} +// end my_multicast_join() + +bool Listener::L2_setup (thread_Settings *server, int sockfd) { +#if defined(HAVE_LINUX_FILTER_H) && defined(HAVE_AF_PACKET) + // + // Supporting parallel L2 UDP threads is a bit tricky. Below are some notes as to why and the approach used. + // + // The primary issues for UDP are: + // + // 1) We want the listener thread to hand off the flow to a server thread and not be burdened by that flow + // 2) For -P support, the listener thread neads to detect new flows which will share the same UDP port + // and UDP is stateless + // + // The listener thread needs to detect new traffic flows and hand them to a new server thread, and then + // rehang a listen/accept. For standard iperf the "flow routing" is done using connect() per the ip quintuple. + // The OS will then route established connected flows to the socket descriptor handled by a server thread and won't + // burden the listener thread with these packets. + // + // For L2 verification, we have to create a two sockets that will exist for the life of the flow. A + // new packet socket (AF_PACKET) will receive L2 frames and bypasses + // the OS network stack. The original AF_INET socket will still send up packets + // to the network stack. + // + // When using packet sockets there is inherent packet duplication, the hand off to a server + // thread is not so straight forward as packets will continue being sent up to the listener thread + // (technical problem is that packet sockets do not support connect() which binds the IP quintuple as the + // forwarding key) Since the Listener uses recvfrom(), there is no OS mechanism to detect new flows nor + // to drop packets. The listener can't listen on quintuple based connected flows because the client's source + // port is unknown. Therefore the Listener thread will continue to receive packets from all established + // flows sharing the same dst port which will impact CPU utilization and hence performance. + // + // The technique used to address this is to open an AF_PACKET socket and leave the AF_INET socket open. + // (This also aligns with BSD based systems) The original AF_INET socket will remain in the (connected) + // state so the network stack has it's connected state. A cBPF is then used to cause the kernel to fast drop + // those packets. A cBPF is set up to drop such packets. The test traffic will then only come over the + // packet (raw) socket and not the AF_INET socket. If we were to try to close the original AF_INET socket + // (vs leave it open w/the fast drop cBPF) then the existing traffic will be sent up by the network stack + // to he Listener thread, flooding it with packets, again something we want to avoid. + // + // On the packet (raw) socket itself, we do two more things to better handle performance + // + // 1) Use a full quintuple cBPF allowing the kernel to filter packets (allow) per the quintuple + // 2) Use the packet fanout option to assign a CBPF to a socket and hence to a single server thread minimizing + // duplication (reduce all cBPF's filtering load) + // + struct sockaddr *p = reinterpret_cast<sockaddr *>(&server->peer); + struct sockaddr *l = reinterpret_cast<sockaddr *>(&server->local); + int rc = 0; + + // + // Establish a packet (raw) socket to be used by the server thread giving it full L2 packets + // + struct sockaddr s; + socklen_t len = sizeof(s); + getpeername(sockfd, &s, &len); + if (isIPV6(server)) { + server->mSock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_IPV6)); + WARN_errno(server->mSock == INVALID_SOCKET, "ip6 packet socket (AF_PACKET)"); + server->l4offset = IPV6HDRLEN + sizeof(struct ether_header); + } else { + server->mSock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_IP)); + WARN_errno(server->mSock == INVALID_SOCKET, "ip packet socket (AF_PACKET)"); + unsetIPV6(server); + server->l4offset = sizeof(struct iphdr) + sizeof(struct ether_header); + } + // Didn't get a valid socket, return now + if (server->mSock < 0) { + return false; + } + // More per thread settings based on using a packet socket + server->l4payloadoffset = server->l4offset + sizeof(struct udphdr); + server->recvflags = MSG_TRUNC; + // The original AF_INET socket only exists to keep the connected state + // in the OS for this flow. Fast drop packets there as + // now packets will use the AF_PACKET (raw) socket + // Also, store the original AF_INET socket descriptor so it can be + // closed in the Server's destructor. (Note: closing the + // socket descriptors will also free the cBPF.) + // + server->mSockDrop = sockfd; + rc = SockAddr_Drop_All_BPF(sockfd); + WARN_errno(rc == SOCKET_ERROR, "l2 all drop bpf"); + + // Now optimize packet flow up the raw socket + // Establish the flow BPF to forward up only "connected" packets to this raw socket + if (l->sa_family == AF_INET6) { +#if HAVE_IPV6 + struct in6_addr *v6peer = SockAddr_get_in6_addr(&server->peer); + struct in6_addr *v6local = SockAddr_get_in6_addr(&server->local); + if (isIPV6(server)) { + rc = SockAddr_v6_Connect_BPF(server->mSock, v6local, v6peer, (reinterpret_cast<struct sockaddr_in6 *>(l))->sin6_port, (reinterpret_cast<struct sockaddr_in6 *>(p))->sin6_port); + WARN_errno(rc == SOCKET_ERROR, "l2 connect ipv6 bpf"); + } else { + // This is an ipv4 address in a v6 family (structure), just pull the lower 32 bits for the v4 addr + rc = SockAddr_v4_Connect_BPF(server->mSock, v6local->s6_addr32[3], v6peer->s6_addr32[3], (reinterpret_cast<struct sockaddr_in6 *>(l))->sin6_port, (reinterpret_cast<struct sockaddr_in6 *>(p))->sin6_port); + WARN_errno(rc == SOCKET_ERROR, "l2 v4in6 connect ip bpf"); + } +#else + fprintf(stderr, "Unfortunately, IPv6 is not supported on this platform\n"); + return false; +#endif /* HAVE_IPV6 */ + } else { + rc = SockAddr_v4_Connect_BPF(server->mSock, (reinterpret_cast<struct sockaddr_in *>(l))->sin_addr.s_addr, (reinterpret_cast<struct sockaddr_in *>(p))->sin_addr.s_addr, (reinterpret_cast<struct sockaddr_in *>(l))->sin_port, (reinterpret_cast<struct sockaddr_in *>(p))->sin_port); + WARN_errno(rc == SOCKET_ERROR, "l2 connect ip bpf"); + } + return rc >= 0; +#else + fprintf(stderr, "Client requested --l2checks but not supported on this platform\n"); + return false; +#endif +} + +bool Listener::tap_setup (thread_Settings *server, int sockfd) { +#if defined(HAVE_IF_TUNTAP) && defined(HAVE_AF_PACKET) && defined(HAVE_DECL_SO_BINDTODEVICE) + struct sockaddr *p = reinterpret_cast<sockaddr *>(&server->peer); + struct sockaddr *l = reinterpret_cast<sockaddr *>(&server->local); + int rc = 0; + + // + // Establish a packet (raw) socket to be used by the server thread giving it full L2 packets + // + struct sockaddr s; + socklen_t len = sizeof(s); + getpeername(sockfd, &s, &len); + if (isIPV6(server)) { + server->l4offset = IPV6HDRLEN + sizeof(struct ether_header); + } else { + server->l4offset = sizeof(struct iphdr) + sizeof(struct ether_header); + } + // Didn't get a valid socket, return now + if (server->mSock < 0) { + return false; + } + // More per thread settings based on using a packet socket + server->l4payloadoffset = server->l4offset + sizeof(struct udphdr); + server->recvflags = MSG_TRUNC; + // Now optimize packet flow up the raw socket + // Establish the flow BPF to forward up only "connected" packets to this raw socket + if (l->sa_family == AF_INET6) { +#if HAVE_IPV6 + struct in6_addr *v6peer = SockAddr_get_in6_addr(&server->peer); + struct in6_addr *v6local = SockAddr_get_in6_addr(&server->local); + if (isIPV6(server)) { + rc = SockAddr_v6_Connect_BPF(server->mSock, v6local, v6peer, (reinterpret_cast<struct sockaddr_in6 *>(l))->sin6_port, (reinterpret_cast<struct sockaddr_in6 *>(p))->sin6_port); + WARN_errno(rc == SOCKET_ERROR, "l2 connect ipv6 bpf"); + } else { + // This is an ipv4 address in a v6 family (structure), just pull the lower 32 bits for the v4 addr + rc = SockAddr_v4_Connect_BPF(server->mSock, v6local->s6_addr32[3], v6peer->s6_addr32[3], (reinterpret_cast<struct sockaddr_in6 *>(l))->sin6_port, (reinterpret_cast<struct sockaddr_in6 *>(p))->sin6_port); + WARN_errno(rc == SOCKET_ERROR, "l2 v4in6 connect ip bpf"); + } +#else + fprintf(stderr, "Unfortunately, IPv6 is not supported on this platform\n"); + return false; +#endif /* HAVE_IPV6 */ + } else { + rc = SockAddr_v4_Connect_BPF(server->mSock, (reinterpret_cast<struct sockaddr_in *>(l))->sin_addr.s_addr, (reinterpret_cast<struct sockaddr_in *>(p))->sin_addr.s_addr, (reinterpret_cast<struct sockaddr_in *>(l))->sin_port, (reinterpret_cast<struct sockaddr_in *>(p))->sin_port); + WARN_errno(rc == SOCKET_ERROR, "l2 connect ip bpf"); + } + return rc >= 0; +#else + fprintf(stderr, "Client requested --l2checks but not supported on this platform\n"); + return false; +#endif +} + +/* ------------------------------------------------------------------------ + * Do the equivalent of an accept() call for UDP sockets. This checks + * a listening UDP socket for new or first received datagram + * ------------------------------------------------------------------- ----*/ +int Listener::udp_accept (thread_Settings *server) { + assert(server != NULL); + int nread = 0; + assert(ListenSocket > 0); + // Preset the server socket to INVALID, hang recvfrom on the Listener's socket + // The INVALID socket is used to keep the while loop going + server->mSock = INVALID_SOCKET; + intmax_t packetID; + struct UDP_datagram* mBuf_UDP = reinterpret_cast<struct UDP_datagram*>(server->mBuf); + // Look for a UDP packet with a postive seq no while draining any neg seq no packets + // The UDP client traffic thread uses negative seq numbers to indicate to the server that + // traffic is over. Some of those "final" packets can be in the stack/network pipeline after the server + // thread has ended and closed its reporting. The Listener will now receive them as if they are + // "first packets. Any "new" packets seen by the Listener causes a new "udp accept" + // per UDP's stateless design. So, in the case of negative seq nos, we know that this is + // most likely not a new client thread requiring a new server thread, but remnants of an + // old one that already ended. Hence, the Listener should ignore "first packets" when + // they have negative seq numbers. + do { + packetID = 0; + nread = recvfrom(ListenSocket, server->mBuf, server->mBufLen, 0, \ + reinterpret_cast<struct sockaddr*>(&server->peer), &server->size_peer); + if (nread > 0) { + // filter and ignore negative sequence numbers, these can be heldover from a previous run + if (isSeqNo64b(mSettings)) { + // New client - Signed PacketID packed into unsigned id2,id + packetID = (static_cast<uint32_t>(ntohl(mBuf_UDP->id))) | (static_cast<uintmax_t>(ntohl(mBuf_UDP->id2)) << 32); + } else { + // Old client - Signed PacketID in Signed id + packetID = static_cast<int32_t>(ntohl(mBuf_UDP->id)); + } + } + } while ((nread > 0) && (packetID < 0) && !sInterupted); + FAIL_errno(nread == SOCKET_ERROR, "recvfrom", mSettings); + if ((nread > 0) && !sInterupted) { + Timestamp now; + server->accept_time.tv_sec = now.getSecs(); + server->accept_time.tv_usec = now.getUsecs(); +#if HAVE_THREAD_DEBUG + { + char tmpaddr[200]; + size_t len=200; + unsigned short port = SockAddr_getPort(&server->peer); + SockAddr_getHostAddress(&server->peer, tmpaddr, len); + thread_debug("rcvfrom peer: %s port %d len=%d", tmpaddr, port, nread); + } +#endif + // Handle connection for UDP sockets + int gid = Iperf_push_host_port_conditional(server); +#if HAVE_THREAD_DEBUG + if (gid < 0) + thread_debug("rcvfrom peer: drop duplicate"); +#endif + if (gid > 0) { + int rc; + // We have a new UDP flow (based upon key of quintuple) + // so let's hand off this socket + // to the server and create a new listener socket + server->mSock = ListenSocket; + ListenSocket = INVALID_SOCKET; + // This connect() will allow the OS to only + // send packets with the ip quintuple up to the server + // socket and, hence, to the server thread (yet to be created) + // This connect() routing is only supported with AF_INET or AF_INET6 sockets, + // e.g. AF_PACKET sockets can't do this. We'll handle packet sockets later + // All UDP accepts here will use AF_INET. This is intentional and needed + rc = connect(server->mSock, reinterpret_cast<struct sockaddr*>(&server->peer), server->size_peer); + FAIL_errno(rc == SOCKET_ERROR, "connect UDP", mSettings); + server->size_local = sizeof(iperf_sockaddr); + getsockname(server->mSock, reinterpret_cast<sockaddr*>(&server->local), &server->size_local); + SockAddr_Ifrname(server); + server->firstreadbytes = nread; + } + } + return server->mSock; +} + + +#if (((HAVE_TUNTAP_TUN) || (HAVE_TUNTAP_TAP)) && (AF_PACKET)) +int Listener::tuntap_accept(thread_Settings *server) { + int rc = recv(server->mSock, server->mBuf, (server->mBufLen + TAPBYTESSLOP + sizeof(struct iphdr) + sizeof(struct ether_header) + sizeof(struct udphdr)), 0); + if (rc <= 0) + return 0; +// rc = udpchecksum((void *)ip_hdr, (void *)udp_hdr, udplen, (isIPV6(mSettings) ? 1 : 0)); + struct iphdr *l3hdr = (struct iphdr *)((char *)server->mBuf + sizeof(struct ether_header)); + struct udphdr *l4hdr = (struct udphdr *)((char *)server->mBuf + sizeof(struct iphdr) + sizeof(struct ether_header)); +// uint16_t ipver = (uint16_t) ntohs(mBuf + sizeof(struct ether_header)); +// printf ("*** version = %d\n", ipver); + // Note: sockaddrs are stored in network bytes order + struct sockaddr_in *local = (struct sockaddr_in *) &server->local; + struct sockaddr_in *peer = (struct sockaddr_in *) &server->peer; + server->size_peer = sizeof(iperf_sockaddr); + server->size_local = sizeof(iperf_sockaddr); + peer->sin_family = AF_INET; + local->sin_family = AF_INET; + peer->sin_addr.s_addr = l3hdr->saddr; + local->sin_addr.s_addr = l3hdr->daddr; + peer->sin_port = l4hdr->source; + local->sin_port = l4hdr->dest; + server->l4offset = sizeof(struct iphdr) + sizeof(struct ether_header); + SockAddr_v4_Connect_TAP_BPF(server->mSock, local->sin_addr.s_addr, peer->sin_addr.s_addr, local->sin_port, peer->sin_port); + server->l4payloadoffset = sizeof(struct iphdr) + sizeof(struct ether_header) + sizeof(struct udphdr); + server->firstreadbytes = rc; + return server->mSock; +} +#endif +/* ------------------------------------------------------------------- + * This is called by the Listener thread main loop, return a socket or error + * ------------------------------------------------------------------- */ +int Listener::my_accept (thread_Settings *server) { + assert(server != NULL); +#ifdef HAVE_THREAD_DEBUG + if (isUDP(server)) { + thread_debug("Listener thread listening for UDP (sock=%d)", ListenSocket); + } else { + thread_debug("Listener thread listening for TCP (sock=%d)", ListenSocket); + } +#endif + SockAddr_zeroAddress(&server->peer); + server->size_peer = sizeof(iperf_sockaddr); + server->accept_time.tv_sec = 0; + server->accept_time.tv_usec = 0; + if (isUDP(server)) { +#if (((HAVE_TUNTAP_TUN) || (HAVE_TUNTAP_TAP)) && (AF_PACKET)) + if (isTapDev(server) || isTunDev(server)) { + server->mSock = tuntap_accept(server); + } else +#endif + { + server->mSock = udp_accept(server); + } + // note udp_accept will update the active host table + } else { + // accept a TCP connection + server->mSock = accept(ListenSocket, reinterpret_cast<sockaddr*>(&server->peer), &server->size_peer); + if (server->mSock > 0) { + Timestamp now; + server->accept_time.tv_sec = now.getSecs(); + server->accept_time.tv_usec = now.getUsecs(); + server->size_local = sizeof(iperf_sockaddr); + getsockname(server->mSock, reinterpret_cast<sockaddr*>(&server->local), &server->size_local); + SockAddr_Ifrname(server); + Iperf_push_host(server); + } + } + return server->mSock; +} // end my_accept + +// Read deep enough into the packet to get the client settings +// Read the headers but don't pull them from the queue in order to +// preserve server thread accounting, i.e. these exchanges will +// be part of traffic accounting. Return false if it's determined +// this traffic shouldn't be accepted for a test run +// Description of bits and fields is in include/payloads.h +bool Listener::apply_client_settings (thread_Settings *server) { + assert(server != NULL); + bool rc = false; + + // Set the receive timeout for the very first read + int sorcvtimer = TESTEXCHANGETIMEOUT; // 4 sec in usecs + SetSocketOptionsReceiveTimeout(server, sorcvtimer); + server->peer_version_u = 0; + server->peer_version_l = 0; + server->mMode = kTest_Normal; + + if (isUDP(server)) { + rc = apply_client_settings_udp(server); + } else if (!isConnectOnly(server)) { + rc = apply_client_settings_tcp(server); + } + if (isOverrideTOS(server)) { + SetSocketOptionsIPTos(server, server->mRTOS); + } else if (server->mTOS) { + SetSocketOptionsIPTos(server, server->mTOS); + } + return rc; +} + +inline bool Listener::test_permit_key(uint32_t flags, thread_Settings *server, int keyoffset) { + if (!(flags & HEADER_KEYCHECK)) { + server->mKeyCheck= false; + return false; + } + struct permitKey *thiskey = reinterpret_cast<struct permitKey *>(server->mBuf + (keyoffset - sizeof(thiskey->length))); + int keylen = ntohs(thiskey->length); + if ((keylen < MIN_PERMITKEY_LEN) || (keylen > MAX_PERMITKEY_LEN)) { + server->mKeyCheck= false; +// fprintf(stderr, "REJECT: key length bounds error (%d)\n", keylen); + return false; + } + if (keylen != static_cast<int>(strlen(server->mPermitKey))) { + server->mKeyCheck= false; +// fprintf(stderr, "REJECT: key length mismatch (%d!=%d)\n", keylen, (int) strlen(server->mPermitKey)); + return false; + } + if (!isUDP(server)) { + int nread = 0; + nread = recvn(server->mSock, reinterpret_cast<char *>(&thiskey->value), keylen, 0); + FAIL_errno((nread < keylen), "read key", server); + } + strncpy(server->mPermitKey, thiskey->value, MAX_PERMITKEY_LEN + 1); + if (strncmp(server->mPermitKey, mSettings->mPermitKey, keylen) != 0) { + server->mKeyCheck= false; +// fprintf(stderr, "REJECT: key value mismatch per %s\n", thiskey->value); + return false; + } + server->mKeyCheck= true; + return true; +} + +bool Listener::apply_client_settings_udp (thread_Settings *server) { + struct client_udp_testhdr *hdr = reinterpret_cast<struct client_udp_testhdr *>(server->mBuf + server->l4payloadoffset); + uint32_t flags = ntohl(hdr->base.flags); + uint16_t upperflags = 0; + if (flags & HEADER_SEQNO64B) { + setSeqNo64b(server); + } +#if HAVE_THREAD_DEBUG + thread_debug("UDP test flags = %X", flags); +#endif + if (flags & HEADER32_SMALL_TRIPTIMES) { +#if HAVE_THREAD_DEBUG + thread_debug("UDP small header"); +#endif + server->sent_time.tv_sec = ntohl(hdr->seqno_ts.tv_sec); + server->sent_time.tv_usec = ntohl(hdr->seqno_ts.tv_usec); + uint32_t seqno = ntohl(hdr->seqno_ts.id); + if (seqno != 1) { + fprintf(stderr, "WARN: first received packet (id=%d) was not first sent packet, report start time will be off\n", seqno); + } + Timestamp now; + if (!isTxStartTime(server) && ((abs(now.getSecs() - server->sent_time.tv_sec)) > (MAXDIFFTIMESTAMPSECS + 1))) { + fprintf(stdout,"WARN: ignore --trip-times because client didn't provide valid start timestamp within %d seconds of now\n", MAXDIFFTIMESTAMPSECS); + unsetTripTime(server); + } else { + setTripTime(server); + } + setEnhanced(server); + } else if ((flags & HEADER_VERSION1) || (flags & HEADER_VERSION2) || (flags & HEADER_EXTEND)) { + if ((flags & HEADER_VERSION1) && !(flags & HEADER_VERSION2)) { + if (flags & RUN_NOW) + server->mMode = kTest_DualTest; + else + server->mMode = kTest_TradeOff; + } + if (flags & HEADER_EXTEND) { + upperflags = htons(hdr->extend.upperflags); + server->mTOS = ntohs(hdr->extend.tos); + server->peer_version_u = ntohl(hdr->extend.version_u); + server->peer_version_l = ntohl(hdr->extend.version_l); + if (flags & HEADER_UDPTESTS) { + // Handle stateless flags + if (upperflags & HEADER_ISOCH) { + setIsochronous(server); + } + if (upperflags & HEADER_L2ETHPIPV6) { + setIPV6(server); + } else { + unsetIPV6(server); + } + if (upperflags & HEADER_L2LENCHECK) { + setL2LengthCheck(server); + } + if (upperflags & HEADER_NOUDPFIN) { + setNoUDPfin(server); + } + } + if (upperflags & HEADER_EPOCH_START) { + server->txstart_epoch.tv_sec = ntohl(hdr->start_fq.start_tv_sec); + server->txstart_epoch.tv_usec = ntohl(hdr->start_fq.start_tv_usec); + Timestamp now; + if ((abs(now.getSecs() - server->txstart_epoch.tv_sec)) > (MAXDIFFTXSTART + 1)) { + fprintf(stdout,"WARN: ignore --txstart-time because client didn't provide valid start timestamp within %d seconds of now\n", MAXDIFFTXSTART); + unsetTxStartTime(server); + } else { + setTxStartTime(server); + } + } + if (upperflags & HEADER_TRIPTIME) { + server->sent_time.tv_sec = ntohl(hdr->start_fq.start_tv_sec); + server->sent_time.tv_usec = ntohl(hdr->start_fq.start_tv_usec); + Timestamp now; + if (!isTxStartTime(server) && ((abs(now.getSecs() - server->sent_time.tv_sec)) > (MAXDIFFTIMESTAMPSECS + 1))) { + fprintf(stdout,"WARN: ignore --trip-times because client didn't provide valid start timestamp within %d seconds of now\n", MAXDIFFTIMESTAMPSECS); + unsetTripTime(server); + } else { + setTripTime(server); + setEnhanced(server); + } + } + } + if (flags & HEADER_VERSION2) { + upperflags = htons(hdr->extend.upperflags); + if (upperflags & HEADER_FULLDUPLEX) { + setFullDuplex(server); + setServerReverse(server); + } + if (upperflags & HEADER_REVERSE) { + server->mThreadMode=kMode_Client; + setServerReverse(server); + if (server->mSumReport != NULL) { + server->mSumReport->info.common->ThreadMode=kMode_Client; + setServerReverse(server->mSumReport->info.common); + } + setNoUDPfin(server); + unsetReport(server); + } + } + } + return true; +} +bool Listener::apply_client_settings_tcp (thread_Settings *server) { + bool rc = false; +#if HAVE_TCP_STATS + if (!isUDP(mSettings)) { + gettcpinfo(server->mSock, &server->tcpinitstats); + } +#endif + int nread = recvn(server->mSock, server->mBuf, sizeof(uint32_t), 0); + char *readptr = server->mBuf; + if (nread == 0) { + //peer closed the socket, with no writes e.g. a connect-only test + WARN(1, "read tcp flags (peer close)"); + goto DONE; + } + if (nread < (int) sizeof(uint32_t)) { + WARN(1, "read tcp flags (runt)"); + goto DONE; + } else { + rc = true; + readptr += nread; + struct client_tcp_testhdr *hdr = reinterpret_cast<struct client_tcp_testhdr *>(server->mBuf); + uint32_t flags = ntohl(hdr->base.flags); + if (flags & HEADER_BOUNCEBACK) { + if (!isServerModeTime(server)) { + unsetModeTime(server); + } + struct bounceback_hdr *bbhdr = reinterpret_cast<struct bounceback_hdr *>(server->mBuf); + setBounceBack(server); + nread = recvn(server->mSock, readptr, sizeof(struct bounceback_hdr), 0); + if (nread != sizeof(struct bounceback_hdr)) { + WARN(1, "read bounce back header failed"); + rc = false; + goto DONE; + } + readptr += nread; + server->mBounceBackBytes = ntohl(bbhdr->bbsize); + server->mBounceBackHold = ntohl(bbhdr->bbhold); + uint16_t bbflags = ntohs(bbhdr->bbflags); + if (bbflags & HEADER_BBCLOCKSYNCED) { + setTripTime(server); + server->sent_time.tv_sec = ntohl(bbhdr->bbclientTx_ts.sec); + server->sent_time.tv_usec = ntohl(bbhdr->bbclientTx_ts.usec); + } + if (bbflags & HEADER_BBTOS) { + server->mTOS = ntohs(bbhdr->tos); + } +#if HAVE_DECL_TCP_QUICKACK + if (bbflags & HEADER_BBQUICKACK) { + setTcpQuickAck(server); + } +#endif + int remaining = server->mBounceBackBytes - (sizeof(struct bounceback_hdr) + sizeof(uint32_t)); + if (remaining < 0) { + WARN(1, "bounce back bytes too small"); + rc = false; + goto DONE; + } else if (remaining > 0) { + nread = recvn(server->mSock, readptr, remaining, 0); + if (nread != remaining) { + WARN(1, "read bounce back payload failed"); + rc = false; + goto DONE; + } + } + Timestamp now; + bbhdr->bbserverRx_ts.sec = htonl(now.getSecs()); + bbhdr->bbserverRx_ts.usec = htonl(now.getUsecs()); + } else { + uint16_t upperflags = 0; + int readlen; + // figure out the length of the test header + if ((readlen = Settings_ClientTestHdrLen(flags, server)) > 0) { + // read the test settings passed to the server by the client + nread += recvn(server->mSock, readptr, (readlen - (int) sizeof(uint32_t)), 0); + FAIL_errno((nread < readlen), "read tcp test info", server); + if (isPermitKey(mSettings)) { + if (!test_permit_key(flags, server, readlen)) { + rc = false; + goto DONE; + } + } else if (flags & HEADER_KEYCHECK) { + rc = false; + server->mKeyCheck = false; + goto DONE; + } + server->firstreadbytes = nread; + struct client_tcp_testhdr *hdr = reinterpret_cast<struct client_tcp_testhdr*>(server->mBuf); + if ((flags & HEADER_VERSION1) && !(flags & HEADER_VERSION2)) { + if (flags & RUN_NOW) + server->mMode = kTest_DualTest; + else + server->mMode = kTest_TradeOff; + } + if (flags & HEADER_EXTEND) { + upperflags = htons(hdr->extend.upperflags); + server->mTOS = ntohs(hdr->extend.tos); + server->peer_version_u = ntohl(hdr->extend.version_u); + server->peer_version_l = ntohl(hdr->extend.version_l); + if (upperflags & HEADER_ISOCH) { + setIsochronous(server); + } + if (upperflags & HEADER_EPOCH_START) { + server->txstart_epoch.tv_sec = ntohl(hdr->start_fq.start_tv_sec); + server->txstart_epoch.tv_usec = ntohl(hdr->start_fq.start_tv_usec); + Timestamp now; + if ((abs(now.getSecs() - server->txstart_epoch.tv_sec)) > (MAXDIFFTXSTART + 1)) { + fprintf(stdout,"WARN: ignore --txstart-time because client didn't provide valid start timestamp within %d seconds of now\n", MAXDIFFTXSTART); + unsetTxStartTime(server); + } else { + setTxStartTime(server); + } + } + if (upperflags & HEADER_TRIPTIME) { + Timestamp now; + server->sent_time.tv_sec = ntohl(hdr->start_fq.start_tv_sec); + server->sent_time.tv_usec = ntohl(hdr->start_fq.start_tv_usec); + if (!isTxStartTime(server) && ((abs(now.getSecs() - server->sent_time.tv_sec)) > (MAXDIFFTIMESTAMPSECS + 1))) { + fprintf(stdout,"WARN: ignore --trip-times because client didn't provide valid start timestamp within %d seconds of now\n", MAXDIFFTIMESTAMPSECS); + unsetTripTime(server); + } else { + setTripTime(server); + setEnhanced(server); + } + } + if (upperflags & HEADER_PERIODICBURST) { + setEnhanced(server); + setFrameInterval(server); + setPeriodicBurst(server); + { + struct client_tcp_testhdr *hdr = reinterpret_cast<struct client_tcp_testhdr *>(server->mBuf); + server->mFPS = ntohl(hdr->isoch_settings.FPSl); + server->mFPS += ntohl(hdr->isoch_settings.FPSu) / static_cast<double>(rMillion); + } + if (!server->mFPS) { + server->mFPS = 1.0; + } + } + if (flags & HEADER_VERSION2) { + if (upperflags & HEADER_FULLDUPLEX) { + setFullDuplex(server); + setServerReverse(server); + } + if (upperflags & HEADER_REVERSE) { + server->mThreadMode=kMode_Client; + setServerReverse(server); + if (server->mSumReport != NULL) { + server->mSumReport->info.common->ThreadMode=kMode_Client; + setServerReverse(server->mSumReport->info.common); + } + } + } +#if HAVE_DECL_TCP_NOTSENT_LOWAT + if ((isServerReverse(server) || isFullDuplex(server)) && (upperflags & HEADER_WRITEPREFETCH)) { + server->mWritePrefetch = ntohl(hdr->extend.TCPWritePrefetch); + if (server->mWritePrefetch > 0) { + setWritePrefetch(server); + } + } +#endif +#if HAVE_DECL_TCP_QUICKACK + if (upperflags & HEADER_TCPQUICKACK) { + setTcpQuickAck(server); + } +#endif + if (upperflags & HEADER_BOUNCEBACK) { + setBounceBack(server); + } + } + } + } + // Handle case that requires an ack back to the client + // Signaled by not UDP (only supported by TCP) + // and either 2.0.13 flags or the newer 2.0.14 flag of + // V2PEERDETECT + if (!isUDP(server) && !isCompat(mSettings) && \ + ((!(flags & HEADER_VERSION2) && (flags & HEADER_EXTEND)) || \ + (flags & HEADER_V2PEERDETECT))) { + client_test_ack(server); + } + } + DONE: + return rc; +} + +int Listener::client_test_ack(thread_Settings *server) { + if (isUDP(server)) + return 1; + + client_hdr_ack ack; + int sotimer = 0; + int size = sizeof(struct client_hdr_ack); + ack.typelen.type = htonl(CLIENTHDRACK); + + ack.flags = 0; + ack.reserved1 = 0; + ack.reserved2 = 0; + ack.version_u = htonl(IPERF_VERSION_MAJORHEX); + ack.version_l = htonl(IPERF_VERSION_MINORHEX); + if (isTripTime(server)) { + ack.ts.sent_tv_sec = htonl(server->sent_time.tv_sec); + ack.ts.sent_tv_usec = htonl(server->sent_time.tv_usec); + ack.ts.sentrx_tv_sec = htonl(server->accept_time.tv_sec); + ack.ts.sentrx_tv_usec = htonl(server->accept_time.tv_usec); + Timestamp now; + ack.ts.ack_tv_sec = htonl(now.getSecs()); + ack.ts.ack_tv_usec = htonl(now.getUsecs()); + } else { + size -= sizeof (struct client_hdr_ack_ts); + } + ack.typelen.length = htonl(size); + int rc = 1; + // This is a version 2.0.10 or greater client + // write back to the client so it knows the server + // version + + // sotimer units microseconds convert + if (server->mInterval) { + sotimer = static_cast<int>((server->mInterval) / 4); + } else if (isModeTime(server)) { + sotimer = static_cast<int>((server->mAmount * 10000) / 4); + } + if (sotimer > HDRXACKMAX) { + sotimer = HDRXACKMAX; + } else if (sotimer < HDRXACKMIN) { + sotimer = HDRXACKMIN; + } + SetSocketOptionsSendTimeout(server, sotimer); +#if HAVE_DECL_TCP_NODELAY + int optflag = 1; + // Disable Nagle to reduce latency of this intial message + if ((rc = setsockopt(server->mSock, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char *>(&optflag), sizeof(int))) < 0) { + WARN_errno(rc < 0, "tcpnodelay"); + } +#endif + if ((rc = send(server->mSock, reinterpret_cast<const char*>(&ack), size, 0)) < 0) { + WARN_errno(rc <= 0, "send_ack"); + rc = 0; + } +#if HAVE_DECL_TCP_NODELAY + // Re-nable Nagle + optflag = isNoDelay(server) ? 1 : 0; + if (!isUDP(server) && (rc = setsockopt(server->mSock, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char *>(&optflag), sizeof(int))) < 0) { + WARN_errno(rc < 0, "tcpnodelay"); + } +#endif + return rc; +} diff --git a/src/Locale.c b/src/Locale.c new file mode 100644 index 0000000..09333b0 --- /dev/null +++ b/src/Locale.c @@ -0,0 +1,757 @@ +/*--------------------------------------------------------------- + * Copyright (c) 1999,2000,2001,2002,2003 + * The Board of Trustees of the University of Illinois + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software (Iperf) and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the names of the University of Illinois, NCSA, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * National Laboratory for Applied Network Research + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * http://www.ncsa.uiuc.edu + * ________________________________________________________________ + * + * Locale.c + * by Ajay Tirumala <tirumala@ncsa.uiuc.edu> + * & Mark Gates <mgates@nlanr.net> + * ------------------------------------------------------------------- + * Strings and other stuff that is locale specific. + * ------------------------------------------------------------------- */ +#include "headers.h" +#include "version.h" + +#ifdef __cplusplus +extern "C" { +#endif +/* ------------------------------------------------------------------- + * usage + * ------------------------------------------------------------------- */ + +const char usage_short[] = "\ +Usage: %s [-s|-c host] [options]\n\ +Try `%s --help' for more information.\n"; + +const char usage_long1[] = "\ +Usage: iperf [-s|-c host] [options]\n\ + iperf [-h|--help] [-v|--version]\n\ +\n\ +Client/Server:\n\ + -b, --bandwidth #[kmgKMG | pps] bandwidth to read/send at in bits/sec or packets/sec\n\ + -e, --enhanced use enhanced reporting giving more tcp/udp and traffic information\n\ + -f, --format [kmgKMG] format to report: Kbits, Mbits, KBytes, MBytes\n\ + --hide-ips hide ip addresses and host names within outputs\n\ + -i, --interval # seconds between periodic bandwidth reports\n\ + -l, --len #[kmKM] length of buffer in bytes to read or write (Defaults: TCP=128K, v4 UDP=1470, v6 UDP=1450)\n\ + -m, --print_mss print TCP maximum segment size\n\ + -o, --output <filename> output the report or error message to this specified file\n\ + -p, --port # client/server port to listen/send on and to connect\n\ + --permit-key permit key to be used to verify client and server (TCP only)\n\ + --sum-only output sum only reports\n\ + -u, --udp use UDP rather than TCP\n\ + --utc use coordinated universal time (UTC) with time output\n\ + -w, --window #[KM] TCP window size (socket buffer size)\n" +#ifdef HAVE_SCHED_SETSCHEDULER +" -z, --realtime request realtime scheduler\n" +#endif +" -B, --bind <host>[:<port>][%<dev>] bind to <host>, ip addr (including multicast address) and optional port and device\n\ + -C, --compatibility for use with older versions does not sent extra msgs\n\ + --NUM_REPORT_STRUCTS increase the shared memory between the traffic threads and the reporter thread (default is 10,000 entries)\n\ + -M, --mss # set TCP maximum segment size using TCP_MAXSEG\n\ + -N, --nodelay set TCP no delay, disabling Nagle's Algorithm\n\ + -S, --tos # set the socket's IP_TOS (byte) field\n\ + -Z, --tcp-congestion <algo> set TCP congestion control algorithm (Linux only)\n\ +\n\ +Server specific:\n\ + -p, --port #[-#] server port(s) to listen on/connect to\n\ + -s, --server run in server mode\n\ + -1, --singleclient run one server at a time\n\ + --histograms enable latency histograms\n\ + --jitter-histograms enable jitter histograms\n\ + --permit-key-timeout set the timeout for a permit key in seconds\n\ + --tcp-rx-window-clamp set the TCP receive window clamp size in bytes\n\ + --tap-dev #[<dev>] use TAP device to receive at L2 layer\n\ + -t, --time # time in seconds to listen for new connections as well as to receive traffic (default not set)\n\ + -B, --bind <ip>[%<dev>] bind to multicast address and optional device\n\ + -U, --single_udp run in single threaded UDP mode\n\ + --sum-dstip sum traffic threads based upon destination ip address (default is src ip)\n\ + -D, --daemon run the server as a daemon\n" +#ifdef WIN32 +" -R, --remove remove service in win32\n" +#endif +" -V, --ipv6_domain Enable IPv6 reception by setting the domain and socket to AF_INET6 (Can receive on both IPv4 and IPv6)\n" +; + +const char usage_long2[] = "\ +\n\ +Client specific:\n\ + --bounceback request a bounceback test (use -l for size, defaults to 100 bytes)\n\ + --bounceback-hold request the server to insert a delay of n milliseconds between its read and write\n\ + --bounceback-period request the client schedule a send every n milliseconds\n\ + --bounceback-no-quickack request the server not set the TCP_QUICKACK socket option (disabling TCP ACK delays) during a bounceback test\n\ + -c, --client <host> run in client mode, connecting to <host>\n\ + --connect-only run a connect only test\n\ + --connect-retries # number of times to retry tcp connect\n\ + -d, --dualtest Do a bidirectional test simultaneously (multiple sockets)\n\ + --fq-rate #[kmgKMG] bandwidth to socket pacing\n\ + --full-duplex run full duplex test using same socket\n\ + --ipg set the the interpacket gap (milliseconds) for packets within an isochronous frame\n\ + --isochronous <frames-per-second>:<mean>,<stddev> send traffic in bursts (frames - emulate video traffic)\n\ + --incr-dstip Increment the destination ip with parallel (-P) traffic threads\n\ + --incr-dstport Increment the destination port with parallel (-P) traffic threads\n\ + --incr-srcip Increment the source ip with parallel (-P) traffic threads\n\ + --incr-srcport Increment the source port with parallel (-P) traffic threads\n\ + --local-only Set don't route on socket\n\ + --near-congestion=[w] Use a weighted write delay per the sampled TCP RTT (experimental)\n\ + --no-connect-sync No sychronization after connect when -P or parallel traffic threads\n\ + --no-udp-fin No final server to client stats at end of UDP test\n\ + -n, --num #[kmgKMG] number of bytes to transmit (instead of -t)\n\ + -r, --tradeoff Do a fullduplexectional test individually\n\ + --tcp-quickack set the socket's TCP_QUICKACK option (off by default)\n\ + --tcp-write-prefetch set the socket's TCP_NOTSENT_LOWAT value in bytes and use event based writes\n\ + --tcp-write-times measure the socket write times at the application level\n\ + -t, --time # time in seconds to transmit for (default 10 secs)\n\ + --trip-times enable end to end measurements (requires client and server clock sync)\n\ + --txdelay-time time in seconds to hold back after connect and before first write\n\ + --txstart-time unix epoch time to schedule first write and start traffic\n\ + -B, --bind [<ip> | <ip:port>] bind ip (and optional port) from which to source traffic\n\ + -F, --fileinput <name> input the data to be transmitted from a file\n\ + -H, --ssm-host <ip> set the SSM source, use with -B for (S,G) \n\ + -I, --stdin input the data to be transmitted from stdin\n\ + -L, --listenport # port to receive fullduplexectional tests back on\n\ + -P, --parallel # number of parallel client threads to run\n" +#ifndef WIN32 +" -R, --reverse reverse the test (client receives, server sends)\n" +#else +" -R Remove the windows service\n" +" --reverse reverse the test (client receives, server sends)\n" +#endif +" -S, --tos IP DSCP or tos settings\n\ + -T, --ttl # time-to-live, for multicast (default 1)\n\ + --working-load request a concurrent TCP stream\n\ + -V, --ipv6_domain Set the domain to IPv6 (send packets over IPv6)\n\ + -X, --peer-detect perform server version detection and version exchange\n\ +\n\ +Miscellaneous:\n\ + -x, --reportexclude [CDMSV] exclude C(connection) D(data) M(multicast) S(settings) V(server) reports\n\ + -y, --reportstyle C report as a Comma-Separated Values\n\ + -h, --help print this message and quit\n\ + -v, --version print version information and quit\n\ +\n\ +[kmgKMG] Indicates options that support a k,m,g,K,M or G suffix\n\ +Lowercase format characters are 10^3 based and uppercase are 2^n based\n\ +(e.g. 1k = 1000, 1K = 1024, 1m = 1,000,000 and 1M = 1,048,576)\n\ +\n\ +Accepted tos values are: af11, af12, af13, af21, af22, af23, af31, af32, af33, af41, af42, af43,\n\ +cs0, cs1, cs2, cs3, cs4, cs5, cs6, cs7, ef, le, nqb, nqb2, ac_be, ac_bk, ac_vi, ac_vo, lowdelay, throughput,\n\ +reliability, or a numeric value.\n\ +\n\ +The TCP window size option can be set by the environment variable\n\ +TCP_WINDOW_SIZE. Most other options can be set by an environment variable\n\ +IPERF_<long option name>, such as IPERF_BANDWIDTH.\n\ +\n\ +Source at <http://sourceforge.net/projects/iperf2/>\n\ +Report bugs to <iperf-users@lists.sourceforge.net>\n"; + +// include a description of the threading in the version +#if defined( HAVE_POSIX_THREAD ) + #define IPERF_THREADS "pthreads" +#elif defined( HAVE_WIN32_THREAD ) + #define IPERF_THREADS "win32 threads" +#else + #define IPERF_THREADS "single threaded" +#endif + +const char version[] = +"iperf version " IPERF_VERSION " (" IPERF_VERSION_DATE ") " IPERF_THREADS "\n"; + +/* ------------------------------------------------------------------- + * settings + * ------------------------------------------------------------------- */ + +const char separator_line[] = +"------------------------------------------------------------\n"; + +const char server_port[] = +"Server listening on %s port %d\n"; + +const char client_port[] = +"Client connecting to %s, %s port %d\n"; + +const char server_pid_port[] = +"Server listening on %s port %d with pid %d\n"; + +const char server_pid_portrange[] = +"Server listening on %s ports %d-%d with pid %d\n"; + +const char client_pid_port[] = +"Client connecting to %s, %s port %d with pid %d (%d flows)\n"; + +const char client_pid_port_dev[] = +"Client connecting to %s, %s port %d with pid %d via %s (%d flows)\n"; + +const char bind_address[] = +"Binding to local address %s\n"; + +const char bind_address_iface[] = +"Binding to local address %s and iface %s\n"; + +const char bind_address_iface_taptun[] = +"Using virtual iface %s (AF_PACKET & SOCK_RAW)\n"; + +const char multicast_ttl[] = +"Setting multicast TTL to %d\n"; + +const char join_multicast[] = +"Joining multicast group %s\n"; + +const char join_multicast_sg[] = +"Joining multicast (S,G)=%s,%s\n"; + +const char join_multicast_starg_dev[] = +"Joining multicast (*,G)=*,%s w/iface %s\n"; + +const char join_multicast_sg_dev[] = +"Joining multicast (S,G)=%s,%s w/iface %s\n"; + +const char client_datagram_size[] = +"Sending %d byte datagrams, IPG target: %.2f us\n"; + +const char client_datagram_size_kalman[] = +"Sending %d byte datagrams, IPG target: %.2f us (kalman adjust)\n"; + +const char server_datagram_size[] = +"Receiving %d byte datagrams\n"; + +const char tcp_window_size[] = +"TCP window size"; + +const char udp_buffer_size[] = +"UDP buffer size"; + +const char window_default[] = +"(default)"; + +const char wait_server_threads[] = +"Waiting for server threads to complete. Interrupt again to force quit.\n"; + +const char client_isochronous[] = +"Isochronous: %0.2f frames/sec mean=%s/s, stddev=%s/s, Period/IPG=%0.2f/%.3f ms\n"; + +const char client_burstperiod[] = +"Bursting: %s every %0.2f second(s)\n"; + +const char client_burstperiodcount[] = +"Bursting: %s writes %d times every %0.2f second(s)\n"; + +const char client_bounceback[] = +"Bounce-back test (size=%s) (server hold req=%d usecs & tcp_quickack)\n"; + +const char client_bounceback_noqack[] = +"Bounce-back test (size=%s) (server hold req=%d usecs)\n"; + +const char server_burstperiod[] = +"Burst wait timeout set to (2 * %0.2f) seconds (use --burst-period=<n secs> to change)\n"; + +const char client_fq_pacing [] = +"fair-queue socket pacing set to %s/s\n"; + +/* ------------------------------------------------------------------- + * Legacy reports + * ------------------------------------------------------------------- */ + +const char report_bw_header[] = +"[ ID] Interval Transfer Bandwidth\n"; + +const char report_bw_format[] = +"%s" IPERFTimeFrmt " sec %ss %ss/sec\n"; + +const char report_sum_bw_format[] = +"[SUM] " IPERFTimeFrmt " sec %ss %ss/sec\n"; + +const char report_sumcnt_bw_format[] = +"[SUM-%d] " IPERFTimeFrmt " sec %ss %ss/sec\n"; + +const char report_bw_jitter_loss_header[] = +"[ ID] Interval Transfer Bandwidth Jitter Lost/Total Datagrams\n"; + +const char report_bw_jitter_loss_format[] = +"%s" IPERFTimeFrmt " sec %ss %ss/sec %6.3f ms %" PRIdMAX "/%" PRIdMAX " (%.2g%%)\n"; + +const char report_sum_bw_jitter_loss_format[] = +"[SUM] " IPERFTimeFrmt " sec %ss %ss/sec %" PRIdMAX "/%" PRIdMAX " (%.2g%%)\n"; + +const char report_sumcnt_bw_jitter_loss_header[] = +"[SUM-cnt] Interval Transfer Bandwidth Lost/Total PPS\n"; + +const char report_sumcnt_bw_jitter_loss_format[] = +"[SUM-%d] " IPERFTimeFrmt " sec %ss %ss/sec %" PRIdMAX "/%" PRIdMAX " %8.0f pps\n"; + +/* ------------------------------------------------------------------- + * Enhanced reports (per -e) + * ------------------------------------------------------------------- */ +const char report_sumcnt_bw_header[] = +"[SUM-cnt] Interval Transfer Bandwidth\n"; + +const char client_report_epoch_start_current[] = +"[%3d] Client traffic to start in %d seconds at %s current time is %s\n"; + +const char client_write_size[] = +"Write buffer size"; + +const char server_read_size[] = +"Read buffer size"; + +const char report_bw_enhanced_format[] = +"%s" IPERFTimeFrmt " sec %ss %ss/sec\n"; + +const char report_sum_bw_enhanced_format[] = +"[SUM] " IPERFTimeFrmt " sec %ss %ss/sec\n"; + +const char report_bw_read_enhanced_header[] = +"[ ID] Interval" IPERFTimeSpace "Transfer Bandwidth Reads=Dist\n"; + +const char report_bw_read_enhanced_format[] = +"%s" IPERFTimeFrmt " sec %ss %ss/sec %" PRIdMAX "=%d:%d:%d:%d:%d:%d:%d:%d\n"; + +const char report_sumcnt_bw_read_enhanced_header[] = +"[SUM-cnt] Interval" IPERFTimeSpace "Transfer Bandwidth Reads=Dist\n"; + +const char report_sumcnt_bw_read_enhanced_format[] = +"[SUM-%d] " IPERFTimeFrmt " sec %ss %ss/sec %" PRIdMAX "=%d:%d:%d:%d:%d:%d:%d:%d\n"; + +const char report_sumcnt_bw_read_triptime_header[] = +"[SUM-cnt] Interval" IPERFTimeSpace "Transfer Bandwidth InP Reads=Dist\n"; + +const char report_sumcnt_bw_read_triptime_format[] = +"[SUM-%d] " IPERFTimeFrmt " sec %ss %ss/sec %s %" PRIdMAX "=%d:%d:%d:%d:%d:%d:%d:%d\n"; + +const char report_bw_read_enhanced_netpwr_header[] = +"[ ID] Interval" IPERFTimeSpace "Transfer Bandwidth Burst Latency avg/min/max/stdev (cnt/size) inP NetPwr Reads=Dist\n"; + +const char report_bw_read_enhanced_netpwr_format[] = +"%s" IPERFTimeFrmt " sec %ss %ss/sec %.3f/%.3f/%.3f/%.3f ms (%d/%d) %s %s %" PRIdMAX "=%d:%d:%d:%d:%d:%d:%d:%d\n"; + +const char report_bw_isoch_enhanced_netpwr_header[] = +"[ ID] Interval" IPERFTimeSpace "Transfer Bandwidth Burst Latency avg/min/max/stdev (cnt/size) NetPwr Reads=Dist\n"; + +const char report_bw_isoch_enhanced_netpwr_format[] = +"%s" IPERFTimeFrmt " sec %ss %ss/sec %.3f/%.3f/%.3f/%.3f ms (%d/%d) %s %" PRIdMAX "=%d:%d:%d:%d:%d:%d:%d:%d\n"; + +const char report_sum_bw_read_enhanced_format[] = +"[SUM] " IPERFTimeFrmt " sec %ss %ss/sec %" PRIdMAX "=%d:%d:%d:%d:%d:%d:%d:%d\n"; + +const char report_triptime_enhanced_format[] = +"%s" IPERFTimeFrmt " trip-time (3WHS done->fin+finack) = %.4f sec\n"; + +#if HAVE_TCP_STATS +const char report_client_bb_bw_header[] = +"[ ID] Interval" IPERFTimeSpace "Transfer Bandwidth BB cnt=avg/min/max/stdev Rtry Cwnd/RTT RPS\n"; + +const char report_client_bb_bw_format[] = +"%s" IPERFTimeFrmt " sec %ss %ss/sec %" PRIdMAX "=%.3f/%.3f/%.3f/%.3f ms %4d %4dK/%u us %s rps\n"; +#else +const char report_client_bb_bw_header[] = +"[ ID] Interval" IPERFTimeSpace "Transfer Bandwidth BB cnt=avg/min/max/stdev RPS\n"; + +const char report_client_bb_bw_format[] = +"%s" IPERFTimeFrmt " sec %ss %ss/sec %" PRIdMAX "=%.3f/%.3f/%.3f/%.3f ms %s rps\n"; +#endif +const char report_client_bb_bw_triptime_format[] = +"%s" IPERFTimeFrmt " sec OWD Delays (ms) Cnt=%" PRIdMAX " To=%.3f/%.3f/%.3f/%.3f From=%.3f/%.3f/%.3f/%.3f Asymmetry=%.3f/%.3f/%.3f/%.3f %s rps\n"; + +const char report_write_enhanced_write_header[] = +"[ ID] Interval" IPERFTimeSpace "Transfer Bandwidth Write/Err Rtry Cwnd/RTT NetPwr write-times avg/min/max/stdev (cnt)\n"; + +const char report_write_enhanced_write_format[] = +"%s" IPERFTimeFrmt " sec %ss %ss/sec %" PRIdMAX "/%" PRIdMAX " %10" PRIdMAX "%8dK/%u us %s %.3f/%.3f/%.3f/%.3f ms (%" PRIdMAX ")\n"; + +const char report_write_enhanced_nocwnd_write_format[] = +"%s" IPERFTimeFrmt " sec %ss %ss/sec %" PRIdMAX "/%" PRIdMAX " %10" PRIdMAX " NA/%u us %s %.3f/%.3f/%.3f/%.3f ms (%" PRIdMAX ")\n"; + + +#if HAVE_TCP_STATS +const char report_bw_write_enhanced_header[] = +"[ ID] Interval" IPERFTimeSpace "Transfer Bandwidth Write/Err Rtry Cwnd/RTT(var) NetPwr\n"; + +const char report_sum_bw_write_enhanced_format[] = +"[SUM] " IPERFTimeFrmt " sec %ss %ss/sec %" PRIdMAX "/%" PRIdMAX "%10" PRIdMAX "\n"; + +const char report_bw_write_enhanced_format[] = +"%s" IPERFTimeFrmt " sec %ss %ss/sec %" PRIdMAX "/%" PRIdMAX "%10" PRIdMAX " %8dK/%u(%u) us %s\n"; + +const char report_bw_write_enhanced_nocwnd_format[] = +"%s" IPERFTimeFrmt " sec %ss %ss/sec %" PRIdMAX "/%" PRIdMAX " %10" PRIdMAX " NA/%u us %s\n"; + +const char report_write_enhanced_isoch_header[] = +"[ ID] Interval" IPERFTimeSpace "Transfer Bandwidth Write/Err Rtry Cwnd/RTT isoch:tx/miss/slip NetPwr\n"; + +const char report_write_enhanced_isoch_format[] = +"%s" IPERFTimeFrmt " sec %ss %ss/sec %" PRIdMAX "/%" PRIdMAX " %8d %8dK/%u us %9" PRIuMAX "/%" PRIuMAX "/%" PRIuMAX " %s\n"; + +const char report_write_enhanced_isoch_nocwnd_format[] = +"%s" IPERFTimeFrmt " sec %ss %ss/sec %" PRIdMAX "/%" PRIdMAX " %10" PRIdMAX " NA/%u us %9" PRIuMAX "/%" PRIuMAX "/%" PRIuMAX " %s\n"; + +#else + +const char report_bw_write_enhanced_header[] = +"[ ID] Interval" IPERFTimeSpace "Transfer Bandwidth Write/Err\n"; + +const char report_bw_write_enhanced_format[] = +"%s" IPERFTimeFrmt " sec %ss %ss/sec %" PRIdMAX "/%" PRIdMAX "\n"; + +const char report_sum_bw_write_enhanced_format[] = +"[SUM] " IPERFTimeFrmt " sec %ss %ss/sec %" PRIdMAX "/%" PRIdMAX "\n"; + +const char report_write_enhanced_isoch_header[] = +"[ ID] Interval" IPERFTimeSpace "Transfer Bandwidth Write/Err isoch:tx/miss/slip\n"; + +const char report_write_enhanced_isoch_format[] = +"%s" IPERFTimeFrmt " sec %ss %ss/sec %" PRIdMAX "/%" PRIdMAX "%9" PRIuMAX "/%" PRIuMAX "/%" PRIuMAX "\n"; +#endif + +const char report_sumcnt_bw_write_enhanced_header[] = +"[SUM-cnt] Interval" IPERFTimeSpace "Transfer Bandwidth Write/Err Rtry\n"; + +const char report_sumcnt_bw_write_enhanced_format[] = +"[SUM-%d] " IPERFTimeFrmt " sec %ss %ss/sec %" PRIdMAX "/%" PRIdMAX "%10" PRIdMAX "\n"; + +const char report_bw_pps_enhanced_header[] = +"[ ID] Interval" IPERFTimeSpace "Transfer Bandwidth Write/Err PPS\n"; + +const char report_bw_pps_enhanced_format[] = +"%s" IPERFTimeFrmt " sec %ss %ss/sec %" PRIdMAX "/%" PRIdMAX " %8.0f pps\n"; + +const char report_sumcnt_bw_pps_enhanced_header[] = +"[SUM-cnt] Interval" IPERFTimeSpace "Transfer Bandwidth Write/Err PPS\n"; + +const char report_sumcnt_bw_pps_enhanced_format[] = +"[SUM-%d] " IPERFTimeFrmt " sec %ss %ss/sec %" PRIdMAX "/%" PRIdMAX " %8.0f pps\n"; + +const char report_sumcnt_udp_enhanced_header[] = +"[SUM-cnt] Interval" IPERFTimeSpace "Transfer Bandwidth Lost/Total PPS\n"; + +const char report_sumcnt_udp_enhanced_format[] = +"[SUM-%d] " IPERFTimeFrmt " sec %ss %ss/sec %" PRIdMAX "/%" PRIdMAX " %8.0f pps\n"; + +const char report_sumcnt_udp_triptime_header[] = +"[SUM-cnt] Interval" IPERFTimeSpace "Transfer Bandwidth Lost/Total Rx/inP PPS\n"; + +const char report_sumcnt_udp_triptime_format[] = +"[SUM-%d] " IPERFTimeFrmt " sec %ss %ss/sec %" PRIdMAX "/%" PRIdMAX " %" PRIdMAX "/%.0f %8.0f pps\n"; + +const char report_bw_pps_enhanced_isoch_header[] = +"[ ID] Interval" IPERFTimeSpace "Transfer Bandwidth Write/Err PPS isoch:tx/miss/slip\n"; + +const char report_bw_pps_enhanced_isoch_format[] = +"%s" IPERFTimeFrmt " sec %ss %ss/sec %" PRIdMAX "/%" PRIdMAX "%8.0f pps %3" PRIuMAX "/%" PRIuMAX "/%" PRIuMAX "\n"; + +const char report_sum_bw_pps_enhanced_format[] = +"[SUM] " IPERFTimeFrmt " sec %ss %ss/sec %" PRIdMAX "/%" PRIdMAX "%8.0f pps\n"; + +const char report_bw_jitter_loss_pps_header[] = +"[ ID] Interval Transfer Bandwidth Jitter Lost/Total Datagrams PPS\n"; + +const char report_bw_jitter_loss_pps_format[] = +"%s" IPERFTimeFrmt " sec %ss %ss/sec %6.3f ms %" PRIdMAX "/%" PRIdMAX " (%.2g%%) %8.0f pps\n"; + +const char report_bw_jitter_loss_enhanced_header[] = +"[ ID] Interval" IPERFTimeSpace "Transfer Bandwidth Jitter Lost/Total \ + Latency avg/min/max/stdev PPS NetPwr\n"; + +const char report_bw_jitter_loss_enhanced_format[] = +"%s" IPERFTimeFrmt " sec %ss %ss/sec %6.3f ms %" PRIdMAX "/%" PRIdMAX " (%.2g%%) %.3f/%.3f/%.3f/%.3f ms %.0f pps %s\n"; + +const char report_bw_jitter_loss_enhanced_triptime_header[] = +"[ ID] Interval" IPERFTimeSpace "Transfer Bandwidth Jitter Lost/Total \ + Latency avg/min/max/stdev PPS Rx/inP NetPwr\n"; + +const char report_bw_jitter_loss_enhanced_triptime_format[] = +"%s" IPERFTimeFrmt " sec %ss %ss/sec %6.3f ms %" PRIdMAX "/%" PRIdMAX " (%.2g%%) %.3f/%.3f/%.3f/%.3f ms %.0f pps %" PRIdMAX "/%s %s\n"; + +const char report_bw_jitter_loss_enhanced_isoch_header[] = +"[ ID] Interval" IPERFTimeSpace "Transfer Bandwidth Jitter Lost/Total \ + Latency avg/min/max/stdev PPS NetPwr Isoch:rx/lost\n"; + +const char report_bw_jitter_loss_enhanced_isoch_triptime_header[] = +"[ ID] Interval" IPERFTimeSpace "Transfer Bandwidth Jitter Lost/Total \ +Latency avg/min/max/stdev PPS Frame:rx/lost Frame-latency avg/min/max/stdev NetPwr\n"; + +const char report_bw_jitter_loss_enhanced_isoch_format[] = +"%s" IPERFTimeFrmt " sec %ss %ss/sec %6.3f ms %" PRIdMAX "/%" PRIdMAX " (%.2g%%) %.3f/%.3f/%.3f/%.3f ms %.0f pps %3d/%d %.3f/%.3f/%.3f/%.3f ms %s\n"; + +const char report_sum_bw_jitter_loss_enhanced_format[] = +"[SUM] " IPERFTimeFrmt " sec %ss %ss/sec %6.3f ms %" PRIdMAX "/%" PRIdMAX " (%.2g%%) %.0f pps\n"; + +const char report_sumcnt_bw_jitter_loss_enhanced_format[] = +"[SUM-%d] " IPERFTimeFrmt " sec %ss %ss/sec %6.3f ms %" PRIdMAX "/%" PRIdMAX " (%.2g%%) %.0f pps\n"; + +const char report_bw_jitter_loss_suppress_enhanced_format[] = +"%s" IPERFTimeFrmt " sec %ss %ss/sec %6.3f ms %" PRIdMAX "/%" PRIdMAX " (%.2g%%) -/-/-/- ms %.0f pps\n"; + +/* + * Frame interval reports + */ +#define IPERFFTimeFrmt "%4.4f-%4.4f" +#define IPERFFTimeSpace " " +const char report_frame_jitter_loss_enhanced_header[] = +"[ ID] Interval(f-transit)" IPERFFTimeSpace "Transfer Bandwidth FrameID Jitter Lost/Total \ + Latency avg/min/max/stdev PPS inP NetPwr\n"; + +const char report_frame_jitter_loss_enhanced_format[] = +"%s" IPERFFTimeFrmt "(%0.4f) sec %ss %ss/sec %" PRIdMAX " %6.3f ms %" PRIdMAX "/%" PRIdMAX " (%.2g%%) %.3f/%.3f/%.3f/%.3f ms %.0f pps %2.0f pkts %s\n"; + +const char report_frame_jitter_loss_suppress_enhanced_format[] = +"%s" IPERFTimeFrmt "(%0.4f) sec %" PRIdMAX " %ss %ss/sec %" PRIdMAX " %6.3f ms %" PRIdMAX "/%" PRIdMAX " (%.2g%%) -/-/-/- ms %.0f pps\n"; + +const char report_frame_tcp_enhanced_header[] = +"[ ID] Interval(f-transit)" IPERFFTimeSpace "Transfer Bandwidth FrameID\n"; + +const char report_burst_read_tcp_header[] = +"[ ID] Burst (start-end)" IPERFFTimeSpace "Transfer Bandwidth XferTime (DC%) Reads=Dist NetPwr\n"; + +const char report_burst_read_tcp_format[] = +"%s" IPERFTimeFrmt " sec %ss %ss/sec %6.3f ms (%.2g%%) %" PRIdMAX "=%d:%d:%d:%d:%d:%d:%d:%d %s\n"; + +const char report_burst_read_tcp_final_format[] = +"%s" IPERFTimeFrmt " sec %ss %ss/sec %.3f/%.3f/%.3f/%.3f ms %" PRIdMAX "=%d:%d:%d:%d:%d:%d:%d:%d\n"; +#if HAVE_TCP_STATS +const char report_burst_write_tcp_header[] = +"[ ID] Burst (start-end)" IPERFFTimeSpace "Transfer Bandwidth XferTime Write/Err Rtry Cwnd/RTT NetPwr\n"; + +const char report_burst_write_tcp_format[] = +"%s" IPERFTimeFrmt " sec %ss %ss/sec %6.3f ms %" PRIdMAX "/%" PRIdMAX "%10" PRIdMAX "%8dK/%u %s\n"; + +#else +const char report_burst_write_tcp_header[] = +"[ ID] Burst (start-end)" IPERFFTimeSpace "Transfer Bandwidth XferTime Write/Err\n"; + +const char report_burst_write_tcp_format[] = +"%s" IPERFTimeFrmt " sec %ss %ss/sec %6.3f ms %" PRIdMAX "/%" PRIdMAX"\n"; +#endif + +const char report_burst_write_tcp_nocwnd_format[] = +"%s" IPERFTimeFrmt " sec %ss %ss/sec %6.3f ms %" PRIdMAX "/%" PRIdMAX "%10" PRIdMAX "NA/%u %s\n"; + +const char report_burst_write_tcp_final_format[] = +"%s" IPERFTimeFrmt " sec %ss %ss/sec %" PRIdMAX "=%d:%d:%d:%d:%d:%d:%d:%d\n"; + +/* ------------------------------------------------------------------- + * Fullduplex reports + * ------------------------------------------------------------------- */ +const char report_bw_sum_fullduplex_format[] = +"%s" IPERFTimeFrmt " sec %ss %ss/sec\n"; + +const char report_bw_sum_fullduplex_enhanced_format[] = +"[FD%d] " IPERFTimeFrmt " sec %ss %ss/sec\n"; + +const char report_udp_fullduplex_header[] = +"[ ID] Interval Transfer Bandwidth Datagrams PPS\n"; + +const char report_sumcnt_udp_fullduplex_header[] = +"[SUM-cnt] Interval Transfer Bandwidth Datagrams PPS\n"; + +const char report_sumcnt_udp_fullduplex_format[] = +"[SUM-%d] " IPERFTimeFrmt " sec %ss %ss/sec %" PRIdMAX "%8.0f pps\n"; + +const char report_udp_fullduplex_format[] = +"%s" IPERFTimeFrmt " sec %ss %ss/sec %" PRIdMAX "%8.0f pps\n"; + +const char report_udp_fullduplex_enhanced_format[] = +"[FD%d] " IPERFTimeFrmt " sec %ss %ss/sec %" PRIdMAX "%8.0f pps\n"; + +const char report_udp_fullduplex_sum_format[] = +"[SUM] " IPERFTimeFrmt " sec %ss %ss/sec %" PRIdMAX "%8.0f pps\n"; + +/* ------------------------------------------------------------------- + * Misc reports + * ------------------------------------------------------------------- */ +const char report_outoforder[] = +"%s" IPERFTimeFrmt " sec %d datagrams received out-of-order\n"; + +const char report_sumcnt_outoforder[] = +"[SUM-%d] " IPERFTimeFrmt " sec %d datagrams received out-of-order\n"; + +const char report_l2statistics[] = +"%s" IPERFTimeFrmt " sec L2 processing detected errors, total(length/checksum/unknown) = %" PRIdMAX "(%" PRIdMAX "/%" PRIdMAX "/%" PRIdMAX ")\n"; + +const char report_sum_outoforder[] = +"[SUM] " IPERFTimeFrmt " sec %d datagrams received out-of-order\n"; + +const char report_peer [] = +"%slocal %s port %u connected with %s port %u%s\n"; + +const char report_peer_dev [] = +"%slocal %s%%%s port %u connected with %s port %u%s\n"; + +const char report_peer_fail [] = +"[drop] local %s port %u connection with %s port %u%s (permit key fail)\n"; + +const char report_mss_unsupported[] = +"%sMSS and MTU size unknown (TCP_MAXSEG not supported)\n"; + +const char report_default_mss[] = +"MSS size %d bytes\n"; + +const char report_mss[] = +"MSS req size %d bytes (per TCP_MAXSEG)\n"; + +const char report_datagrams[] = +"[%3d] Sent %d datagrams\n"; + +const char report_sumcnt_datagrams[] = +"[SUM-%d] Sent %d datagrams\n"; + +const char report_sum_datagrams[] = +"[SUM] Sent %d datagrams\n"; + +const char server_reporting[] = +"[%3d] Server Report:\n"; + +const char reportCSV_peer[] = +"%s,%u,%s,%u"; + +const char report_l2length_error[] = +"%s" IPERFTimeFrmt " sec %d datagrams received out-of-order\n"; + +/*------------------------------------------------------------------- + * CSV outputs + *------------------------------------------------------------------*/ +const char reportCSV_bw_format[] = +"%s,%s,%d,%.1f-%.1f,%" PRIdMAX ",%" PRIdMAX "\n"; + +const char reportCSV_bw_read_enhanced_format[] = +"%s,%s,%d,%.1f-%.1f,%" PRIdMAX ",%" PRIdMAX ",%" PRIdMAX ",%d,%d,%d,%d,%d,%d,%d,%d\n"; + +const char reportCSV_bw_write_enhanced_format[] = +"%s,%s,%d,%.1f-%.1f,%" PRIdMAX ",%" PRIdMAX ",%" PRIdMAX ",%" PRIdMAX ",%" PRIdMAX ",%d,%u,%u\n"; + +const char reportCSV_bw_jitter_loss_format[] = +"%s,%s,%d,%.1f-%.1f,%" PRIdMAX ",%" PRIdMAX ",%.3f,%" PRIdMAX ",%" PRIdMAX ",%.3f,%" PRIdMAX "\n"; + +const char reportCSV_bw_jitter_loss_pps_format[] = +"%s,%s,%d,%.1f-%.1f,%" PRIdMAX ",%" PRIdMAX ",%.3f,%" PRIdMAX ",%" PRIdMAX ",%.3f,%" PRIdMAX ",%" PRIdMAX ",%" PRIdMAX ",%f\n"; + +/* ------------------------------------------------------------------- + * warnings + * ------------------------------------------------------------------- */ + +const char warn_window_requested[] = +" (WARNING: requested %s)"; + +const char warn_window_small[] = "\ +WARNING: TCP window size set to %d bytes. A small window size\n\ +will give poor performance. See the Iperf documentation.\n"; + +const char warn_delay_large[] = +"WARNING: delay too large, reducing from %.1f to 1.0 seconds.\n"; + +const char warn_no_pathmtu[] = +"WARNING: Path MTU Discovery may not be enabled.\n"; + +const char warn_no_ack[]= +"[%3d] WARNING: did not receive ack of last datagram after %d tries.\n"; + +const char warn_ack_failed[]= +"[%3d] WARNING: ack of last datagram failed.\n"; + +const char warn_fileopen_failed[]= +"WARNING: Unable to open file stream for transfer\n\ +Using default data stream. \n"; + +const char unable_to_change_win[]= +"WARNING: Unable to change the window size\n"; + +const char opt_estimate[]= +"Optimal Estimate\n"; + +#ifdef HAVE_FASTSAMPLING +const char report_interval_small[] = +"WARNING: interval too small, increasing to %3.4f milliseconds.\n"; +#else +const char report_interval_small[] = +"WARNING: interval too small, increasing to %3.3f milliseconds.\n"; +#endif +const char warn_invalid_server_option[] = +"WARNING: option -%c is not valid for server mode\n"; + +const char warn_invalid_client_option[] = +"WARNING: option -%c is not valid for client mode\n"; + +const char warn_invalid_compatibility_option[] = +"WARNING: option -%c is not valid in compatibility mode\n"; + +const char warn_implied_udp[] = +"WARNING: option -%c implies udp testing\n"; + +const char warn_implied_compatibility[] = +"WARNING: option -%c has implied compatibility mode\n"; + +const char warn_buffer_too_small[] = +"WARNING: %s socket buffer size (-l value) increased to %d bytes for proper operation\n"; + +const char warn_invalid_single_threaded[] = +"WARNING: option -%c is not valid in single threaded versions\n"; + +const char warn_invalid_report_style[] = +"WARNING: unknown reporting style \"%s\", switching to default\n"; + +const char warn_invalid_report[] = +"WARNING: unknown reporting type \"%c\", ignored\n valid options are:\n\t exclude: C(connection) D(data) M(multicast) S(settings) V(server) report\n\n"; + +const char warn_server_old[] = +"WARNING: iperf server version is likely very old\n"; + +const char warn_test_exchange_failed[] = +"WARNING: client/server version exchange failed\n"; + +const char warn_len_too_small_peer_exchange[] = +"WARNING: %s option -l value of %d is too small for peer exchange (suggested min value is %d bytes)\n"; + +const char warn_compat_and_peer_exchange[] = +"WARNING: Options of '-C' '--compatibility' AND '-X' '--peerdetect' are mutually exclusive, --peerdetect ignored\n"; + +const char warn_start_before_now[] = +"[%3d] WARNING: --txstart-time (%" PRIdMAX ".%" PRIdMAX ") %s is before now %s\n"; + +const char error_starttime_exceeds[] = +"ERROR: --txstart-time (%" PRIdMAX ".%" PRIdMAX ") %s exceeds max scheduled delay of %d secs\n"; + +const char error_delaytime_exceeds[] = +"ERROR: --txdelay-time of %d seconds is more than the supported delay of %d seconds\n"; + +#ifdef __cplusplus +} /* end extern "C" */ +#endif diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..37db611 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,71 @@ +bin_PROGRAMS = iperf + +LIBCOMPAT_LDADDS = @STRIP_BEGIN@ \ + $(top_builddir)/compat/libcompat.a \ + @STRIP_END@ + +AM_CPPFLAGS = @STRIP_BEGIN@ \ + -I$(top_srcdir)/include \ + -I$(top_builddir)/include \ + @STRIP_END@ + +AM_CXXFLAGS = -Wall +AM_CFLAGS = -Wall + +if DEBUG_SYMBOLS +AM_CFLAGS += -g3 -O0 +AM_CXXFLAGS += -g3 -O0 +else +AM_CFLAGS += -O2 +AM_CXXFLAGS += -O2 +endif + + +iperf_LDFLAGS = @CFLAGS@ @PTHREAD_CFLAGS@ @WEB100_CFLAGS@ @DEFS@ + +iperf_SOURCES = \ + Client.cpp \ + Extractor.c \ + isochronous.cpp \ + Launch.cpp \ + active_hosts.cpp \ + Listener.cpp \ + Locale.c \ + PerfSocket.cpp \ + Reporter.c \ + Reports.c \ + ReportOutputs.c \ + Server.cpp \ + Settings.cpp \ + SocketAddr.c \ + gnu_getopt.c \ + gnu_getopt_long.c \ + histogram.c \ + main.cpp \ + service.c \ + socket_io.c \ + stdio.c \ + packet_ring.c \ + tcp_window_size.c \ + pdfs.c \ + dscp.c \ + iperf_formattime.c +iperf_LDADD = $(LIBCOMPAT_LDADDS) + + +if CHECKPROGRAMS +noinst_PROGRAMS = checkdelay checkpdfs checkisoch igmp_querier +checkdelay_SOURCES = checkdelay.c +checkdelay_LDADD = $(LIBCOMPAT_LDADDS) +checkpdfs_SOURCES = pdfs.c checkpdfs.c stdio.c +checkpdfs_LDADD = -lm +checkisoch_SOURCES = checkisoch.cpp isochronous.cpp pdfs.c stdio.c +igmp_querier_SOURCES = igmp_querier.c +checkisoch_LDADD = $(LIBCOMPAT_LDADDS) +endif + + +if AF_PACKET +iperf_SOURCES += checksums.c +endif + diff --git a/src/Makefile.in b/src/Makefile.in new file mode 100644 index 0000000..a8ab595 --- /dev/null +++ b/src/Makefile.in @@ -0,0 +1,829 @@ +# Makefile.in generated by automake 1.16.2 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +bin_PROGRAMS = iperf$(EXEEXT) +@DEBUG_SYMBOLS_TRUE@am__append_1 = -g3 -O0 +@DEBUG_SYMBOLS_TRUE@am__append_2 = -g3 -O0 +@DEBUG_SYMBOLS_FALSE@am__append_3 = -O2 +@DEBUG_SYMBOLS_FALSE@am__append_4 = -O2 +@CHECKPROGRAMS_TRUE@noinst_PROGRAMS = checkdelay$(EXEEXT) \ +@CHECKPROGRAMS_TRUE@ checkpdfs$(EXEEXT) checkisoch$(EXEEXT) \ +@CHECKPROGRAMS_TRUE@ igmp_querier$(EXEEXT) +@AF_PACKET_TRUE@am__append_5 = checksums.c +subdir = src +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/m4/dast.m4 $(top_srcdir)/m4/ax_pthread.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" +PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) +am__checkdelay_SOURCES_DIST = checkdelay.c +@CHECKPROGRAMS_TRUE@am_checkdelay_OBJECTS = checkdelay.$(OBJEXT) +checkdelay_OBJECTS = $(am_checkdelay_OBJECTS) +am__DEPENDENCIES_1 = $(top_builddir)/compat/libcompat.a +@CHECKPROGRAMS_TRUE@checkdelay_DEPENDENCIES = $(am__DEPENDENCIES_1) +am__checkisoch_SOURCES_DIST = checkisoch.cpp isochronous.cpp pdfs.c \ + stdio.c +@CHECKPROGRAMS_TRUE@am_checkisoch_OBJECTS = checkisoch.$(OBJEXT) \ +@CHECKPROGRAMS_TRUE@ isochronous.$(OBJEXT) pdfs.$(OBJEXT) \ +@CHECKPROGRAMS_TRUE@ stdio.$(OBJEXT) +checkisoch_OBJECTS = $(am_checkisoch_OBJECTS) +@CHECKPROGRAMS_TRUE@checkisoch_DEPENDENCIES = $(am__DEPENDENCIES_1) +am__checkpdfs_SOURCES_DIST = pdfs.c checkpdfs.c stdio.c +@CHECKPROGRAMS_TRUE@am_checkpdfs_OBJECTS = pdfs.$(OBJEXT) \ +@CHECKPROGRAMS_TRUE@ checkpdfs.$(OBJEXT) stdio.$(OBJEXT) +checkpdfs_OBJECTS = $(am_checkpdfs_OBJECTS) +checkpdfs_DEPENDENCIES = +am__igmp_querier_SOURCES_DIST = igmp_querier.c +@CHECKPROGRAMS_TRUE@am_igmp_querier_OBJECTS = igmp_querier.$(OBJEXT) +igmp_querier_OBJECTS = $(am_igmp_querier_OBJECTS) +igmp_querier_LDADD = $(LDADD) +am__iperf_SOURCES_DIST = Client.cpp Extractor.c isochronous.cpp \ + Launch.cpp active_hosts.cpp Listener.cpp Locale.c \ + PerfSocket.cpp Reporter.c Reports.c ReportOutputs.c Server.cpp \ + Settings.cpp SocketAddr.c gnu_getopt.c gnu_getopt_long.c \ + histogram.c main.cpp service.c socket_io.c stdio.c \ + packet_ring.c tcp_window_size.c pdfs.c dscp.c \ + iperf_formattime.c checksums.c +@AF_PACKET_TRUE@am__objects_1 = checksums.$(OBJEXT) +am_iperf_OBJECTS = Client.$(OBJEXT) Extractor.$(OBJEXT) \ + isochronous.$(OBJEXT) Launch.$(OBJEXT) active_hosts.$(OBJEXT) \ + Listener.$(OBJEXT) Locale.$(OBJEXT) PerfSocket.$(OBJEXT) \ + Reporter.$(OBJEXT) Reports.$(OBJEXT) ReportOutputs.$(OBJEXT) \ + Server.$(OBJEXT) Settings.$(OBJEXT) SocketAddr.$(OBJEXT) \ + gnu_getopt.$(OBJEXT) gnu_getopt_long.$(OBJEXT) \ + histogram.$(OBJEXT) main.$(OBJEXT) service.$(OBJEXT) \ + socket_io.$(OBJEXT) stdio.$(OBJEXT) packet_ring.$(OBJEXT) \ + tcp_window_size.$(OBJEXT) pdfs.$(OBJEXT) dscp.$(OBJEXT) \ + iperf_formattime.$(OBJEXT) $(am__objects_1) +iperf_OBJECTS = $(am_iperf_OBJECTS) +iperf_DEPENDENCIES = $(am__DEPENDENCIES_1) +iperf_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(iperf_LDFLAGS) \ + $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/Client.Po ./$(DEPDIR)/Extractor.Po \ + ./$(DEPDIR)/Launch.Po ./$(DEPDIR)/Listener.Po \ + ./$(DEPDIR)/Locale.Po ./$(DEPDIR)/PerfSocket.Po \ + ./$(DEPDIR)/ReportOutputs.Po ./$(DEPDIR)/Reporter.Po \ + ./$(DEPDIR)/Reports.Po ./$(DEPDIR)/Server.Po \ + ./$(DEPDIR)/Settings.Po ./$(DEPDIR)/SocketAddr.Po \ + ./$(DEPDIR)/active_hosts.Po ./$(DEPDIR)/checkdelay.Po \ + ./$(DEPDIR)/checkisoch.Po ./$(DEPDIR)/checkpdfs.Po \ + ./$(DEPDIR)/checksums.Po ./$(DEPDIR)/dscp.Po \ + ./$(DEPDIR)/gnu_getopt.Po ./$(DEPDIR)/gnu_getopt_long.Po \ + ./$(DEPDIR)/histogram.Po ./$(DEPDIR)/igmp_querier.Po \ + ./$(DEPDIR)/iperf_formattime.Po ./$(DEPDIR)/isochronous.Po \ + ./$(DEPDIR)/main.Po ./$(DEPDIR)/packet_ring.Po \ + ./$(DEPDIR)/pdfs.Po ./$(DEPDIR)/service.Po \ + ./$(DEPDIR)/socket_io.Po ./$(DEPDIR)/stdio.Po \ + ./$(DEPDIR)/tcp_window_size.Po +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +SOURCES = $(checkdelay_SOURCES) $(checkisoch_SOURCES) \ + $(checkpdfs_SOURCES) $(igmp_querier_SOURCES) $(iperf_SOURCES) +DIST_SOURCES = $(am__checkdelay_SOURCES_DIST) \ + $(am__checkisoch_SOURCES_DIST) $(am__checkpdfs_SOURCES_DIST) \ + $(am__igmp_querier_SOURCES_DIST) $(am__iperf_SOURCES_DIST) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +STRIP_BEGIN = @STRIP_BEGIN@ +STRIP_DUMMY = @STRIP_DUMMY@ +STRIP_END = @STRIP_END@ +VERSION = @VERSION@ +WEB100_CFLAGS = @WEB100_CFLAGS@ +WEB100_CONFIG = @WEB100_CONFIG@ +WEB100_LIBS = @WEB100_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +LIBCOMPAT_LDADDS = @STRIP_BEGIN@ \ + $(top_builddir)/compat/libcompat.a \ + @STRIP_END@ + +AM_CPPFLAGS = @STRIP_BEGIN@ \ + -I$(top_srcdir)/include \ + -I$(top_builddir)/include \ + @STRIP_END@ + +AM_CXXFLAGS = -Wall $(am__append_2) $(am__append_4) +AM_CFLAGS = -Wall $(am__append_1) $(am__append_3) +iperf_LDFLAGS = @CFLAGS@ @PTHREAD_CFLAGS@ @WEB100_CFLAGS@ @DEFS@ +iperf_SOURCES = Client.cpp Extractor.c isochronous.cpp Launch.cpp \ + active_hosts.cpp Listener.cpp Locale.c PerfSocket.cpp \ + Reporter.c Reports.c ReportOutputs.c Server.cpp Settings.cpp \ + SocketAddr.c gnu_getopt.c gnu_getopt_long.c histogram.c \ + main.cpp service.c socket_io.c stdio.c packet_ring.c \ + tcp_window_size.c pdfs.c dscp.c iperf_formattime.c \ + $(am__append_5) +iperf_LDADD = $(LIBCOMPAT_LDADDS) +@CHECKPROGRAMS_TRUE@checkdelay_SOURCES = checkdelay.c +@CHECKPROGRAMS_TRUE@checkdelay_LDADD = $(LIBCOMPAT_LDADDS) +@CHECKPROGRAMS_TRUE@checkpdfs_SOURCES = pdfs.c checkpdfs.c stdio.c +@CHECKPROGRAMS_TRUE@checkpdfs_LDADD = -lm +@CHECKPROGRAMS_TRUE@checkisoch_SOURCES = checkisoch.cpp isochronous.cpp pdfs.c stdio.c +@CHECKPROGRAMS_TRUE@igmp_querier_SOURCES = igmp_querier.c +@CHECKPROGRAMS_TRUE@checkisoch_LDADD = $(LIBCOMPAT_LDADDS) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .cpp .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) + +clean-noinstPROGRAMS: + -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS) + +checkdelay$(EXEEXT): $(checkdelay_OBJECTS) $(checkdelay_DEPENDENCIES) $(EXTRA_checkdelay_DEPENDENCIES) + @rm -f checkdelay$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(checkdelay_OBJECTS) $(checkdelay_LDADD) $(LIBS) + +checkisoch$(EXEEXT): $(checkisoch_OBJECTS) $(checkisoch_DEPENDENCIES) $(EXTRA_checkisoch_DEPENDENCIES) + @rm -f checkisoch$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(checkisoch_OBJECTS) $(checkisoch_LDADD) $(LIBS) + +checkpdfs$(EXEEXT): $(checkpdfs_OBJECTS) $(checkpdfs_DEPENDENCIES) $(EXTRA_checkpdfs_DEPENDENCIES) + @rm -f checkpdfs$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(checkpdfs_OBJECTS) $(checkpdfs_LDADD) $(LIBS) + +igmp_querier$(EXEEXT): $(igmp_querier_OBJECTS) $(igmp_querier_DEPENDENCIES) $(EXTRA_igmp_querier_DEPENDENCIES) + @rm -f igmp_querier$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(igmp_querier_OBJECTS) $(igmp_querier_LDADD) $(LIBS) + +iperf$(EXEEXT): $(iperf_OBJECTS) $(iperf_DEPENDENCIES) $(EXTRA_iperf_DEPENDENCIES) + @rm -f iperf$(EXEEXT) + $(AM_V_CXXLD)$(iperf_LINK) $(iperf_OBJECTS) $(iperf_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Client.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Extractor.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Launch.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Listener.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Locale.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PerfSocket.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ReportOutputs.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Reporter.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Reports.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Server.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Settings.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SocketAddr.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/active_hosts.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/checkdelay.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/checkisoch.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/checkpdfs.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/checksums.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dscp.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnu_getopt.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnu_getopt_long.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/histogram.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/igmp_querier.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iperf_formattime.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/isochronous.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/packet_ring.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pdfs.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/service.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket_io.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stdio.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcp_window_size.Po@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cpp.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/Client.Po + -rm -f ./$(DEPDIR)/Extractor.Po + -rm -f ./$(DEPDIR)/Launch.Po + -rm -f ./$(DEPDIR)/Listener.Po + -rm -f ./$(DEPDIR)/Locale.Po + -rm -f ./$(DEPDIR)/PerfSocket.Po + -rm -f ./$(DEPDIR)/ReportOutputs.Po + -rm -f ./$(DEPDIR)/Reporter.Po + -rm -f ./$(DEPDIR)/Reports.Po + -rm -f ./$(DEPDIR)/Server.Po + -rm -f ./$(DEPDIR)/Settings.Po + -rm -f ./$(DEPDIR)/SocketAddr.Po + -rm -f ./$(DEPDIR)/active_hosts.Po + -rm -f ./$(DEPDIR)/checkdelay.Po + -rm -f ./$(DEPDIR)/checkisoch.Po + -rm -f ./$(DEPDIR)/checkpdfs.Po + -rm -f ./$(DEPDIR)/checksums.Po + -rm -f ./$(DEPDIR)/dscp.Po + -rm -f ./$(DEPDIR)/gnu_getopt.Po + -rm -f ./$(DEPDIR)/gnu_getopt_long.Po + -rm -f ./$(DEPDIR)/histogram.Po + -rm -f ./$(DEPDIR)/igmp_querier.Po + -rm -f ./$(DEPDIR)/iperf_formattime.Po + -rm -f ./$(DEPDIR)/isochronous.Po + -rm -f ./$(DEPDIR)/main.Po + -rm -f ./$(DEPDIR)/packet_ring.Po + -rm -f ./$(DEPDIR)/pdfs.Po + -rm -f ./$(DEPDIR)/service.Po + -rm -f ./$(DEPDIR)/socket_io.Po + -rm -f ./$(DEPDIR)/stdio.Po + -rm -f ./$(DEPDIR)/tcp_window_size.Po + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/Client.Po + -rm -f ./$(DEPDIR)/Extractor.Po + -rm -f ./$(DEPDIR)/Launch.Po + -rm -f ./$(DEPDIR)/Listener.Po + -rm -f ./$(DEPDIR)/Locale.Po + -rm -f ./$(DEPDIR)/PerfSocket.Po + -rm -f ./$(DEPDIR)/ReportOutputs.Po + -rm -f ./$(DEPDIR)/Reporter.Po + -rm -f ./$(DEPDIR)/Reports.Po + -rm -f ./$(DEPDIR)/Server.Po + -rm -f ./$(DEPDIR)/Settings.Po + -rm -f ./$(DEPDIR)/SocketAddr.Po + -rm -f ./$(DEPDIR)/active_hosts.Po + -rm -f ./$(DEPDIR)/checkdelay.Po + -rm -f ./$(DEPDIR)/checkisoch.Po + -rm -f ./$(DEPDIR)/checkpdfs.Po + -rm -f ./$(DEPDIR)/checksums.Po + -rm -f ./$(DEPDIR)/dscp.Po + -rm -f ./$(DEPDIR)/gnu_getopt.Po + -rm -f ./$(DEPDIR)/gnu_getopt_long.Po + -rm -f ./$(DEPDIR)/histogram.Po + -rm -f ./$(DEPDIR)/igmp_querier.Po + -rm -f ./$(DEPDIR)/iperf_formattime.Po + -rm -f ./$(DEPDIR)/isochronous.Po + -rm -f ./$(DEPDIR)/main.Po + -rm -f ./$(DEPDIR)/packet_ring.Po + -rm -f ./$(DEPDIR)/pdfs.Po + -rm -f ./$(DEPDIR)/service.Po + -rm -f ./$(DEPDIR)/socket_io.Po + -rm -f ./$(DEPDIR)/stdio.Po + -rm -f ./$(DEPDIR)/tcp_window_size.Po + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-binPROGRAMS clean-generic clean-noinstPROGRAMS \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-binPROGRAMS \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-binPROGRAMS + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/PerfSocket.cpp b/src/PerfSocket.cpp new file mode 100644 index 0000000..bad4074 --- /dev/null +++ b/src/PerfSocket.cpp @@ -0,0 +1,445 @@ +/*--------------------------------------------------------------- + * Copyright (c) 1999,2000,2001,2002,2003 + * The Board of Trustees of the University of Illinois + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software (Iperf) and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the names of the University of Illinois, NCSA, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * National Laboratory for Applied Network Research + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * http://www.ncsa.uiuc.edu + * ________________________________________________________________ + * + * PerfSocket.cpp + * by Mark Gates <mgates@nlanr.net> + * Ajay Tirumala <tirumala@ncsa.uiuc.edu> + * ------------------------------------------------------------------- + * Has routines the Client and Server classes use in common for + * performance testing the network. + * Changes in version 1.2.0 + * for extracting data from files + * ------------------------------------------------------------------- + * headers + * uses + * <stdlib.h> + * <stdio.h> + * <string.h> + * + * <sys/types.h> + * <sys/socket.h> + * <unistd.h> + * + * <arpa/inet.h> + * <netdb.h> + * <netinet/in.h> + * <sys/socket.h> + * ------------------------------------------------------------------- */ +#define HEADERS() + +#include "headers.h" +#include "PerfSocket.hpp" +#include "SocketAddr.h" +#include "util.h" + +/* ------------------------------------------------------------------- + * Set socket options before the listen() or connect() calls. + * These are optional performance tuning factors. + * ------------------------------------------------------------------- */ +void SetSocketOptions (struct thread_Settings *inSettings) { + // set the TCP window size (socket buffer sizes) + // also the UDP buffer size + // must occur before call to accept() for large window sizes + setsock_tcp_windowsize(inSettings->mSock, inSettings->mTCPWin, + (inSettings->mThreadMode == kMode_Client ? 1 : 0)); + + if (isCongestionControl(inSettings)) { +#ifdef TCP_CONGESTION + Socklen_t len = strlen(inSettings->mCongestion) + 1; + int rc = setsockopt(inSettings->mSock, IPPROTO_TCP, TCP_CONGESTION, + inSettings->mCongestion, len); + if (rc == SOCKET_ERROR) { + fprintf(stderr, "Attempt to set '%s' congestion control failed: %s\n", + inSettings->mCongestion, strerror(errno)); + unsetCongestionControl(inSettings); + } +#else + fprintf(stderr, "The -Z option is not available on this operating system\n"); +#endif + } + + +#if ((HAVE_TUNTAP_TAP) && (HAVE_TUNTAP_TUN)) + if (isTunDev(inSettings) || isTapDev(inSettings)) { + char **device = (inSettings->mThreadMode == kMode_Client) ? &inSettings->mIfrnametx : &inSettings->mIfrname; + struct ifreq ifr; + struct sockaddr_ll saddr; + memset(&ifr, 0, sizeof(ifr)); + if (*device) { + snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", *device); +// ifr.ifr_flags = IFF_MULTI_QUEUE; + } + inSettings->tuntapdev = open("/dev/net/tun", O_RDWR); + FAIL_errno((inSettings->tuntapdev == -1), "open tun dev", inSettings); + ifr.ifr_flags |= isTapDev(inSettings) ? IFF_TAP : IFF_TUN; + ifr.ifr_flags |= IFF_NO_PI; + int rc = ioctl(inSettings->tuntapdev, TUNSETIFF, (void*) &ifr); + FAIL_errno((rc == -1), "tunsetiff", inSettings); + if (!(*device)) { + int len = snprintf(NULL, 0, "tap%d", inSettings->tuntapdev); + len++; // Trailing null byte + extra + (*device) = static_cast<char *>(calloc(0,len)); + len = snprintf(*device, len, "tap%d", inSettings->tuntapdev); + } + memset(&saddr, 0, sizeof(saddr)); + saddr.sll_family = AF_PACKET; + saddr.sll_protocol = htons(ETH_P_ALL); + saddr.sll_ifindex = if_nametoindex(*device); + if (!saddr.sll_ifindex) { + fprintf(stderr, "tuntap device of %s used for index lookup\n", (*device)); + FAIL_errno(!saddr.sll_ifindex, "tuntap nametoindex", inSettings); + } + saddr.sll_pkttype = PACKET_HOST; + rc = bind(inSettings->mSock, reinterpret_cast<sockaddr*>(&saddr), sizeof(saddr)); + FAIL_errno((rc == SOCKET_ERROR), "tap bind", inSettings); +#ifdef HAVE_THREAD_DEBUG + thread_debug("tuntap device of %s configured", inSettings->mIfrname); +#endif + } else +#endif +#if (HAVE_DECL_SO_BINDTODEVICE) + { + char **device = (inSettings->mThreadMode == kMode_Client) ? &inSettings->mIfrnametx : &inSettings->mIfrname; + if (*device) { + struct ifreq ifr; + memset(&ifr, 0, sizeof(ifr)); + snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", *device); + if (setsockopt(inSettings->mSock, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) < 0) { + char *buf; + int len = snprintf(NULL, 0, "%s %s", "bind to device", *device); + len++; // Trailing null byte + extra + buf = static_cast<char *>(malloc(len)); + len = snprintf(buf, len, "%s %s", "bind to device", *device); + WARN_errno(1, buf); + free(buf); + free(*device); + *device = NULL; + FAIL(1, "setsockopt() SO_BINDTODEVICE", inSettings); + } + } + } +#endif + + // check if we're sending multicast + if (isMulticast(inSettings)) { +#ifdef HAVE_MULTICAST + if (!isUDP(inSettings)) { + FAIL(1, "Multicast requires -u option ", inSettings); + exit(1); + } + // check for default TTL, multicast is 1 and unicast is the system default + if (inSettings->mTTL == -1) { + inSettings->mTTL = 1; + } + if (inSettings->mTTL > 0) { + // set TTL + if (!isIPV6(inSettings)) { + unsigned char cval = inSettings->mTTL; + int rc = setsockopt(inSettings->mSock, IPPROTO_IP, IP_MULTICAST_TTL, \ + reinterpret_cast<const char *>(&cval), sizeof(cval)); + WARN_errno(rc == SOCKET_ERROR, "multicast v4 ttl"); + } else +# ifdef HAVE_IPV6_MULTICAST + { + int val = inSettings->mTTL; + int rc = setsockopt(inSettings->mSock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, \ + reinterpret_cast<char *>(&val), static_cast<Socklen_t>(sizeof(val))); + WARN_errno(rc == SOCKET_ERROR, "multicast v6 ttl"); + } +# else + FAIL_errno(1, "v6 multicast not supported", inSettings); +# endif + } +#endif + } else if (inSettings->mTTL > 0) { + int val = inSettings->mTTL; + int rc = setsockopt(inSettings->mSock, IPPROTO_IP, IP_TTL, \ + reinterpret_cast<char *>(&val), static_cast<Socklen_t>(sizeof(val))); + WARN_errno(rc == SOCKET_ERROR, "v4 ttl"); + } + +#if HAVE_DECL_IP_TOS + SetSocketOptionsIPTos(inSettings, inSettings->mTOS); +#endif + + if (!isUDP(inSettings)) { + if (isTCPMSS(inSettings)) { + // set the TCP maximum segment size + setsock_tcp_mss(inSettings->mSock, inSettings->mMSS); + } +#if HAVE_DECL_TCP_NODELAY + { + int nodelay = 1; + Socklen_t len = sizeof(nodelay); + int rc = 0; + // set TCP nodelay option + if (isNoDelay(inSettings)) { + rc = setsockopt(inSettings->mSock, IPPROTO_TCP, TCP_NODELAY, + reinterpret_cast<char*>(&nodelay), len); + WARN_errno(rc == SOCKET_ERROR, "setsockopt TCP_NODELAY"); + } + // Read the socket setting, could be set on by kernel + if (isEnhanced(inSettings) && (rc == 0)) { + rc = getsockopt(inSettings->mSock, IPPROTO_TCP, TCP_NODELAY, + reinterpret_cast<char*>(&nodelay), &len); + WARN_errno(rc == SOCKET_ERROR, "getsockopt TCP_NODELAY"); + if (rc == 0) { + if (nodelay) + setNoDelay(inSettings); + else + unsetNoDelay(inSettings); + } + } + } +#endif +#if HAVE_DECL_TCP_WINDOW_CLAMP + // set TCP clamp option + if (isRxClamp(inSettings)) { + int clamp = inSettings->mClampSize; + Socklen_t len = sizeof(clamp); + int rc = setsockopt(inSettings->mSock, IPPROTO_TCP, TCP_WINDOW_CLAMP, + reinterpret_cast<char*>(&clamp), len); + WARN_errno(rc == SOCKET_ERROR, "setsockopt TCP_WINDOW_CLAMP"); + } +#endif +#if HAVE_DECL_TCP_NOTSENT_LOWAT + // set TCP not sent low watermark + if (isWritePrefetch(inSettings)) { + int bytecnt = inSettings->mWritePrefetch; + Socklen_t len = sizeof(bytecnt); + int rc = setsockopt(inSettings->mSock, IPPROTO_TCP, TCP_NOTSENT_LOWAT, + reinterpret_cast<char*>(&bytecnt), len); + WARN_errno(rc == SOCKET_ERROR, "setsockopt TCP_NOTSENT_LOWAT"); + } +#endif + } + +#if HAVE_DECL_SO_MAX_PACING_RATE + /* If socket pacing is specified try to enable it. */ + if (isFQPacing(inSettings) && inSettings->mFQPacingRate > 0) { + int rc = setsockopt(inSettings->mSock, SOL_SOCKET, SO_MAX_PACING_RATE, &inSettings->mFQPacingRate, sizeof(inSettings->mFQPacingRate)); + WARN_errno(rc == SOCKET_ERROR, "setsockopt SO_MAX_PACING_RATE"); + } +#endif /* HAVE_SO_MAX_PACING_RATE */ +#if HAVE_DECL_SO_DONTROUTE + /* If socket pacing is specified try to enable it. */ + if (isDontRoute(inSettings)) { + int option = 1; + Socklen_t len = sizeof(option); + int rc = setsockopt(inSettings->mSock, SOL_SOCKET, SO_DONTROUTE, reinterpret_cast<char*>(&option), len); + WARN_errno(rc == SOCKET_ERROR, "setsockopt SO_DONTROUTE"); + } +#endif /* HAVE_DECL_SO_DONTROUTE */ +} + +// Note that timer units are microseconds, be careful +void SetSocketOptionsSendTimeout (struct thread_Settings *mSettings, int timer) { + assert (timer > 0); +#ifdef WIN32 + // Windows SO_SNDTIMEO uses ms + DWORD timeout = (double) timer / 1e3; +#else + struct timeval timeout; + timeout.tv_sec = timer / 1000000; + timeout.tv_usec = timer % 1000000; +#endif + if (setsockopt(mSettings->mSock, SOL_SOCKET, SO_SNDTIMEO, reinterpret_cast<char *>(&timeout), sizeof(timeout)) < 0) { + WARN_errno(mSettings->mSock == SO_SNDTIMEO, "socket"); + } +// fprintf(stderr,"**** tx timeout %d usecs\n", timer); +} + +void SetSocketOptionsReceiveTimeout (struct thread_Settings *mSettings, int timer) { + assert(timer>0); +#ifdef WIN32 + // Windows SO_RCVTIMEO uses ms + DWORD timeout = (double) timer / 1e3; +#else + struct timeval timeout; + timeout.tv_sec = timer / 1000000; + timeout.tv_usec = timer % 1000000; +#endif + if (setsockopt(mSettings->mSock, SOL_SOCKET, SO_RCVTIMEO, reinterpret_cast<char *>(&timeout), sizeof(timeout)) < 0) { + WARN_errno(mSettings->mSock == SO_RCVTIMEO, "socket"); + } +// fprintf(stderr,"**** rx timeout %d usecs\n", timer); +} + + +void SetSocketOptionsIPTos (struct thread_Settings *mSettings, int tos) { +#if HAVE_DECL_IP_TOS +#ifdef HAVE_THREAD_DEBUG + thread_debug("Set socket IP_TOS to 0x%x", tos); +#endif +#if HAVE_DECL_IPV6_TCLASS && ! defined HAVE_WINSOCK2_H + // IPV6_TCLASS is defined on Windows but not implemented. + if (isIPV6(mSettings)) { + const int dscp = tos; + int rc = setsockopt(mSettings->mSock, IPPROTO_IPV6, IPV6_TCLASS, (char*) &dscp, sizeof(dscp)); + WARN_errno(rc == SOCKET_ERROR, "setsockopt IPV6_TCLASS"); + } else +#endif + // set IP TOS (type-of-service) field + if (isOverrideTOS(mSettings) || (tos > 0)) { + int reqtos = tos; + Socklen_t len = sizeof(reqtos); + int rc = setsockopt(mSettings->mSock, IPPROTO_IP, IP_TOS, + reinterpret_cast<char*>(&reqtos), len); + WARN_errno(rc == SOCKET_ERROR, "setsockopt IP_TOS"); + rc = getsockopt(mSettings->mSock, IPPROTO_IP, IP_TOS, + reinterpret_cast<char*>(&reqtos), &len); + WARN_errno(rc == SOCKET_ERROR, "getsockopt IP_TOS"); + WARN((reqtos != tos), "IP_TOS setting failed"); + } +#endif +} + + +/* + * Set a socket to blocking or non-blocking +* + * Returns true on success, or false if there was an error +*/ +bool setsock_blocking (int fd, bool blocking) { + if (fd < 0) return false; +#ifdef WIN32 + unsigned long mode = blocking ? 0 : 1; + return (ioctlsocket(fd, FIONBIO, &mode) == 0) ? true : false; +#else + int flags = fcntl(fd, F_GETFL, 0); + if (flags < 0) return false; + flags = blocking ? (flags&~O_NONBLOCK) : (flags|O_NONBLOCK); + return (fcntl(fd, F_SETFL, flags) == 0) ? true : false; +#endif +} + +/* ------------------------------------------------------------------- + * If inMSS > 0, set the TCP maximum segment size for inSock. + * Otherwise leave it as the system default. + * ------------------------------------------------------------------- */ + +const char warn_mss_fail[] = "\ +WARNING: attempt to set TCP maxmimum segment size to %d failed\n"; + +void setsock_tcp_mss (int inSock, int inMSS) { +#if HAVE_DECL_TCP_MAXSEG + int rc; + int newMSS; + Socklen_t len; + + assert(inSock != INVALID_SOCKET); + + if (inMSS > 0) { + /* set */ + newMSS = inMSS; + len = sizeof(newMSS); + rc = setsockopt(inSock, IPPROTO_TCP, TCP_MAXSEG, (char*) &newMSS, len); + if (rc == SOCKET_ERROR) { + fprintf(stderr, warn_mss_fail, newMSS); + return; + } + } +#endif +} /* end setsock_tcp_mss */ + +/* ------------------------------------------------------------------- + * returns the TCP maximum segment size + * ------------------------------------------------------------------- */ + +int getsock_tcp_mss (int inSock) { + int theMSS = -1; +#if HAVE_DECL_TCP_MAXSEG + int rc; + Socklen_t len; + assert(inSock >= 0); + + /* query for MSS */ + len = sizeof(theMSS); + rc = getsockopt(inSock, IPPROTO_TCP, TCP_MAXSEG, (char*)&theMSS, &len); + WARN_errno(rc == SOCKET_ERROR, "getsockopt TCP_MAXSEG"); +#endif + return theMSS; +} /* end getsock_tcp_mss */ + +#ifdef DEFAULT_PAYLOAD_LEN_PER_MTU_DISCOVERY +#define UDPMAXSIZE ((1024 * 64) - 64) // 16 bit field for UDP +void checksock_max_udp_payload (struct thread_Settings *inSettings) { +#if HAVE_DECL_SIOCGIFMTU + struct ifreq ifr; + if (!isBuflenSet(inSettings) && inSettings->mIfrname) { + strncpy(ifr.ifr_name, inSettings->mIfrname, (size_t) (IFNAMSIZ - 1)); + if (!ioctl(inSettings->mSock, SIOCGIFMTU, &ifr)) { + int max; + if (!isIPV6(inSettings)) { + max = ifr.ifr_mtu - IPV4HDRLEN - UDPHDRLEN; + } else { + max = ifr.ifr_mtu - IPV6HDRLEN - UDPHDRLEN; + } + if ((max > 0) && (max != inSettings->mBufLen)) { + if (max > UDPMAXSIZE) { + max = UDPMAXSIZE; + } + if (max > inSettings->mBufLen) { + char *tmp = new char[max]; + assert(tmp!=NULL); + if (tmp) { + pattern(tmp, max); + memcpy(tmp, inSettings->mBuf, inSettings->mBufLen); + DELETE_ARRAY(inSettings->mBuf); + inSettings->mBuf = tmp; + inSettings->mBufLen = max; + } + } else { + inSettings->mBufLen = max; + } + } + } + } +#endif +} +#endif + +// end SetSocketOptions diff --git a/src/ReportOutputs.c b/src/ReportOutputs.c new file mode 100644 index 0000000..e977433 --- /dev/null +++ b/src/ReportOutputs.c @@ -0,0 +1,2019 @@ +/*--------------------------------------------------------------- + * Copyright (c) 2020 + * Broadcom Corporation + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the name of Broadcom Coporation, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * + * reporter output routines + * + * by Robert J. McMahon (rjmcmahon@rjmcmahon.com, bob.mcmahon@broadcom.com) + * ------------------------------------------------------------------- + */ +#include <math.h> +#include "headers.h" +#include "Settings.hpp" +#include "Reporter.h" +#include "Locale.h" +#include "SocketAddr.h" +#include "iperf_formattime.h" + +// These static variables are not thread safe but ok to use becase only +// the repoter thread usses them +#define SNBUFFERSIZE 512 +#define SNBUFFEREXTENDSIZE 512 +static char outbuffer[SNBUFFERSIZE]; // Buffer for printing +static char outbufferext[SNBUFFEREXTENDSIZE]; // Buffer for printing + +#define LLAWBUFSIZE 100 +static char netpower_buf[100]; + +static int HEADING_FLAG(report_bw) = 0; +static int HEADING_FLAG(report_client_bb_bw) = 0; +static int HEADING_FLAG(report_bw_jitter_loss) = 0; +static int HEADING_FLAG(report_bw_read_enhanced) = 0; +static int HEADING_FLAG(report_bw_read_enhanced_netpwr) = 0; +static int HEADING_FLAG(report_bw_write_enhanced) = 0; +static int HEADING_FLAG(report_write_enhanced_write) = 0; +static int HEADING_FLAG(report_bw_write_enhanced_netpwr) = 0; +static int HEADING_FLAG(report_bw_pps_enhanced) = 0; +static int HEADING_FLAG(report_bw_pps_enhanced_isoch) = 0; +static int HEADING_FLAG(report_bw_jitter_loss_pps) = 0; +static int HEADING_FLAG(report_bw_jitter_loss_enhanced) = 0; +static int HEADING_FLAG(report_bw_jitter_loss_enhanced_isoch) = 0; +static int HEADING_FLAG(report_write_enhanced_isoch) = 0; +static int HEADING_FLAG(report_frame_jitter_loss_enhanced) = 0; +static int HEADING_FLAG(report_frame_tcp_enhanced) = 0; +static int HEADING_FLAG(report_frame_read_tcp_enhanced_triptime) = 0; +static int HEADING_FLAG(report_udp_fullduplex) = 0; +static int HEADING_FLAG(report_sumcnt_bw) = 0; +static int HEADING_FLAG(report_sumcnt_udp_fullduplex) = 0; +static int HEADING_FLAG(report_sumcnt_bw_read_enhanced) = 0; +static int HEADING_FLAG(report_sumcnt_bw_read_triptime) = 0; +static int HEADING_FLAG(report_sumcnt_bw_write_enhanced) = 0; +static int HEADING_FLAG(report_sumcnt_bw_pps_enhanced) = 0; +static int HEADING_FLAG(report_bw_jitter_loss_enhanced_triptime) = 0; +static int HEADING_FLAG(report_bw_jitter_loss_enhanced_isoch_triptime) = 0; +static int HEADING_FLAG(report_sumcnt_bw_jitter_loss) = 0; +static int HEADING_FLAG(report_burst_read_tcp) = 0; +static int HEADING_FLAG(report_burst_write_tcp) = 0; +static int HEADING_FLAG(report_bw_isoch_enhanced_netpwr) = 0; +static int HEADING_FLAG(report_sumcnt_udp_enhanced) = 0; +static int HEADING_FLAG(report_sumcnt_udp_triptime) = 0; + +void reporter_default_heading_flags (int flag) { + HEADING_FLAG(report_bw) = flag; + HEADING_FLAG(report_client_bb_bw) = flag; + HEADING_FLAG(report_sumcnt_bw) = flag; + HEADING_FLAG(report_sumcnt_udp_fullduplex) = flag; + HEADING_FLAG(report_bw_jitter_loss) = flag; + HEADING_FLAG(report_bw_read_enhanced) = flag; + HEADING_FLAG(report_bw_read_enhanced_netpwr) = flag; + HEADING_FLAG(report_bw_write_enhanced) = flag; + HEADING_FLAG(report_write_enhanced_write) = flag; + HEADING_FLAG(report_write_enhanced_isoch) = flag; + HEADING_FLAG(report_bw_write_enhanced_netpwr) = flag; + HEADING_FLAG(report_bw_pps_enhanced) = flag; + HEADING_FLAG(report_bw_pps_enhanced_isoch) = flag; + HEADING_FLAG(report_bw_jitter_loss_pps) = flag; + HEADING_FLAG(report_bw_jitter_loss_enhanced) = flag; + HEADING_FLAG(report_bw_jitter_loss_enhanced_isoch) = flag; + HEADING_FLAG(report_frame_jitter_loss_enhanced) = flag; + HEADING_FLAG(report_frame_tcp_enhanced) = flag; + HEADING_FLAG(report_frame_read_tcp_enhanced_triptime) = flag; + HEADING_FLAG(report_sumcnt_bw_read_enhanced) = flag; + HEADING_FLAG(report_sumcnt_bw_read_triptime) = flag; + HEADING_FLAG(report_sumcnt_bw_write_enhanced) = flag; + HEADING_FLAG(report_udp_fullduplex) = flag; + HEADING_FLAG(report_sumcnt_bw_jitter_loss) = flag; + HEADING_FLAG(report_sumcnt_bw_pps_enhanced) = flag; + HEADING_FLAG(report_burst_read_tcp) = flag; + HEADING_FLAG(report_burst_write_tcp) = flag; + HEADING_FLAG(report_bw_isoch_enhanced_netpwr) = flag; + HEADING_FLAG(report_sumcnt_udp_enhanced) = flag; + HEADING_FLAG(report_sumcnt_udp_triptime) = flag; +} +static inline void _print_stats_common (struct TransferInfo *stats) { + assert(stats!=NULL); + outbuffer[0] = '\0'; + outbufferext[0] = '\0'; + byte_snprintf(outbuffer, sizeof(outbuffer), (double) stats->cntBytes, toupper((int)stats->common->Format)); + if (stats->ts.iEnd < SMALLEST_INTERVAL_SEC) { + stats->cntBytes = 0; + } + byte_snprintf(outbufferext, sizeof(outbufferext), (double)stats->cntBytes / (stats->ts.iEnd - stats->ts.iStart), \ + stats->common->Format); + outbuffer[sizeof(outbuffer)-1]='\0'; + outbufferext[sizeof(outbufferext)-1]='\0'; +} + +static inline void _output_outoforder(struct TransferInfo *stats) { + if (stats->cntOutofOrder > 0) { + printf(report_outoforder, + stats->common->transferIDStr, stats->ts.iStart, + stats->ts.iEnd, stats->cntOutofOrder); + } + if (stats->l2counts.cnt) { + printf(report_l2statistics, + stats->common->transferIDStr, stats->ts.iStart, + stats->ts.iEnd, stats->l2counts.cnt, stats->l2counts.lengtherr, + stats->l2counts.udpcsumerr, stats->l2counts.unknown); + } +} + +// +// Little's law is L = lambda * W, where L is queue depth, +// lambda the arrival rate and W is the processing time +// +#define LLAW_LOWERBOUNDS -1e7 + +static inline void human_format_llawbuf(char *dststr, size_t len, double inP) { + if (inP < LLAW_LOWERBOUNDS) { + char oobstr[] = "OBL"; + if (len > sizeof(oobstr)) + strcpy(dststr, oobstr); + } else { + //force to adpative bytes for human readable + byte_snprintf(dststr, len, inP, 'A'); + dststr[len-1] = '\0'; + } +} + +#if 0 +static inline void set_llawbuf_frames (int lambda, double meantransit, double variance, intmax_t framecnt) { + int Lvar = 0; + int L = round(lambda * meantransit); + if (variance > 0.0) { + Lvar = round(lambda * variance); + } else { + Lvar = 0; + } + snprintf(llaw_buf, sizeof(llaw_buf), "%" PRIdMAX "/%d(%d) frames", framecnt, L, Lvar); + llaw_buf[sizeof(llaw_buf) - 1] = '\0'; +} +#endif + +#define NETPWR_LOWERBOUNDS -1e7 +static inline void set_netpowerbuf(double meantransit, struct TransferInfo *stats) { + if (meantransit == 0.0) { + strcpy(netpower_buf, "NAN"); + } else { + double netpwr = NETPOWERCONSTANT * (((double) stats->cntBytes) / (stats->ts.iEnd - stats->ts.iStart) / meantransit); + if (netpwr < NETPWR_LOWERBOUNDS) { + strcpy(netpower_buf, "OBL"); + } else if (netpwr > 100) { + snprintf(netpower_buf, sizeof(netpower_buf), "%.0f", netpwr); + } else if (netpwr > 10) { + snprintf(netpower_buf, sizeof(netpower_buf), "%.2f", netpwr); + } else { + snprintf(netpower_buf, sizeof(netpower_buf), "%.6f", netpwr); + } + } +} + +//TCP Output +void tcp_output_fullduplex (struct TransferInfo *stats) { + HEADING_PRINT_COND(report_bw); + _print_stats_common(stats); + printf(report_bw_sum_fullduplex_format, stats->common->transferIDStr, stats->ts.iStart, stats->ts.iEnd, outbuffer, outbufferext); + fflush(stdout); +} + +void tcp_output_fullduplex_sum (struct TransferInfo *stats) { + HEADING_PRINT_COND(report_bw); + _print_stats_common(stats); + printf(report_sum_bw_format, stats->ts.iStart, stats->ts.iEnd, outbuffer, outbufferext); + fflush(stdout); +} + +void tcp_output_fullduplex_enhanced (struct TransferInfo *stats) { + HEADING_PRINT_COND(report_bw); + _print_stats_common(stats); + printf(report_bw_sum_fullduplex_enhanced_format, stats->common->transferID, stats->ts.iStart, stats->ts.iEnd, outbuffer, outbufferext); + fflush(stdout); +} + +void tcp_output_read (struct TransferInfo *stats) { + HEADING_PRINT_COND(report_bw); + _print_stats_common(stats); + printf(report_bw_format, stats->common->transferIDStr, stats->ts.iStart, stats->ts.iEnd, outbuffer, outbufferext); + fflush(stdout); +} +//TCP read or server output +void tcp_output_read_enhanced (struct TransferInfo *stats) { + HEADING_PRINT_COND(report_bw_read_enhanced); + _print_stats_common(stats); + printf(report_bw_read_enhanced_format, + stats->common->transferIDStr, stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + stats->sock_callstats.read.cntRead, + stats->sock_callstats.read.bins[0], + stats->sock_callstats.read.bins[1], + stats->sock_callstats.read.bins[2], + stats->sock_callstats.read.bins[3], + stats->sock_callstats.read.bins[4], + stats->sock_callstats.read.bins[5], + stats->sock_callstats.read.bins[6], + stats->sock_callstats.read.bins[7]); + fflush(stdout); +} +void tcp_output_read_triptime (struct TransferInfo *stats) { + double meantransit; + HEADING_PRINT_COND(report_bw_read_enhanced_netpwr); + char llaw_bufstr[LLAWBUFSIZE]; + human_format_llawbuf(llaw_bufstr, sizeof(llaw_bufstr), ((stats->final) ? stats->fInP : stats->iInP)); + _print_stats_common(stats); + if (!stats->final) { + meantransit = (stats->transit.current.cnt > 0) ? (stats->transit.current.sum / stats->transit.current.cnt) : 0; + set_netpowerbuf(meantransit, stats); + printf(report_bw_read_enhanced_netpwr_format, + stats->common->transferIDStr, stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + (meantransit * 1e3), + (stats->transit.current.cnt < 2) ? 0 : stats->transit.current.min * 1e3, + (stats->transit.current.cnt < 2) ? 0 : stats->transit.current.max * 1e3, + (stats->transit.current.cnt < 2) ? 0 : 1e3 * (sqrt(stats->transit.current.m2 / (stats->transit.current.cnt - 1))), + stats->transit.current.cnt, + stats->transit.current.cnt ? (long) ((double)stats->cntBytes / (double) stats->transit.current.cnt) : 0, + llaw_bufstr, + netpower_buf, + stats->sock_callstats.read.cntRead, + stats->sock_callstats.read.bins[0], + stats->sock_callstats.read.bins[1], + stats->sock_callstats.read.bins[2], + stats->sock_callstats.read.bins[3], + stats->sock_callstats.read.bins[4], + stats->sock_callstats.read.bins[5], + stats->sock_callstats.read.bins[6], + stats->sock_callstats.read.bins[7]); + } else { + meantransit = (stats->transit.total.cnt > 0) ? (stats->transit.total.sum / stats->transit.total.cnt) : 0; + set_netpowerbuf(meantransit, stats); + printf(report_bw_read_enhanced_netpwr_format, + stats->common->transferIDStr, stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + (meantransit * 1e3), + stats->transit.total.min * 1e3, + stats->transit.total.max * 1e3, + (stats->transit.total.cnt < 2) ? 0 : 1e3 * (sqrt(stats->transit.total.m2 / (stats->transit.total.cnt - 1))), + stats->transit.total.cnt, + stats->transit.total.cnt ? (long) ((double)stats->cntBytes / (double) stats->transit.total.cnt) : 0, + llaw_bufstr, + netpower_buf, + stats->sock_callstats.read.cntRead, + stats->sock_callstats.read.bins[0], + stats->sock_callstats.read.bins[1], + stats->sock_callstats.read.bins[2], + stats->sock_callstats.read.bins[3], + stats->sock_callstats.read.bins[4], + stats->sock_callstats.read.bins[5], + stats->sock_callstats.read.bins[6], + stats->sock_callstats.read.bins[7]); + } + if (stats->framelatency_histogram) { + histogram_print(stats->framelatency_histogram, stats->ts.iStart, stats->ts.iEnd); + } + fflush(stdout); +} +void tcp_output_read_enhanced_isoch (struct TransferInfo *stats) { + HEADING_PRINT_COND(report_bw_isoch_enhanced_netpwr); + _print_stats_common(stats); + double meantransit; + if (!stats->final) { + meantransit = (stats->isochstats.transit.current.cnt > 0) ? (stats->isochstats.transit.current.sum / stats->isochstats.transit.current.cnt) : 0; + set_netpowerbuf(meantransit, stats); + printf(report_bw_isoch_enhanced_netpwr_format, + stats->common->transferIDStr, stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + (meantransit * 1e3), + (stats->isochstats.transit.current.cnt < 2) ? 0 : stats->isochstats.transit.current.min * 1e3, + (stats->isochstats.transit.current.cnt < 2) ? 0 : stats->isochstats.transit.current.max * 1e3, + (stats->isochstats.transit.current.cnt < 2) ? 0 : 1e3 * (sqrt(stats->isochstats.transit.current.m2 / (stats->isochstats.transit.current.cnt - 1))), + stats->isochstats.transit.current.cnt, + stats->isochstats.transit.current.cnt ? (long) ((double)stats->cntBytes / (double) stats->isochstats.transit.current.cnt) : 0, + netpower_buf, + stats->sock_callstats.read.cntRead, + stats->sock_callstats.read.bins[0], + stats->sock_callstats.read.bins[1], + stats->sock_callstats.read.bins[2], + stats->sock_callstats.read.bins[3], + stats->sock_callstats.read.bins[4], + stats->sock_callstats.read.bins[5], + stats->sock_callstats.read.bins[6], + stats->sock_callstats.read.bins[7]); + } else { + meantransit = (stats->isochstats.transit.total.cnt > 0) ? (stats->isochstats.transit.total.sum / stats->isochstats.transit.total.cnt) : 0; + set_netpowerbuf(meantransit, stats); + printf(report_bw_isoch_enhanced_netpwr_format, + stats->common->transferIDStr, stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + (meantransit * 1e3), + stats->isochstats.transit.total.min * 1e3, + stats->isochstats.transit.total.max * 1e3, + (stats->isochstats.transit.total.cnt < 2) ? 0 : 1e3 * (sqrt(stats->isochstats.transit.total.m2 / (stats->isochstats.transit.total.cnt - 1))), + stats->isochstats.transit.total.cnt, + stats->isochstats.transit.total.cnt ? (long) ((double)stats->cntBytes / (double) stats->isochstats.transit.total.cnt) : 0, + netpower_buf, + stats->sock_callstats.read.cntRead, + stats->sock_callstats.read.bins[0], + stats->sock_callstats.read.bins[1], + stats->sock_callstats.read.bins[2], + stats->sock_callstats.read.bins[3], + stats->sock_callstats.read.bins[4], + stats->sock_callstats.read.bins[5], + stats->sock_callstats.read.bins[6], + stats->sock_callstats.read.bins[7]); + } + if (stats->framelatency_histogram) { + histogram_print(stats->framelatency_histogram, stats->ts.iStart, stats->ts.iEnd); + } + fflush(stdout); +} + +void tcp_output_frame_read (struct TransferInfo *stats) { + HEADING_PRINT_COND(report_frame_tcp_enhanced); + _print_stats_common(stats); + printf(report_bw_read_enhanced_format, + stats->common->transferIDStr, stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + stats->sock_callstats.read.cntRead, + stats->sock_callstats.read.bins[0], + stats->sock_callstats.read.bins[1], + stats->sock_callstats.read.bins[2], + stats->sock_callstats.read.bins[3], + stats->sock_callstats.read.bins[4], + stats->sock_callstats.read.bins[5], + stats->sock_callstats.read.bins[6], + stats->sock_callstats.read.bins[7]); + fflush(stdout); +} +void tcp_output_frame_read_triptime (struct TransferInfo *stats) { + fprintf(stderr, "FIXME\n"); +} +void tcp_output_burst_read (struct TransferInfo *stats) { + HEADING_PRINT_COND(report_burst_read_tcp); + _print_stats_common(stats); + if (!stats->final) { + set_netpowerbuf(stats->transit.current.mean, stats); + printf(report_burst_read_tcp_format, + stats->common->transferIDStr, stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + stats->transit.current.mean * 1e3, + (1e2 * stats->transit.current.mean * stats->common->FPS), // (1e3 / 100%) + stats->sock_callstats.read.cntRead, + stats->sock_callstats.read.bins[0], + stats->sock_callstats.read.bins[1], + stats->sock_callstats.read.bins[2], + stats->sock_callstats.read.bins[3], + stats->sock_callstats.read.bins[4], + stats->sock_callstats.read.bins[5], + stats->sock_callstats.read.bins[6], + stats->sock_callstats.read.bins[7], + netpower_buf); + } else { + printf(report_burst_read_tcp_final_format, + stats->common->transferIDStr, stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + stats->transit.total.mean * 1e3, + (stats->transit.total.cnt < 2) ? 0 : stats->transit.total.min * 1e3, + (stats->transit.total.cnt < 2) ? 0 : stats->transit.total.max * 1e3, + (stats->transit.total.cnt < 2) ? 0 : 1e3 * (sqrt(stats->transit.total.m2 / (stats->transit.total.cnt - 1))), + stats->sock_callstats.read.cntRead, + stats->sock_callstats.read.bins[0], + stats->sock_callstats.read.bins[1], + stats->sock_callstats.read.bins[2], + stats->sock_callstats.read.bins[3], + stats->sock_callstats.read.bins[4], + stats->sock_callstats.read.bins[5], + stats->sock_callstats.read.bins[6], + stats->sock_callstats.read.bins[7]); + } + fflush(stdout); +} + +//TCP write or client output +void tcp_output_write (struct TransferInfo *stats) { + HEADING_PRINT_COND(report_bw); + _print_stats_common(stats); + printf(report_bw_format, stats->common->transferIDStr, + stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext); + fflush(stdout); +} + +void tcp_output_write_bb (struct TransferInfo *stats) { + HEADING_PRINT_COND(report_client_bb_bw); + _print_stats_common(stats); + char rps_string[80]; + if (stats->final) { + double rps = ((stats->fBBrunning > 0) && (stats->bbrtt.total.cnt > 0)) ? ((double) stats->bbrtt.total.cnt / stats->fBBrunning) : 0; + if (rps < 10) + snprintf(rps_string, sizeof(rps_string), "%0.1f", rps); + else + snprintf(rps_string, sizeof(rps_string), "%0.0f", rps); + rps_string[sizeof(rps_string) - 1] = '\0'; + +#if HAVE_TCP_STATS + printf(report_client_bb_bw_format, stats->common->transferIDStr, + stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + stats->bbrtt.total.cnt, + (stats->bbrtt.total.mean * 1e3), + (stats->bbrtt.total.cnt < 2) ? 0 : (stats->bbrtt.total.min * 1e3), + (stats->bbrtt.total.cnt < 2) ? 0 : (stats->bbrtt.total.max * 1e3), + (stats->bbrtt.total.cnt < 2) ? 0 : 1e3 * (sqrt(stats->bbrtt.total.m2 / (stats->bbrtt.total.cnt - 1))), + stats->sock_callstats.write.tcpstats.retry, + stats->sock_callstats.write.tcpstats.cwnd, + stats->sock_callstats.write.tcpstats.rtt, + rps_string); +#else + printf(report_client_bb_bw_format, stats->common->transferIDStr, + stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + stats->bbrtt.total.cnt, + (stats->bbrtt.total.mean * 1e3), + (stats->bbrtt.total.cnt < 2) ? 0 : (stats->bbrtt.total.min * 1e3), + (stats->bbrtt.total.cnt < 2) ? 0 : (stats->bbrtt.total.max * 1e3), + (stats->bbrtt.total.cnt < 2) ? 0 : 1e3 * (sqrt(stats->bbrtt.total.m2 / (stats->bbrtt.total.cnt - 1))), + rps_string); +#endif + if (isTripTime(stats->common)) { + printf(report_client_bb_bw_triptime_format, stats->common->transferIDStr, + stats->ts.iStart, stats->ts.iEnd, + stats->bbowdto.total.cnt, + (stats->bbowdto.total.mean * 1e3), + (stats->bbowdto.total.cnt < 2) ? 0 : (stats->bbowdto.total.min * 1e3), + (stats->bbowdto.total.cnt < 2) ? 0 : (stats->bbowdto.total.max * 1e3), + (stats->bbowdto.total.cnt < 2) ? 0 : 1e3 * (sqrt(stats->bbowdto.total.m2 / (stats->bbowdto.total.cnt - 1))), + (stats->bbowdfro.total.mean * 1e3), + (stats->bbowdfro.total.cnt < 2) ? 0 : (stats->bbowdfro.total.min * 1e3), + (stats->bbowdfro.total.cnt < 2) ? 0 : (stats->bbowdfro.total.max * 1e3), + (stats->bbowdfro.total.cnt < 2) ? 0 : 1e3 * (sqrt(stats->bbowdfro.total.m2 / (stats->bbowdfro.total.cnt - 1))), + (stats->bbasym.total.mean * 1e3), + (stats->bbasym.total.cnt < 2) ? 0 : (stats->bbasym.total.min * 1e3), + (stats->bbasym.total.cnt < 2) ? 0 : (stats->bbasym.total.max * 1e3), + (stats->bbasym.total.cnt < 2) ? 0 : 1e3 * (sqrt(stats->bbasym.total.m2 / (stats->bbasym.total.cnt - 1))), + rps_string); + } + if (stats->bbrtt_histogram) { + histogram_print(stats->bbrtt_histogram, stats->ts.iStart, stats->ts.iEnd); + } + } else { + double rps = ((stats->bbrtt.current.cnt > 0) && (stats->iBBrunning > 0)) ? ((double) stats->bbrtt.current.cnt / stats->iBBrunning) : 0; + if (rps < 10) + snprintf(rps_string, sizeof(rps_string), "%0.1f", rps); + else + snprintf(rps_string, sizeof(rps_string), "%0.0f", rps); + rps_string[sizeof(rps_string) - 1] = '\0'; + +#if HAVE_TCP_STATS + printf(report_client_bb_bw_format, stats->common->transferIDStr, + stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + stats->bbrtt.current.cnt, + (stats->bbrtt.current.mean * 1e3), + (stats->bbrtt.current.cnt < 2) ? 0 : (stats->bbrtt.current.min * 1e3), + (stats->bbrtt.current.cnt < 2) ? 0 : (stats->bbrtt.current.max * 1e3), + (stats->bbrtt.current.cnt < 2) ? 0 : 1e3 * (sqrt(stats->bbrtt.current.m2 / (stats->bbrtt.current.cnt - 1))), + stats->sock_callstats.write.tcpstats.retry, + stats->sock_callstats.write.tcpstats.cwnd, + stats->sock_callstats.write.tcpstats.rtt, + rps_string); +#else + printf(report_client_bb_bw_format, stats->common->transferIDStr, + stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + stats->bbrtt.current.cnt, + (stats->bbrtt.current.mean * 1e3), + (stats->bbrtt.current.cnt < 2) ? 0 : (stats->bbrtt.current.min * 1e3), + (stats->bbrtt.current.cnt < 2) ? 0 : (stats->bbrtt.current.max * 1e3), + (stats->bbrtt.current.cnt < 2) ? 0 : 1e3 * (sqrt(stats->bbrtt.current.m2 / (stats->bbrtt.current.cnt - 1))), + rps_string); +#endif + } + fflush(stdout); +} + +void tcp_output_burst_write (struct TransferInfo *stats) { + HEADING_PRINT_COND(report_burst_write_tcp); + _print_stats_common(stats); +#if HAVE_TCP_STATS + set_netpowerbuf((stats->transit.current.mean + stats->sock_callstats.write.tcpstats.rtt), stats); + printf(report_burst_write_tcp_format, stats->common->transferIDStr, + stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + stats->transit.current.mean, + stats->sock_callstats.write.WriteCnt, + stats->sock_callstats.write.WriteErr, + stats->sock_callstats.write.tcpstats.retry, + stats->sock_callstats.write.tcpstats.cwnd, + stats->sock_callstats.write.tcpstats.rtt, + netpower_buf); + #else + printf(report_burst_write_tcp_format, stats->common->transferIDStr, + stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + stats->transit.current.mean, + stats->sock_callstats.write.WriteCnt, + stats->sock_callstats.write.WriteErr); +#endif + fflush(stdout); +} + +void tcp_output_write_enhanced (struct TransferInfo *stats) { + HEADING_PRINT_COND(report_bw_write_enhanced); + _print_stats_common(stats); +#if !(HAVE_TCP_STATS) + printf(report_bw_write_enhanced_format, + stats->common->transferIDStr, stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + stats->sock_callstats.write.WriteCnt, + stats->sock_callstats.write.WriteErr); +#else + set_netpowerbuf(stats->sock_callstats.write.tcpstats.rtt * 1e-6, stats); + if (stats->sock_callstats.write.tcpstats.cwnd > 0) { + printf(report_bw_write_enhanced_format, + stats->common->transferIDStr, stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + stats->sock_callstats.write.WriteCnt, + stats->sock_callstats.write.WriteErr, + stats->sock_callstats.write.tcpstats.retry, + stats->sock_callstats.write.tcpstats.cwnd, + stats->sock_callstats.write.tcpstats.rtt, + stats->sock_callstats.write.tcpstats.rttvar, + netpower_buf); + } else { + printf(report_bw_write_enhanced_nocwnd_format, + stats->common->transferIDStr, stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + stats->sock_callstats.write.WriteCnt, + stats->sock_callstats.write.WriteErr, + stats->sock_callstats.write.tcpstats.retry, + stats->sock_callstats.write.tcpstats.rtt, + netpower_buf); + } +#endif +#if HAVE_DECL_TCP_NOTSENT_LOWAT + if (stats->latency_histogram) { + histogram_print(stats->latency_histogram, stats->ts.iStart, stats->ts.iEnd); + } +#endif + fflush(stdout); +} + +void tcp_output_write_enhanced_write (struct TransferInfo *stats) { + HEADING_PRINT_COND(report_write_enhanced_write); + _print_stats_common(stats); +#if !(HAVE_TCP_STATS) + printf(report_write_enhanced_write_format, + stats->common->transferIDStr, stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + stats->sock_callstats.write.WriteCnt, + stats->sock_callstats.write.WriteErr, + stats->write_mmm.current.mean * 1e3, + stats->write_mmm.current.min * 1e3, + stats->write_mmm.current.max * 1e3, + (stats->write_mmm.current.cnt < 2) ? 0 : (1e-3 * sqrt(stats->write_mmm.current.m2 / (stats->write_mmm.current.cnt - 1))), + stats->write_mmm.current.cnt); +#else + set_netpowerbuf(stats->sock_callstats.write.tcpstats.rtt * 1e-6, stats); + if (stats->sock_callstats.write.tcpstats.cwnd > 0) { + printf(report_write_enhanced_write_format, + stats->common->transferIDStr, stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + stats->sock_callstats.write.WriteCnt, + stats->sock_callstats.write.WriteErr, + stats->sock_callstats.write.tcpstats.retry, + stats->sock_callstats.write.tcpstats.cwnd, + stats->sock_callstats.write.tcpstats.rtt, + netpower_buf, + stats->write_mmm.current.mean * 1e-3, + stats->write_mmm.current.min * 1e-3, + stats->write_mmm.current.max * 1e-3, + (stats->write_mmm.current.cnt < 2) ? 0 : (1e-3 * sqrt(stats->write_mmm.current.m2 / (stats->write_mmm.current.cnt - 1))), + stats->write_mmm.current.cnt); + } else { + printf(report_write_enhanced_nocwnd_write_format, + stats->common->transferIDStr, stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + stats->sock_callstats.write.WriteCnt, + stats->sock_callstats.write.WriteErr, + stats->sock_callstats.write.tcpstats.retry, + stats->sock_callstats.write.tcpstats.rtt, + netpower_buf, + stats->write_mmm.current.mean * 1e3, + stats->write_mmm.current.min * 1e3, + stats->write_mmm.current.max * 1e3, + (stats->write_mmm.current.cnt < 2) ? 0 : (1e3 * sqrt(stats->write_mmm.current.m2 / (stats->write_mmm.current.cnt - 1))), + stats->write_mmm.current.cnt); + } +#endif + if (stats->latency_histogram) { + histogram_print(stats->latency_histogram, stats->ts.iStart, stats->ts.iEnd); + } + if (stats->write_histogram) { + histogram_print(stats->write_histogram, stats->ts.iStart, stats->ts.iEnd); + } + fflush(stdout); +} + +void tcp_output_write_enhanced_isoch (struct TransferInfo *stats) { + HEADING_PRINT_COND(report_write_enhanced_isoch); + _print_stats_common(stats); +#if !(HAVE_TCP_STATS) + printf(report_write_enhanced_isoch_format, + stats->common->transferIDStr, stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + stats->sock_callstats.write.WriteCnt, + stats->sock_callstats.write.WriteErr, + stats->isochstats.cntFrames, stats->isochstats.cntFramesMissed, stats->isochstats.cntSlips); +#else + set_netpowerbuf(stats->sock_callstats.write.tcpstats.rtt * 1e-6, stats); + if (stats->sock_callstats.write.tcpstats.cwnd > 0) { + printf(report_write_enhanced_isoch_format, + stats->common->transferIDStr, stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + stats->sock_callstats.write.WriteCnt, + stats->sock_callstats.write.WriteErr, + stats->sock_callstats.write.tcpstats.retry, + stats->sock_callstats.write.tcpstats.cwnd, + stats->sock_callstats.write.tcpstats.rtt, + stats->isochstats.cntFrames, stats->isochstats.cntFramesMissed, stats->isochstats.cntSlips, + netpower_buf); + } else { + printf(report_write_enhanced_isoch_nocwnd_format, + stats->common->transferIDStr, stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + stats->sock_callstats.write.WriteCnt, + stats->sock_callstats.write.WriteErr, + stats->sock_callstats.write.tcpstats.retry, + stats->sock_callstats.write.tcpstats.rtt, + stats->isochstats.cntFrames, stats->isochstats.cntFramesMissed, stats->isochstats.cntSlips, + netpower_buf); + } +#endif +#if HAVE_DECL_TCP_NOTSENT_LOWAT + if (stats->latency_histogram) { + histogram_print(stats->latency_histogram, stats->ts.iStart, stats->ts.iEnd); + } +#endif + fflush(stdout); +} + + +//UDP output +void udp_output_fullduplex (struct TransferInfo *stats) { + HEADING_PRINT_COND(report_udp_fullduplex); + _print_stats_common(stats); + printf(report_udp_fullduplex_format, stats->common->transferIDStr, stats->ts.iStart, stats->ts.iEnd, outbuffer, outbufferext, \ + stats->cntDatagrams, (stats->cntIPG && (stats->IPGsum > 0.0) ? (stats->cntIPG / stats->IPGsum) : 0.0)); + fflush(stdout); +} + +void udp_output_fullduplex_enhanced (struct TransferInfo *stats) { + HEADING_PRINT_COND(report_udp_fullduplex); + _print_stats_common(stats); + printf(report_udp_fullduplex_enhanced_format, stats->common->transferID, stats->ts.iStart, stats->ts.iEnd, outbuffer, outbufferext, \ + stats->cntDatagrams, (stats->cntIPG && (stats->IPGsum > 0.0) ? (stats->cntIPG / stats->IPGsum) : 0.0)); + fflush(stdout); +} + +void udp_output_fullduplex_sum (struct TransferInfo *stats) { + HEADING_PRINT_COND(report_udp_fullduplex); + _print_stats_common(stats); + printf(report_udp_fullduplex_sum_format, stats->ts.iStart, stats->ts.iEnd, outbuffer, outbufferext, \ + stats->cntDatagrams, (stats->cntIPG && (stats->IPGsum > 0.0) ? (stats->cntIPG / stats->IPGsum) : 0.0)); + fflush(stdout); +} + + +void udp_output_read (struct TransferInfo *stats) { + HEADING_PRINT_COND(report_bw_jitter_loss); + _print_stats_common(stats); + printf(report_bw_jitter_loss_format, stats->common->transferIDStr, + stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + (stats->final) ? ((stats->inline_jitter.total.sum / (double) stats->inline_jitter.total.cnt) * 1e3) : (stats->jitter * 1e3), \ + stats->cntError, stats->cntDatagrams, + (100.0 * stats->cntError) / stats->cntDatagrams); + _output_outoforder(stats); + fflush(stdout); +} + +void udp_output_read_triptime (struct TransferInfo *stats) { + HEADING_PRINT_COND(report_bw_jitter_loss_enhanced_triptime); + _print_stats_common(stats); + if (!stats->cntIPG) { + printf(report_bw_jitter_loss_suppress_enhanced_format, stats->common->transferIDStr, + stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + 0.0, stats->cntError, + stats->cntDatagrams, + 0.0,0.0,0.0,0.0,0.0,0.0); + } else { + if ((stats->transit.current.min > UNREALISTIC_LATENCYMINMAX) || + (stats->transit.current.min < UNREALISTIC_LATENCYMINMIN)) { + printf(report_bw_jitter_loss_suppress_enhanced_format, stats->common->transferIDStr, + stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + (stats->final) ? ((stats->inline_jitter.total.sum / (double) stats->inline_jitter.total.cnt) * 1e3) : (stats->jitter * 1e3), + stats->cntError, stats->cntDatagrams, + (100.0 * stats->cntError) / stats->cntDatagrams, + (stats->cntIPG / stats->IPGsum)); + } else { + double meantransit; + double variance; + char llaw_bufstr[LLAWBUFSIZE]; + int lambda = ((stats->IPGsum > 0.0) ? (round (stats->cntIPG / stats->IPGsum)) : 0.0); + if (!stats->final) { + meantransit = (stats->transit.current.cnt > 0) ? (stats->transit.current.sum / stats->transit.current.cnt) : 0; + variance = (stats->transit.current.cnt < 2) ? 0 : \ + (sqrt(stats->transit.current.m2 / (stats->transit.current.cnt - 1))); + snprintf(llaw_bufstr, sizeof(llaw_bufstr), "%.0f(%.0f) pkts", stats->iInP, ((double) lambda * variance)); + } else { + meantransit = (stats->transit.total.cnt > 0) ? (stats->transit.total.sum / stats->transit.total.cnt) : 0; + variance = (stats->transit.total.cnt < 2) ? 0 : \ + (sqrt(stats->transit.total.m2 / (stats->transit.total.cnt - 1))); + snprintf(llaw_bufstr, sizeof(llaw_bufstr), "%.0f(%.0f) pkts", stats->fInP, ((double) lambda * variance)); + } + llaw_bufstr[sizeof(llaw_bufstr)-1] = '\0'; + set_netpowerbuf(meantransit, stats); + printf(report_bw_jitter_loss_enhanced_triptime_format, stats->common->transferIDStr, + stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + (stats->final) ? ((stats->inline_jitter.total.sum / (double) stats->inline_jitter.total.cnt) * 1e3) : (stats->jitter * 1e3), \ + stats->cntError, stats->cntDatagrams, + (100.0 * stats->cntError) / stats->cntDatagrams, + (meantransit * 1e3), + ((stats->final ? stats->transit.total.min : stats->transit.current.min) * 1e3), + ((stats->final ? stats->transit.total.max : stats->transit.current.max) * 1e3), + (stats->final ? (stats->transit.total.cnt < 2) : (stats->transit.current.cnt < 2)) ? 0 : (1e3 * variance), // convert from sec to ms + (stats->cntIPG / stats->IPGsum), + stats->cntIPG, + llaw_bufstr, + netpower_buf); + } + } + if (stats->latency_histogram) { + histogram_print(stats->latency_histogram, stats->ts.iStart, stats->ts.iEnd); + } + if (stats->jitter_histogram) { + histogram_print(stats->jitter_histogram, stats->ts.iStart, stats->ts.iEnd); + } + _output_outoforder(stats); + fflush(stdout); +} +void udp_output_read_enhanced (struct TransferInfo *stats) { + HEADING_PRINT_COND(report_bw_jitter_loss_enhanced); + _print_stats_common(stats); + if (!stats->cntIPG) { + printf(report_bw_jitter_loss_suppress_enhanced_format, stats->common->transferIDStr, + stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + 0.0, stats->cntError, + stats->cntDatagrams, + 0.0,0.0,0.0,0.0,0.0,0.0); + } else { + if ((stats->transit.current.min > UNREALISTIC_LATENCYMINMAX) || + (stats->transit.current.min < UNREALISTIC_LATENCYMINMIN)) { + printf(report_bw_jitter_loss_suppress_enhanced_format, stats->common->transferIDStr, + stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + (stats->final) ? ((stats->inline_jitter.total.sum / (double) stats->inline_jitter.total.cnt) * 1e3) : (stats->jitter * 1e3), + stats->cntError, stats->cntDatagrams, + (100.0 * stats->cntError) / stats->cntDatagrams, + (stats->cntIPG / stats->IPGsum)); + } else { + double meantransit; + double variance; + if (!stats->final) { + meantransit = (stats->transit.current.cnt > 0) ? (stats->transit.current.sum / stats->transit.current.cnt) : 0; + variance = (stats->transit.current.cnt < 2) ? 0 : \ + (sqrt(stats->transit.current.m2 / (stats->transit.current.cnt - 1))); + } else { + meantransit = (stats->transit.total.cnt > 0) ? (stats->transit.total.sum / stats->transit.total.cnt) : 0; + variance = (stats->transit.total.cnt < 2) ? 0 : \ + (sqrt(stats->transit.total.m2 / (stats->transit.total.cnt - 1))); + } + set_netpowerbuf(meantransit, stats); + printf(report_bw_jitter_loss_enhanced_format, stats->common->transferIDStr, + stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + (stats->final) ? ((stats->inline_jitter.total.sum / (double) stats->inline_jitter.total.cnt) * 1e3) : (stats->jitter * 1e3), \ + stats->cntError, stats->cntDatagrams, + (100.0 * stats->cntError) / stats->cntDatagrams, + (meantransit * 1e3), + ((stats->final ? stats->transit.total.min : stats->transit.current.min) * 1e3), + ((stats->final ? stats->transit.total.max : stats->transit.current.max) * 1e3), + (stats->final ? (stats->transit.total.cnt < 2) : (stats->transit.current.cnt < 2)) ? 0 : (1e3 * variance), // convert from sec to ms + (stats->cntIPG / stats->IPGsum), + netpower_buf); + } + } + if (stats->latency_histogram) { + histogram_print(stats->latency_histogram, stats->ts.iStart, stats->ts.iEnd); + } + if (stats->jitter_histogram) { + histogram_print(stats->jitter_histogram, stats->ts.iStart, stats->ts.iEnd); + } + _output_outoforder(stats); + fflush(stdout); +} +void udp_output_read_triptime_isoch (struct TransferInfo *stats) { + HEADING_PRINT_COND(report_bw_jitter_loss_enhanced_isoch_triptime); + _print_stats_common(stats); + if (!stats->cntIPG) { + printf(report_bw_jitter_loss_suppress_enhanced_format, stats->common->transferIDStr, + stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + 0.0, stats->cntError, + stats->cntDatagrams, + 0.0,0.0,0.0,0.0,0.0,0.0); + + } else { + // If the min latency is out of bounds of a realistic value + // assume the clocks are not synched and suppress the + // latency output + if ((stats->transit.current.min > UNREALISTIC_LATENCYMINMAX) || + (stats->transit.current.min < UNREALISTIC_LATENCYMINMIN)) { + printf(report_bw_jitter_loss_suppress_enhanced_format, stats->common->transferIDStr, + stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + (stats->final) ? ((stats->inline_jitter.total.sum / (double) stats->inline_jitter.total.cnt) * 1e3) : (stats->jitter * 1e3), + stats->cntError, stats->cntDatagrams, + (100.0 * stats->cntError) / stats->cntDatagrams, + (stats->cntIPG / stats->IPGsum)); + } else { + double frame_meantransit = (stats->isochstats.transit.current.cnt > 0) ? (stats->isochstats.transit.current.sum / stats->isochstats.transit.current.cnt) : 0; + double meantransit = (stats->transit.current.cnt > 0) ? (stats->transit.current.sum / stats->transit.current.cnt) : 0; + set_netpowerbuf(meantransit, stats); + printf(report_bw_jitter_loss_enhanced_isoch_format, stats->common->transferIDStr, + stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + (stats->final) ? ((stats->inline_jitter.total.sum / (double) stats->inline_jitter.total.cnt) * 1e3) : (stats->jitter * 1e3), \ + stats->cntError, stats->cntDatagrams, + (100.0 * stats->cntError) / stats->cntDatagrams, + (meantransit * 1e3), + stats->transit.current.min * 1e3, + stats->transit.current.max * 1e3, + (stats->transit.current.cnt < 2) ? 0 : 1e3 * (sqrt(stats->transit.current.m2 / (stats->transit.current.cnt - 1))), + (stats->cntIPG / stats->IPGsum), + stats->isochstats.cntFrames, stats->isochstats.cntFramesMissed, + (frame_meantransit * 1e3), + stats->isochstats.transit.current.min * 1e3, + stats->isochstats.transit.current.max * 1e3, + (stats->isochstats.transit.current.cnt < 2) ? 0 : 1e3 * (sqrt(stats->isochstats.transit.current.m2 / (stats->isochstats.transit.current.cnt - 1))), + netpower_buf); +#if 0 + if (stats->final) { + printf("***** Jitter MMM = %f/%f/%f\n",stats->inline_jitter.total.mean, stats->inline_jitter.total.min, stats->inline_jitter.total.max); + } +#endif + } + } + if (stats->latency_histogram) { + histogram_print(stats->latency_histogram, stats->ts.iStart, stats->ts.iEnd); + } + if (stats->jitter_histogram) { + histogram_print(stats->jitter_histogram, stats->ts.iStart, stats->ts.iEnd); + } + if (stats->framelatency_histogram) { + histogram_print(stats->framelatency_histogram, stats->ts.iStart, stats->ts.iEnd); + } + _output_outoforder(stats); + fflush(stdout); +} +void udp_output_write (struct TransferInfo *stats) { + HEADING_PRINT_COND(report_bw); + _print_stats_common(stats); + printf(report_bw_format, stats->common->transferIDStr, + stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext); + fflush(stdout); +} + +void udp_output_write_enhanced (struct TransferInfo *stats) { + HEADING_PRINT_COND(report_bw_pps_enhanced); + _print_stats_common(stats); + printf(report_bw_pps_enhanced_format, stats->common->transferIDStr, + stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + stats->sock_callstats.write.WriteCnt, + stats->sock_callstats.write.WriteErr, + (stats->cntIPG ? (stats->cntIPG / stats->IPGsum) : 0.0)); + fflush(stdout); +} +void udp_output_write_enhanced_isoch (struct TransferInfo *stats) { + HEADING_PRINT_COND(report_bw_pps_enhanced_isoch); + _print_stats_common(stats); + printf(report_bw_pps_enhanced_isoch_format, stats->common->transferIDStr, + stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + stats->sock_callstats.write.WriteCnt, + stats->sock_callstats.write.WriteErr, + (stats->cntIPG ? (stats->cntIPG / stats->IPGsum) : 0.0), + stats->isochstats.cntFrames, stats->isochstats.cntFramesMissed, stats->isochstats.cntSlips); + fflush(stdout); +} + +// Sum reports +void udp_output_sum_read (struct TransferInfo *stats) { + HEADING_PRINT_COND(report_bw); + _print_stats_common(stats); + printf(report_sum_bw_jitter_loss_format, + stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + stats->cntError, stats->cntDatagrams, + (100.0 * stats->cntError) / stats->cntDatagrams); + if ((stats->cntOutofOrder > 0) && stats->final) { + printf(report_sum_outoforder, + stats->ts.iStart, + stats->ts.iEnd, stats->cntOutofOrder); + } + fflush(stdout); +} +void udp_output_sumcnt (struct TransferInfo *stats) { + HEADING_PRINT_COND(report_sumcnt_bw); + _print_stats_common(stats); + printf(report_sumcnt_bw_format, stats->threadcnt, + stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext); + if ((stats->cntOutofOrder > 0) && stats->final) { + if (isSumOnly(stats->common)) { + printf(report_sumcnt_outoforder, + stats->threadcnt, + stats->ts.iStart, + stats->ts.iEnd, stats->cntOutofOrder); + } else { + printf(report_outoforder, + stats->common->transferIDStr, stats->ts.iStart, + stats->ts.iEnd, stats->cntOutofOrder); + } + } + fflush(stdout); +} +void udp_output_sumcnt_enhanced (struct TransferInfo *stats) { + HEADING_PRINT_COND(report_sumcnt_bw_jitter_loss); + _print_stats_common(stats); + printf(report_sumcnt_bw_jitter_loss_format, stats->threadcnt, stats->ts.iStart, stats->ts.iEnd, outbuffer, outbufferext, \ + stats->cntError, stats->cntDatagrams, (stats->cntIPG && (stats->IPGsum > 0.0) ? (stats->cntIPG / stats->IPGsum) : 0.0)); + if ((stats->cntOutofOrder > 0) && stats->final) { + if (isSumOnly(stats->common)) { + printf(report_sumcnt_outoforder, + stats->threadcnt, + stats->ts.iStart, + stats->ts.iEnd, stats->cntOutofOrder); + } else { + printf(report_sum_outoforder, + stats->ts.iStart, + stats->ts.iEnd, stats->cntOutofOrder); + } + } + fflush(stdout); +} + +void udp_output_sumcnt_read_enhanced (struct TransferInfo *stats) { + HEADING_PRINT_COND(report_sumcnt_bw_read_enhanced); + _print_stats_common(stats); + printf(report_sumcnt_bw_read_enhanced_format, stats->threadcnt, + stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + (stats->final) ? ((stats->inline_jitter.total.sum / (double) stats->inline_jitter.total.cnt) * 1e3) : (stats->jitter * 1e3), \ + stats->cntError, stats->cntDatagrams, + (100.0 * stats->cntError) / stats->cntDatagrams); + if ((stats->cntOutofOrder > 0) && stats->final) { + if (isSumOnly(stats->common)) { + printf(report_sumcnt_outoforder, + stats->threadcnt, + stats->ts.iStart, + stats->ts.iEnd, stats->cntOutofOrder); + } else { + printf(report_sum_outoforder, + stats->ts.iStart, + stats->ts.iEnd, stats->cntOutofOrder); + } + } + fflush(stdout); +} + +void udp_output_sumcnt_read_triptime (struct TransferInfo *stats) { + HEADING_PRINT_COND(report_sumcnt_udp_triptime); + _print_stats_common(stats); + printf(report_sumcnt_udp_triptime_format, stats->threadcnt, stats->ts.iStart, stats->ts.iEnd, outbuffer, outbufferext, \ + stats->cntError, stats->cntDatagrams, stats->cntIPG, (stats->final ? stats->fInP : stats->iInP), (stats->cntIPG && (stats->IPGsum > 0.0) ? (stats->cntIPG / stats->IPGsum) : 0.0)); + if ((stats->cntOutofOrder > 0) && stats->final) { + if (isSumOnly(stats->common)) { + printf(report_sumcnt_outoforder, + stats->threadcnt, + stats->ts.iStart, + stats->ts.iEnd, stats->cntOutofOrder); + } else { + printf(report_sum_outoforder, + stats->ts.iStart, + stats->ts.iEnd, stats->cntOutofOrder); + } + } + fflush(stdout); +} + +void udp_output_sum_write (struct TransferInfo *stats) { + HEADING_PRINT_COND(report_bw); + _print_stats_common(stats); + printf(report_sum_bw_format, stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext); + fflush(stdout); +} +void udp_output_sumcnt_write (struct TransferInfo *stats) { + HEADING_PRINT_COND(report_sumcnt_bw); + _print_stats_common(stats); + printf(report_sumcnt_bw_format, stats->threadcnt, + stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext); + fflush(stdout); +} +void udp_output_sum_read_enhanced (struct TransferInfo *stats) { + HEADING_PRINT_COND(report_sumcnt_udp_enhanced); + _print_stats_common(stats); + printf(report_sumcnt_udp_enhanced_format, stats->threadcnt, + stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + stats->cntError, stats->cntDatagrams, + (stats->cntIPG ? (stats->cntIPG / stats->IPGsum) : 0.0)); + if (stats->latency_histogram && stats->final) { + histogram_print(stats->latency_histogram, stats->ts.iStart, stats->ts.iEnd); + } + if (stats->jitter_histogram && stats->final) { + histogram_print(stats->jitter_histogram, stats->ts.iStart, stats->ts.iEnd); + } + if ((stats->cntOutofOrder > 0) && stats->final) { + if (isSumOnly(stats->common)) { + printf(report_sumcnt_outoforder, + stats->threadcnt, + stats->ts.iStart, + stats->ts.iEnd, stats->cntOutofOrder); + } else { + printf(report_sum_outoforder, + stats->ts.iStart, + stats->ts.iEnd, stats->cntOutofOrder); + } + } + fflush(stdout); +} +void udp_output_sum_write_enhanced (struct TransferInfo *stats) { + HEADING_PRINT_COND(report_bw_pps_enhanced); + _print_stats_common(stats); + printf(report_sum_bw_pps_enhanced_format, + stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + stats->sock_callstats.write.WriteCnt, + stats->sock_callstats.write.WriteErr, + ((stats->cntIPG && (stats->IPGsum > 0.0)) ? (stats->cntIPG / stats->IPGsum) : 0.0)); + fflush(stdout); +} +void udp_output_sumcnt_write_enhanced (struct TransferInfo *stats) { + HEADING_PRINT_COND(report_sumcnt_bw_pps_enhanced); + _print_stats_common(stats); + printf(report_sumcnt_bw_pps_enhanced_format, stats->threadcnt, + stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + stats->sock_callstats.write.WriteCnt, + stats->sock_callstats.write.WriteErr, + ((stats->cntIPG && (stats->IPGsum > 0.0)) ? (stats->cntIPG / stats->IPGsum) : 0.0)); + fflush(stdout); +} + +void tcp_output_sum_read (struct TransferInfo *stats) { + HEADING_PRINT_COND(report_bw); + _print_stats_common(stats); + printf(report_sum_bw_format, + stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext); + fflush(stdout); +} +void tcp_output_sum_read_enhanced (struct TransferInfo *stats) { + HEADING_PRINT_COND(report_bw_read_enhanced); + _print_stats_common(stats); + printf(report_sum_bw_read_enhanced_format, + stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + stats->sock_callstats.read.cntRead, + stats->sock_callstats.read.bins[0], + stats->sock_callstats.read.bins[1], + stats->sock_callstats.read.bins[2], + stats->sock_callstats.read.bins[3], + stats->sock_callstats.read.bins[4], + stats->sock_callstats.read.bins[5], + stats->sock_callstats.read.bins[6], + stats->sock_callstats.read.bins[7]); + if (stats->framelatency_histogram && stats->final) { + histogram_print(stats->framelatency_histogram, stats->ts.iStart, stats->ts.iEnd); + } + fflush(stdout); +} +void tcp_output_sumcnt_read (struct TransferInfo *stats) { + HEADING_PRINT_COND(report_sumcnt_bw); + _print_stats_common(stats); + printf(report_sumcnt_bw_format, stats->threadcnt, + stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext); + fflush(stdout); +} +void tcp_output_sumcnt_read_enhanced (struct TransferInfo *stats) { + HEADING_PRINT_COND(report_sumcnt_bw_read_enhanced); + _print_stats_common(stats); + printf(report_sumcnt_bw_read_enhanced_format, stats->threadcnt, + stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + stats->sock_callstats.read.cntRead, + stats->sock_callstats.read.bins[0], + stats->sock_callstats.read.bins[1], + stats->sock_callstats.read.bins[2], + stats->sock_callstats.read.bins[3], + stats->sock_callstats.read.bins[4], + stats->sock_callstats.read.bins[5], + stats->sock_callstats.read.bins[6], + stats->sock_callstats.read.bins[7]); + fflush(stdout); +} +void tcp_output_sumcnt_read_triptime (struct TransferInfo *stats) { + HEADING_PRINT_COND(report_sumcnt_bw_read_triptime); + _print_stats_common(stats); + char llaw_bufstr[LLAWBUFSIZE]; + human_format_llawbuf(llaw_bufstr, sizeof(llaw_bufstr), ((stats->final) ? stats->fInP : stats->iInP)); + printf(report_sumcnt_bw_read_triptime_format, stats->threadcnt, + stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + llaw_bufstr, + stats->sock_callstats.read.cntRead, + stats->sock_callstats.read.bins[0], + stats->sock_callstats.read.bins[1], + stats->sock_callstats.read.bins[2], + stats->sock_callstats.read.bins[3], + stats->sock_callstats.read.bins[4], + stats->sock_callstats.read.bins[5], + stats->sock_callstats.read.bins[6], + stats->sock_callstats.read.bins[7]); + fflush(stdout); +} + +void tcp_output_sum_write (struct TransferInfo *stats) { + HEADING_PRINT_COND(report_bw); + _print_stats_common(stats); + printf(report_sum_bw_format, + stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext); + fflush(stdout); +} +void tcp_output_sumcnt_write (struct TransferInfo *stats) { + HEADING_PRINT_COND(report_sumcnt_bw); + _print_stats_common(stats); + printf(report_sumcnt_bw_format, stats->threadcnt, + stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext); + fflush(stdout); +} +void tcp_output_sum_write_enhanced (struct TransferInfo *stats) { + HEADING_PRINT_COND(report_bw_write_enhanced); + _print_stats_common(stats); + printf(report_sum_bw_write_enhanced_format, + stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + stats->sock_callstats.write.WriteCnt, + stats->sock_callstats.write.WriteErr +#if HAVE_TCP_STATS + ,stats->sock_callstats.write.tcpstats.retry +#endif + ); + fflush(stdout); +} +void tcp_output_sumcnt_write_enhanced (struct TransferInfo *stats) { + HEADING_PRINT_COND(report_sumcnt_bw_write_enhanced); + _print_stats_common(stats); + printf(report_sumcnt_bw_write_enhanced_format, stats->threadcnt, + stats->ts.iStart, stats->ts.iEnd, + outbuffer, outbufferext, + stats->sock_callstats.write.WriteCnt, + stats->sock_callstats.write.WriteErr +#if HAVE_TCP_STATS + ,stats->sock_callstats.write.tcpstats.retry +#endif + ); + fflush(stdout); +} + +// CSV outputs +void format_ips_port_string (struct TransferInfo *stats, bool sum) { + char local_addr[REPORT_ADDRLEN]; + char remote_addr[REPORT_ADDRLEN]; + uint16_t local_port; + uint16_t remote_port; + int swap = (stats->common->ThreadMode == kMode_Server); + int reverse = (isServerReverse(stats->common) || isReverse(stats->common)); + struct sockaddr *local = (swap ? (struct sockaddr*)&stats->common->peer : (struct sockaddr*)&stats->common->local); + struct sockaddr *peer = (swap ? (struct sockaddr*)&stats->common->local : (struct sockaddr*)&stats->common->peer); + + if (local->sa_family == AF_INET) { + if (isHideIPs(stats->common)) { + inet_ntop_hide(AF_INET, &((struct sockaddr_in*)local)->sin_addr, + local_addr, REPORT_ADDRLEN); + } else { + inet_ntop(AF_INET, &((struct sockaddr_in*)local)->sin_addr, + local_addr, REPORT_ADDRLEN); + } + if (!reverse && sum) + local_port = 0; + else + local_port = ntohs(((struct sockaddr_in*)local)->sin_port); + } else { +#if HAVE_IPV6 + if (local->sa_family == AF_INET6) { + inet_ntop(AF_INET6, &((struct sockaddr_in6*)local)->sin6_addr, + local_addr, REPORT_ADDRLEN); + if (swap && sum) + local_port = 0; + else + local_port = ntohs(((struct sockaddr_in6*)local)->sin6_port); + } else +#endif + { + local_addr[0] = '\0'; + local_port = 0; + } + } + + if (peer->sa_family == AF_INET) { + if (isHideIPs(stats->common)) { + inet_ntop_hide(AF_INET, &((struct sockaddr_in*)peer)->sin_addr, + remote_addr, REPORT_ADDRLEN); + } else { + inet_ntop(AF_INET, &((struct sockaddr_in*)peer)->sin_addr, + remote_addr, REPORT_ADDRLEN); + } + if (reverse && sum) + remote_port = 0; + else + remote_port = ntohs(((struct sockaddr_in*)peer)->sin_port); + } else { +#if HAVE_IPV6 + if (local->sa_family == AF_INET6) { + inet_ntop(AF_INET6, &((struct sockaddr_in6*)peer)->sin6_addr, + remote_addr, REPORT_ADDRLEN); + if (!swap && sum) + remote_port = 0; + else + remote_port = ntohs(((struct sockaddr_in6*)peer)->sin6_port); + } else +#endif + { + remote_addr[0] = '\0'; + remote_port = 0; + } + } + + snprintf((char *)&stats->csv_peer, CSVPEERLIMIT, reportCSV_peer, + local_addr, local_port, + remote_addr, remote_port); + stats->csv_peer[(CSVPEERLIMIT-1)] = '\0'; +#if 0 // use to debug CSV ouput + printf("*** output = %s swap=%d reverse=%d sum=%d\n", stats->csv_peer, swap, reverse, sum); +#endif +} + +void udp_output_basic_csv (struct TransferInfo *stats) { + char timestr[120]; + iperf_formattime(timestr, sizeof(timestr), (!stats->final ? stats->ts.nextTime : stats->ts.packetTime), \ + isEnhanced(stats->common), isUTC(stats->common), (isEnhanced(stats->common) ? CSVTZ : CSV)); + intmax_t speed = (intmax_t) (((stats->cntBytes > 0) && (stats->ts.iEnd - stats->ts.iStart) > 0.0) ? \ + (((double)stats->cntBytes * 8.0) / (stats->ts.iEnd - stats->ts.iStart)) : 0); + printf(reportCSV_bw_jitter_loss_format, + timestr, + stats->csv_peer, + stats->common->transferID, + stats->ts.iStart, + stats->ts.iEnd, + stats->cntBytes, + speed, + (stats->final) ? ((stats->inline_jitter.total.sum / (double) stats->inline_jitter.total.cnt) * 1e3) : (stats->jitter * 1e3), + stats->cntError, + stats->cntDatagrams, + (100.0 * stats->cntError) / stats->cntDatagrams, stats->cntOutofOrder ); +} + +void udp_output_enhanced_csv (struct TransferInfo *stats) { + char timestr[80]; + iperf_formattime(timestr, sizeof(timestr), (!stats->final ? stats->ts.nextTime : stats->ts.packetTime), \ + isEnhanced(stats->common), isUTC(stats->common), + isEnhanced(stats->common) ? CSVTZ : CSV); + intmax_t speed = (intmax_t) (((stats->cntBytes > 0) && (stats->ts.iEnd - stats->ts.iStart) > 0.0) ? \ + (((double)stats->cntBytes * 8.0) / (stats->ts.iEnd - stats->ts.iStart)) : 0); + printf(reportCSV_bw_jitter_loss_pps_format, + timestr, + stats->csv_peer, + stats->common->transferID, + stats->ts.iStart, + stats->ts.iEnd, + stats->cntBytes, + speed, + (stats->jitter * 1e3), + stats->cntError, + stats->cntDatagrams, + (100.0 * stats->cntError) / stats->cntDatagrams, + stats->cntOutofOrder, + stats->sock_callstats.write.WriteCnt, + stats->sock_callstats.write.WriteErr, + (stats->cntIPG ? (stats->cntIPG / stats->IPGsum) : 0.0)); +} + +void tcp_output_basic_csv (struct TransferInfo *stats) { + char timestr[80]; + iperf_formattime(timestr, sizeof(timestr), (!stats->final ? stats->ts.nextTime : stats->ts.packetTime), \ + isEnhanced(stats->common), isUTC(stats->common), (isEnhanced(stats->common) ? CSVTZ : CSV)); + intmax_t speed = (intmax_t) (((stats->cntBytes > 0) && (stats->ts.iEnd - stats->ts.iStart) > 0.0) ? \ + (((double)stats->cntBytes * 8.0) / (stats->ts.iEnd - stats->ts.iStart)) : 0); + printf(reportCSV_bw_format, + timestr, + stats->csv_peer, + stats->common->transferID, + stats->ts.iStart, + stats->ts.iEnd, + stats->cntBytes, + speed); +} + +void tcp_output_read_enhanced_csv (struct TransferInfo *stats) { + char timestr[80]; + iperf_formattime(timestr, sizeof(timestr), (!stats->final ? stats->ts.nextTime : stats->ts.packetTime), \ + isEnhanced(stats->common), isUTC(stats->common), + isEnhanced(stats->common) ? CSVTZ : CSV); + intmax_t speed = (intmax_t) (((stats->cntBytes > 0) && (stats->ts.iEnd - stats->ts.iStart) > 0.0) ? \ + (((double)stats->cntBytes * 8.0) / (stats->ts.iEnd - stats->ts.iStart)) : 0); + printf(reportCSV_bw_read_enhanced_format, + timestr, + stats->csv_peer, + stats->common->transferID, + stats->ts.iStart, + stats->ts.iEnd, + stats->cntBytes, + speed, + stats->sock_callstats.read.cntRead, + stats->sock_callstats.read.bins[0], + stats->sock_callstats.read.bins[1], + stats->sock_callstats.read.bins[2], + stats->sock_callstats.read.bins[3], + stats->sock_callstats.read.bins[4], + stats->sock_callstats.read.bins[5], + stats->sock_callstats.read.bins[6], + stats->sock_callstats.read.bins[7]); +} + +void tcp_output_write_enhanced_csv (struct TransferInfo *stats) { + char timestr[80]; + iperf_formattime(timestr, sizeof(timestr), (!stats->final ? stats->ts.nextTime : stats->ts.packetTime), \ + isEnhanced(stats->common), isUTC(stats->common), + isEnhanced(stats->common) ? CSVTZ : CSV); + intmax_t speed = (intmax_t) (((stats->cntBytes > 0) && (stats->ts.iEnd - stats->ts.iStart) > 0.0) ? \ + (((double)stats->cntBytes * 8.0) / (stats->ts.iEnd - stats->ts.iStart)) : 0); +#if !(HAVE_TCP_STATS) + printf(reportCSV_bw_write_enhanced_format, + timestr, + stats->csv_peer, + stats->common->transferID, + stats->ts.iStart, + stats->ts.iEnd, + stats->cntBytes, + speed, + -1, + -1, + -1, + -1, + 0, + 0); +#else + if (stats->common->transferID == -1) { + /* Sums */ + printf(reportCSV_bw_write_enhanced_format, + timestr, + stats->csv_peer, + stats->common->transferID, + stats->ts.iStart, + stats->ts.iEnd, + stats->cntBytes, + speed, + stats->sock_callstats.write.WriteCnt, + stats->sock_callstats.write.WriteErr, + stats->sock_callstats.write.tcpstats.retry, + -1, + 0, + 0); + } else if (stats->sock_callstats.write.tcpstats.cwnd > 0) { + printf(reportCSV_bw_write_enhanced_format, + timestr, + stats->csv_peer, + stats->common->transferID, + stats->ts.iStart, + stats->ts.iEnd, + stats->cntBytes, + speed, + stats->sock_callstats.write.WriteCnt, + stats->sock_callstats.write.WriteErr, + stats->sock_callstats.write.tcpstats.retry, + stats->sock_callstats.write.tcpstats.cwnd, + stats->sock_callstats.write.tcpstats.rtt, + stats->sock_callstats.write.tcpstats.rttvar); + } else { + printf(reportCSV_bw_write_enhanced_format, + timestr, + stats->csv_peer, + stats->common->transferID, + stats->ts.iStart, + stats->ts.iEnd, + stats->cntBytes, + speed, + stats->sock_callstats.write.WriteCnt, + stats->sock_callstats.write.WriteErr, + stats->sock_callstats.write.tcpstats.retry, + -1, + stats->sock_callstats.write.tcpstats.rtt, + 0); + } +#endif +} + +/* + * Report the client or listener Settings in default style + */ +static void output_window_size (struct ReportSettings *report) { + int winsize = getsock_tcp_windowsize(report->common->socket, (report->common->ThreadMode != kMode_Client ? 0 : 1)); + byte_snprintf(outbuffer, sizeof(outbuffer), winsize, \ + ((toupper(report->common->Format) == 'B') ? 'B' : 'A')); + outbuffer[(sizeof(outbuffer)-1)] = '\0'; + printf("%s: %s", (isUDP(report->common) ? udp_buffer_size : tcp_window_size), outbuffer); + if (report->common->winsize_requested == 0) { + printf(" %s", window_default); + } else if (winsize != report->common->winsize_requested) { + byte_snprintf(outbuffer, sizeof(outbuffer), report->common->winsize_requested, + toupper((int)report->common->Format)); + outbuffer[(sizeof(outbuffer)-1)] = '\0'; + printf(warn_window_requested, outbuffer); + } + fflush(stdout); +} +static void reporter_output_listener_settings (struct ReportSettings *report) { + if (report->common->PortLast > report->common->Port) { + printf(server_pid_portrange, (isUDP(report->common) ? "UDP" : "TCP"), \ + report->common->Port, report->common->PortLast, report->pid); + } else { + printf(isEnhanced(report->common) ? server_pid_port : server_port, + (isUDP(report->common) ? "UDP" : "TCP"), report->common->Port, report->pid); + } + if (report->common->Localhost != NULL) { + if (isEnhanced(report->common) && !SockAddr_isMulticast(&report->local)) { + if (report->common->Ifrname) { + printf(bind_address_iface, report->common->Localhost, report->common->Ifrname); + } else { + char *host_ip = (char *) malloc(REPORT_ADDRLEN); + if (host_ip != NULL) { + if (((struct sockaddr*)(&report->common->local))->sa_family == AF_INET) { + if (isHideIPs(report->common)) { + inet_ntop_hide(AF_INET, &((struct sockaddr_in*)(&report->common->local))->sin_addr, + host_ip, REPORT_ADDRLEN); + } else { + inet_ntop(AF_INET, &((struct sockaddr_in*)(&report->common->local))->sin_addr, + host_ip, REPORT_ADDRLEN); + } + } +#if HAVE_IPV6 + else { + inet_ntop(AF_INET6, &((struct sockaddr_in6*)(&report->common->local))->sin6_addr, + host_ip, REPORT_ADDRLEN); + } +#endif + printf(bind_address, host_ip); + free(host_ip); + } + } + } + if (SockAddr_isMulticast(&report->local)) { + if(!report->common->SSMMulticastStr) + if (!report->common->Ifrname) + printf(join_multicast, report->common->Localhost); + else + printf(join_multicast_starg_dev, report->common->Localhost,report->common->Ifrname); + else if(!report->common->Ifrname) + printf(join_multicast_sg, report->common->SSMMulticastStr, report->common->Localhost); + else + printf(join_multicast_sg_dev, report->common->SSMMulticastStr, report->common->Localhost, report->common->Ifrname); + } + } + if (isTunDev(report->common) || isTapDev(report->common)) { + printf(bind_address_iface_taptun, report->common->Ifrname); + } + if (isEnhanced(report->common)) { + byte_snprintf(outbuffer, sizeof(outbuffer), report->common->BufLen, toupper((int)report->common->Format)); + byte_snprintf(outbufferext, sizeof(outbufferext), report->common->BufLen / 8, 'A'); + outbuffer[(sizeof(outbuffer)-1)] = '\0'; + outbufferext[(sizeof(outbufferext)-1)] = '\0'; + printf("%s: %s (Dist bin width=%s)\n", server_read_size, outbuffer, outbufferext); + } + if (isCongestionControl(report->common) && report->common->Congestion) { + fprintf(stdout, "TCP congestion control set to %s\n", report->common->Congestion); + } + if (isOverrideTOS(report->common)) { + fprintf(stdout, "Reflected TOS will be set to 0x%x\n", report->common->RTOS); + } + if (isPrintMSS(report->common)) { + if (isTCPMSS(report->common)) { + printf(report_mss, report->sockmaxseg); + } else { + printf(report_default_mss, report->sockmaxseg); + } + } + if (report->common->TOS) { + fprintf(stdout, "TOS will be set to 0x%x\n", report->common->TOS); + } + if (isUDP(report->common)) { + if (isSingleClient(report->common)) { + fprintf(stdout, "WARN: Suggested to use lower case -u instead of -U (to avoid serialize & bypass of reporter thread)\n"); + } else if (isSingleClient(report->common)) { + fprintf(stdout, "Server set to single client traffic mode per -U (serialize traffic tests)\n"); + } + } else if (isSingleClient(report->common)) { + fprintf(stdout, "Server set to single client traffic mode (serialize traffic tests)\n"); + } + if (isMulticast(report->common)) { + fprintf(stdout, "Server set to single client traffic mode (per multicast receive)\n"); + } + if (isHistogram(report->common)) { + fprintf(stdout, "Enabled receive histograms bin-width=%0.3f ms, bins=%d (clients should use --trip-times)\n", \ + ((1e3 * report->common->HistBinsize) / pow(10,report->common->HistUnits)), report->common->HistBins); + } + if (isJitterHistogram(report->common)) { + fprintf(stdout, "Enabled jitter histograms (bin-width=%d us)\n", report->common->jitter_binwidth); + } + if (isFrameInterval(report->common)) { +#if HAVE_FASTSAMPLING + fprintf(stdout, "Frame or burst interval reporting (feature is experimental)\n"); +#else + fprintf(stdout, "Frame or burst interval reporting (feature is experimental, ./configure --enable-fastsampling suggested)\n"); +#endif + } + output_window_size(report); + printf("\n"); + if (isPermitKey(report->common) && report->common->PermitKey) { + if (report->common->ListenerTimeout > 0) { + fprintf(stdout, "Permit key is '%s' (timeout in %0.1f seconds)\n", report->common->PermitKey, report->common->ListenerTimeout); + } else { + fprintf(stdout, "Permit key is '%s' (WARN: no timeout)\n", report->common->PermitKey); + } + } + fflush(stdout); +} +static void reporter_output_client_settings (struct ReportSettings *report) { + char *hoststr = (isHideIPs(report->common) ? report->common->HideHost \ + : report->common->Host); + if (!report->common->Ifrnametx) { + printf(isEnhanced(report->common) ? client_pid_port : client_port, hoststr, + (isUDP(report->common) ? "UDP" : "TCP"), report->common->Port, report->pid, \ + (!report->common->threads ? 1 : report->common->threads)); + } else { + printf(client_pid_port_dev, hoststr, + (isUDP(report->common) ? "UDP" : "TCP"), report->common->Port, report->pid, \ + report->common->Ifrnametx, (!report->common->threads ? 1 : report->common->threads)); + } + if ((isEnhanced(report->common) || isNearCongest(report->common)) && !isUDP(report->common)) { + byte_snprintf(outbuffer, sizeof(outbuffer), report->common->BufLen, 'B'); + outbuffer[(sizeof(outbuffer)-1)] = '\0'; + if (isTcpWriteTimes(report->common)) { + printf("%s: %s (writetimer-enabled)\n", client_write_size, outbuffer); + } else { + printf("%s: %s\n", client_write_size, outbuffer); + } + } + if (isIsochronous(report->common)) { + char meanbuf[40]; + char variancebuf[40]; + byte_snprintf(meanbuf, sizeof(meanbuf), report->isochstats.mMean, 'a'); + byte_snprintf(variancebuf, sizeof(variancebuf), report->isochstats.mVariance, 'a'); + meanbuf[39]='\0'; variancebuf[39]='\0'; + printf(client_isochronous, report->isochstats.mFPS, meanbuf, variancebuf, (report->isochstats.mBurstInterval/1000.0), (report->isochstats.mBurstIPG/1000.0)); + } + if (isPeriodicBurst(report->common)) { + char tmpbuf[40]; + byte_snprintf(tmpbuf, sizeof(tmpbuf), report->common->BurstSize, 'A'); + tmpbuf[39]='\0'; + if (report->common->bbcount) { + printf(client_burstperiodcount, tmpbuf, report->common->bbcount, (1.0 / report->common->FPS)); + } else { + printf(client_burstperiod, tmpbuf, (1.0 / report->common->FPS)); + } + } + if (isBounceBack(report->common)) { + char tmpbuf[40]; + byte_snprintf(tmpbuf, sizeof(tmpbuf), report->common->bbsize, 'A'); + tmpbuf[39]='\0'; + if (isTcpQuickAck(report->common)) { + printf(client_bounceback, tmpbuf, report->common->bbhold); + } else { + printf(client_bounceback_noqack, tmpbuf, report->common->bbhold); + } + } + if (isFQPacing(report->common)) { + byte_snprintf(outbuffer, sizeof(outbuffer), report->common->FQPacingRate, 'a'); + outbuffer[(sizeof(outbuffer)-1)] = '\0'; + printf(client_fq_pacing,outbuffer); + } + if (isPrintMSS(report->common)) { + if (isTCPMSS(report->common)) { + printf(report_mss, report->sockmaxseg); + } else { + printf(report_default_mss, report->sockmaxseg); + } + } + + if (isCongestionControl(report->common) && report->common->Congestion) { + fprintf(stdout, "TCP congestion control set to %s\n", report->common->Congestion); + } + if (isEnhanced(report->common)) { + if (isNoDelay(report->common)) { + fprintf(stdout, "TOS set to 0x%x and nodelay (Nagle off)\n", report->common->TOS); + } else { + fprintf(stdout, "TOS set to 0x%x (Nagle on)\n", report->common->TOS); + } + } + if (isNearCongest(report->common)) { + if (report->common->rtt_weight == NEARCONGEST_DEFAULT) { + fprintf(stdout, "TCP near-congestion delay weight set to %2.4f (use --near-congestion=<value> to change)\n", report->common->rtt_weight); + } else { + fprintf(stdout, "TCP near-congestion delay weight set to %2.4f\n", report->common->rtt_weight); + } + } + if (isSingleClient(report->common)) { + fprintf(stdout, "WARN: Client set to bypass reporter thread per -U (suggest use lower case -u instead)\n"); + } + if ((isIPG(report->common) || isUDP(report->common)) && !isIsochronous(report->common)) { + byte_snprintf(outbuffer, sizeof(outbuffer), report->common->pktIPG, 'a'); + outbuffer[(sizeof(outbuffer)-1)] = '\0'; +#ifdef HAVE_KALMAN + printf(client_datagram_size_kalman, report->common->BufLen, report->common->pktIPG); +#else + printf(client_datagram_size, report->common->BufLen, report->common->pktIPG); +#endif + } + if (isConnectOnly(report->common)) { + fprintf(stdout, "TCP three-way-handshake (3WHS) only\n"); + } else { + output_window_size(report); + printf("\n"); +#if HAVE_DECL_TCP_NOTSENT_LOWAT + if (isWritePrefetch(report->common)) { + fprintf(stdout, "Event based writes (pending queue watermark at %d bytes)\n", report->common->WritePrefetch); + } +#endif + if (isHistogram(report->common)) { + if (!isBounceBack(report->common)) { + fprintf(stdout, "Enabled write histograms bin-width=%0.3f ms, bins=%d\n", \ + ((1e3 * report->common->HistBinsize) / pow(10,report->common->HistUnits)), report->common->HistBins); + } else { + fprintf(stdout, "Set bounceback histograms to bin-width=%0.3f ms, bins=%d\n", \ + ((1e3 * report->common->HistBinsize) / pow(10,report->common->HistUnits)), report->common->HistBins); + } + } + } + fflush(stdout); +} + +void reporter_connect_printf_tcp_final (struct ConnectionInfo * report) { + if (report->connect_times.cnt > 1) { + double variance = (report->connect_times.cnt < 2) ? 0 : 1e3* (sqrt(report->connect_times.m2 / (report->connect_times.cnt - 1))); + fprintf(stdout, "[ CT] final connect times (min/avg/max/stdev) = %0.3f/%0.3f/%0.3f/%0.3f ms (tot/err) = %" PRIdMAX "/%" PRIdMAX "\n", \ + report->connect_times.min, \ + (report->connect_times.sum / report->connect_times.cnt), \ + report->connect_times.max, variance, \ + (report->connect_times.cnt + report->connect_times.err), \ + report->connect_times.err); + } + fflush(stdout); +} + +void reporter_print_connection_report (struct ConnectionInfo *report) { + assert(report->common); + // copy the inet_ntop into temp buffers, to avoid overwriting + char local_addr[REPORT_ADDRLEN]; + char remote_addr[REPORT_ADDRLEN]; + struct sockaddr *local = ((struct sockaddr*)&report->common->local); + struct sockaddr *peer = ((struct sockaddr*)&report->common->peer); + outbuffer[0]='\0'; + outbufferext[0]='\0'; + char *b = &outbuffer[0]; + +#if HAVE_DECL_TCP_WINDOW_CLAMP + if (!isUDP(report->common) && isRxClamp(report->common)) { + snprintf(b, SNBUFFERSIZE-strlen(b), " (%s%d)", "clamp=", report->common->ClampSize); + b += strlen(b); + } +#endif +#if HAVE_DECL_TCP_NOTSENT_LOWAT + if (!isUDP(report->common) && (report->common->socket > 0) && isWritePrefetch(report->common)) { + snprintf(b, SNBUFFERSIZE-strlen(b), " (%s%d)", "prefetch=", report->common->WritePrefetch); + b += strlen(b); + } +#endif + if (isIsochronous(report->common)) { + snprintf(b, SNBUFFERSIZE-strlen(b), " (isoch)"); + b += strlen(b); + } + if (isPeriodicBurst(report->common) && (report->common->ThreadMode != kMode_Client) && !isServerReverse(report->common)) { +#if HAVE_FASTSAMPLING + snprintf(b, SNBUFFERSIZE-strlen(b), " (burst-period=%0.4fs)", (1.0 / report->common->FPS)); +#else + snprintf(b, SNBUFFERSIZE-strlen(b), " (burst-period=%0.2fs)", (1.0 / report->common->FPS)); +#endif + b += strlen(b); + } + if (isFullDuplex(report->common)) { + snprintf(b, SNBUFFERSIZE-strlen(b), " (full-duplex)"); + b += strlen(b); + } else if (isServerReverse(report->common) || isReverse(report->common)) { + snprintf(b, SNBUFFERSIZE-strlen(b), " (reverse)"); + b += strlen(b); + if (isFQPacing(report->common)) { + snprintf(b, SNBUFFERSIZE-strlen(b), " (fq)"); + b += strlen(b); + } + } + if (isTxStartTime(report->common)) { + snprintf(b, SNBUFFERSIZE-strlen(b), " (epoch-start)"); + b += strlen(b); + } + if (isBounceBack(report->common)) { + if (isTcpQuickAck(report->common)) { + snprintf(b, SNBUFFERSIZE-strlen(b), " (bb w/quickack len/hold=%d/%d)", report->common->bbsize, report->common->bbhold); + } else { + snprintf(b, SNBUFFERSIZE-strlen(b), " (bb len/hold=%d/%d)", report->common->bbsize, report->common->bbhold); + } + b += strlen(b); + } + if (isL2LengthCheck(report->common)) { + snprintf(b, SNBUFFERSIZE-strlen(b), " (l2mode)"); + b += strlen(b); + } + if (isUDP(report->common) && isNoUDPfin(report->common)) { + snprintf(b, SNBUFFERSIZE-strlen(b), " (no-udp-fin)"); + b += strlen(b); + } + if (isTripTime(report->common)) { + snprintf(b, SNBUFFERSIZE-strlen(b), " (trip-times)"); + b += strlen(b); + } + if (isEnhanced(report->common)) { + snprintf(b, SNBUFFERSIZE-strlen(b), " (sock=%d)", report->common->socket);; + b += strlen(b); + } + if (isOverrideTOS(report->common)) { + if (isFullDuplex(report->common)) { + snprintf(b, SNBUFFERSIZE-strlen(b), " (tos rx/tx=0x%x/0x%x)", report->common->TOS, report->common->RTOS); + } else if (isReverse(report->common)) { + snprintf(b, SNBUFFERSIZE-strlen(b), " (tos tx=0x%x)", report->common->TOS); + } + b += strlen(b); + } else if (report->common->TOS) { + if (isFullDuplex(report->common) || isBounceBack(report->common)) { + snprintf(b, SNBUFFERSIZE-strlen(b), " (tos rx/tx=0x%x/0x%x)", report->common->TOS, report->common->TOS); + } else if (isReverse(report->common)) { + snprintf(b, SNBUFFERSIZE-strlen(b), " (tos tx=0x%x)", report->common->TOS); + } else { + snprintf(b, SNBUFFERSIZE-strlen(b), " (tos rx=0x%x)", report->common->TOS); + } + b += strlen(b); + } + if (isEnhanced(report->common) || isPeerVerDetect(report->common)) { + if (report->peerversion[0] != '\0') { + snprintf(b, SNBUFFERSIZE-strlen(b), "%s", report->peerversion); + b += strlen(b); + } + } +#if HAVE_DECL_TCP_QUICKACK + if (isTcpQuickAck(report->common) && !isBounceBack(report->common)) { + snprintf(b, SNBUFFERSIZE-strlen(b), " (qack)"); + b += strlen(b); + } +#endif +#if HAVE_TCP_STATS + if (!isUDP(report->common) && (report->tcpinitstats.isValid)) { + snprintf(b, SNBUFFERSIZE-strlen(b), " (icwnd/mss/irtt=%u/%u/%u)", \ + report->tcpinitstats.cwnd, report->tcpinitstats.mss_negotiated, report->tcpinitstats.rtt); + b += strlen(b); + } +#endif + + if ((isFullDuplex(report->common) || !isServerReverse(report->common)) \ + && (isEnhanced(report->common) || isConnectOnly(report->common))) { + if (report->connect_timestamp.tv_sec > 0) { + char timestr[80]; + iperf_formattime(timestr, sizeof(timestr), report->connect_timestamp, \ + isEnhanced(report->common), isUTC(report->common), YearThruSecTZ); + if (!isUDP(report->common) && (report->common->ThreadMode == kMode_Client) && (report->tcpinitstats.connecttime > 0)) { + snprintf(b, SNBUFFERSIZE-strlen(b), " (ct=%4.2f ms) on %s", report->tcpinitstats.connecttime, timestr); + } else { + snprintf(b, SNBUFFERSIZE-strlen(b), " on %s", timestr); + } + b += strlen(b); + } + } + if (local->sa_family == AF_INET) { + if (isHideIPs(report->common)) { + inet_ntop_hide(AF_INET, &((struct sockaddr_in*)local)->sin_addr, local_addr, REPORT_ADDRLEN); + } else { + inet_ntop(AF_INET, &((struct sockaddr_in*)local)->sin_addr, local_addr, REPORT_ADDRLEN); + } + } +#if HAVE_IPV6 + else { + inet_ntop(AF_INET6, &((struct sockaddr_in6*)local)->sin6_addr, local_addr, REPORT_ADDRLEN); + } +#endif + if (peer->sa_family == AF_INET) { + if (isHideIPs(report->common)) { + inet_ntop_hide(AF_INET, &((struct sockaddr_in*)peer)->sin_addr, remote_addr, REPORT_ADDRLEN); + } else { + inet_ntop(AF_INET, &((struct sockaddr_in*)peer)->sin_addr, remote_addr, REPORT_ADDRLEN); + } + } +#if HAVE_IPV6 + else { + inet_ntop(AF_INET6, &((struct sockaddr_in6*)peer)->sin6_addr, remote_addr, REPORT_ADDRLEN); + } +#endif +#if HAVE_IPV6 + if (report->common->KeyCheck) { + if (isEnhanced(report->common) && report->common->Ifrname && (strlen(report->common->Ifrname) < SNBUFFERSIZE-strlen(b))) { + printf(report_peer_dev, report->common->transferIDStr, local_addr, report->common->Ifrname, \ + (local->sa_family == AF_INET ? ntohs(((struct sockaddr_in*)local)->sin_port) : \ + ntohs(((struct sockaddr_in6*)local)->sin6_port)), \ + remote_addr, (peer->sa_family == AF_INET ? ntohs(((struct sockaddr_in*)peer)->sin_port) : \ + ntohs(((struct sockaddr_in6*)peer)->sin6_port)), outbuffer); + } else { + printf(report_peer, report->common->transferIDStr, local_addr, \ + (local->sa_family == AF_INET ? ntohs(((struct sockaddr_in*)local)->sin_port) : \ + ntohs(((struct sockaddr_in6*)local)->sin6_port)), \ + remote_addr, (peer->sa_family == AF_INET ? ntohs(((struct sockaddr_in*)peer)->sin_port) : \ + ntohs(((struct sockaddr_in6*)peer)->sin6_port)), outbuffer); + } + } else { + printf(report_peer_fail, local_addr, \ + (local->sa_family == AF_INET ? ntohs(((struct sockaddr_in*)local)->sin_port) : \ + ntohs(((struct sockaddr_in6*)local)->sin6_port)), \ + remote_addr, (peer->sa_family == AF_INET ? ntohs(((struct sockaddr_in*)peer)->sin_port) : \ + ntohs(((struct sockaddr_in6*)peer)->sin6_port)), outbuffer); + } + +#else + if (report->common->KeyCheck) { + if (isEnhanced(report->common) && report->common->Ifrname && (strlen(report->common->Ifrname) < SNBUFFERSIZE-strlen(b))) { + printf(report_peer_dev, report->common->transferIDStr, local_addr, report->common->Ifrname, \ + local_addr, (local->sa_family == AF_INET ? ntohs(((struct sockaddr_in*)local)->sin_port) : 0), \ + remote_addr, (peer->sa_family == AF_INET ? ntohs(((struct sockaddr_in*)peer)->sin_port) : 0), \ + outbuffer); + } else { + printf(report_peer, report->common->transferIDStr, \ + local_addr, (local->sa_family == AF_INET ? ntohs(((struct sockaddr_in*)local)->sin_port) : 0), \ + remote_addr, (peer->sa_family == AF_INET ? ntohs(((struct sockaddr_in*)peer)->sin_port) : 0), \ + outbuffer); + } + } else { + printf(report_peer_fail, local_addr, (local->sa_family == AF_INET ? ntohs(((struct sockaddr_in*)local)->sin_port) : 0), \ + remote_addr, (peer->sa_family == AF_INET ? ntohs(((struct sockaddr_in*)peer)->sin_port) : 0), \ + outbuffer); + } +#endif + if ((report->common->ThreadMode == kMode_Client) && !isServerReverse(report->common)) { + if (isTxHoldback(report->common) || isTxStartTime(report->common)) { + struct timeval now; +#ifdef HAVE_CLOCK_GETTIME + struct timespec t1; + clock_gettime(CLOCK_REALTIME, &t1); + now.tv_sec = t1.tv_sec; + now.tv_usec = t1.tv_nsec / 1000; +#else + gettimeofday(&now, NULL); +#endif + int seconds_from_now; + if (isTxHoldback(report->common)) { + seconds_from_now = report->txholdbacktime.tv_sec; + if (report->txholdbacktime.tv_usec > 0) + seconds_from_now++; + } else { + seconds_from_now = ceil(TimeDifference(report->epochStartTime, now)); + } + struct timeval start; + start = now; + char start_timebuf[80]; + start.tv_sec = now.tv_sec + seconds_from_now; + char now_timebuf[80]; + iperf_formattime(now_timebuf, sizeof(now_timebuf), now, \ + isEnhanced(report->common), isUTC(report->common), YearThruSecTZ); + iperf_formattime(start_timebuf, sizeof(start_timebuf), start, \ + isEnhanced(report->common), isUTC(report->common), YearThruSec); + if (seconds_from_now > 0) { + printf(client_report_epoch_start_current, report->common->transferID, seconds_from_now, \ + start_timebuf, now_timebuf); + } else if (!isBounceBack(report->common)) { + printf(warn_start_before_now, report->common->transferID, report->epochStartTime.tv_sec, \ + report->epochStartTime.tv_usec, start_timebuf, now_timebuf); + } + } + } + fflush(stdout); +} + +void reporter_print_settings_report (struct ReportSettings *report) { + assert(report != NULL); + report->pid = (int) getpid(); + printf("%s", separator_line); + if (report->common->ThreadMode == kMode_Listener) { + reporter_output_listener_settings(report); + } else { + reporter_output_client_settings(report); + } + printf("%s", separator_line); + fflush(stdout); +} + +void reporter_peerversion (struct ConnectionInfo *report, uint32_t upper, uint32_t lower) { + if (!upper || !lower) { + report->peerversion[0]='\0'; + } else { + int rel, major, minor, alpha; + rel = (upper & 0xFFFF0000) >> 16; + major = (upper & 0x0000FFFF); + minor = (lower & 0xFFFF0000) >> 16; + alpha = (lower & 0x0000000F); + snprintf(report->peerversion, (PEERVERBUFSIZE-10), " (peer %d.%d.%d)", rel, major, minor); + switch(alpha) { + case 0: + sprintf(report->peerversion + strlen(report->peerversion) - 1,"-dev)"); + break; + case 1: + sprintf(report->peerversion + strlen(report->peerversion) - 1,"-rc)"); + break; + case 2: + sprintf(report->peerversion + strlen(report->peerversion) - 1,"-rc2)"); + break; + case 3: + break; + case 4: + sprintf(report->peerversion + strlen(report->peerversion) - 1,"-private)"); + break; + case 5: + sprintf(report->peerversion + strlen(report->peerversion) - 1,"-master)"); + break; + default: + sprintf(report->peerversion + strlen(report->peerversion) - 1, "-unk)"); + } + report->peerversion[PEERVERBUFSIZE-1]='\0'; + } +} + +void reporter_print_server_relay_report (struct ServerRelay *report) { + printf(server_reporting, report->info.common->transferID); + if (isTripTime(report->info.common) || isEnhanced(report->info.common)) { + udp_output_read_triptime(&report->info); + } else { + udp_output_read(&report->info); + } + fflush(stdout); +} diff --git a/src/Reporter.c b/src/Reporter.c new file mode 100644 index 0000000..bbd6fd5 --- /dev/null +++ b/src/Reporter.c @@ -0,0 +1,1937 @@ +/*--------------------------------------------------------------- + * Copyright (c) 1999,2000,2001,2002,2003 + * The Board of Trustees of the University of Illinois + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software (Iperf) and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the names of the University of Illinois, NCSA, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * National Laboratory for Applied Network Research + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * http://www.ncsa.uiuc.edu + * ________________________________________________________________ + * + * Reporter.c + * by Kevin Gibbs <kgibbs@nlanr.net> + * + * Major rewrite by Robert McMahon (Sept 2020, ver 2.0.14) + * ________________________________________________________________ */ + +#include <math.h> +#include "headers.h" +#include "Settings.hpp" +#include "util.h" +#include "Reporter.h" +#include "Thread.h" +#include "Locale.h" +#include "PerfSocket.hpp" +#include "SocketAddr.h" +#include "histogram.h" +#include "delay.h" +#include "packet_ring.h" +#include "payloads.h" +#include "gettcpinfo.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef INITIAL_PACKETID +# define INITIAL_PACKETID 0 +#endif + +struct ReportHeader *ReportRoot = NULL; +struct ReportHeader *ReportPendingHead = NULL; +struct ReportHeader *ReportPendingTail = NULL; + +// Reporter's reset of stats after a print occurs +static void reporter_reset_transfer_stats_client_tcp(struct TransferInfo *stats); +static void reporter_reset_transfer_stats_client_udp(struct TransferInfo *stats); +static void reporter_reset_transfer_stats_server_udp(struct TransferInfo *stats); +static void reporter_reset_transfer_stats_server_tcp(struct TransferInfo *stats); + +// code for welfornd's algorithm to produce running mean/min/max/var +static void reporter_update_mmm (struct MeanMinMaxStats *stats, double value); +static void reporter_reset_mmm (struct MeanMinMaxStats *stats); + + +// one way delay (OWD) calculations +static void reporter_handle_packet_oneway_transit(struct TransferInfo *stats, struct ReportStruct *packet); +static void reporter_handle_isoch_oneway_transit_tcp(struct TransferInfo *stats, struct ReportStruct *packet); +static void reporter_handle_isoch_oneway_transit_udp(struct TransferInfo *stats, struct ReportStruct *packet); +static void reporter_handle_frame_isoch_oneway_transit(struct TransferInfo *stats, struct ReportStruct *packet); +static void reporter_handle_txmsg_oneway_transit(struct TransferInfo *stats, struct ReportStruct *packet); +static void reporter_handle_rxmsg_oneway_transit(struct TransferInfo *stats, struct ReportStruct *packet); + +static inline void reporter_compute_packet_pps (struct TransferInfo *stats, struct ReportStruct *packet); + +#if HAVE_TCP_STATS +static inline void reporter_handle_packet_tcpistats(struct ReporterData *data, struct ReportStruct *packet); +#endif +static struct ConnectionInfo *myConnectionReport; + +void PostReport (struct ReportHeader *reporthdr) { +#ifdef HAVE_THREAD_DEBUG + char rs[REPORTTXTMAX]; + reporttype_text(reporthdr, &rs[0]); + thread_debug("Jobq *POST* report %p (%s)", reporthdr, &rs[0]); +#endif + if (reporthdr) { +#ifdef HAVE_THREAD + /* + * Update the ReportRoot to include this report. + */ + Condition_Lock(ReportCond); + reporthdr->next = NULL; + if (!ReportPendingHead) { + ReportPendingHead = reporthdr; + ReportPendingTail = reporthdr; + } else { + ReportPendingTail->next = reporthdr; + ReportPendingTail = reporthdr; + } + Condition_Unlock(ReportCond); + // wake up the reporter thread + Condition_Signal(&ReportCond); +#else + /* + * Process the report in this thread + */ + reporthdr->next = NULL; + reporter_process_report(reporthdr); +#endif + } +} +/* + * ReportPacket is called by a transfer agent to record + * the arrival or departure of a "packet" (for TCP it + * will actually represent many packets). This needs to + * be as simple and fast as possible as it gets called for + * every "packet". + * + * Returns true when the tcpinfo was sampled, false ohterwise + */ +bool ReportPacket (struct ReporterData* data, struct ReportStruct *packet) { + assert(data != NULL); + + bool rc = false; + #ifdef HAVE_THREAD_DEBUG + if (packet->packetID < 0) { + thread_debug("Reporting last packet for %p qdepth=%d sock=%d", (void *) data, packetring_getcount(data->packetring), data->info.common->socket); + } + #endif +#if HAVE_TCP_STATS + struct TransferInfo *stats = &data->info; + packet->tcpstats.isValid = false; + if (stats->isEnableTcpInfo) { + if (!TimeZero(stats->ts.nextTCPSampleTime) && (TimeDifference(stats->ts.nextTCPSampleTime, packet->packetTime) < 0)) { + gettcpinfo(data->info.common->socket, &packet->tcpstats); + TimeAdd(stats->ts.nextTCPSampleTime, stats->ts.intervalTime); + } else { + gettcpinfo(data->info.common->socket, &packet->tcpstats); + } + } +#endif + + // Note for threaded operation all that needs + // to be done is to enqueue the packet data + // into the ring. + packetring_enqueue(data->packetring, packet); + // The traffic thread calls the reporting process + // directly forr non-threaded operation + // These defeats the puropse of separating + // traffic i/o from user i/o and really + // should be avoided. + #ifdef HAVE_THREAD + // bypass the reporter thread here for single UDP + if (isSingleUDP(data->info.common)) + reporter_process_transfer_report(data); + #else + /* + * Process the report in this thread + */ + reporter_process_transfer_report(data); + #endif + + return rc; +} + +/* + * EndJob is called by a traffic thread to inform the reporter + * thread to print a final report and to remove the data report from its jobq. + * It also handles the freeing reports and other closing actions + */ +int EndJob (struct ReportHeader *reporthdr, struct ReportStruct *finalpacket) { + assert(reporthdr!=NULL); + assert(finalpacket!=NULL); + struct ReporterData *report = (struct ReporterData *) reporthdr->this_report; + struct ReportStruct packet; + + memset(&packet, 0, sizeof(struct ReportStruct)); + int do_close = 1; + /* + * Using PacketID of -1 ends reporting + * It pushes a "special packet" through + * the packet ring which will be detected + * by the reporter thread as and end of traffic + * event + */ +#if HAVE_TCP_STATS + // tcpi stats are sampled on a final packet + struct TransferInfo *stats = &report->info; + if (stats->isEnableTcpInfo) { + gettcpinfo(report->info.common->socket, &finalpacket->tcpstats); + } +#endif + // clear the reporter done predicate + report->packetring->consumerdone = 0; + // the negative packetID is used to inform the report thread this traffic thread is done + packet.packetID = -1; + packet.packetLen = finalpacket->packetLen; + packet.packetTime = finalpacket->packetTime; + if (isSingleUDP(report->info.common)) { + packetring_enqueue(report->packetring, &packet); + reporter_process_transfer_report(report); + } else { + ReportPacket(report, &packet); +#ifdef HAVE_THREAD_DEBUG + thread_debug( "Traffic thread awaiting reporter to be done with %p and cond %p", (void *)report, (void *) report->packetring->awake_producer); +#endif + Condition_Lock((*(report->packetring->awake_producer))); + while (!report->packetring->consumerdone) { + // This wait time is the lag between the reporter thread + // and the traffic thread, a reporter thread with lots of + // reports (e.g. fastsampling) can lag per the i/o + Condition_TimedWait(report->packetring->awake_producer, 1); + // printf("Consumer done may be stuck\n"); + } + Condition_Unlock((*(report->packetring->awake_producer))); + } + if (report->FullDuplexReport && isFullDuplex(report->FullDuplexReport->info.common)) { + if (fullduplex_stop_barrier(&report->FullDuplexReport->fullduplex_barrier)) { + struct Condition *tmp = &report->FullDuplexReport->fullduplex_barrier.await; + Condition_Destroy(tmp); +#if HAVE_THREAD_DEBUG + thread_debug("Socket fullduplex close sock=%d", report->FullDuplexReport->info.common->socket); +#endif + FreeSumReport(report->FullDuplexReport); + } else { + do_close = 0; + } + } + return do_close; +} + +// This is used to determine the packet/cpu load into the reporter thread +// If the overall reporter load is too low, add some yield +// or delay so the traffic threads can fill the packet rings +#define MINPACKETDEPTH 10 +#define MINPERQUEUEDEPTH 20 +#define REPORTERDELAY_DURATION 16000 // units is microseconds +struct ConsumptionDetectorType { + int accounted_packets; + int accounted_packet_threads; + int reporter_thread_suspends ; +}; +struct ConsumptionDetectorType consumption_detector = \ + {.accounted_packets = 0, .accounted_packet_threads = 0, .reporter_thread_suspends = 0}; + +static inline void reset_consumption_detector (void) { + consumption_detector.accounted_packet_threads = thread_numtrafficthreads(); + if ((consumption_detector.accounted_packets = thread_numtrafficthreads() * MINPERQUEUEDEPTH) <= MINPACKETDEPTH) { + consumption_detector.accounted_packets = MINPACKETDEPTH; + } +} +static inline void apply_consumption_detector (void) { + if (--consumption_detector.accounted_packet_threads <= 0) { + // All active threads have been processed for the loop, + // reset the thread counter and check the consumption rate + // If the rate is too low add some delay to the reporter + consumption_detector.accounted_packet_threads = thread_numtrafficthreads(); + // Check to see if we need to suspend the reporter + if (consumption_detector.accounted_packets > 0) { + /* + * Suspend the reporter thread for some (e.g. 4) milliseconds + * + * This allows the thread to receive client or server threads' + * packet events in "aggregates." This can reduce context + * switching allowing for better CPU utilization, + * which is very noticble on CPU constrained systems. + */ + delay_loop(REPORTERDELAY_DURATION); + consumption_detector.reporter_thread_suspends++; + // printf("DEBUG: forced reporter suspend, accounted=%d, queueue depth after = %d\n", accounted_packets, getcount_packetring(reporthdr)); + } else { + // printf("DEBUG: no suspend, accounted=%d, queueue depth after = %d\n", accounted_packets, getcount_packetring(reporthdr)); + } + reset_consumption_detector(); + } +} + +#ifdef HAVE_THREAD_DEBUG +static void reporter_jobq_dump(void) { + thread_debug("reporter thread job queue request lock"); + Condition_Lock(ReportCond); + struct ReportHeader *itr = ReportRoot; + while (itr) { + thread_debug("Job in queue %p",(void *) itr); + itr = itr->next; + } + Condition_Unlock(ReportCond); + thread_debug("reporter thread job queue unlock"); +} +#endif + + +/* Concatenate pending reports and return the head */ +static inline struct ReportHeader *reporter_jobq_set_root (struct thread_Settings *inSettings) { + struct ReportHeader *root = NULL; + Condition_Lock(ReportCond); + // check the jobq for empty + if (ReportRoot == NULL) { + sInterupted = 0; // reset flags in reporter thread emtpy context + // The reporter is starting from an empty state + // so set the load detect to trigger an initial delay + if (!isSingleUDP(inSettings)) { + reset_consumption_detector(); + reporter_default_heading_flags((inSettings->mReportMode == kReport_CSV)); + } + // Only hang the timed wait if more than this thread is active + if (!ReportPendingHead && (thread_numuserthreads() > 1)) { + Condition_TimedWait(&ReportCond, 1); +#ifdef HAVE_THREAD_DEBUG + thread_debug( "Jobq *WAIT* exit %p/%p cond=%p threads u/t=%d/%d", \ + (void *) ReportRoot, (void *) ReportPendingHead, \ + (void *) &ReportCond, thread_numuserthreads(), thread_numtrafficthreads()); +#endif + } + } + // update the jobq per pending reports + if (ReportPendingHead) { + ReportPendingTail->next = ReportRoot; + ReportRoot = ReportPendingHead; +#ifdef HAVE_THREAD_DEBUG + thread_debug( "Jobq *ROOT* %p (last=%p)", \ + (void *) ReportRoot, (void * ) ReportPendingTail->next); +#endif + ReportPendingHead = NULL; + ReportPendingTail = NULL; + } + root = ReportRoot; + Condition_Unlock(ReportCond); + return root; +} +/* + * Welford's online algorithm + * + * # For a new value newValue, compute the new count, new mean, the new M2. + * # mean accumulates the mean of the entire dataset + * # M2 aggregates the squared distance from the mean + * # count aggregates the number of samples seen so far + * def update(existingAggregate, newValue): + * (count, mean, M2) = existingAggregate + * count += 1 + * delta = newValue - mean + * mean += delta / count + * delta2 = newValue - mean + * M2 += delta * delta2 + * return (count, mean, M2) + * + * # Retrieve the mean, variance and sample variance from an aggregate + * def finalize(existingAggregate): + * (count, mean, M2) = existingAggregate + * if count < 2: + * return float("nan") + * else: + * (mean, variance, sampleVariance) = (mean, M2 / count, M2 / (count - 1)) + * return (mean, variance, sampleVariance) + * + */ +static void reporter_update_mmm (struct MeanMinMaxStats *stats, double value) { + assert(stats != NULL); + stats->cnt++; + if (stats->cnt == 1) { + // Very first entry + stats->min = value; + stats->max = value; + stats->sum = value; + stats->vd = value; + stats->mean = value; + stats->m2 = 0; + stats->sum = value; + } else { + stats->sum += value; + stats->vd = value - stats->mean; + stats->mean += (stats->vd / stats->cnt); + stats->m2 += stats->vd * (value - stats->mean); + // mean min max tests + if (value < stats->min) + stats->min = value; + if (value > stats->max) + stats->max = value; + } + // fprintf(stderr,"**** mmm(%d) val/sum=%f/%f mmm=%f/%f/%f/%f\n", stats->cnt, value, stats->sum, stats->mean, stats->min, stats->max, stats->m2); +} +static void reporter_reset_mmm (struct MeanMinMaxStats *stats) { + stats->min = FLT_MAX; + stats->max = FLT_MIN; + stats->sum = 0; + stats->vd = 0; + stats->mean = 0; + stats->m2 = 0; + stats->cnt = 0; +}; + +/* + * This function is the loop that the reporter thread processes + */ +void reporter_spawn (struct thread_Settings *thread) { +#ifdef HAVE_THREAD_DEBUG + thread_debug( "Reporter thread started"); +#endif + if (isEnhanced(thread)) { + myConnectionReport = InitConnectOnlyReport(thread); + } + /* + * reporter main loop needs to wait on all threads being started + */ + Condition_Lock(threads_start.await); + while (!threads_start.ready) { + Condition_TimedWait(&threads_start.await, 1); + } + Condition_Unlock(threads_start.await); +#ifdef HAVE_THREAD_DEBUG + thread_debug( "Reporter await done"); +#endif + + // + // Signal to other (client) threads that the + // reporter is now running. + // + Condition_Lock(reporter_state.await); + reporter_state.ready = 1; + Condition_Unlock(reporter_state.await); + Condition_Broadcast(&reporter_state.await); +#if HAVE_SCHED_SETSCHEDULER + // set reporter thread to realtime if requested + thread_setscheduler(thread); +#endif + /* + * Keep the reporter thread alive under the following conditions + * + * o) There are more reports to output, ReportRoot has a report + * o) The number of threads is greater than one which indicates + * either traffic threads are still running or a Listener thread + * is running. If equal to 1 then only the reporter thread is alive + */ + while ((reporter_jobq_set_root(thread) != NULL) || (thread_numuserthreads() > 1)){ +#ifdef HAVE_THREAD_DEBUG + // thread_debug( "Jobq *HEAD* %p (%d)", (void *) ReportRoot, thread_numuserthreads()); +#endif + if (ReportRoot) { + // https://blog.kloetzl.info/beautiful-code/ + // Linked list removal/processing is derived from: + // + // remove_list_entry(entry) { + // indirect = &head; + // while ((*indirect) != entry) { + // indirect = &(*indirect)->next; + // } + // *indirect = entry->next + // } + struct ReportHeader **work_item = &ReportRoot; + while (*work_item) { +#ifdef HAVE_THREAD_DEBUG + // thread_debug( "Jobq *NEXT* %p", (void *) *work_item); +#endif + // Report process report returns true + // when a report needs to be removed + // from the jobq. Also, work item might + // be removed as part of processing + // Store a cached pointer for the linked list maitenance + struct ReportHeader *tmp = (*work_item)->next; + if (reporter_process_report(*work_item)) { +#ifdef HAVE_THREAD_DEBUG + thread_debug("Jobq *REMOVE* %p", (void *) (*work_item)); +#endif + // memory for *work_item is gone by now + *work_item = tmp; + if (!tmp) + break; + } + work_item = &(*work_item)->next; + } + } + } + if (myConnectionReport) { + if (myConnectionReport->connect_times.cnt > 1) { + reporter_connect_printf_tcp_final(myConnectionReport); + } + FreeConnectionReport(myConnectionReport); + } +#ifdef HAVE_THREAD_DEBUG + if (sInterupted) + reporter_jobq_dump(); + thread_debug("Reporter thread finished user/traffic %d/%d", thread_numuserthreads(), thread_numtrafficthreads()); +#endif +} + +// The Transfer or Data report is by far the most complicated report +int reporter_process_transfer_report (struct ReporterData *this_ireport) { + assert(this_ireport != NULL); + struct TransferInfo *sumstats = (this_ireport->GroupSumReport ? &this_ireport->GroupSumReport->info : NULL); + struct TransferInfo *fullduplexstats = (this_ireport->FullDuplexReport ? &this_ireport->FullDuplexReport->info : NULL); + int need_free = 0; + // The consumption detector applies delay to the reporter + // thread when its consumption rate is too low. This allows + // the traffic threads to send aggregates vs thrash + // the packet rings. The dissimilarity between the thread + // speeds is due to the performance differences between i/o + // bound threads vs cpu bound ones, and it's expected + // that reporter thread being CPU limited should be much + // faster than the traffic threads, even in aggregate. + // Note: If this detection is not going off it means + // the system is likely CPU bound and iperf is now likely + // becoming a CPU bound test vs a network i/o bound test + if (!isSingleUDP(this_ireport->info.common)) + apply_consumption_detector(); + // If there are more packets to process then handle them + struct ReportStruct *packet = NULL; + int advance_jobq = 0; + while (!advance_jobq && (packet = packetring_dequeue(this_ireport->packetring))) { + // Increment the total packet count processed by this thread + // this will be used to make decisions on if the reporter + // thread should add some delay to eliminate cpu thread + // thrashing, + consumption_detector.accounted_packets--; + // Check against a final packet event on this packet ring +#if HAVE_TCP_STATS + if (this_ireport->info.isEnableTcpInfo && packet->tcpstats.isValid) { + reporter_handle_packet_tcpistats(this_ireport, packet); + } +#endif + if (!(packet->packetID < 0)) { + // Check to output any interval reports, + // bursts need to report the packet first + if (this_ireport->packet_handler_pre_report) { + (*this_ireport->packet_handler_pre_report)(this_ireport, packet); + } + if (this_ireport->transfer_interval_handler) { + advance_jobq = (*this_ireport->transfer_interval_handler)(this_ireport, packet); + } + if (this_ireport->packet_handler_post_report) { + (*this_ireport->packet_handler_post_report)(this_ireport, packet); + } + // Sum reports update the report header's last + // packet time after the handler. This means + // the report header's packet time will be + // the previous time before the interval + if (sumstats) + sumstats->ts.packetTime = packet->packetTime; + if (fullduplexstats) + fullduplexstats->ts.packetTime = packet->packetTime; + } else { + need_free = 1; + advance_jobq = 1; + // A last packet event was detected + // printf("last packet event detected\n"); fflush(stdout); + this_ireport->reporter_thread_suspends = consumption_detector.reporter_thread_suspends; + if (this_ireport->packet_handler_pre_report) { + (*this_ireport->packet_handler_pre_report)(this_ireport, packet); + } + if (this_ireport->packet_handler_post_report) { + (*this_ireport->packet_handler_post_report)(this_ireport, packet); + } + this_ireport->info.ts.packetTime = packet->packetTime; + assert(this_ireport->transfer_protocol_handler != NULL); + (*this_ireport->transfer_protocol_handler)(this_ireport, 1); + // This is a final report so set the sum report header's packet time + // Note, the thread with the max value will set this + if (fullduplexstats && isEnhanced(this_ireport->info.common)) { + // The largest packet timestamp sets the sum report final time + if (TimeDifference(fullduplexstats->ts.packetTime, packet->packetTime) > 0) { + fullduplexstats->ts.packetTime = packet->packetTime; + } + if (DecrSumReportRefCounter(this_ireport->FullDuplexReport) == 0) { + if (this_ireport->FullDuplexReport->transfer_protocol_sum_handler) { + (*this_ireport->FullDuplexReport->transfer_protocol_sum_handler)(fullduplexstats, 1); + } + // FullDuplex report gets freed by a traffic thread (per its barrier) + } + } + if (sumstats) { + if (!this_ireport->GroupSumReport->threads_cntr_fsum) + this_ireport->GroupSumReport->threads_cntr_fsum = this_ireport->GroupSumReport->reference.maxcount; + if (TimeDifference(sumstats->ts.packetTime, packet->packetTime) > 0) { + sumstats->ts.packetTime = packet->packetTime; + } + if (this_ireport->GroupSumReport->transfer_protocol_sum_handler && \ + (--this_ireport->GroupSumReport->threads_cntr_fsum == 0) && (this_ireport->GroupSumReport->reference.maxcount > 1)) { + (*this_ireport->GroupSumReport->transfer_protocol_sum_handler)(&this_ireport->GroupSumReport->info, 1); + } + } + } + } + return need_free; +} +/* + * Process reports + * + * Make notice here, the reporter thread is freeing most reports, traffic threads + * can't use them anymore (except for the DATA REPORT); + * + */ +inline int reporter_process_report (struct ReportHeader *reporthdr) { + assert(reporthdr != NULL); + int done = 1; + switch (reporthdr->type) { + case DATA_REPORT: + done = reporter_process_transfer_report((struct ReporterData *)reporthdr->this_report); + fflush(stdout); + if (done) { + struct ReporterData *tmp = (struct ReporterData *)reporthdr->this_report; + struct PacketRing *pr = tmp->packetring; + pr->consumerdone = 1; + // Data Reports are special because the traffic thread needs to free them, just signal + Condition_Signal(pr->awake_producer); + } + break; + case CONNECTION_REPORT: + { + struct ConnectionInfo *creport = (struct ConnectionInfo *)reporthdr->this_report; + assert(creport!=NULL); + if (!isCompat(creport->common) && (creport->common->ThreadMode == kMode_Client) && myConnectionReport) { + // Clients' connect times will be inputs to the overall connect stats + if (creport->tcpinitstats.connecttime > 0.0) { + reporter_update_mmm(&myConnectionReport->connect_times, creport->tcpinitstats.connecttime); + } else { + myConnectionReport->connect_times.err++; + } + } + reporter_print_connection_report(creport); + fflush(stdout); + FreeReport(reporthdr); + } + break; + case SETTINGS_REPORT: + reporter_print_settings_report((struct ReportSettings *)reporthdr->this_report); + fflush(stdout); + FreeReport(reporthdr); + break; + case SERVER_RELAY_REPORT: + reporter_print_server_relay_report((struct ServerRelay *)reporthdr->this_report); + fflush(stdout); + FreeReport(reporthdr); + break; + default: + fprintf(stderr,"Invalid report type in process report %p\n", reporthdr->this_report); + assert(0); + break; + } +#ifdef HAVE_THREAD_DEBUG + // thread_debug("Processed report %p type=%d", (void *)reporthdr, reporthdr->report.type); +#endif + return done; +} + +/* + * Updates connection stats + */ +#define L2DROPFILTERCOUNTER 100 + +// Reporter private routines +void reporter_handle_packet_null (struct ReporterData *data, struct ReportStruct *packet) { +} +void reporter_transfer_protocol_null (struct ReporterData *data, int final){ +} + +static inline void reporter_compute_packet_pps (struct TransferInfo *stats, struct ReportStruct *packet) { + if (!packet->emptyreport) { + stats->total.Datagrams.current++; + stats->total.IPG.current++; + } + stats->ts.IPGstart = packet->packetTime; + stats->IPGsum += TimeDifference(packet->packetTime, packet->prevPacketTime); +#ifdef DEBUG_PPS + printf("*** IPGsum = %f cnt=%ld ipg=%ld.%ld pkt=%ld.%ld id=%ld empty=%d transit=%f prev=%ld.%ld\n", stats->IPGsum, stats->cntIPG, stats->ts.IPGstart.tv_sec, stats->ts.IPGstart.tv_usec, packet->packetTime.tv_sec, packet->packetTime.tv_usec, packet->packetID, packet->emptyreport, TimeDifference(packet->packetTime, packet->prevPacketTime), packet->prevPacketTime.tv_sec, packet->prevPacketTime.tv_usec); +#endif +} + +static void reporter_handle_packet_oneway_transit (struct TransferInfo *stats, struct ReportStruct *packet) { + // Transit or latency updates done inline below + double transit = TimeDifference(packet->packetTime, packet->sentTime); + if (stats->latency_histogram) { + histogram_insert(stats->latency_histogram, transit, NULL); + } + double deltaTransit; + deltaTransit = transit - stats->transit.current.last; + stats->transit.current.last = transit; // shift transit for next time + if (deltaTransit < 0.0) { + deltaTransit = -deltaTransit; + } + // Compute end/end delay stats + reporter_update_mmm(&stats->transit.total, transit); + reporter_update_mmm(&stats->transit.current, transit); + // + // Compute jitter though filter the case of isoch and between isoch frames + // or, in other words, only calculate jitter for packets within the same isoch frame + // + // Taken from RFC 1889, Real Time Protocol (RTP) + // J = J + ( | D(i-1,i) | - J ) / + // + // interarrival jitter: + // + // An estimate of the statistical variance of the RTP data packet + // interarrival time, measured in timestamp units and expressed as + // an unsigned integer. The interarrival jitter J is defined to be + // the mean deviation (smoothed absolute value) of the difference D + // in packet spacing at the receiver compared to the sender for a + // pair of packets. As shown in the equation below, this is + // equivalent to the difference in the "relative transit time" for + // the two packets; the relative transit time is the difference + // between a packet's RTP timestamp and the receiver's clock at the + // time of arrival, measured in the same units. + // + // If Si is the RTP timestamp from packet i, and Ri is the time of + // arrival in RTP timestamp units for packet i, then for two packets i + // and j, D may be expressed as + // + // D(i,j)=(Rj-Ri)-(Sj-Si)=(Rj-Sj)-(Ri-Si) + // + // The interarrival jitter is calculated continuously as each data + // packet i is received from source SSRC_n, using this difference D for + // that packet and the previous packet i-1 in order of arrival (not + // necessarily in sequence), according to the formula + // + // J=J+(|D(i-1,i)|-J)/16 + // + // Whenever a reception report is issued, the current value of J is + // sampled. This algorithm is the optimal first-order estimator and + // the gain parameter 1/16 gives a good noise reduction ratio while / + // maintaining a reasonable rate of convergence + // + if (isIsochronous(stats->common) && stats->isochstats.newburst) { + --stats->isochstats.newburst; // decr the burst counter, need for RTP estimator w/isoch + // printf("**** skip value %f per frame change packet %d expected %d max = %f %d\n", deltaTransit, packet->frameID, stats->isochstats.frameID, stats->inline_jitter.total.max, stats->isochstats.newburst); + } else if (stats->transit.total.cnt > 1) { + stats->jitter += (deltaTransit - stats->jitter) / (16.0); + reporter_update_mmm(&stats->inline_jitter.total, stats->jitter); + reporter_update_mmm(&stats->inline_jitter.current, stats->jitter); + if (stats->jitter_histogram) { + histogram_insert(stats->jitter_histogram, deltaTransit, NULL); + } + } +} + + +static void reporter_handle_isoch_oneway_transit_tcp (struct TransferInfo *stats, struct ReportStruct *packet) { + // printf("fid=%lu bs=%lu remain=%lu\n", packet->frameID, packet->burstsize, packet->remaining); + if (packet->frameID && packet->transit_ready) { + int framedelta = 0; + double frametransit = 0; + // very first isochronous frame + if (!stats->isochstats.frameID) { + stats->isochstats.framecnt.current=packet->frameID; + stats->isochstats.newburst = 0; // no packet/read filtering of early samples for TCP + } + // perform client and server frame based accounting + if ((framedelta = (packet->frameID - stats->isochstats.frameID))) { + stats->isochstats.framecnt.current++; + if (framedelta > 1) { + stats->isochstats.framelostcnt.current += (framedelta-1); + stats->isochstats.slipcnt.current++; + } else if (stats->common->ThreadMode == kMode_Server) { + // Triptimes use the frame start time in passed in the frame header while + // it's calculated from the very first start time and frame id w/o trip timees + if (isTripTime(stats->common)) { + frametransit = TimeDifference(packet->packetTime, packet->isochStartTime); + } else { + frametransit = TimeDifference(packet->packetTime, packet->isochStartTime) \ + - ((packet->burstperiod * (packet->frameID - 1)) / 1e6); + } + reporter_update_mmm(&stats->isochstats.transit.total, frametransit); + reporter_update_mmm(&stats->isochstats.transit.current, frametransit); + if (stats->framelatency_histogram) { + histogram_insert(stats->framelatency_histogram, frametransit, &packet->packetTime); + } + } + } + stats->isochstats.frameID = packet->frameID; + } +} + +static void reporter_handle_isoch_oneway_transit_udp (struct TransferInfo *stats, struct ReportStruct *packet) { + // printf("fid=%lu bs=%lu remain=%lu\n", packet->frameID, packet->burstsize, packet->remaining); + if (packet->frameID && packet->transit_ready) { + int framedelta = 0; + double frametransit = 0; + // very first isochronous frame + if (!stats->isochstats.frameID) { + stats->isochstats.framecnt.current=1; + } + // perform client and server frame based accounting + framedelta = (packet->frameID - stats->isochstats.frameID); + stats->isochstats.framecnt.current++; +// stats->matchframeID = packet->frameID + 1; + if (framedelta == 1) { + stats->isochstats.newburst = 2; // set to two per RTP's pair calculation + // Triptimes use the frame start time in passed in the frame header while + // it's calculated from the very first start time and frame id w/o trip timees + frametransit = TimeDifference(packet->packetTime, packet->isochStartTime) \ + - ((packet->burstperiod * (packet->frameID - 1)) / 1e6); + reporter_update_mmm(&stats->isochstats.transit.total, frametransit); + reporter_update_mmm(&stats->isochstats.transit.current, frametransit); + if (stats->framelatency_histogram) { + histogram_insert(stats->framelatency_histogram, frametransit, &packet->packetTime); + } + } else if (framedelta > 1) { + stats->isochstats.newburst = 2; // set to two per RTP's pair calculation + if (stats->common->ThreadMode == kMode_Server) { + stats->isochstats.framelostcnt.current += framedelta; + } else { + stats->isochstats.framelostcnt.current += framedelta; + stats->isochstats.slipcnt.current++; + } + } + stats->isochstats.frameID = packet->frameID; + } +} + + +static void reporter_handle_rxmsg_oneway_transit (struct TransferInfo *stats, struct ReportStruct *packet) { + // very first burst + if (!stats->isochstats.frameID) { + stats->isochstats.frameID = packet->frameID; + } + if (packet->frameID && packet->transit_ready) { + double transit = TimeDifference(packet->packetTime, packet->sentTime); +// printf("**** r pt %ld.%ld st %ld.%ld %f\n", packet->packetTime.tv_sec, packet->packetTime.tv_usec, packet->sentTime.tv_sec, packet->sentTime.tv_usec, transit); + reporter_update_mmm(&stats->transit.total, transit); + reporter_update_mmm(&stats->transit.current, transit); + if (stats->framelatency_histogram) { + histogram_insert(stats->framelatency_histogram, transit, &packet->sentTime); + } + if (!TimeZero(stats->ts.prevpacketTime)) { + double delta = TimeDifference(packet->sentTime, stats->ts.prevpacketTime); + stats->IPGsum += delta; + } + stats->ts.prevpacketTime = packet->sentTime; + stats->isochstats.frameID++; // RJM fix this overload + stats->burstid_transition = true; + } else if (stats->burstid_transition && packet->frameID && (packet->frameID != stats->isochstats.frameID)) { + stats->burstid_transition = false; + fprintf(stderr,"%sError: expected burst id %u but got %d\n", \ + stats->common->transferIDStr, stats->isochstats.frameID + 1, packet->frameID); + stats->isochstats.frameID = packet->frameID; + } +} + +static inline void reporter_handle_txmsg_oneway_transit (struct TransferInfo *stats, struct ReportStruct *packet) { + // very first burst + if (!stats->isochstats.frameID) { + stats->isochstats.frameID = packet->frameID; + } + if (!TimeZero(stats->ts.prevpacketTime)) { + double delta = TimeDifference(packet->sentTime, stats->ts.prevpacketTime); + stats->IPGsum += delta; + } + if (packet->transit_ready) { + reporter_handle_packet_oneway_transit(stats, packet); + // printf("***Burst id = %ld, transit = %f\n", packet->frameID, stats->transit.lastTransit); + if (isIsochronous(stats->common)) { + if (packet->frameID && (packet->frameID != (stats->isochstats.frameID + 1))) { + fprintf(stderr,"%sError: expected burst id %u but got %d\n", \ + stats->common->transferIDStr, stats->isochstats.frameID + 1, packet->frameID); + } + stats->isochstats.frameID = packet->frameID; + } + } +} + +static void reporter_handle_frame_isoch_oneway_transit (struct TransferInfo *stats, struct ReportStruct *packet) { + // printf("fid=%lu bs=%lu remain=%lu\n", packet->frameID, packet->burstsize, packet->remaining); + if (packet->scheduled) { + reporter_update_mmm(&stats->schedule_error, (double)(packet->sched_err)); + } + if (packet->frameID && packet->transit_ready) { + int framedelta=0; + // very first isochronous frame + if (!stats->isochstats.frameID) { + stats->isochstats.framecnt.current=packet->frameID; + } + // perform frame based accounting + if ((framedelta = (packet->frameID - stats->isochstats.frameID))) { + stats->isochstats.framecnt.current++; + if (framedelta > 1) { + stats->isochstats.framelostcnt.current += (framedelta-1); + stats->isochstats.slipcnt.current++; + } + } + stats->isochstats.frameID = packet->frameID; + } +} + +// This is done in reporter thread context +void reporter_handle_packet_client (struct ReporterData *data, struct ReportStruct *packet) { + struct TransferInfo *stats = &data->info; + stats->ts.packetTime = packet->packetTime; + if (!packet->emptyreport) { + stats->total.Bytes.current += packet->packetLen; + if (packet->errwrite && (packet->errwrite != WriteErrNoAccount)) { + stats->sock_callstats.write.WriteErr++; + stats->sock_callstats.write.totWriteErr++; + } + // These are valid packets that need standard iperf accounting + stats->sock_callstats.write.WriteCnt += packet->writecnt; + stats->sock_callstats.write.totWriteCnt += packet->writecnt; + if (isIsochronous(stats->common)) { + reporter_handle_frame_isoch_oneway_transit(stats, packet); + } else if (isPeriodicBurst(stats->common)) { + reporter_handle_txmsg_oneway_transit(stats, packet); + } + if (isTcpWriteTimes(stats->common) && !isUDP(stats->common) && (packet->write_time > 0)) { + reporter_update_mmm(&stats->write_mmm.current, ((double) packet->write_time)); + reporter_update_mmm(&stats->write_mmm.total, ((double) packet->write_time)); + if (stats->write_histogram ) { + histogram_insert(stats->write_histogram, (1e-6 * packet->write_time), NULL); + } + } + } + if (isUDP(stats->common)) { + stats->PacketID = packet->packetID; + reporter_compute_packet_pps(stats, packet); + } +} + +#define DEBUG_BB_TIMESTAMPS 0 +void reporter_handle_packet_bb_client (struct ReporterData *data, struct ReportStruct *packet) { + struct TransferInfo *stats = &data->info; + if (packet->scheduled) { + reporter_update_mmm(&stats->schedule_error, (double)(packet->sched_err)); + } + if (!packet->emptyreport && (packet->packetLen > 0)) { + stats->total.Bytes.current += packet->packetLen; + double bbrtt = TimeDifference(packet->packetTime, packet->sentTime); + double bbowdto = TimeDifference(packet->sentTimeRX, packet->sentTime); + double bbowdfro = TimeDifference(packet->packetTime, packet->sentTimeTX); + double asym = bbowdfro - bbowdto; + stats->ts.prevpacketTime = packet->packetTime; +#if DEBUG_BB_TIMESTAMPS + fprintf(stderr, "BB Debug: ctx=%lx.%lx srx=%lx.%lx stx=%lx.%lx crx=%lx.%lx (hex)\n", packet->sentTime.tv_sec, packet->sentTime.tv_usec, packet->sentTimeRX.tv_sec, packet->sentTimeRX.tv_usec, packet->sentTimeTX.tv_sec, packet->sentTimeTX.tv_usec, packet->packetTime.tv_sec, packet->packetTime.tv_usec); + fprintf(stderr, "BB Debug: ctx=%ld.%ld srx=%ld.%ld stx=%ld.%ld crx=%ld.%ld\n", packet->sentTime.tv_sec, packet->sentTime.tv_usec, packet->sentTimeRX.tv_sec, packet->sentTimeRX.tv_usec, packet->sentTimeTX.tv_sec, packet->sentTimeTX.tv_usec, packet->packetTime.tv_sec, packet->packetTime.tv_usec); + fprintf(stderr, "BB RTT=%f OWDTo=%f OWDFro=%f Asym=%f\n", bbrtt, bbowdto, bbowdfro, asym); +#endif + stats->iBBrunning += bbrtt; + stats->fBBrunning += bbrtt; + reporter_update_mmm(&stats->bbrtt.current, bbrtt); + reporter_update_mmm(&stats->bbrtt.total, bbrtt); + reporter_update_mmm(&stats->bbowdto.total, bbowdto); + reporter_update_mmm(&stats->bbowdfro.total, bbowdfro); + reporter_update_mmm(&stats->bbasym.total, fabs(asym)); + if (stats->bbrtt_histogram) { + histogram_insert(stats->bbrtt_histogram, bbrtt, NULL); + } + } +} + +void reporter_handle_packet_bb_server (struct ReporterData *data, struct ReportStruct *packet) { + struct TransferInfo *stats = &data->info; + stats->ts.packetTime = packet->packetTime; + if (!packet->emptyreport && (packet->packetLen > 0)) { + stats->total.Bytes.current += packet->packetLen; + } +} + +inline void reporter_handle_packet_server_tcp (struct ReporterData *data, struct ReportStruct *packet) { + struct TransferInfo *stats = &data->info; + if (packet->packetLen > 0) { + int bin; + stats->total.Bytes.current += packet->packetLen; + // mean min max tests + stats->sock_callstats.read.cntRead++; + stats->sock_callstats.read.totcntRead++; + bin = (int)floor((packet->packetLen -1)/stats->sock_callstats.read.binsize); + if (bin < TCPREADBINCOUNT) { + stats->sock_callstats.read.bins[bin]++; + stats->sock_callstats.read.totbins[bin]++; + } + if (packet->transit_ready) { + if (isIsochronous(stats->common) && packet->frameID) { + reporter_handle_isoch_oneway_transit_tcp(stats, packet); + } else if (isPeriodicBurst(stats->common) || isTripTime(stats->common)) { + reporter_handle_rxmsg_oneway_transit(stats, packet); + } + } + } +} + +inline void reporter_handle_packet_server_udp (struct ReporterData *data, struct ReportStruct *packet) { + struct TransferInfo *stats = &data->info; + stats->ts.packetTime = packet->packetTime; + if (packet->emptyreport && (stats->transit.current.cnt == 0)) { + // This is the case when empty reports + // cross the report interval boundary + // Hence, set the per interval min to infinity + // and the per interval max and sum to zero + reporter_reset_mmm(&stats->transit.current); + } else if (packet->packetID > 0) { + stats->total.Bytes.current += packet->packetLen; + // These are valid packets that need standard iperf accounting + // Do L2 accounting first (if needed) + if (packet->l2errors && (stats->total.Datagrams.current > L2DROPFILTERCOUNTER)) { + stats->l2counts.cnt++; + stats->l2counts.tot_cnt++; + if (packet->l2errors & L2UNKNOWN) { + stats->l2counts.unknown++; + stats->l2counts.tot_unknown++; + } + if (packet->l2errors & L2LENERR) { + stats->l2counts.lengtherr++; + stats->l2counts.tot_lengtherr++; + } + if (packet->l2errors & L2CSUMERR) { + stats->l2counts.udpcsumerr++; + stats->l2counts.tot_udpcsumerr++; + } + } + // packet loss occured if the datagram numbers aren't sequential + if (packet->packetID != stats->PacketID + 1) { + if (packet->packetID < stats->PacketID + 1) { + stats->total.OutofOrder.current++; + } else { + stats->total.Lost.current += packet->packetID - stats->PacketID - 1; + } + } + // never decrease datagramID (e.g. if we get an out-of-order packet) + if (packet->packetID > stats->PacketID) { + stats->PacketID = packet->packetID; + } + reporter_compute_packet_pps(stats, packet); + reporter_handle_packet_oneway_transit(stats, packet); + if (packet->transit_ready) { + if (isIsochronous(stats->common)) { + reporter_handle_isoch_oneway_transit_udp(stats, packet); + } else if (isPeriodicBurst(stats->common)) { + reporter_handle_txmsg_oneway_transit(stats, packet); + } + } + } +} + +// This is done in reporter thread context +#if HAVE_TCP_STATS +static inline void reporter_handle_packet_tcpistats (struct ReporterData *data, struct ReportStruct *packet) { + assert(data!=NULL); + struct TransferInfo *stats = &data->info; + stats->sock_callstats.write.tcpstats.retry += (packet->tcpstats.retry_tot - stats->sock_callstats.write.tcpstats.retry_prev); + stats->sock_callstats.write.tcpstats.retry_prev = packet->tcpstats.retry_tot; + stats->sock_callstats.write.tcpstats.retry_tot = packet->tcpstats.retry_tot; + stats->sock_callstats.write.tcpstats.cwnd = packet->tcpstats.cwnd; + stats->sock_callstats.write.tcpstats.rtt = packet->tcpstats.rtt; + stats->sock_callstats.write.tcpstats.rttvar = packet->tcpstats.rttvar; +} +#endif + + +/* + * Report printing routines below + */ +static inline void reporter_set_timestamps_time (struct TransferInfo *stats, enum TimeStampType tstype) { + // There is a corner case when the first packet is also the last where the start time (which comes + // from app level syscall) is greater than the packetTime (which come for kernel level SO_TIMESTAMP) + // For this case set the start and end time to both zero. + struct ReportTimeStamps *times = &stats->ts; + if (TimeDifference(times->packetTime, times->startTime) < 0) { + times->iEnd = 0; + times->iStart = 0; + } else { + switch (tstype) { + case INTERVAL: + times->iStart = times->iEnd; + times->iEnd = TimeDifference(times->nextTime, times->startTime); + TimeAdd(times->nextTime, times->intervalTime); + stats->final = false; + break; + case TOTAL: + times->iStart = 0; + times->iEnd = TimeDifference(times->packetTime, times->startTime); + stats->final = true; + break; + case FINALPARTIAL: + times->iStart = times->iEnd; + times->iEnd = TimeDifference(times->packetTime, times->startTime); + stats->final = false; + break; + case INTERVALPARTIAL: + if ((times->iStart = TimeDifference(times->prevpacketTime, times->startTime)) < 0) + times->iStart = 0.0; + times->iEnd = TimeDifference(times->packetTime, times->startTime); + stats->final = false; + break; + default: + times->iEnd = -1; + times->iStart = -1; + stats->final = false; + break; + } + } +} + +// If reports were missed, catch up now +static inline void reporter_transfer_protocol_missed_reports (struct TransferInfo *stats, struct ReportStruct *packet) { + while (TimeDifference(packet->packetTime, stats->ts.nextTime) > TimeDouble(stats->ts.intervalTime)) { +// printf("**** cmp=%f/%f next %ld.%ld packet %ld.%ld id=%ld\n", TimeDifference(packet->packetTime, stats->ts.nextTime), TimeDouble(stats->ts.intervalTime), stats->ts.nextTime.tv_sec, stats->ts.nextTime.tv_usec, packet->packetTime.tv_sec, packet->packetTime.tv_usec, packet->packetID); + reporter_set_timestamps_time(stats, INTERVAL); + struct TransferInfo emptystats; + memset(&emptystats, 0, sizeof(struct TransferInfo)); + emptystats.ts.iStart = stats->ts.iStart; + emptystats.ts.iEnd = stats->ts.iEnd; + emptystats.common = stats->common; + if ((stats->output_handler) && !(stats->isMaskOutput)) + (*stats->output_handler)(&emptystats); + } +} + +static inline void reporter_reset_transfer_stats_client_tcp (struct TransferInfo *stats) { + stats->total.Bytes.prev = stats->total.Bytes.current; + stats->sock_callstats.write.WriteCnt = 0; + stats->sock_callstats.write.WriteErr = 0; + stats->isochstats.framecnt.prev = stats->isochstats.framecnt.current; + stats->isochstats.framelostcnt.prev = stats->isochstats.framelostcnt.current; + stats->isochstats.slipcnt.prev = stats->isochstats.slipcnt.current; +#if HAVE_TCP_STATS + // set the interval retry counter to zero + stats->sock_callstats.write.tcpstats.retry = 0; +#endif + if (isBounceBack(stats->common)) { + stats->iBBrunning = 0; + reporter_reset_mmm(&stats->bbrtt.current); + reporter_reset_mmm(&stats->bbowdto.current); + reporter_reset_mmm(&stats->bbowdfro.current); + reporter_reset_mmm(&stats->bbasym.current); + } + if (isTcpWriteTimes(stats->common)) { + stats->write_mmm.current.cnt = 0; + stats->write_mmm.current.min = FLT_MAX; + stats->write_mmm.current.max = FLT_MIN; + stats->write_mmm.current.sum = 0; + stats->write_mmm.current.vd = 0; + stats->write_mmm.current.mean = 0; + stats->write_mmm.current.m2 = 0; + } +} + +static inline void reporter_reset_transfer_stats_client_udp (struct TransferInfo *stats) { + if (stats->cntError < 0) { + stats->cntError = 0; + } + stats->total.Lost.prev = stats->total.Lost.current; + stats->total.Datagrams.prev = stats->total.Datagrams.current; + stats->total.Bytes.prev = stats->total.Bytes.current; + stats->total.IPG.prev = stats->total.IPG.current; + stats->sock_callstats.write.WriteCnt = 0; + stats->sock_callstats.write.WriteErr = 0; + stats->isochstats.framecnt.prev = stats->isochstats.framecnt.current; + stats->isochstats.framelostcnt.prev = stats->isochstats.framelostcnt.current; + stats->isochstats.slipcnt.prev = stats->isochstats.slipcnt.current; + if (stats->cntDatagrams) + stats->IPGsum = 0; +} + +static inline void reporter_reset_transfer_stats_server_tcp (struct TransferInfo *stats) { + int ix; + stats->total.Bytes.prev = stats->total.Bytes.current; + stats->sock_callstats.read.cntRead = 0; + for (ix = 0; ix < 8; ix++) { + stats->sock_callstats.read.bins[ix] = 0; + } + reporter_reset_mmm(&stats->transit.current); + reporter_reset_mmm(&stats->isochstats.transit.current); + stats->IPGsum = 0; +} + +static inline void reporter_reset_transfer_stats_server_udp (struct TransferInfo *stats) { + // Reset the enhanced stats for the next report interval + stats->total.Bytes.prev = stats->total.Bytes.current; + stats->total.Datagrams.prev = stats->PacketID; + stats->total.OutofOrder.prev = stats->total.OutofOrder.current; + stats->total.Lost.prev = stats->total.Lost.current; + stats->total.IPG.prev = stats->total.IPG.current; + reporter_reset_mmm(&stats->transit.current); + stats->isochstats.framecnt.prev = stats->isochstats.framecnt.current; + stats->isochstats.framelostcnt.prev = stats->isochstats.framelostcnt.current; + stats->isochstats.slipcnt.prev = stats->isochstats.slipcnt.current; + stats->l2counts.cnt = 0; + stats->l2counts.unknown = 0; + stats->l2counts.udpcsumerr = 0; + stats->l2counts.lengtherr = 0; + stats->threadcnt = 0; + stats->iInP = 0; + if (stats->cntDatagrams) + stats->IPGsum = 0; +} + +// These do the following +// +// o) set the TransferInfo struct and then calls the individual report output handler +// o) updates the sum and fullduplex reports +// +void reporter_transfer_protocol_server_udp (struct ReporterData *data, int final) { + struct TransferInfo *stats = &data->info; + struct TransferInfo *sumstats = (data->GroupSumReport != NULL) ? &data->GroupSumReport->info : NULL; + struct TransferInfo *fullduplexstats = (data->FullDuplexReport != NULL) ? &data->FullDuplexReport->info : NULL; + // print a interval report and possibly a partial interval report if this a final + stats->cntBytes = stats->total.Bytes.current - stats->total.Bytes.prev; + stats->cntOutofOrder = stats->total.OutofOrder.current - stats->total.OutofOrder.prev; + // assume most of the time out-of-order packets are + // duplicate packets, so conditionally subtract them from the lost packets. + stats->cntError = stats->total.Lost.current - stats->total.Lost.prev - stats->cntOutofOrder; + if (stats->cntError < 0) + stats->cntError = 0; + stats->cntDatagrams = stats->PacketID - stats->total.Datagrams.prev; + stats->cntIPG = stats->total.IPG.current - stats->total.IPG.prev; + + if (stats->latency_histogram) { + stats->latency_histogram->final = final; + } + if (stats->jitter_histogram) { + stats->jitter_histogram->final = final; + } + if (isIsochronous(stats->common)) { + stats->isochstats.cntFrames = stats->isochstats.framecnt.current - stats->isochstats.framecnt.prev; + stats->isochstats.cntFramesMissed = stats->isochstats.framelostcnt.current - stats->isochstats.framelostcnt.prev; + stats->isochstats.cntSlips = stats->isochstats.slipcnt.current - stats->isochstats.slipcnt.prev; + if (stats->framelatency_histogram) { + stats->framelatency_histogram->final = final; + } + } + if (stats->total.Datagrams.current == 1) + stats->jitter = 0; + if (isTripTime(stats->common) && !final) { + double lambda = ((stats->IPGsum > 0.0) ? (round (stats->cntIPG / stats->IPGsum)) : 0.0); + double meantransit = (double) ((stats->transit.current.cnt > 0) ? (stats->transit.current.sum / stats->transit.current.cnt) : 0.0); + double variance = (stats->transit.current.cnt < 2) ? 0 : \ + (sqrt(stats->transit.current.m2 / (stats->transit.current.cnt - 1))); + stats->iInP = (double) lambda * meantransit; + stats->iInPVar = (double) lambda * variance; + } + if (sumstats) { + sumstats->total.OutofOrder.current += stats->total.OutofOrder.current - stats->total.OutofOrder.prev; + // assume most of the time out-of-order packets are not + // duplicate packets, so conditionally subtract them from the lost packets. + sumstats->total.Lost.current += stats->total.Lost.current - stats->total.Lost.prev; + sumstats->total.Datagrams.current += stats->PacketID - stats->total.Datagrams.prev; + sumstats->total.Bytes.current += stats->cntBytes; + sumstats->total.IPG.current += stats->cntIPG; + if (sumstats->IPGsum < stats->IPGsum) + sumstats->IPGsum = stats->IPGsum; + sumstats->threadcnt++; + sumstats->iInP += stats->iInP; + } + if (fullduplexstats) { + fullduplexstats->total.Bytes.current += stats->cntBytes; + fullduplexstats->total.IPG.current += stats->cntIPG; + fullduplexstats->total.Datagrams.current += (stats->total.Datagrams.current - stats->total.Datagrams.prev); + if (fullduplexstats->IPGsum < stats->IPGsum) + fullduplexstats->IPGsum = stats->IPGsum; + } + if (final) { + if ((stats->cntBytes > 0) && !TimeZero(stats->ts.intervalTime)) { + stats->cntOutofOrder = stats->total.OutofOrder.current - stats->total.OutofOrder.prev; + // assume most of the time out-of-order packets are not + // duplicate packets, so conditionally subtract them from the lost packets. + stats->cntError = stats->total.Lost.current - stats->total.Lost.prev; + stats->cntError -= stats->cntOutofOrder; + if (stats->cntError < 0) + stats->cntError = 0; + stats->cntDatagrams = stats->PacketID - stats->total.Datagrams.prev; + if ((stats->output_handler) && !(stats->isMaskOutput)) { + reporter_set_timestamps_time(stats, FINALPARTIAL); + if ((stats->ts.iEnd - stats->ts.iStart) > stats->ts.significant_partial) + (*stats->output_handler)(stats); + } + } + reporter_set_timestamps_time(stats, TOTAL); + stats->IPGsum = TimeDifference(stats->ts.packetTime, stats->ts.startTime); + stats->cntOutofOrder = stats->total.OutofOrder.current; + // assume most of the time out-of-order packets are not + // duplicate packets, so conditionally subtract them from the lost packets. + stats->cntError = stats->total.Lost.current; + stats->cntError -= stats->cntOutofOrder; + if (stats->cntError < 0) + stats->cntError = 0; + stats->cntDatagrams = stats->PacketID; + stats->cntIPG = stats->total.IPG.current; + stats->IPGsum = TimeDifference(stats->ts.packetTime, stats->ts.startTime); + stats->cntBytes = stats->total.Bytes.current; + stats->l2counts.cnt = stats->l2counts.tot_cnt; + stats->l2counts.unknown = stats->l2counts.tot_unknown; + stats->l2counts.udpcsumerr = stats->l2counts.tot_udpcsumerr; + stats->l2counts.lengtherr = stats->l2counts.tot_lengtherr; + stats->transit.current = stats->transit.total; + if (isTripTime(stats->common)) { + double lambda = ((stats->IPGsum > 0.0) ? (round (stats->cntIPG / stats->IPGsum)) : 0.0); + double meantransit = (double) ((stats->transit.total.cnt > 0) ? (stats->transit.total.sum / stats->transit.total.cnt) : 0.0); + double variance = (stats->transit.total.cnt < 2) ? 0 : \ + (sqrt(stats->transit.total.m2 / (stats->transit.total.cnt - 1))); + stats->fInP = (double) lambda * meantransit; + stats->fInPVar = (double) lambda * variance; + if (sumstats) { + sumstats->fInP += stats->fInP; + } + } + if (isIsochronous(stats->common)) { + stats->isochstats.cntFrames = stats->isochstats.framecnt.current; + stats->isochstats.cntFramesMissed = stats->isochstats.framelostcnt.current; + stats->isochstats.cntSlips = stats->isochstats.slipcnt.current; + } + if (stats->latency_histogram) { + if (sumstats && sumstats->latency_histogram) { + histogram_add(sumstats->latency_histogram, stats->latency_histogram); + sumstats->latency_histogram->final = 1; + } + stats->latency_histogram->final = 1; + } + if (stats->jitter_histogram) { + if (sumstats && sumstats->jitter_histogram) { + histogram_add(sumstats->jitter_histogram, stats->jitter_histogram); + sumstats->jitter_histogram->final = 1; + } + stats->jitter_histogram->final = 1; + } + if (stats->framelatency_histogram) { + stats->framelatency_histogram->final = 1; + } + } + if ((stats->output_handler) && !(stats->isMaskOutput)) + (*stats->output_handler)(stats); + if (!final) + reporter_reset_transfer_stats_server_udp(stats); +} + +void reporter_transfer_protocol_sum_server_udp (struct TransferInfo *stats, int final) { + if (final) { + reporter_set_timestamps_time(stats, TOTAL); + stats->cntOutofOrder = stats->total.OutofOrder.current; + // assume most of the time out-of-order packets are not + // duplicate packets, so conditionally subtract them from the lost packets. + stats->cntError = stats->total.Lost.current; + stats->cntError -= stats->cntOutofOrder; + if (stats->cntError < 0) + stats->cntError = 0; + stats->cntDatagrams = stats->total.Datagrams.current; + stats->cntBytes = stats->total.Bytes.current; + stats->IPGsum = TimeDifference(stats->ts.packetTime, stats->ts.startTime); + stats->cntIPG = stats->total.IPG.current; + } else { + stats->cntOutofOrder = stats->total.OutofOrder.current - stats->total.OutofOrder.prev; + // assume most of the time out-of-order packets are not + // duplicate packets, so conditionally subtract them from the lost packets. + stats->cntError = stats->total.Lost.current - stats->total.Lost.prev; + stats->cntError -= stats->cntOutofOrder; + if (stats->cntError < 0) + stats->cntError = 0; + stats->cntDatagrams = stats->total.Datagrams.current - stats->total.Datagrams.prev; + stats->cntBytes = stats->total.Bytes.current - stats->total.Bytes.prev; + stats->cntIPG = stats->total.IPG.current - stats->total.IPG.prev; + } + if ((stats->output_handler) && !(stats->isMaskOutput)) + (*stats->output_handler)(stats); + if (!final) { + // there is no packet ID for sum server reports, set it to total cnt for calculation + stats->PacketID = stats->total.Datagrams.current; + reporter_reset_transfer_stats_server_udp(stats); + } +} +void reporter_transfer_protocol_sum_client_udp (struct TransferInfo *stats, int final) { + if (final) { + reporter_set_timestamps_time(stats, TOTAL); + stats->sock_callstats.write.WriteErr = stats->sock_callstats.write.totWriteErr; + stats->sock_callstats.write.WriteCnt = stats->sock_callstats.write.totWriteCnt; + stats->cntDatagrams = stats->total.Datagrams.current; + stats->cntBytes = stats->total.Bytes.current; + stats->IPGsum = TimeDifference(stats->ts.packetTime, stats->ts.startTime); + stats->cntIPG = stats->total.IPG.current; + } else { + stats->cntBytes = stats->total.Bytes.current - stats->total.Bytes.prev; + stats->cntIPG = stats->total.IPG.current - stats->total.IPG.prev; + stats->cntDatagrams = stats->total.Datagrams.current - stats->total.Datagrams.prev; + } + if ((stats->output_handler) && !(stats->isMaskOutput)) + (*stats->output_handler)(stats); + + if (!final) { + stats->threadcnt = 0; + reporter_reset_transfer_stats_client_udp(stats); + } else if ((stats->common->ReportMode != kReport_CSV) && !(stats->isMaskOutput)) { + printf(report_sumcnt_datagrams, stats->threadcnt, stats->total.Datagrams.current); + fflush(stdout); + } +} + +void reporter_transfer_protocol_client_udp (struct ReporterData *data, int final) { + struct TransferInfo *stats = &data->info; + struct TransferInfo *sumstats = (data->GroupSumReport != NULL) ? &data->GroupSumReport->info : NULL; + struct TransferInfo *fullduplexstats = (data->FullDuplexReport != NULL) ? &data->FullDuplexReport->info : NULL; + stats->cntBytes = stats->total.Bytes.current - stats->total.Bytes.prev; + stats->cntDatagrams = stats->total.Datagrams.current - stats->total.Datagrams.prev; + stats->cntIPG = stats->total.IPG.current - stats->total.IPG.prev; + if (isIsochronous(stats->common)) { + stats->isochstats.cntFrames = stats->isochstats.framecnt.current - stats->isochstats.framecnt.prev; + stats->isochstats.cntFramesMissed = stats->isochstats.framelostcnt.current - stats->isochstats.framelostcnt.prev; + stats->isochstats.cntSlips = stats->isochstats.slipcnt.current - stats->isochstats.slipcnt.prev; + } + if (sumstats) { + sumstats->total.Bytes.current += stats->cntBytes; + sumstats->sock_callstats.write.WriteErr += stats->sock_callstats.write.WriteErr; + sumstats->sock_callstats.write.WriteCnt += stats->sock_callstats.write.WriteCnt; + sumstats->sock_callstats.write.totWriteErr += stats->sock_callstats.write.WriteErr; + sumstats->sock_callstats.write.totWriteCnt += stats->sock_callstats.write.WriteCnt; + sumstats->total.Datagrams.current += stats->cntDatagrams; + if (sumstats->IPGsum < stats->IPGsum) + sumstats->IPGsum = stats->IPGsum; + sumstats->total.IPG.current += stats->cntIPG; + sumstats->threadcnt++; + } + if (fullduplexstats) { + fullduplexstats->total.Bytes.current += stats->cntBytes; + fullduplexstats->total.IPG.current += stats->cntIPG; + fullduplexstats->total.Datagrams.current += stats->cntDatagrams; + if (fullduplexstats->IPGsum < stats->IPGsum) + fullduplexstats->IPGsum = stats->IPGsum; + } + if (final) { + reporter_set_timestamps_time(stats, TOTAL); + stats->cntBytes = stats->total.Bytes.current; + stats->sock_callstats.write.WriteErr = stats->sock_callstats.write.totWriteErr; + stats->sock_callstats.write.WriteCnt = stats->sock_callstats.write.totWriteCnt; + stats->cntIPG = stats->total.IPG.current; + stats->cntDatagrams = stats->PacketID; + stats->IPGsum = TimeDifference(stats->ts.packetTime, stats->ts.startTime); + if (isIsochronous(stats->common)) { + stats->isochstats.cntFrames = stats->isochstats.framecnt.current; + stats->isochstats.cntFramesMissed = stats->isochstats.framelostcnt.current; + stats->isochstats.cntSlips = stats->isochstats.slipcnt.current; + } + } else { + if (stats->ts.iEnd > 0) { + stats->cntIPG = (stats->total.IPG.current - stats->total.IPG.prev); + } else { + stats->cntIPG = 0; + } + } + if ((stats->output_handler) && !(stats->isMaskOutput)) { + (*stats->output_handler)(stats); + if (final && (stats->common->ReportMode != kReport_CSV)) { + printf(report_datagrams, stats->common->transferID, stats->total.Datagrams.current); + fflush(stdout); + } + } + reporter_reset_transfer_stats_client_udp(stats); +} + +void reporter_transfer_protocol_server_tcp (struct ReporterData *data, int final) { + struct TransferInfo *stats = &data->info; + struct TransferInfo *sumstats = (data->GroupSumReport != NULL) ? &data->GroupSumReport->info : NULL; + struct TransferInfo *fullduplexstats = (data->FullDuplexReport != NULL) ? &data->FullDuplexReport->info : NULL; + stats->cntBytes = stats->total.Bytes.current - stats->total.Bytes.prev; + int ix; + if (stats->framelatency_histogram) { + stats->framelatency_histogram->final = 0; + } + double thisInP; + if (!final) { + double bytecnt = (double) (stats->total.Bytes.current - stats->total.Bytes.prev); + double lambda = (stats->IPGsum > 0.0) ? (bytecnt / stats->IPGsum) : 0.0; + double meantransit = (double) ((stats->transit.current.cnt > 0) ? (stats->transit.current.sum / stats->transit.current.cnt) : 0.0); + thisInP = lambda * meantransit; + stats->iInP = thisInP; + } else { + double bytecnt = (double) stats->cntBytes; + double lambda = (stats->IPGsum > 0.0) ? (bytecnt / stats->IPGsum) : 0.0; + double meantransit = (double) ((stats->transit.total.cnt > 0) ? (stats->transit.total.sum / stats->transit.total.cnt) : 0.0); + thisInP = lambda * meantransit; + stats->fInP = thisInP; + } + if (sumstats) { + sumstats->threadcnt++; + sumstats->total.Bytes.current += stats->cntBytes; + sumstats->sock_callstats.read.cntRead += stats->sock_callstats.read.cntRead; + sumstats->sock_callstats.read.totcntRead += stats->sock_callstats.read.cntRead; + for (ix = 0; ix < TCPREADBINCOUNT; ix++) { + sumstats->sock_callstats.read.bins[ix] += stats->sock_callstats.read.bins[ix]; + sumstats->sock_callstats.read.totbins[ix] += stats->sock_callstats.read.bins[ix]; + } + if (!final) { + sumstats->iInP += thisInP; + } else { + sumstats->fInP += thisInP; + } + } + if (fullduplexstats) { + fullduplexstats->total.Bytes.current += stats->cntBytes; + } + if (final) { + if ((stats->cntBytes > 0) && stats->output_handler && !TimeZero(stats->ts.intervalTime)) { + // print a partial interval report if enable and this a final + if ((stats->output_handler) && !(stats->isMaskOutput)) { + if (isIsochronous(stats->common)) { + stats->isochstats.cntFrames = stats->isochstats.framecnt.current - stats->isochstats.framecnt.prev; + stats->isochstats.cntFramesMissed = stats->isochstats.framelostcnt.current - stats->isochstats.framelostcnt.prev; + stats->isochstats.cntSlips = stats->isochstats.slipcnt.current - stats->isochstats.slipcnt.prev; + } + reporter_set_timestamps_time(stats, FINALPARTIAL); + if ((stats->ts.iEnd - stats->ts.iStart) > stats->ts.significant_partial) + (*stats->output_handler)(stats); + reporter_reset_transfer_stats_server_tcp(stats); + } + } + if (stats->framelatency_histogram) { + stats->framelatency_histogram->final = 1; + } + reporter_set_timestamps_time(stats, TOTAL); + stats->cntBytes = stats->total.Bytes.current; + stats->IPGsum = stats->ts.iEnd; + stats->sock_callstats.read.cntRead = stats->sock_callstats.read.totcntRead; + for (ix = 0; ix < TCPREADBINCOUNT; ix++) { + stats->sock_callstats.read.bins[ix] = stats->sock_callstats.read.totbins[ix]; + } + if (isIsochronous(stats->common)) { + stats->isochstats.cntFrames = stats->isochstats.framecnt.current; + stats->isochstats.cntFramesMissed = stats->isochstats.framelostcnt.current; + stats->isochstats.cntSlips = stats->isochstats.slipcnt.current; + } + stats->transit.current = stats->transit.total; + if (stats->framelatency_histogram) { + if (sumstats && sumstats->framelatency_histogram) { + histogram_add(sumstats->framelatency_histogram, stats->framelatency_histogram); + sumstats->framelatency_histogram->final = 1; + } + stats->framelatency_histogram->final = 1; + } + } else if (isIsochronous(stats->common)) { + stats->isochstats.cntFrames = stats->isochstats.framecnt.current - stats->isochstats.framecnt.prev; + stats->isochstats.cntFramesMissed = stats->isochstats.framelostcnt.current - stats->isochstats.framelostcnt.prev; + stats->isochstats.cntSlips = stats->isochstats.slipcnt.current - stats->isochstats.slipcnt.prev; + } + if ((stats->output_handler) && !stats->isMaskOutput) { + (*stats->output_handler)(stats); + if (isFrameInterval(stats->common) && stats->framelatency_histogram) { + histogram_print(stats->framelatency_histogram, stats->ts.iStart, stats->ts.iEnd); + } + } + if (!final) + reporter_reset_transfer_stats_server_tcp(stats); +} + +void reporter_transfer_protocol_client_tcp (struct ReporterData *data, int final) { + struct TransferInfo *stats = &data->info; + struct TransferInfo *sumstats = (data->GroupSumReport != NULL) ? &data->GroupSumReport->info : NULL; + struct TransferInfo *fullduplexstats = (data->FullDuplexReport != NULL) ? &data->FullDuplexReport->info : NULL; + stats->cntBytes = stats->total.Bytes.current - stats->total.Bytes.prev; + if (stats->latency_histogram) { + stats->latency_histogram->final = final; + } + if (stats->write_histogram) { + stats->write_histogram->final = final; + } + if (isIsochronous(stats->common)) { + if (final) { + stats->isochstats.cntFrames = stats->isochstats.framecnt.current; + stats->isochstats.cntFramesMissed = stats->isochstats.framelostcnt.current; + stats->isochstats.cntSlips = stats->isochstats.slipcnt.current; + } else { + stats->isochstats.cntFrames = stats->isochstats.framecnt.current - stats->isochstats.framecnt.prev; + stats->isochstats.cntFramesMissed = stats->isochstats.framelostcnt.current - stats->isochstats.framelostcnt.prev; + stats->isochstats.cntSlips = stats->isochstats.slipcnt.current - stats->isochstats.slipcnt.prev; + } + } + if (sumstats) { + sumstats->total.Bytes.current += stats->cntBytes; + sumstats->sock_callstats.write.WriteErr += stats->sock_callstats.write.WriteErr; + sumstats->sock_callstats.write.WriteCnt += stats->sock_callstats.write.WriteCnt; + sumstats->sock_callstats.write.totWriteErr += stats->sock_callstats.write.WriteErr; + sumstats->sock_callstats.write.totWriteCnt += stats->sock_callstats.write.WriteCnt; + sumstats->threadcnt++; +#if HAVE_TCP_STATS + sumstats->sock_callstats.write.tcpstats.retry += stats->sock_callstats.write.tcpstats.retry; + sumstats->sock_callstats.write.tcpstats.retry_tot += stats->sock_callstats.write.tcpstats.retry; +#endif + } + if (fullduplexstats) { + fullduplexstats->total.Bytes.current += stats->cntBytes; + } + if (final) { + if (stats->latency_histogram) { + stats->latency_histogram->final = 1; + } + if (stats->write_histogram) { + stats->write_histogram->final = 1; + } + if ((stats->cntBytes > 0) && stats->output_handler && !TimeZero(stats->ts.intervalTime)) { + // print a partial interval report if enable and this a final + if ((stats->output_handler) && !(stats->isMaskOutput)) { + if (isIsochronous(stats->common)) { + stats->isochstats.cntFrames = stats->isochstats.framecnt.current - stats->isochstats.framecnt.prev; + stats->isochstats.cntFramesMissed = stats->isochstats.framelostcnt.current - stats->isochstats.framelostcnt.prev; + stats->isochstats.cntSlips = stats->isochstats.slipcnt.current - stats->isochstats.slipcnt.prev; + } + reporter_set_timestamps_time(stats, FINALPARTIAL); + if ((stats->ts.iEnd - stats->ts.iStart) > stats->ts.significant_partial) + (*stats->output_handler)(stats); + reporter_reset_transfer_stats_client_tcp(stats); + } + } + if (isIsochronous(stats->common)) { + stats->isochstats.cntFrames = stats->isochstats.framecnt.current; + stats->isochstats.cntFramesMissed = stats->isochstats.framelostcnt.current; + stats->isochstats.cntSlips = stats->isochstats.slipcnt.current; + } + stats->sock_callstats.write.WriteErr = stats->sock_callstats.write.totWriteErr; + stats->sock_callstats.write.WriteCnt = stats->sock_callstats.write.totWriteCnt; +#if HAVE_TCP_STATS + stats->sock_callstats.write.tcpstats.retry = stats->sock_callstats.write.tcpstats.retry_tot; +#endif + if (stats->framelatency_histogram) { + stats->framelatency_histogram->final = 1; + } + stats->cntBytes = stats->total.Bytes.current; + stats->write_mmm.current = stats->write_mmm.total; + reporter_set_timestamps_time(stats, TOTAL); + } else if (isIsochronous(stats->common)) { + stats->isochstats.cntFrames = stats->isochstats.framecnt.current - stats->isochstats.framecnt.prev; + stats->isochstats.cntFramesMissed = stats->isochstats.framelostcnt.current - stats->isochstats.framelostcnt.prev; + stats->isochstats.cntSlips = stats->isochstats.slipcnt.current - stats->isochstats.slipcnt.prev; + } + if ((stats->output_handler) && !(stats->isMaskOutput)) { + (*stats->output_handler)(stats); + } + if (!final) + reporter_reset_transfer_stats_client_tcp(stats); +} + +/* + * Handles summing of threads + */ +void reporter_transfer_protocol_sum_client_tcp (struct TransferInfo *stats, int final) { + if (!final || (final && (stats->cntBytes > 0) && !TimeZero(stats->ts.intervalTime))) { + stats->cntBytes = stats->total.Bytes.current - stats->total.Bytes.prev; + if (final) { + if ((stats->output_handler) && !(stats->isMaskOutput)) { + reporter_set_timestamps_time(stats, FINALPARTIAL); + if ((stats->ts.iEnd - stats->ts.iStart) > stats->ts.significant_partial) + (*stats->output_handler)(stats); + reporter_reset_transfer_stats_client_tcp(stats); + } + } else if ((stats->output_handler) && !(stats->isMaskOutput)) { + (*stats->output_handler)(stats); + stats->threadcnt = 0; + } + reporter_reset_transfer_stats_client_tcp(stats); + } + if (final) { + stats->sock_callstats.write.WriteErr = stats->sock_callstats.write.totWriteErr; + stats->sock_callstats.write.WriteCnt = stats->sock_callstats.write.totWriteCnt; +#if HAVE_TCP_STATS + stats->sock_callstats.write.tcpstats.retry = stats->sock_callstats.write.tcpstats.retry_tot; +#endif + stats->cntBytes = stats->total.Bytes.current; + reporter_set_timestamps_time(stats, TOTAL); + if ((stats->output_handler) && !(stats->isMaskOutput)) + (*stats->output_handler)(stats); + } +} + +void reporter_transfer_protocol_client_bb_tcp (struct ReporterData *data, int final) { + struct TransferInfo *stats = &data->info; + + if (final) { + if ((stats->cntBytes > 0) && stats->output_handler && !TimeZero(stats->ts.intervalTime)) { + // print a partial interval report if enable and this a final + if ((stats->output_handler) && !(stats->isMaskOutput)) { + reporter_set_timestamps_time(stats, FINALPARTIAL); + if ((stats->ts.iEnd - stats->ts.iStart) > stats->ts.significant_partial) + (*stats->output_handler)(stats); + reporter_reset_transfer_stats_client_tcp(stats); + } + } +#if HAVE_TCP_STATS + stats->sock_callstats.write.tcpstats.retry = stats->sock_callstats.write.tcpstats.retry_tot; +#endif + stats->cntBytes = stats->total.Bytes.current; + reporter_set_timestamps_time(stats, TOTAL); + } else { + stats->cntBytes = stats->total.Bytes.current - stats->total.Bytes.prev; + } + if ((stats->output_handler) && !(stats->isMaskOutput)) + (*stats->output_handler)(stats); + if (!final) { + reporter_reset_transfer_stats_client_tcp(stats); + } +} + +void reporter_transfer_protocol_server_bb_tcp (struct ReporterData *data, int final) { + struct TransferInfo *stats = &data->info; + if (final) { + if ((stats->cntBytes > 0) && stats->output_handler && !TimeZero(stats->ts.intervalTime)) { + // print a partial interval report if enable and this a final + if ((stats->output_handler) && !(stats->isMaskOutput)) { + reporter_set_timestamps_time(stats, FINALPARTIAL); + if ((stats->ts.iEnd - stats->ts.iStart) > stats->ts.significant_partial) + (*stats->output_handler)(stats); + reporter_reset_transfer_stats_server_tcp(stats); + } + } +#if HAVE_TCP_STATS + + stats->sock_callstats.write.tcpstats.retry = stats->sock_callstats.write.tcpstats.retry_tot; +#endif + stats->cntBytes = stats->total.Bytes.current; + reporter_set_timestamps_time(stats, TOTAL); + } else { + stats->cntBytes = stats->total.Bytes.current - stats->total.Bytes.prev; + } + if ((stats->output_handler) && !(stats->isMaskOutput)) + (*stats->output_handler)(stats); + if (!final) + reporter_reset_transfer_stats_client_tcp(stats); +} + +void reporter_transfer_protocol_sum_server_tcp (struct TransferInfo *stats, int final) { + if (!final || (final && (stats->cntBytes > 0) && !TimeZero(stats->ts.intervalTime))) { + stats->cntBytes = stats->total.Bytes.current - stats->total.Bytes.prev; + if (final) { + if ((stats->output_handler) && !(stats->isMaskOutput)) { + reporter_set_timestamps_time(stats, FINALPARTIAL); + if ((stats->ts.iEnd - stats->ts.iStart) > stats->ts.significant_partial) + (*stats->output_handler)(stats); + } + } else if ((stats->output_handler) && !(stats->isMaskOutput)) { + (*stats->output_handler)(stats); + stats->threadcnt = 0; + stats->iInP = 0; + } + reporter_reset_transfer_stats_server_tcp(stats); + } + if (final) { + int ix; + stats->cntBytes = stats->total.Bytes.current; + stats->sock_callstats.read.cntRead = stats->sock_callstats.read.totcntRead; + for (ix = 0; ix < TCPREADBINCOUNT; ix++) { + stats->sock_callstats.read.bins[ix] = stats->sock_callstats.read.totbins[ix]; + } + stats->cntBytes = stats->total.Bytes.current; + reporter_set_timestamps_time(stats, TOTAL); + if ((stats->output_handler) && !(stats->isMaskOutput)) + (*stats->output_handler)(stats); + } +} +void reporter_transfer_protocol_fullduplex_tcp (struct TransferInfo *stats, int final) { + if (!final || (final && (stats->cntBytes > 0) && !TimeZero(stats->ts.intervalTime))) { + stats->cntBytes = stats->total.Bytes.current - stats->total.Bytes.prev; + if (final) { + if ((stats->output_handler) && !(stats->isMaskOutput)) { + reporter_set_timestamps_time(stats, FINALPARTIAL); + if ((stats->ts.iEnd - stats->ts.iStart) > stats->ts.significant_partial) + (*stats->output_handler)(stats); + } + } + stats->total.Bytes.prev = stats->total.Bytes.current; + } + if (final) { + stats->cntBytes = stats->total.Bytes.current; + reporter_set_timestamps_time(stats, TOTAL); + } else { + reporter_set_timestamps_time(stats, INTERVAL); + } + if ((stats->output_handler) && !(stats->isMaskOutput)) + (*stats->output_handler)(stats); +} + +void reporter_transfer_protocol_fullduplex_udp (struct TransferInfo *stats, int final) { + if (!final || (final && (stats->cntBytes > 0) && !TimeZero(stats->ts.intervalTime))) { + stats->cntBytes = stats->total.Bytes.current - stats->total.Bytes.prev; + stats->cntDatagrams = stats->total.Datagrams.current - stats->total.Datagrams.prev; + stats->cntIPG = stats->total.IPG.current - stats->total.IPG.prev; + if (final) { + if ((stats->output_handler) && !(stats->isMaskOutput)) { + reporter_set_timestamps_time(stats, FINALPARTIAL); + if ((stats->ts.iEnd - stats->ts.iStart) > stats->ts.significant_partial) + (*stats->output_handler)(stats); + } + } + stats->total.Bytes.prev = stats->total.Bytes.current; + stats->total.IPG.prev = stats->total.IPG.current; + stats->total.Datagrams.prev = stats->total.Datagrams.current; + } + if (final) { + stats->cntBytes = stats->total.Bytes.current; + stats->cntBytes = stats->total.Bytes.current; + stats->cntDatagrams = stats->total.Datagrams.current ; + stats->cntIPG = stats->total.IPG.current; + stats->IPGsum = TimeDifference(stats->ts.packetTime, stats->ts.startTime); + reporter_set_timestamps_time(stats, TOTAL); + } else { + reporter_set_timestamps_time(stats, INTERVAL); + } + if ((stats->output_handler) && !(stats->isMaskOutput)) + (*stats->output_handler)(stats); + if (stats->cntDatagrams) + stats->IPGsum = 0.0; +} + +// Conditional print based on time +int reporter_condprint_time_interval_report (struct ReporterData *data, struct ReportStruct *packet) { + struct TransferInfo *stats = &data->info; + assert(stats!=NULL); + // printf("***sum handler = %p\n", (void *) data->GroupSumReport->transfer_protocol_sum_handler); + int advance_jobq = 0; + // Print a report if packet time exceeds the next report interval time, + // Also signal to the caller to move to the next report (or packet ring) + // if there was output. This will allow for more precise interval sum accounting. + // printf("***** pt = %ld.%ld next = %ld.%ld\n", packet->packetTime.tv_sec, packet->packetTime.tv_usec, stats->ts.nextTime.tv_sec, stats->ts.nextTime.tv_usec); + // printf("***** nt %ld.%ld pt %ld.%ld pid=%lld empty=%d\n", stats->ts.nextTime.tv_sec, stats->ts.nextTime.tv_usec, packet->packetTime.tv_sec, packet->packetTime.tv_usec, packet->packetID, packet->emptyreport); + if (TimeDifference(stats->ts.nextTime, packet->packetTime) < 0) { + assert(data->transfer_protocol_handler!=NULL); + advance_jobq = 1; + struct TransferInfo *sumstats = (data->GroupSumReport ? &data->GroupSumReport->info : NULL); + struct TransferInfo *fullduplexstats = (data->FullDuplexReport ? &data->FullDuplexReport->info : NULL); + stats->ts.packetTime = packet->packetTime; +#ifdef DEBUG_PPS + printf("*** packetID TRIGGER = %ld pt=%ld.%ld empty=%d nt=%ld.%ld\n",packet->packetID, packet->packetTime.tv_sec, packet->packetTime.tv_usec, packet->emptyreport, stats->ts.nextTime.tv_sec, stats->ts.nextTime.tv_usec); +#endif + reporter_set_timestamps_time(stats, INTERVAL); + (*data->transfer_protocol_handler)(data, 0); + if (fullduplexstats && ((++data->FullDuplexReport->threads) == 2) && isEnhanced(stats->common)) { + data->FullDuplexReport->threads = 0; + assert(data->FullDuplexReport->transfer_protocol_sum_handler != NULL); + (*data->FullDuplexReport->transfer_protocol_sum_handler)(fullduplexstats, 0); + } + if (sumstats) { + if ((++data->GroupSumReport->threads) == data->GroupSumReport->reference.count) { + data->GroupSumReport->threads = 0; + if ((data->GroupSumReport->reference.count > (fullduplexstats ? 2 : 1)) || \ + isSumOnly(data->info.common)) { + sumstats->isMaskOutput = false; + } else { + sumstats->isMaskOutput = true; + } + reporter_set_timestamps_time(sumstats, INTERVAL); + assert(data->GroupSumReport->transfer_protocol_sum_handler != NULL); + (*data->GroupSumReport->transfer_protocol_sum_handler)(sumstats, 0); + } + } + // In the (hopefully unlikely event) the reporter fell behind + // output the missed reports to catch up + if ((stats->output_handler) && !(stats->isMaskOutput)) + reporter_transfer_protocol_missed_reports(stats, packet); + } + return advance_jobq; +} + +// Conditional print based on bursts or frames +int reporter_condprint_frame_interval_report_server_udp (struct ReporterData *data, struct ReportStruct *packet) { + struct TransferInfo *stats = &data->info; + int advance_jobq = 0; + // first packet of a burst and not a duplicate + if ((packet->burstsize == (packet->remaining + packet->packetLen)) && (stats->matchframeID != packet->frameID)) { + stats->matchframeID=packet->frameID; + } + if ((packet->packetLen == packet->remaining) && (packet->frameID == stats->matchframeID)) { + if ((stats->ts.iStart = TimeDifference(stats->ts.nextTime, stats->ts.startTime)) < 0) + stats->ts.iStart = 0.0; + stats->frameID = packet->frameID; + stats->ts.iEnd = TimeDifference(packet->packetTime, stats->ts.startTime); + stats->cntBytes = stats->total.Bytes.current - stats->total.Bytes.prev; + stats->cntOutofOrder = stats->total.OutofOrder.current - stats->total.OutofOrder.prev; + // assume most of the time out-of-order packets are not + // duplicate packets, so conditionally subtract them from the lost packets. + stats->cntError = stats->total.Lost.current - stats->total.Lost.prev; + stats->cntError -= stats->cntOutofOrder; + if (stats->cntError < 0) + stats->cntError = 0; + stats->cntDatagrams = stats->PacketID - stats->total.Datagrams.prev; + if ((stats->output_handler) && !(stats->isMaskOutput)) + (*stats->output_handler)(stats); + reporter_reset_transfer_stats_server_udp(stats); + advance_jobq = 1; + } + return advance_jobq; +} + +int reporter_condprint_frame_interval_report_server_tcp (struct ReporterData *data, struct ReportStruct *packet) { + fprintf(stderr, "FIX ME\n"); + return 1; +} + +int reporter_condprint_burst_interval_report_server_tcp (struct ReporterData *data, struct ReportStruct *packet) { + struct TransferInfo *stats = &data->info; + int advance_jobq = 0; + if (packet->transit_ready) { + stats->ts.prevpacketTime = packet->sentTime; + stats->ts.packetTime = packet->packetTime; + reporter_set_timestamps_time(stats, INTERVALPARTIAL); + stats->cntBytes = stats->total.Bytes.current - stats->total.Bytes.prev; + if ((stats->output_handler) && !(stats->isMaskOutput)) + (*stats->output_handler)(stats); + reporter_reset_transfer_stats_server_tcp(stats); + advance_jobq = 1; + } + return advance_jobq; +} + +int reporter_condprint_burst_interval_report_client_tcp (struct ReporterData *data, struct ReportStruct *packet) { + struct TransferInfo *stats = &data->info; + int advance_jobq = 0; + // first packet of a burst and not a duplicate + if (packet->transit_ready) { + reporter_handle_packet_oneway_transit(stats, packet); +// printf("****sndpkt=%ld.%ld rxpkt=%ld.%ld\n", packet->sentTime.tv_sec, packet->sentTime.tv_usec, packet->packetTime.tv_sec,packet->packetTime.tv_usec); + stats->ts.prevpacketTime = packet->prevSentTime; + stats->ts.packetTime = packet->packetTime; + reporter_set_timestamps_time(stats, INTERVALPARTIAL); + stats->cntBytes = stats->total.Bytes.current - stats->total.Bytes.prev; + if ((stats->output_handler) && !(stats->isMaskOutput)) + (*stats->output_handler)(stats); + reporter_reset_transfer_stats_client_tcp(stats); + advance_jobq = 1; + } + return advance_jobq; +} + +#ifdef __cplusplus +} /* end extern "C" */ +#endif diff --git a/src/Reports.c b/src/Reports.c new file mode 100644 index 0000000..008f7f4 --- /dev/null +++ b/src/Reports.c @@ -0,0 +1,1091 @@ +/*--------------------------------------------------------------- + * Copyright (c) 1999,2000,2001,2002,2003 + * The Board of Trustees of the University of Illinois + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software (Iperf) and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the names of the University of Illinois, NCSA, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * National Laboratory for Applied Network Research + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * http://www.ncsa.uiuc.edu + * ________________________________________________________________ + * + * Reporter.c + * rewritten by Robert McMahon + * ------------------------------------------------------------------- + * Handle instantiation and deletion of reports, including sum reports, + * in a thread safe way + * ------------------------------------------------------------------- */ + +#include "headers.h" +#include <math.h> +#include "Settings.hpp" +#include "PerfSocket.hpp" +#include "Reporter.h" +#include "Locale.h" +#include "active_hosts.h" +#include "payloads.h" +static int transferid_counter = 0; + +static inline int my_str_copy(char **dst, char *src) { + int cnt = 0; + if (src) { + *dst = (char *) calloc(strlen(src) + 1, sizeof(char)); + if (*dst == NULL) { + fprintf(stderr, "Out of Memory!!\n"); + exit(1); + } + cnt = strlen(src) + 1; + strcpy((*dst), src); + } else { + *dst = NULL; + } + return cnt; +} + +// These are the thread settings that are shared among report types +// Make a copy vs referencing the thread setting object. This will +// better encpasulate report handling. +static void common_copy (struct ReportCommon **common, struct thread_Settings *inSettings) { + // Do deep copies from settings + *common = (struct ReportCommon *) calloc(1, sizeof(struct ReportCommon)); + my_str_copy(&(*common)->Host, inSettings->mHost); + my_str_copy(&(*common)->HideHost, inSettings->mHideHost); + my_str_copy(&(*common)->Localhost, inSettings->mLocalhost); + my_str_copy(&(*common)->Ifrname, inSettings->mIfrname); + my_str_copy(&(*common)->Ifrnametx, inSettings->mIfrnametx); + my_str_copy(&(*common)->SSMMulticastStr, inSettings->mSSMMulticastStr); + my_str_copy(&(*common)->Congestion, inSettings->mCongestion); + my_str_copy(&(*common)->transferIDStr, inSettings->mTransferIDStr); + my_str_copy(&(*common)->PermitKey, inSettings->mPermitKey); + + // copy some relevant settings + (*common)->flags = inSettings->flags; + (*common)->flags_extend = inSettings->flags_extend; + (*common)->flags_extend2 = inSettings->flags_extend2; + (*common)->ThreadMode = inSettings->mThreadMode; + (*common)->ReportMode = inSettings->mReportMode; + (*common)->KeyCheck = inSettings->mKeyCheck; + (*common)->Format = inSettings->mFormat; + (*common)->TTL = inSettings->mTTL; + // copy some traffic related settings + (*common)->BufLen = inSettings->mBufLen; + (*common)->MSS = inSettings->mMSS; + (*common)->TCPWin = inSettings->mTCPWin; + (*common)->FQPacingRate = inSettings->mFQPacingRate; + (*common)->Port = inSettings->mPort; + (*common)->PortLast = inSettings->mPortLast; + (*common)->BindPort = inSettings->mBindPort; + (*common)->ListenPort = inSettings->mListenPort; + (*common)->AppRate = inSettings->mAppRate; + (*common)->BurstSize = inSettings->mBurstSize; + (*common)->AppRateUnits = inSettings->mAppRateUnits; + (*common)->socket = inSettings->mSock; + (*common)->transferID = inSettings->mTransferID; + (*common)->threads = inSettings->mThreads; + (*common)->winsize_requested = inSettings->mTCPWin; +#if defined(HAVE_LINUX_FILTER_H) && defined(HAVE_AF_PACKET) + (*common)->socketdrop = inSettings->mSockDrop; +#endif + (*common)->peer = inSettings->peer; + (*common)->size_peer = inSettings->size_peer; + (*common)->jitter_binwidth = inSettings->jitter_binwidth; + (*common)->local = inSettings->local; + (*common)->size_local = inSettings->size_local; + (*common)->HistBins =inSettings->mHistBins; + (*common)->HistBinsize =inSettings->mHistBinsize; + (*common)->HistUnits =inSettings->mHistUnits; + (*common)->pktIPG =inSettings->mBurstIPG; + (*common)->rtt_weight = inSettings->rtt_nearcongest_weight_factor; + (*common)->ListenerTimeout =inSettings->mListenerTimeout; + (*common)->FPS = inSettings->mFPS; + (*common)->TOS = inSettings->mTOS; + (*common)->RTOS = inSettings->mRTOS; + (*common)->bbsize = inSettings->mBounceBackBytes; + (*common)->bbhold = inSettings->mBounceBackHold; + (*common)->bbcount = inSettings->mBounceBackBurst; +#if HAVE_DECL_TCP_WINDOW_CLAMP + (*common)->ClampSize = inSettings->mClampSize; +#endif +#if HAVE_DECL_TCP_NOTSENT_LOWAT + (*common)->WritePrefetch = inSettings->mWritePrefetch; +#endif +#ifdef HAVE_THREAD_DEBUG + thread_debug("Alloc common rpt/com/size %p/%p/%d", (void *) common, (void *)(*common), sizeof(struct ReportCommon)); +#endif +} + +static void free_common_copy (struct ReportCommon *common) { + assert(common != NULL); +#ifdef HAVE_THREAD_DEBUG + thread_debug("Free common=%p", (void *)common); +#endif + // Free deep copies + if (common->Host) + free(common->Host); + if (common->HideHost) + free(common->HideHost); + if (common->Localhost) + free(common->Localhost); + if (common->Ifrname) + free(common->Ifrname); + if (common->Ifrnametx) + free(common->Ifrnametx); + if (common->SSMMulticastStr) + free(common->SSMMulticastStr); + if (common->Congestion) + free(common->Congestion); + if (common->transferIDStr) + free(common->transferIDStr); + if (common->PermitKey) + free(common->PermitKey); + free(common); +} + +// This will set the transfer id and id string +// on the setting object. If the current id is zero +// this will get the next one. Otherwise it will use +// the value. +void setTransferID (struct thread_Settings *inSettings, int role_reversal) { + if (!inSettings->mTransferIDStr) { + if (!inSettings->mTransferID) { + Mutex_Lock(&transferid_mutex); + inSettings->mTransferID = ++transferid_counter; + Mutex_Unlock(&transferid_mutex); + } + int len = 0; + if (role_reversal) { +#ifdef HAVE_ROLE_REVERSAL_ID + if (isPermitKey(inSettings) && (inSettings->mPermitKey[0] != '\0')) { + len = snprintf(NULL, 0, "[%s(*%d)] ", \ + inSettings->mPermitKey, inSettings->mTransferID); + inSettings->mTransferIDStr = (char *) calloc(len + 1, sizeof(char)); + len = sprintf(inSettings->mTransferIDStr, "[%s(*%d)] ", \ + inSettings->mPermitKey, inSettings->mTransferID); + } else if (inSettings->mTransferID < 10) { + len = snprintf(NULL, 0, "[ *%d] ", inSettings->mTransferID); + inSettings->mTransferIDStr = (char *) calloc(len + 1, sizeof(char)); + len = sprintf(inSettings->mTransferIDStr, "[ *%d] ", inSettings->mTransferID); + } else { + len = snprintf(NULL, 0, "[*%d] ", inSettings->mTransferID); + inSettings->mTransferIDStr = (char *) calloc(len + 1, sizeof(char)); + len = sprintf(inSettings->mTransferIDStr, "[*%d] ", inSettings->mTransferID); + } +#endif + } else if (isPermitKey(inSettings) && (inSettings->mPermitKey[0] != '\0')) { + len = snprintf(NULL, 0, "[%s(%d)] ", \ + inSettings->mPermitKey, inSettings->mTransferID); + inSettings->mTransferIDStr = (char *) calloc(len + 1, sizeof(char)); + len = sprintf(inSettings->mTransferIDStr, "[%s(%d)] ", \ + inSettings->mPermitKey, inSettings->mTransferID); + } else { + len = snprintf(NULL, 0, "[%3d] ", inSettings->mTransferID); + inSettings->mTransferIDStr = (char *) calloc(len+1, sizeof(char)); + len = sprintf(inSettings->mTransferIDStr, "[%3d] ", inSettings->mTransferID); + } + } +} + +void SetFullDuplexHandlers (struct thread_Settings *inSettings, struct SumReport* sumreport) { + if (isUDP(inSettings)) { + sumreport->transfer_protocol_sum_handler = reporter_transfer_protocol_fullduplex_udp; + sumreport->info.output_handler = ((inSettings->mReportMode == kReport_CSV) ? NULL : \ + (isSumOnly(inSettings) ? NULL : \ + (isEnhanced(inSettings) ? udp_output_fullduplex_enhanced : udp_output_fullduplex))); + } else { + sumreport->transfer_protocol_sum_handler = reporter_transfer_protocol_fullduplex_tcp; + sumreport->info.output_handler = ((inSettings->mReportMode == kReport_CSV) ? NULL : \ + (isSumOnly(inSettings) ? NULL : \ + (isEnhanced(inSettings) ? tcp_output_fullduplex_enhanced : tcp_output_fullduplex))); + } +} + +void SetSumHandlers (struct thread_Settings *inSettings, struct SumReport* sumreport) { + switch (inSettings->mThreadMode) { + case kMode_Server : + if (isUDP(inSettings)) { + sumreport->transfer_protocol_sum_handler = reporter_transfer_protocol_sum_server_udp; + if (inSettings->mReportMode == kReport_CSV) { + if (isEnhanced(inSettings)) + sumreport->info.output_handler = udp_output_enhanced_csv; + else + sumreport->info.output_handler = udp_output_basic_csv; + } else { + if (isTripTime(inSettings)) { + sumreport->info.output_handler = udp_output_sumcnt_read_triptime; + } else if (isSumOnly(inSettings)) { + sumreport->info.output_handler = udp_output_sumcnt_enhanced; + } else if (isFullDuplex(inSettings)) { + sumreport->info.output_handler = udp_output_fullduplex_sum; + } else { + sumreport->info.output_handler = (isEnhanced(inSettings) ? udp_output_sum_read_enhanced : udp_output_sum_read); + } + } + } else { + sumreport->transfer_protocol_sum_handler = reporter_transfer_protocol_sum_server_tcp; + if (inSettings->mReportMode == kReport_CSV) { + if (isEnhanced(inSettings)) + sumreport->info.output_handler = tcp_output_read_enhanced_csv; + else + sumreport->info.output_handler = tcp_output_basic_csv; + } else { + if (isTripTime(inSettings)) { + sumreport->info.output_handler = tcp_output_sumcnt_read_triptime; + } else if (isSumOnly(inSettings)) { + sumreport->info.output_handler = (isEnhanced(inSettings) ? tcp_output_sumcnt_read_enhanced : tcp_output_sumcnt_read); + } else if (isFullDuplex(inSettings)) { + sumreport->info.output_handler = tcp_output_sum_read; + } else { + sumreport->info.output_handler = (isEnhanced(inSettings) ? tcp_output_sum_read_enhanced : tcp_output_sum_read); + } + } + } + break; + case kMode_Client : + if (isUDP(inSettings)) { + sumreport->transfer_protocol_sum_handler = reporter_transfer_protocol_sum_client_udp; + if (inSettings->mReportMode == kReport_CSV) { + if (isEnhanced(inSettings)) + sumreport->info.output_handler = udp_output_enhanced_csv; + else + sumreport->info.output_handler = udp_output_basic_csv; + } else { + if (isSumOnly(inSettings)) { + sumreport->info.output_handler = ((isEnhanced(inSettings) && !isFullDuplex(inSettings)) ? \ + udp_output_sumcnt_write_enhanced : udp_output_sumcnt); + } else if (isFullDuplex(inSettings)) { + sumreport->info.output_handler = udp_output_fullduplex_sum; + } else { + sumreport->info.output_handler = (isEnhanced(inSettings) ? udp_output_sum_write_enhanced : udp_output_sum_write); + } + } + } else { + sumreport->transfer_protocol_sum_handler = reporter_transfer_protocol_sum_client_tcp; + if (inSettings->mReportMode == kReport_CSV) { + if (isEnhanced(inSettings)) + sumreport->info.output_handler = tcp_output_write_enhanced_csv; + else + sumreport->info.output_handler = tcp_output_basic_csv; + } else { + if (isSumOnly(inSettings)) { + sumreport->info.output_handler = (isEnhanced(inSettings) ? tcp_output_sumcnt_write_enhanced : tcp_output_sumcnt_write); + } else if (isFullDuplex(inSettings)) { + sumreport->info.output_handler = tcp_output_fullduplex_sum; + } else { + sumreport->info.output_handler = (isEnhanced(inSettings) ? tcp_output_sum_write_enhanced : tcp_output_sum_write); + } + } + } + break; + default: + FAIL(1, "SetSumReport", inSettings); + } +} + +struct SumReport* InitSumReport(struct thread_Settings *inSettings, int inID, int fullduplex_report) { + struct SumReport *sumreport = (struct SumReport *) calloc(1, sizeof(struct SumReport)); + if (sumreport == NULL) { + FAIL(1, "Out of Memory!!\n", inSettings); + } + sumreport->reference.count = 0; + sumreport->reference.maxcount = 0; + Mutex_Initialize(&sumreport->reference.lock); + sumreport->threads = 0; + common_copy(&sumreport->info.common, inSettings); + // sumreport->info.common->transferID = inID; // this is now set in the active code + sumreport->info.threadcnt = 0; + sumreport->info.isMaskOutput = false; + if (inSettings->mReportMode == kReport_CSV) { + format_ips_port_string(&sumreport->info, 1); + } + + // Only initialize the interval time here + // The startTime and nextTime for summing reports will be set by + // the reporter thread in realtime + if ((inSettings->mInterval) && (inSettings->mIntervalMode == kInterval_Time)) { + sumreport->info.ts.intervalTime.tv_sec = (long) (inSettings->mInterval / rMillion); + sumreport->info.ts.intervalTime.tv_usec = (long) (inSettings->mInterval % rMillion); + sumreport->info.ts.significant_partial = ((double) inSettings->mInterval * PARTIALPERCENT / rMillion) ; + } + // Note that for UDP the client flag settings have not been read (and set) so only use server side flags in tests + if (isEnhanced(inSettings) && (inSettings->mThreadMode == kMode_Server) && !fullduplex_report) { + if (isHistogram(inSettings)) { + if (isUDP(inSettings)) { + char name[] = "SUMT8"; + sumreport->info.latency_histogram = histogram_init(inSettings->mHistBins,inSettings->mHistBinsize,0,\ + pow(10,inSettings->mHistUnits), \ + inSettings->mHistci_lower, inSettings->mHistci_upper, sumreport->info.common->transferID, name); + } else { + char name[] = "SUMF8"; + sumreport->info.framelatency_histogram = histogram_init(inSettings->mHistBins,inSettings->mHistBinsize,0, \ + pow(10,inSettings->mHistUnits), inSettings->mHistci_lower, \ + inSettings->mHistci_upper, sumreport->info.common->transferID, name); + } + } + if (isJitterHistogram(inSettings) && isUDP(inSettings)) { + char name[] = "SUMJ8"; + sumreport->info.jitter_histogram = histogram_init(JITTER_BINCNT,inSettings->jitter_binwidth,0,JITTER_UNITS, \ + JITTER_LCI, JITTER_UCI, sumreport->info.common->transferID, name); + } + } + if (fullduplex_report) { + SetFullDuplexHandlers(inSettings, sumreport); + if (!isServerReverse(inSettings)) { + sumreport->fullduplex_barrier.count = 0; + Condition_Initialize(&sumreport->fullduplex_barrier.await); + sumreport->fullduplex_barrier.timeout = ((isModeTime(inSettings) && isUDP(inSettings)) ? \ + ((int)(inSettings->mAmount / 100) + 1) : MINBARRIERTIMEOUT); + if (sumreport->fullduplex_barrier.timeout < MINBARRIERTIMEOUT) + sumreport->fullduplex_barrier.timeout = MINBARRIERTIMEOUT; + } else { + sumreport->info.ts.startTime = inSettings->accept_time; + sumreport->info.ts.nextTime = sumreport->info.ts.startTime; + TimeAdd(sumreport->info.ts.nextTime, sumreport->info.ts.intervalTime); + } + } else { + SetSumHandlers(inSettings, sumreport); + } +#ifdef HAVE_THREAD_DEBUG + thread_debug("Init sum report %p id=%d", (void *)sumreport, inID); +#endif + return sumreport; +} + +struct ConnectionInfo * InitConnectOnlyReport (struct thread_Settings *thread) { + assert(thread != NULL); + // this connection report used only by report for accumulate stats + struct ConnectionInfo *creport = (struct ConnectionInfo *) calloc(1, sizeof(struct ConnectionInfo)); + if (!creport) { + FAIL(1, "Out of Memory!!\n", thread); + } + common_copy(&creport->common, thread); + creport->connect_times.min = FLT_MAX; + creport->connect_times.max = FLT_MIN; + creport->connect_times.vd = 0; + creport->connect_times.m2 = 0; + creport->connect_times.mean = 0; + creport->txholdbacktime = thread->txholdback_timer; + return creport; +} + +void FreeSumReport (struct SumReport *sumreport) { + assert(sumreport); +#ifdef HAVE_THREAD_DEBUG + thread_debug("Free sum report hdr=%p", (void *)sumreport); +#endif + Condition_Destroy_Reference(&sumreport->reference); + if (sumreport->info.latency_histogram) { + histogram_delete(sumreport->info.latency_histogram); + } + if (sumreport->info.framelatency_histogram) { + histogram_delete(sumreport->info.framelatency_histogram); + } + if (sumreport->info.bbrtt_histogram) { + histogram_delete(sumreport->info.bbrtt_histogram); + } + if (sumreport->info.jitter_histogram) { + histogram_delete(sumreport->info.jitter_histogram); + } + free_common_copy(sumreport->info.common); + free(sumreport); +} + + +static void Free_iReport (struct ReporterData *ireport) { + assert(ireport != NULL); + +#ifdef HAVE_THREAD_DEBUG + thread_debug("Free report hdr=%p reporter thread suspend count=%d packetring=%p histo=%p frame histo=%p", \ + (void *)ireport, ireport->reporter_thread_suspends, (void *) ireport->packetring, \ + (void *)ireport->info.latency_histogram, (void *) ireport->info.framelatency_histogram); +#endif + if (ireport->packetring && ireport->info.total.Bytes.current && !(isSingleUDP(ireport->info.common)) && \ + !TimeZero(ireport->info.ts.intervalTime) && (ireport->reporter_thread_suspends < 3)) { + fprintf(stdout, "WARN: this test may have been CPU bound (%d) (or may not be detecting the underlying network devices)\n", \ + ireport->reporter_thread_suspends); + } + if (ireport->packetring) { + packetring_free(ireport->packetring); + } + if (ireport->info.latency_histogram) { + histogram_delete(ireport->info.latency_histogram); + } + if (ireport->info.jitter_histogram) { + histogram_delete(ireport->info.jitter_histogram); + } + if (ireport->info.framelatency_histogram) { + histogram_delete(ireport->info.framelatency_histogram); + } + if (ireport->info.bbrtt_histogram) { + histogram_delete(ireport->info.bbrtt_histogram); + } + free_common_copy(ireport->info.common); + free(ireport); +} + +void FreeConnectionReport (struct ConnectionInfo *report) { + free_common_copy(report->common); + free(report); +} + +static void Free_sReport (struct ReportSettings *report) { + free_common_copy(report->common); + free(report); +} + +static void Free_srReport (struct TransferInfo *report) { + free_common_copy(report->common); + free(report); +} + +void FreeReport (struct ReportHeader *reporthdr) { + assert(reporthdr != NULL); +#ifdef HAVE_THREAD_DEBUG + char rs[REPORTTXTMAX]; + reporttype_text(reporthdr, &rs[0]); + thread_debug("Jobq *FREE* report hdr/rpt %p/%p (%s)", (void *) reporthdr, (void *) reporthdr->this_report, &rs[0]); +#endif + switch (reporthdr->type) { + case DATA_REPORT: + Free_iReport((struct ReporterData *)reporthdr->this_report); + break; + case CONNECTION_REPORT: + FreeConnectionReport((struct ConnectionInfo *)reporthdr->this_report); + break; + case SETTINGS_REPORT: + Free_sReport((struct ReportSettings *)reporthdr->this_report); + break; + case SERVER_RELAY_REPORT: + Free_srReport((struct TransferInfo *)reporthdr->this_report); + break; + default: + fprintf(stderr, "Invalid report type in free (%x)\n", reporthdr->type); + assert(0); + break; + } + free(reporthdr); +} + +/* + * InitReport is called by a transfer agent (client or + * server) to setup the needed structures to communicate + * traffic and connection information. Also initialize + * the report start time and next interval report time + * Finally, in the case of parallel clients, have them all + * synchronize on compeleting their connect() + */ + +void IncrSumReportRefCounter (struct SumReport *sumreport) { + assert(sumreport); +#ifdef HAVE_THREAD_DEBUG + thread_debug("Sum multiheader %p ref=%d->%d", (void *)sumreport, sumreport->reference.count, (sumreport->reference.count + 1)); +#endif + Mutex_Lock(&sumreport->reference.lock); + sumreport->reference.count++; + if (sumreport->reference.count > sumreport->reference.maxcount) + sumreport->reference.maxcount = sumreport->reference.count; + Mutex_Unlock(&sumreport->reference.lock); +} + +int DecrSumReportRefCounter (struct SumReport *sumreport) { + assert(sumreport); +// thread_debug("before lock hdr=%p", (void *)sumreport); + Mutex_Lock(&sumreport->reference.lock); +#ifdef HAVE_THREAD_DEBUG + thread_debug("Sum multiheader %p ref=%d->%d", (void *)sumreport, sumreport->reference.count, (sumreport->reference.count - 1)); +#endif +// thread_debug("in lock hdr=%p", (void *)sumreport); + int refcnt = --sumreport->reference.count; + Mutex_Unlock(&sumreport->reference.lock); +// thread_debug("unlock hdr=%p", (void *)sumreport); + return refcnt; +} + + +// Note, this report structure needs to remain self contained and not coupled +// to any settings structure pointers. This allows the thread settings to +// be freed without impacting the reporter. It's not recommended that +// this be done, i.e. free the settings before the report, but be defensive +// here to allow it +struct ReportHeader* InitIndividualReport (struct thread_Settings *inSettings) { + /* + * Create the report header and an ireport (if needed) + */ + assert(inSettings!=NULL); + struct ReportHeader *reporthdr = (struct ReportHeader *) calloc(1, sizeof(struct ReportHeader)); + if (reporthdr == NULL) { + FAIL(1, "Out of Memory!!\n", inSettings); + } + reporthdr->this_report = calloc(1, sizeof(struct ReporterData)); + if (reporthdr->this_report == NULL) { + FAIL(1, "Out of Memory!!\n", inSettings); + } + reporthdr->type = DATA_REPORT; + reporthdr->ReportMode = inSettings->mReportMode; + + struct ReporterData *ireport = (struct ReporterData *)(reporthdr->this_report); + if (inSettings->mSumReport) { + ireport->GroupSumReport = inSettings->mSumReport; + } + if (isFullDuplex(inSettings)) { + assert(inSettings->mFullDuplexReport != NULL); + IncrSumReportRefCounter(inSettings->mFullDuplexReport); + ireport->FullDuplexReport = inSettings->mFullDuplexReport; + } + // Copy common settings into the transfer report section + common_copy(&ireport->info.common, inSettings); + ireport->info.final = false; + ireport->info.burstid_transition = false; + ireport->info.isEnableTcpInfo = false; + + // Create a new packet ring which is used to communicate + // packet stats from the traffic thread to the reporter + // thread. The reporter thread does all packet accounting + ireport->packetring = packetring_init((inSettings->numreportstructs ? inSettings->numreportstructs : (isSingleUDP(inSettings) ? 40 : NUM_REPORT_STRUCTS)), \ + &ReportCond, (isSingleUDP(inSettings) ? NULL : &inSettings->awake_me)); +#ifdef HAVE_THREAD_DEBUG + char rs[REPORTTXTMAX]; + reporttype_text(reporthdr, &rs[0]); + thread_debug("Init %s report hdr/rpt/com=%p/%p/%p multireport/fullduplex=%p/%p pring(bytes)/cond=%p(%d)/%p (socket=%d)", &rs[0], \ + (void *) reporthdr, (void *) ireport, (void *) ireport->info.common, \ + (void *) inSettings->mSumReport, (void *) inSettings->mFullDuplexReport, \ + (void *) ireport->packetring, ireport->packetring->bytes, (void *) ireport->packetring->awake_producer, inSettings->mSock); +#endif + if (inSettings->numreportstructs) + fprintf (stdout, "%sNUM_REPORT_STRUCTS override from %d to %d\n", inSettings->mTransferIDStr, NUM_REPORT_STRUCTS, inSettings->numreportstructs); + + // Set up the function vectors, there are three + // 1) packet_handler: does packet accounting per the test and protocol + // 2) transfer_protocol_handler: performs output, e.g. interval reports, per the test and protocol + + if (inSettings->mIntervalMode == kInterval_Time) { + ireport->info.ts.intervalTime.tv_sec = (long) (inSettings->mInterval / rMillion); + ireport->info.ts.intervalTime.tv_usec = (long) (inSettings->mInterval % rMillion); + ireport->transfer_interval_handler = reporter_condprint_time_interval_report; + ireport->info.ts.significant_partial = (double) inSettings->mInterval * PARTIALPERCENT / rMillion ; + } else { + ireport->transfer_interval_handler = NULL; + } + ireport->packet_handler_pre_report = NULL; + ireport->packet_handler_post_report = NULL; + switch (inSettings->mThreadMode) { + case kMode_Server : + if (isUDP(inSettings)) { + ireport->packet_handler_post_report = reporter_handle_packet_server_udp; + ireport->transfer_protocol_handler = reporter_transfer_protocol_server_udp; + if ((inSettings->mIntervalMode == kInterval_Frames) && isIsochronous(inSettings)) { + ireport->transfer_interval_handler = reporter_condprint_frame_interval_report_server_udp; + ireport->transfer_protocol_handler = reporter_transfer_protocol_server_udp; + } else { + ireport->transfer_protocol_handler = reporter_transfer_protocol_server_udp; + if (isSumOnly(inSettings)) { + ireport->info.output_handler = NULL; + } else if ((inSettings->mReportMode == kReport_CSV) && !isSumOnly(inSettings)) { + if (isEnhanced(inSettings)) + ireport->info.output_handler = udp_output_enhanced_csv; + else + ireport->info.output_handler = udp_output_basic_csv; + } else if (isTripTime(inSettings)) { + if (isIsochronous(inSettings)) + ireport->info.output_handler = udp_output_read_triptime_isoch; + else + ireport->info.output_handler = udp_output_read_triptime; + } else if (isEnhanced(inSettings)) { + ireport->info.output_handler = udp_output_read_enhanced; + } else if (isFullDuplex(inSettings)) { + ireport->info.output_handler = udp_output_read; + } else { + ireport->info.output_handler = udp_output_read; + } + } + } else { // TCP case + ireport->packet_handler_post_report = reporter_handle_packet_server_tcp; + ireport->transfer_protocol_handler = reporter_transfer_protocol_server_tcp; + if (isPeriodicBurst(inSettings)) { + ireport->transfer_interval_handler = reporter_condprint_burst_interval_report_server_tcp; + ireport->info.output_handler = tcp_output_burst_read; + ireport->packet_handler_pre_report = reporter_handle_packet_server_tcp; + ireport->packet_handler_post_report = NULL; + } else if ((inSettings->mIntervalMode == kInterval_Frames) && isIsochronous(inSettings)) { + ireport->transfer_interval_handler = reporter_condprint_frame_interval_report_server_tcp; + ireport->info.output_handler = tcp_output_frame_read_triptime; + ireport->packet_handler_pre_report = reporter_handle_packet_server_tcp; + ireport->packet_handler_post_report = NULL; + } else if (isSumOnly(inSettings)) { + ireport->info.output_handler = NULL; + } else if ((inSettings->mReportMode == kReport_CSV) && !isSumOnly(inSettings)) { + if (isEnhanced(inSettings)) + ireport->info.output_handler = tcp_output_read_enhanced_csv; + else + ireport->info.output_handler = tcp_output_basic_csv; + } else if (isBounceBack(inSettings)) { + ireport->packet_handler_post_report = reporter_handle_packet_bb_server; + ireport->transfer_protocol_handler = reporter_transfer_protocol_server_bb_tcp; + ireport->info.output_handler = tcp_output_write; + } else if (isTripTime(inSettings) && isIsochronous(inSettings)) { + ireport->info.output_handler = tcp_output_read_enhanced_isoch; + } else if (isTripTime(inSettings)) { + ireport->info.output_handler = tcp_output_read_triptime; + } else if (isEnhanced(inSettings)) { + ireport->info.output_handler = tcp_output_read_enhanced; + } else if (!isFullDuplex(inSettings)) { + ireport->info.output_handler = tcp_output_read; + } else { + ireport->info.output_handler = tcp_output_read; + } + } + break; + case kMode_Client : + ireport->packet_handler_post_report = reporter_handle_packet_client; + if (isUDP(inSettings)) { + ireport->transfer_protocol_handler = reporter_transfer_protocol_client_udp; + if (isSumOnly(inSettings)) { + ireport->info.output_handler = NULL; + } else if ((inSettings->mReportMode == kReport_CSV) && !isSumOnly(inSettings)) { + if (isEnhanced(inSettings)) + ireport->info.output_handler = udp_output_enhanced_csv; + else + ireport->info.output_handler = udp_output_basic_csv; + } else if (isIsochronous(inSettings)) { + ireport->info.output_handler = udp_output_write_enhanced_isoch; + } else if (isEnhanced(inSettings)) { + ireport->info.output_handler = udp_output_write_enhanced; + } else if (isFullDuplex(inSettings)) { + ireport->info.output_handler = udp_output_write; + } else { + ireport->info.output_handler = udp_output_write; + } + } else { + ireport->transfer_protocol_handler = reporter_transfer_protocol_client_tcp; + if (isSumOnly(inSettings)) { + ireport->info.output_handler = NULL; + } else if ((inSettings->mReportMode == kReport_CSV) && !isSumOnly(inSettings)) { + if (isEnhanced(inSettings)) + ireport->info.output_handler = tcp_output_write_enhanced_csv; + else + ireport->info.output_handler = tcp_output_basic_csv; + } else if (isBounceBack(inSettings)) { + ireport->packet_handler_post_report = reporter_handle_packet_bb_client; + ireport->transfer_protocol_handler = reporter_transfer_protocol_client_bb_tcp; + ireport->info.output_handler = tcp_output_write_bb; + } else if (isIsochronous(inSettings)) { + ireport->info.output_handler = tcp_output_write_enhanced_isoch; + } else if (isTcpWriteTimes(inSettings)) { + ireport->info.output_handler = tcp_output_write_enhanced_write; + } else if (isEnhanced(inSettings)) { + ireport->info.output_handler = tcp_output_write_enhanced; + } else if (isFullDuplex(inSettings)) { + ireport->info.output_handler = tcp_output_write; + } else { + ireport->info.output_handler = tcp_output_write; + } + } + break; + case kMode_Unknown : + case kMode_Reporter : + case kMode_ReporterClient : + case kMode_Listener: + default: + FAIL(1, "InitIndividualReport\n", inSettings); + } + + if (inSettings->mThreadMode == kMode_Server) { + ireport->info.sock_callstats.read.binsize = inSettings->mBufLen / 8; + if (isUDP(inSettings)) { + if (isJitterHistogram(inSettings)) { + char name[] = "J8"; + ireport->info.jitter_histogram = histogram_init(JITTER_BINCNT,inSettings->jitter_binwidth,0,JITTER_UNITS, \ + JITTER_LCI, JITTER_UCI, ireport->info.common->transferID, name); + } + if (isTripTime(inSettings) && isHistogram(inSettings)) { + char name[] = "T8"; + ireport->info.latency_histogram = histogram_init(inSettings->mHistBins,inSettings->mHistBinsize,0,\ + pow(10,inSettings->mHistUnits), \ + inSettings->mHistci_lower, inSettings->mHistci_upper, ireport->info.common->transferID, name); + } + } + if (isHistogram(inSettings) && (isIsochronous(inSettings) || (!isUDP(inSettings) && isTripTime(inSettings)))) { + char name[] = "F8"; + // make sure frame bin size min is 100 microsecond + ireport->info.framelatency_histogram = histogram_init(inSettings->mHistBins,inSettings->mHistBinsize,0, \ + pow(10,inSettings->mHistUnits), inSettings->mHistci_lower, \ + inSettings->mHistci_upper, ireport->info.common->transferID, name); + } + } + if ((inSettings->mThreadMode == kMode_Client) && !isUDP(inSettings) && isHistogram(inSettings)) { + if (isTcpWriteTimes(inSettings)) { + char name[] = "W8"; + ireport->info.write_histogram = histogram_init(inSettings->mHistBins,inSettings->mHistBinsize,0,\ + pow(10,inSettings->mHistUnits), \ + inSettings->mHistci_lower, inSettings->mHistci_upper, ireport->info.common->transferID, name); + } else if (isWritePrefetch(inSettings)) { + char name[] = "S8"; + ireport->info.latency_histogram = histogram_init(inSettings->mHistBins,inSettings->mHistBinsize,0,\ + pow(10,inSettings->mHistUnits), \ + inSettings->mHistci_lower, inSettings->mHistci_upper, ireport->info.common->transferID, name); + } + } + if ((inSettings->mThreadMode == kMode_Client) && isBounceBack(inSettings)) { + char name[] = "BB8"; + if (!isHistogram(inSettings)) { + inSettings->mHistBins = 100000; // 10 seconds wide + inSettings->mHistBinsize = 100; // 100 usec bins + inSettings->mHistUnits = 6; // usecs 10 pow(x) + inSettings->mHistci_lower = 5; + inSettings->mHistci_upper = 95; + } + ireport->info.bbrtt_histogram = histogram_init(inSettings->mHistBins,inSettings->mHistBinsize,0, \ + pow(10,inSettings->mHistUnits), \ + inSettings->mHistci_lower, inSettings->mHistci_upper, ireport->info.common->transferID, name); + } + return reporthdr; +} + + +/* + * This init/update and print/finish (in the ReportDefault.c) + * is poor. It has to be done this way to preserve the + * interface to older versions where the reporter settings + * were delayed until a Transfer report came through. + * This transfer report has all the reports bound to it. + * + * The better implmementation is to treat all reports + * as independent objects that can be updated, processed, + * and output independlty per the Reporter threads job queue + * without shared state or copied state variables between these + * reports. The shared state, is really reporter state, that + * should be maintained in and by the reporter object/thread. + * + * For now, just fix it good enough. Later, write a c++ + * reporter object and use standard c++ design techniques + * to achieve this. Such code will be easier to maintain + * and to extend. + */ +struct ReportHeader* InitConnectionReport (struct thread_Settings *inSettings) { + assert(inSettings != NULL); + struct ReportHeader *reporthdr = (struct ReportHeader *) calloc(1, sizeof(struct ReportHeader)); + if (reporthdr == NULL) { + FAIL(1, "Out of Memory!!\n", inSettings); + } + reporthdr->this_report = calloc(1, sizeof(struct ConnectionInfo)); + if (reporthdr->this_report == NULL) { + FAIL(1, "Out of Memory!!\n", inSettings); + } + reporthdr->type = CONNECTION_REPORT; + reporthdr->ReportMode = inSettings->mReportMode; + + struct ConnectionInfo * creport = (struct ConnectionInfo *)(reporthdr->this_report); + common_copy(&creport->common, inSettings); + tcpstats_copy(&creport->tcpinitstats, &inSettings->tcpinitstats); + // Fill out known fields for the connection report + reporter_peerversion(creport, inSettings->peer_version_u, inSettings->peer_version_l); + if (isEnhanced(inSettings) && isTxStartTime(inSettings)) { + creport->epochStartTime.tv_sec = inSettings->txstart_epoch.tv_sec; + creport->epochStartTime.tv_usec = inSettings->txstart_epoch.tv_usec; + } else if (isTripTime(inSettings)) { + creport->epochStartTime.tv_sec = inSettings->accept_time.tv_sec; + creport->epochStartTime.tv_usec = inSettings->accept_time.tv_usec; + } + // Copy state from the settings object into the connection report + creport->connect_times.min = FLT_MAX; + creport->connect_times.max = FLT_MIN; + creport->connect_times.vd = 0; + creport->connect_times.m2 = 0; + creport->connect_times.mean = 0; + if (inSettings->mSock > 0) { + creport->winsize = getsock_tcp_windowsize(inSettings->mSock, \ + (inSettings->mThreadMode != kMode_Client ? 0 : 1) ); +#if HAVE_DECL_TCP_WINDOW_CLAMP + if (isRxClamp(inSettings)) { + getsock_tcp_windowclamp(inSettings->mSock); + } +#endif + } + creport->common->winsize_requested = inSettings->mTCPWin; + creport->txholdbacktime = inSettings->txholdback_timer; + if (isPeriodicBurst(inSettings)) { + creport->common->FPS = inSettings->mFPS; + } +#ifdef HAVE_THREAD_DEBUG + char rs[REPORTTXTMAX]; + reporttype_text(reporthdr, &rs[0]); + thread_debug("Init %s report hdr/rpt/com %p/%p/%p", &rs[0], \ + (void *) reporthdr, (void *) reporthdr->this_report, (void *) creport->common); +#endif + return reporthdr; +} + +/* + * ReportSettings will generate a summary report for + * settings being used with Listeners or Clients + */ +struct ReportHeader *InitSettingsReport (struct thread_Settings *inSettings) { + assert(inSettings != NULL); + struct ReportHeader *reporthdr = (struct ReportHeader *) calloc(1, sizeof(struct ReportHeader)); + if (reporthdr == NULL) { + FAIL(1, "Out of Memory!!\n", inSettings); + } + reporthdr->this_report = calloc(1, sizeof(struct ReportSettings)); + if (reporthdr->this_report == NULL) { + FAIL(1, "Out of Memory!!\n", inSettings); + } + reporthdr->type = SETTINGS_REPORT; + reporthdr->ReportMode = inSettings->mReportMode; + + struct ReportSettings *sreport = (struct ReportSettings *)reporthdr->this_report; + common_copy(&sreport->common, inSettings); + sreport->peer = inSettings->peer; + sreport->size_peer = inSettings->size_peer; + sreport->local = inSettings->local; + sreport->size_local = inSettings->size_local; + sreport->isochstats.mFPS = inSettings->mFPS; + sreport->isochstats.mMean = inSettings->mMean/8; + sreport->isochstats.mVariance = inSettings->mVariance/8; + sreport->isochstats.mBurstIPG = (unsigned int) (inSettings->mBurstIPG*1000.0); + sreport->isochstats.mBurstInterval = (unsigned int) (1 / inSettings->mFPS * 1000000); + if (!isUDP(inSettings)) { + if (inSettings->mMSS > 0) { + sreport->sockmaxseg = inSettings->mMSS; + } else if (isPrintMSS(inSettings) && !(inSettings->mMSS > 0)) { + sreport->sockmaxseg = getsock_tcp_mss(inSettings->mSock); + } + } +#ifdef HAVE_THREAD_DEBUG + char rs[REPORTTXTMAX]; + reporttype_text(reporthdr, &rs[0]); + thread_debug("Init %s report hdr/rpt/com %p/%p/%p", &rs[0], \ + (void *) reporthdr, (void *) reporthdr->this_report, (void *) sreport->common); +#endif + return reporthdr; +} + +/* + * This will generate a report of the UDP + * statistics as reported by the server on the client + * side. + */ +struct ReportHeader* InitServerRelayUDPReport(struct thread_Settings *inSettings, struct server_hdr *server) { + /* + * Create the report header and an ireport (if needed) + */ + struct ReportHeader *reporthdr = (struct ReportHeader *) calloc(1, sizeof(struct ReportHeader)); + if (reporthdr == NULL) { + FAIL(1, "Out of Memory!!\n", inSettings); + } + reporthdr->this_report = calloc(1, sizeof(struct ServerRelay)); + if (!reporthdr->this_report) { + FAIL(1, "Out of Memory!!\n", inSettings); + } +#ifdef HAVE_THREAD_DEBUG + thread_debug("Init server relay report %p size %ld", (void *)reporthdr, sizeof(struct ReportHeader) + sizeof(struct ServerRelay)); +#endif + reporthdr->type = SERVER_RELAY_REPORT; + reporthdr->ReportMode = inSettings->mReportMode; + struct ServerRelay *sr_report = (struct ServerRelay *)reporthdr->this_report; + common_copy(&sr_report->info.common, inSettings); + struct TransferInfo *stats = &sr_report->info; + stats->common->transferID = inSettings->mTransferID; + + stats->jitter = ntohl(server->base.jitter1); + stats->jitter += ntohl(server->base.jitter2) / (double)rMillion; +#ifdef HAVE_INT64_T + stats->cntBytes = (((intmax_t) ntohl(server->base.total_len1)) << 32) + \ + ntohl(server->base.total_len2); +#else + stats->cntBytes = (intmax_t) ntohl(server->base.total_len2); +#endif + stats->ts.iStart = 0; + stats->ts.iEnd = ntohl(server->base.stop_sec); + stats->ts.iEnd += ntohl(server->base.stop_usec) / (double)rMillion; + uint32_t flags = ntohl(server->base.flags); + if ((flags & HEADER_SEQNO64B)) { + stats->cntError = (((intmax_t) ntohl(server->extend2.error_cnt2)) << 32) + \ + ntohl(server->base.error_cnt); + stats->cntOutofOrder = (((intmax_t) ntohl(server->extend2.outorder_cnt2)) << 32) + \ + ntohl(server->base.outorder_cnt); + stats->cntDatagrams = (((intmax_t) ntohl(server->extend2.datagrams2)) << 32) + \ + ntohl(server->base.datagrams); + } else { + stats->cntError = ntohl(server->base.error_cnt); + stats->cntOutofOrder = ntohl(server->base.outorder_cnt); + stats->cntDatagrams = ntohl(server->base.datagrams); + } + if ((flags & SERVER_HEADER_EXTEND) != 0) { + setEnhanced(stats->common); + stats->transit.current.min = ntohl(server->extend.minTransit1); + stats->transit.current.min += ntohl(server->extend.minTransit2) / (double)rMillion; + stats->transit.current.max = ntohl(server->extend.maxTransit1); + stats->transit.current.max += ntohl(server->extend.maxTransit2) / (double)rMillion; + stats->transit.current.sum = ntohl(server->extend.sumTransit1); + stats->transit.current.sum += ntohl(server->extend.sumTransit2) / (double)rMillion; + stats->transit.current.mean = ntohl(server->extend.meanTransit1); + stats->transit.current.mean += ntohl(server->extend.meanTransit2) / (double)rMillion; + stats->transit.current.m2 = ntohl(server->extend.m2Transit1); + stats->transit.current.m2 += ntohl(server->extend.m2Transit2) / (double)rMillion; + stats->transit.current.m2 *= 1e-12; + stats->transit.current.vd = ntohl(server->extend.vdTransit1); + stats->transit.current.vd += ntohl(server->extend.vdTransit2) / (double)rMillion; + stats->transit.current.cnt = ntohl(server->extend.cntTransit); + stats->cntIPG = ntohl(server->extend.cntIPG); + stats->IPGsum = ntohl(server->extend.IPGsum); + } else { + unsetEnhanced(stats->common); + } + sr_report->peer = inSettings->local; + sr_report->size_peer = inSettings->size_local; + sr_report->local = inSettings->peer; + sr_report->size_local = inSettings->size_peer; + return reporthdr; +} + +/* ------------------------------------------------------------------- + * Send an AckFIN (a datagram acknowledging a FIN) on the socket, + * then select on the socket for some time to check for silence. + * If additional datagrams come in (not silent), probably our AckFIN + * was lost so the client has re-transmitted + * termination datagrams, so re-transmit our AckFIN. + * Sent by server to client + * ------------------------------------------------------------------- */ +void write_UDP_AckFIN (struct TransferInfo *stats, int len) { + assert(stats!= NULL); + int ackpacket_length = (int) (sizeof(struct UDP_datagram) + sizeof(struct server_hdr)); + int readlen = ((ackpacket_length * 2) > len * 2) ? (ackpacket_length * 2) : (len * 2); + char *ackPacket = (char *) calloc(1, readlen); + int success = 0; + assert(ackPacket); + fd_set readSet; + int rc = 1; + struct timeval timeout; + + if (ackPacket) { + struct UDP_datagram *UDP_Hdr = (struct UDP_datagram *)ackPacket; + struct server_hdr *hdr = (struct server_hdr *)(UDP_Hdr+1); + + UDP_Hdr = (struct UDP_datagram*) ackPacket; + int flags = HEADER_VERSION1; + if (isEnhanced(stats->common) || isTripTime(stats->common)) + flags |= SERVER_HEADER_EXTEND; +#ifdef HAVE_INT64_T + flags |= HEADER_SEQNO64B; +#endif + hdr->base.flags = htonl((long) flags); +#ifdef HAVE_INT64_T + hdr->base.total_len1 = htonl((long) (stats->cntBytes >> 32)); +#else + hdr->base.total_len1 = htonl(0x0); +#endif + hdr->base.total_len2 = htonl((long) (stats->cntBytes & 0xFFFFFFFF)); + hdr->base.stop_sec = htonl( (long) stats->ts.iEnd); + hdr->base.stop_usec = htonl( (long)((stats->ts.iEnd - (long)stats->ts.iEnd) * rMillion)); + hdr->base.error_cnt = htonl((long) (stats->cntError & 0xFFFFFFFF)); + hdr->base.outorder_cnt = htonl((long) (stats->cntOutofOrder & 0xFFFFFFFF)); + hdr->base.datagrams = htonl((long) (stats->cntDatagrams & 0xFFFFFFFF)); + if (flags & HEADER_SEQNO64B) { + hdr->extend2.error_cnt2 = htonl((long) (stats->cntError >> 32)); + hdr->extend2.outorder_cnt2 = htonl((long) (stats->cntOutofOrder >> 32) ); + hdr->extend2.datagrams2 = htonl((long) (stats->cntDatagrams >> 32)); + } + // printf("****** Server final estimator %f calculated average %f\n", stats->jitter, (stats->inline_jitter.total.sum / stats->inline_jitter.total.cnt)); + if (stats->inline_jitter.total.cnt > 0) + stats->jitter = (stats->inline_jitter.total.sum / stats->inline_jitter.total.cnt); // overide the final estimator with an average + hdr->base.jitter1 = htonl((long) stats->jitter); + hdr->base.jitter2 = htonl((long) ((stats->jitter - (long)stats->jitter) * rMillion)); + + hdr->extend.minTransit1 = htonl((long) stats->transit.total.min); + hdr->extend.minTransit2 = htonl((long) ((stats->transit.total.min - (long)stats->transit.total.min) * rMillion)); + hdr->extend.maxTransit1 = htonl((long) stats->transit.total.max); + hdr->extend.maxTransit2 = htonl((long) ((stats->transit.total.max - (long)stats->transit.total.max) * rMillion)); + hdr->extend.sumTransit1 = htonl((long) stats->transit.total.sum); + hdr->extend.sumTransit2 = htonl((long) ((stats->transit.total.sum - (long)stats->transit.total.sum) * rMillion)); + hdr->extend.meanTransit1 = htonl((long) stats->transit.total.mean); + hdr->extend.meanTransit2 = htonl((long) ((stats->transit.total.mean - (long)stats->transit.total.mean) * rMillion)); + stats->transit.total.m2 *= 1e12; + hdr->extend.m2Transit1 = htonl((long) stats->transit.total.m2); + hdr->extend.m2Transit2 = htonl((long) ((stats->transit.total.m2 - (long)stats->transit.total.m2) * rMillion)); + hdr->extend.vdTransit1 = htonl((long) stats->transit.total.vd); + hdr->extend.vdTransit2 = htonl((long) ((stats->transit.total.vd - (long)stats->transit.total.vd) * rMillion)); + hdr->extend.cntTransit = htonl(stats->transit.total.cnt); + hdr->extend.cntIPG = htonl((long) (stats->cntDatagrams / (stats->ts.iEnd - stats->ts.iStart))); + hdr->extend.IPGsum = htonl(1); + +#define TRYCOUNT 10 + int count = TRYCOUNT; + while (--count) { + // write data +#if defined(HAVE_LINUX_FILTER_H) && defined(HAVE_AF_PACKET) + // If in l2mode, use the AF_INET socket to write this packet + // +#ifdef HAVE_THREAD_DEBUG + thread_debug("UDP server send done-ack w/server-stats to client (sock=%d)", stats->common->socket); +#endif + rc = write(((stats->common->socketdrop > 0) ? stats->common->socketdrop : stats->common->socket), ackPacket, ackpacket_length); +#else + rc = write(stats->common->socket, ackPacket, ackpacket_length); +#endif + WARN_errno(rc < 0, "write-ackfin"); + // wait here is for silence, no more packets from the client + + FD_ZERO(&readSet); + FD_SET(stats->common->socket, &readSet); + timeout.tv_sec = 0; + timeout.tv_usec = 250000; + rc = select(stats->common->socket+1, &readSet, NULL, NULL, &timeout); + if (rc == 0) { +#ifdef HAVE_THREAD_DEBUG + thread_debug("UDP server detected silence - server stats assumed received by client"); +#endif + success = 1; + break; + } + rc = read(stats->common->socket, ackPacket, readlen); + // WARN_errno(rc < 0, "ack await silence"); + if ((rc < 0) && FATALUDPREADERR(errno)) { + break; + } +#ifdef HAVE_THREAD_DEBUG + if (rc > 0) { + thread_debug("UDP server thinks server stats packet maybe lost, will retransmit and try again", rc); + } +#endif + } + free(ackPacket); + } + if (!success && (stats->common->ReportMode != kReport_CSV)) { + fprintf(stderr, warn_ack_failed, stats->common->socket); + } +} +// end write_UDP_AckFIN diff --git a/src/Server.cpp b/src/Server.cpp new file mode 100644 index 0000000..c271cd7 --- /dev/null +++ b/src/Server.cpp @@ -0,0 +1,946 @@ +/*--------------------------------------------------------------- + * Copyright (c) 1999,2000,2001,2002,2003 + * The Board of Trustees of the University of Illinois + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software (Iperf) and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the names of the University of Illinois, NCSA, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * National Laboratory for Applied Network Research + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * http://www.ncsa.uiuc.edu + * ________________________________________________________________ + * + * Server.cpp + * by Mark Gates <mgates@nlanr.net> + * Ajay Tirumala (tirumala@ncsa.uiuc.edu>. + * ------------------------------------------------------------------- + * A server thread is initiated for each connection accept() returns. + * Handles sending and receiving data, and then closes socket. + * Changes to this version : The server can be run as a daemon + * ------------------------------------------------------------------- */ + +#define HEADERS() + +#include "headers.h" +#include "Server.hpp" +#include "active_hosts.h" +#include "Extractor.h" +#include "Reporter.h" +#include "Locale.h" +#include "delay.h" +#include "PerfSocket.hpp" +#include "SocketAddr.h" +#include "payloads.h" +#include <cmath> +#if defined(HAVE_LINUX_FILTER_H) && defined(HAVE_AF_PACKET) +#include "checksums.h" +#endif + + +/* ------------------------------------------------------------------- + * Stores connected socket and socket info. + * ------------------------------------------------------------------- */ + +Server::Server (thread_Settings *inSettings) { +#ifdef HAVE_THREAD_DEBUG + thread_debug("Server constructor with thread=%p sum=%p (sock=%d)", (void *) inSettings, (void *)inSettings->mSumReport, inSettings->mSock); +#endif + mSettings = inSettings; + myJob = NULL; + reportstruct = &scratchpad; + memset(&scratchpad, 0, sizeof(struct ReportStruct)); + mySocket = inSettings->mSock; + peerclose = false; +#if defined(HAVE_LINUX_FILTER_H) && defined(HAVE_AF_PACKET) + myDropSocket = inSettings->mSockDrop; + if (isL2LengthCheck(mSettings)) { + // For L2 UDP make sure we can receive a full ethernet packet plus a bit more + if (mSettings->mBufLen < (2 * ETHER_MAX_LEN)) { + mSettings->mBufLen = (2 * ETHER_MAX_LEN); + } + } +#endif + // Enable kernel level timestamping if available + InitKernelTimeStamping(); + int sorcvtimer = 0; + // sorcvtimer units microseconds convert to that + // minterval double, units seconds + // mAmount integer, units 10 milliseconds + // divide by two so timeout is 1/2 the interval + if (mSettings->mInterval && (mSettings->mIntervalMode == kInterval_Time)) { + sorcvtimer = static_cast<int>(round(mSettings->mInterval / 2.0)); + } else if (isServerModeTime(mSettings)) { + sorcvtimer = static_cast<int>(round(mSettings->mAmount * 10000) / 2); + } + isburst = (isIsochronous(mSettings) || isPeriodicBurst(mSettings) || (isTripTime(mSettings) && !isUDP(mSettings))); + if (isburst && (mSettings->mFPS > 0.0)) { + sorcvtimer = static_cast<int>(round(2000000.0 / mSettings->mFPS)); + } + if (sorcvtimer > 0) { + SetSocketOptionsReceiveTimeout(mSettings, sorcvtimer); + } +} + +/* ------------------------------------------------------------------- + * Destructor close socket. + * ------------------------------------------------------------------- */ +Server::~Server () { +#if HAVE_THREAD_DEBUG + thread_debug("Server destructor sock=%d fullduplex=%s", mySocket, (isFullDuplex(mSettings) ? "true" : "false")); +#endif +#if defined(HAVE_LINUX_FILTER_H) && defined(HAVE_AF_PACKET) + if (myDropSocket != INVALID_SOCKET) { + int rc = close(myDropSocket); + WARN_errno(rc == SOCKET_ERROR, "server close drop"); + myDropSocket = INVALID_SOCKET; + } +#endif +} + +inline bool Server::InProgress () { + return !(sInterupted || peerclose || + ((isServerModeTime(mSettings) || (isModeTime(mSettings) && isReverse(mSettings))) && mEndTime.before(reportstruct->packetTime))); +} + +/* ------------------------------------------------------------------- + * Receive TCP data from the (connected) socket. + * Sends termination flag several times at the end. + * Does not close the socket. + * ------------------------------------------------------------------- */ +void Server::RunTCP () { + long currLen; + intmax_t totLen = 0; + struct TCP_burst_payload burst_info; // used to store burst header and report in last packet of burst + Timestamp time1, time2; + double tokens=0.000004; + + if (!InitTrafficLoop()) + return; + myReport->info.ts.prevsendTime = myReport->info.ts.startTime; + + int burst_nleft = 0; + burst_info.burst_id = 0; + burst_info.burst_period_us = 0; + burst_info.send_tt.write_tv_sec = 0; + burst_info.send_tt.write_tv_usec = 0; + now.setnow(); + reportstruct->packetTime.tv_sec = now.getSecs(); + reportstruct->packetTime.tv_usec = now.getUsecs(); + while (InProgress()) { +// printf("***** bid expect = %u\n", burstid_expect); + reportstruct->emptyreport=1; + currLen = 0; + // perform read + if (isBWSet(mSettings)) { + time2.setnow(); + tokens += time2.subSec(time1) * (mSettings->mAppRate / 8.0); + time1 = time2; + } + reportstruct->transit_ready = 0; + if (tokens >= 0.0) { + int n = 0; + int readLen = mSettings->mBufLen; + if (burst_nleft > 0) + readLen = (mSettings->mBufLen < burst_nleft) ? mSettings->mBufLen : burst_nleft; + reportstruct->emptyreport=1; +#if HAVE_DECL_TCP_QUICKACK + if (isTcpQuickAck(mSettings)) { + int opt = 1; + Socklen_t len = sizeof(opt); + int rc = setsockopt(mySocket, IPPROTO_TCP, TCP_QUICKACK, + reinterpret_cast<char*>(&opt), len); + WARN_errno(rc == SOCKET_ERROR, "setsockopt TCP_QUICKACK"); + } +#endif + if (isburst && (burst_nleft == 0)) { + if ((n = recvn(mSettings->mSock, reinterpret_cast<char *>(&burst_info), sizeof(struct TCP_burst_payload), 0)) == sizeof(struct TCP_burst_payload)) { + // burst_info.typelen.type = ntohl(burst_info.typelen.type); + // burst_info.typelen.length = ntohl(burst_info.typelen.length); + // This is the first stamp of the burst + burst_info.flags = ntohl(burst_info.flags); + burst_info.burst_size = ntohl(burst_info.burst_size); + assert(burst_info.burst_size > 0); + reportstruct->burstsize = burst_info.burst_size; + burst_info.burst_id = ntohl(burst_info.burst_id); + reportstruct->frameID = burst_info.burst_id; + if (isTripTime(mSettings)) { + burst_info.send_tt.write_tv_sec = ntohl(burst_info.send_tt.write_tv_sec); + burst_info.send_tt.write_tv_usec = ntohl(burst_info.send_tt.write_tv_usec); + } else if (isIsochronous(mSettings)) { + burst_info.send_tt.write_tv_sec = (uint32_t)myReport->info.ts.startTime.tv_sec; + burst_info.send_tt.write_tv_usec = (uint32_t)myReport->info.ts.startTime.tv_usec; + burst_info.burst_period_us = ntohl(burst_info.burst_period_us); + } else { + now.setnow(); + burst_info.send_tt.write_tv_sec = (uint32_t)now.getSecs(); + burst_info.send_tt.write_tv_usec = (uint32_t)now.getUsecs(); + } + reportstruct->sentTime.tv_sec = burst_info.send_tt.write_tv_sec; + reportstruct->sentTime.tv_usec = burst_info.send_tt.write_tv_usec; + myReport->info.ts.prevsendTime = reportstruct->sentTime; + burst_nleft = burst_info.burst_size - n; + if (burst_nleft == 0) { + reportstruct->prevSentTime = myReport->info.ts.prevsendTime; + reportstruct->transit_ready = 1; + reportstruct->burstperiod = burst_info.burst_period_us; + } + currLen += n; + readLen = (mSettings->mBufLen < burst_nleft) ? mSettings->mBufLen : burst_nleft; + WARN(burst_nleft <= 0, "invalid burst read req size"); + // thread_debug("***read burst header size %d id=%d", burst_info.burst_size, burst_info.burst_id); + } else { + if (n > 0) { + WARN(1, "partial readn"); +#ifdef HAVE_THREAD_DEBUG + thread_debug("TCP burst partial read of %d wanted %d", n, sizeof(struct TCP_burst_payload)); + } else { + thread_debug("Detected peer close"); +#endif + } + goto Done; + } + } + if (!reportstruct->transit_ready) { + n = recv(mSettings->mSock, mSettings->mBuf, readLen, 0); + if (n > 0) { + reportstruct->emptyreport = 0; + if (isburst) { + burst_nleft -= n; + if (burst_nleft == 0) { + reportstruct->sentTime = myReport->info.ts.prevsendTime; + if (isTripTime(mSettings) || isIsochronous(mSettings)) { + reportstruct->isochStartTime.tv_sec = burst_info.send_tt.write_tv_sec; + reportstruct->isochStartTime.tv_usec = burst_info.send_tt.write_tv_usec; + reportstruct->burstperiod = burst_info.burst_period_us; + } + reportstruct->transit_ready = 1; + } + } + } else if (n == 0) { + peerclose = true; +#ifdef HAVE_THREAD_DEBUG + thread_debug("Server thread detected EOF on socket %d", mSettings->mSock); +#endif + } else if ((n < 0) && (FATALTCPREADERR(errno))) { + WARN_errno(1, "recv"); + peerclose = true; + n = 0; + } + currLen += n; + } + now.setnow(); + reportstruct->packetTime.tv_sec = now.getSecs(); + reportstruct->packetTime.tv_usec = now.getUsecs(); + totLen += currLen; + if (isBWSet(mSettings)) + tokens -= currLen; + + reportstruct->packetLen = currLen; + ReportPacket(myReport, reportstruct); + // Check for reverse and amount where + // the server stops after receiving + // the expected byte count + if (isReverse(mSettings) && !isModeTime(mSettings) && (totLen >= static_cast<intmax_t>(mSettings->mAmount))) { + break; + } + } else { + // Use a 4 usec delay to fill tokens + delay_loop(4); + } + } + Done: + disarm_itimer(); + // stop timing + now.setnow(); + reportstruct->packetTime.tv_sec = now.getSecs(); + reportstruct->packetTime.tv_usec = now.getUsecs(); + reportstruct->packetLen = 0; + if (EndJob(myJob, reportstruct)) { +#if HAVE_THREAD_DEBUG + thread_debug("tcp close sock=%d", mySocket); +#endif + int rc = close(mySocket); + WARN_errno(rc == SOCKET_ERROR, "server close"); + } + Iperf_remove_host(mSettings); + FreeReport(myJob); +} + +void Server::PostNullEvent () { + assert(myReport!=NULL); + // push a nonevent into the packet ring + // this will cause the reporter to process + // up to this event + memset(reportstruct, 0, sizeof(struct ReportStruct)); + now.setnow(); + reportstruct->packetTime.tv_sec = now.getSecs(); + reportstruct->packetTime.tv_usec = now.getUsecs(); + reportstruct->emptyreport=1; + ReportPacket(myReport, reportstruct); +} + +inline bool Server::ReadBBWithRXTimestamp () { + bool rc = false; + int n; + while (1) { + if ((n = recvn(mySocket, mSettings->mBuf, mSettings->mBounceBackBytes, 0)) == mSettings->mBounceBackBytes) { + struct bounceback_hdr *bbhdr = reinterpret_cast<struct bounceback_hdr *>(mSettings->mBuf); + uint16_t bbflags = ntohs(bbhdr->bbflags); + if (!(bbflags & HEADER_BBSTOP)) { + now.setnow(); + reportstruct->packetTime.tv_sec = now.getSecs(); + reportstruct->packetTime.tv_usec = now.getUsecs(); + reportstruct->emptyreport=0; + reportstruct->packetLen = mSettings->mBounceBackBytes; + // write the rx timestamp back into the payload + bbhdr->bbserverRx_ts.sec = htonl(reportstruct->packetTime.tv_sec); + bbhdr->bbserverRx_ts.usec = htonl(reportstruct->packetTime.tv_usec); + ReportPacket(myReport, reportstruct); + rc = true; + } else { + peerclose = true; + } + break; + } else if (n==0) { + peerclose = true; + break; + } else if (n == -2){ + PostNullEvent(); + } else { + break; + } + } + return rc; +} + +void Server::RunBounceBackTCP () { + if (!InitTrafficLoop()) + return; +#if HAVE_DECL_TCP_NODELAY + { + int nodelay = 1; + // set TCP nodelay option + int rc = setsockopt(mySocket, IPPROTO_TCP, TCP_NODELAY, + reinterpret_cast<char*>(&nodelay), sizeof(nodelay)); + WARN_errno(rc == SOCKET_ERROR, "setsockopt BB TCP_NODELAY"); + setNoDelay(mSettings); + } +#endif + if (mSettings->mInterval && (mSettings->mIntervalMode == kInterval_Time)) { + int sotimer = static_cast<int>(round(mSettings->mInterval / 2.0)); + SetSocketOptionsSendTimeout(mSettings, sotimer); + SetSocketOptionsReceiveTimeout(mSettings, sotimer); + } else if (isModeTime(mSettings)) { + int sotimer = static_cast<int>(round(mSettings->mAmount * 10000) / 2); + SetSocketOptionsSendTimeout(mSettings, sotimer); + SetSocketOptionsReceiveTimeout(mSettings, sotimer); + } + myReport->info.ts.prevsendTime = myReport->info.ts.startTime; + now.setnow(); + reportstruct->packetTime.tv_sec = now.getSecs(); + reportstruct->packetTime.tv_usec = now.getUsecs(); + reportstruct->packetLen = mSettings->mBounceBackBytes; + reportstruct->emptyreport=0; + ReportPacket(myReport, reportstruct); + + while (InProgress()) { + int n; + reportstruct->emptyreport=1; + do { + struct bounceback_hdr *bbhdr = reinterpret_cast<struct bounceback_hdr *>(mSettings->mBuf); + if (mSettings->mBounceBackHold) { +#if HAVE_DECL_TCP_QUICKACK + if (isTcpQuickAck(mSettings)) { + int opt = 1; + Socklen_t len = sizeof(opt); + int rc = setsockopt(mySocket, IPPROTO_TCP, TCP_QUICKACK, + reinterpret_cast<char*>(&opt), len); + WARN_errno(rc == SOCKET_ERROR, "setsockopt TCP_QUICKACK"); + } +#endif + delay_loop(mSettings->mBounceBackHold); + } + now.setnow(); + bbhdr->bbserverTx_ts.sec = htonl(now.getSecs()); + bbhdr->bbserverTx_ts.usec = htonl(now.getUsecs()); + if (mSettings->mTOS) { + bbhdr->tos = htons((uint16_t)(mSettings->mTOS & 0xFF)); + } + if ((n = writen(mySocket, mSettings->mBuf, mSettings->mBounceBackBytes, &reportstruct->writecnt)) == mSettings->mBounceBackBytes) { + reportstruct->emptyreport=0; + reportstruct->packetLen = n; + ReportPacket(myReport, reportstruct); + } else { + break; + } + } while (ReadBBWithRXTimestamp()); + } + disarm_itimer(); + // stop timing + now.setnow(); + reportstruct->packetTime.tv_sec = now.getSecs(); + reportstruct->packetTime.tv_usec = now.getUsecs(); + reportstruct->packetLen = 0; + if (EndJob(myJob, reportstruct)) { +#if HAVE_THREAD_DEBUG + thread_debug("tcp close sock=%d", mySocket); +#endif + int rc = close(mySocket); + WARN_errno(rc == SOCKET_ERROR, "server close"); + } + Iperf_remove_host(mSettings); + FreeReport(myJob); +} + +void Server::InitKernelTimeStamping () { +#if HAVE_DECL_SO_TIMESTAMP + iov[0].iov_base=mSettings->mBuf; + iov[0].iov_len=mSettings->mBufLen; + + message.msg_iov=iov; + message.msg_iovlen=1; + message.msg_name=&srcaddr; + message.msg_namelen=sizeof(srcaddr); + + message.msg_control = (char *) ctrl; + message.msg_controllen = sizeof(ctrl); + + int timestampOn = 1; + if (setsockopt(mSettings->mSock, SOL_SOCKET, SO_TIMESTAMP, ×tampOn, sizeof(timestampOn)) < 0) { + WARN_errno(mSettings->mSock == SO_TIMESTAMP, "socket"); + } +#endif +} + +// +// Set the report start times and next report times, options +// are now, the accept time or the first write time +// +inline void Server::SetFullDuplexReportStartTime () { + assert(myReport->FullDuplexReport != NULL); + struct TransferInfo *fullduplexstats = &myReport->FullDuplexReport->info; + assert(fullduplexstats != NULL); + if (TimeZero(fullduplexstats->ts.startTime)) { + fullduplexstats->ts.startTime = myReport->info.ts.startTime; + if (isModeTime(mSettings)) { + fullduplexstats->ts.nextTime = myReport->info.ts.nextTime; + } + } +#ifdef HAVE_THREAD_DEBUG + thread_debug("Server fullduplex report start=%ld.%ld next=%ld.%ld", fullduplexstats->ts.startTime.tv_sec, fullduplexstats->ts.startTime.tv_usec, fullduplexstats->ts.nextTime.tv_sec, fullduplexstats->ts.nextTime.tv_usec); +#endif +} + +inline void Server::SetReportStartTime () { + if (TimeZero(myReport->info.ts.startTime)) { + if (!TimeZero(mSettings->sent_time) && !isTxStartTime(mSettings)) { + // Servers that aren't full duplex use the accept timestamp for start + myReport->info.ts.startTime.tv_sec = mSettings->sent_time.tv_sec; + myReport->info.ts.startTime.tv_usec = mSettings->sent_time.tv_usec; + } else if (!TimeZero(mSettings->accept_time) && !isTxStartTime(mSettings)) { + // Servers that aren't full duplex use the accept timestamp for start + myReport->info.ts.startTime.tv_sec = mSettings->accept_time.tv_sec; + myReport->info.ts.startTime.tv_usec = mSettings->accept_time.tv_usec; + } else { + now.setnow(); + myReport->info.ts.startTime.tv_sec = now.getSecs(); + myReport->info.ts.startTime.tv_usec = now.getUsecs(); + } + } + myReport->info.ts.IPGstart = myReport->info.ts.startTime; + + if (!TimeZero(myReport->info.ts.intervalTime)) { + myReport->info.ts.nextTime = myReport->info.ts.startTime; + TimeAdd(myReport->info.ts.nextTime, myReport->info.ts.intervalTime); + } + if (myReport->GroupSumReport) { + struct TransferInfo *sumstats = &myReport->GroupSumReport->info; + assert(sumstats != NULL); + Mutex_Lock(&myReport->GroupSumReport->reference.lock); + if (TimeZero(sumstats->ts.startTime)) { + sumstats->ts.startTime = myReport->info.ts.startTime; + if (isModeTime(mSettings) || isModeInfinite(mSettings)) { + sumstats->ts.nextTime = myReport->info.ts.nextTime; + } + } + Mutex_Unlock(&myReport->GroupSumReport->reference.lock); + } +#ifdef HAVE_THREAD_DEBUG + thread_debug("Server(%d) report start=%ld.%ld next=%ld.%ld", mSettings->mSock, myReport->info.ts.startTime.tv_sec, myReport->info.ts.startTime.tv_usec, myReport->info.ts.nextTime.tv_sec, myReport->info.ts.nextTime.tv_usec); +#endif +} + +void Server::ClientReverseFirstRead (void) { + // Handle the case when the client spawns a server (no listener) and need the initial header + // Case of --trip-times and --reverse or --fullduplex, listener handles normal case + // Handle the case when the client spawns a server (no listener) and need the initial header + // Case of --trip-times and --reverse or --fullduplex, listener handles normal case + if (isReverse(mSettings) && (isTripTime(mSettings) || isPeriodicBurst(mSettings) || isIsochronous(mSettings))) { + int nread = 0; + uint32_t flags = 0; + int readlen = 0; + if (isUDP(mSettings)) { + nread = recvn(mSettings->mSock, mSettings->mBuf, mSettings->mBufLen, 0); + switch (nread) { + case 0: + //peer closed the socket, with no writes e.g. a connect-only test + peerclose = true; + break; + case -1 : + FAIL_errno(1, "recvn-reverse", mSettings); + break; + default : + struct client_udp_testhdr *udp_pkt = reinterpret_cast<struct client_udp_testhdr *>(mSettings->mBuf); + flags = ntohl(udp_pkt->base.flags); + mSettings->sent_time.tv_sec = 0; + if (isTripTime(mSettings)) { + mSettings->sent_time.tv_sec = ntohl(udp_pkt->start_fq.start_tv_sec); + mSettings->sent_time.tv_usec = ntohl(udp_pkt->start_fq.start_tv_usec); + } + if (!mSettings->sent_time.tv_sec) { + now.setnow(); + mSettings->sent_time.tv_sec = now.getSecs(); + mSettings->sent_time.tv_usec = now.getUsecs(); + } + reportstruct->packetLen = nread; + reportstruct->packetID = 1; + break; + } + } else { + nread = recvn(mSettings->mSock, mSettings->mBuf, sizeof(uint32_t), 0); + if (nread == 0) { + fprintf(stderr, "WARN: zero read on header flags\n"); + //peer closed the socket, with no writes e.g. a connect-only test + peerclose = true; + } + FAIL_errno((nread < (int) sizeof(uint32_t)), "client read tcp flags", mSettings); + reportstruct->packetID = 1; + struct client_tcp_testhdr *tcp_pkt = reinterpret_cast<struct client_tcp_testhdr *>(mSettings->mBuf); + flags = ntohl(tcp_pkt->base.flags); + // figure out the length of the test header + if ((readlen = Settings_ClientTestHdrLen(flags, mSettings)) > 0) { + // read the test settings passed to the mSettings by the client + int adj = (readlen - sizeof(uint32_t)); + nread = recvn(mSettings->mSock, (mSettings->mBuf + sizeof(uint32_t)), adj, 0); + if (nread == 0) { + peerclose = true; + } + FAIL_errno((nread < adj), "client read tcp test info", mSettings); + if (nread > 0) { + if (isTripTime(mSettings)) { + struct client_tcp_testhdr *tcp_pkt = reinterpret_cast<struct client_tcp_testhdr *>(mSettings->mBuf); + mSettings->sent_time.tv_sec = ntohl(tcp_pkt->start_fq.start_tv_sec); + mSettings->sent_time.tv_usec = ntohl(tcp_pkt->start_fq.start_tv_usec); + } else { + now.setnow(); + mSettings->sent_time.tv_sec = now.getSecs(); + mSettings->sent_time.tv_sec = now.getUsecs(); + } + } + mSettings->firstreadbytes = readlen; + } + } + } +} + +bool Server::InitTrafficLoop (void) { + bool UDPReady = true; + myJob = InitIndividualReport(mSettings); + myReport = static_cast<struct ReporterData *>(myJob->this_report); + assert(myJob != NULL); + if (mSettings->mReportMode == kReport_CSV) { + format_ips_port_string(&myReport->info, 0); + } + // copy the thread drop socket to this object such + // that the destructor can close it if needed +#if defined(HAVE_LINUX_FILTER_H) && defined(HAVE_AF_PACKET) + if (mSettings->mSockDrop > 0) + myDropSocket = mSettings->mSockDrop; +#endif + // Initialze the reportstruct scratchpad + reportstruct = &scratchpad; + reportstruct->packetID = 0; + reportstruct->l2len = 0; + reportstruct->l2errors = 0x0; + + int setfullduplexflag = 0; + if (isFullDuplex(mSettings) && !isServerReverse(mSettings)) { + assert(mSettings->mFullDuplexReport != NULL); + if ((setfullduplexflag = fullduplex_start_barrier(&mSettings->mFullDuplexReport->fullduplex_barrier)) < 0) + exit(-1); + } + Timestamp now; + if (isReverse(mSettings)) { + mSettings->accept_time.tv_sec = now.getSecs(); + mSettings->accept_time.tv_usec = now.getUsecs(); + ClientReverseFirstRead(); + } + if (isTripTime(mSettings)) { + if ((abs(now.getSecs() - mSettings->sent_time.tv_sec)) > MAXDIFFTIMESTAMPSECS) { + unsetTripTime(mSettings); + fprintf(stdout,"WARN: ignore --trip-times because client didn't provide valid start timestamp within %d seconds of now\n", MAXDIFFTIMESTAMPSECS); + mSettings->accept_time.tv_sec = now.getSecs(); + mSettings->accept_time.tv_usec = now.getUsecs(); + } + } + SetReportStartTime(); + reportstruct->prevPacketTime = myReport->info.ts.startTime; + + if (setfullduplexflag) + SetFullDuplexReportStartTime(); + + if (isServerModeTime(mSettings) || (isModeTime(mSettings) && (isBounceBack(mSettings) || isServerReverse(mSettings) || isFullDuplex(mSettings) || isReverse(mSettings)))) { + + if (isServerReverse(mSettings) || isFullDuplex(mSettings) || isReverse(mSettings)) + mSettings->mAmount += (SLOPSECS * 100); // add 2 sec for slop on reverse, units are 10 ms + + uintmax_t end_usecs (mSettings->mAmount * 10000); //amount units is 10 ms + if (int err = set_itimer(end_usecs)) + FAIL_errno(err != 0, "setitimer", mSettings); + mEndTime.setnow(); + mEndTime.add(mSettings->mAmount / 100.0); + } + if (!isSingleUDP(mSettings)) + PostReport(myJob); + // The first payload is different for TCP so read it and report it + // before entering the main loop + if (mSettings->firstreadbytes > 0) { + reportstruct->frameID = 0; + reportstruct->packetLen = mSettings->firstreadbytes; + if (isUDP(mSettings)) { + int offset = 0; + UDPReady = !ReadPacketID(offset); + reportstruct->packetTime = mSettings->accept_time; + } else { + reportstruct->sentTime.tv_sec = myReport->info.ts.startTime.tv_sec; + reportstruct->sentTime.tv_usec = myReport->info.ts.startTime.tv_usec; + reportstruct->packetTime = reportstruct->sentTime; + } + ReportPacket(myReport, reportstruct); + } + return UDPReady; +} + +inline int Server::ReadWithRxTimestamp () { + long currLen; + int tsdone = 0; + +#if HAVE_DECL_SO_TIMESTAMP + cmsg = reinterpret_cast<struct cmsghdr *>(&ctrl); + currLen = recvmsg(mSettings->mSock, &message, mSettings->recvflags); + if (currLen > 0) { + for (cmsg = CMSG_FIRSTHDR(&message); cmsg != NULL; + cmsg = CMSG_NXTHDR(&message, cmsg)) { + if (cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SCM_TIMESTAMP && + cmsg->cmsg_len == CMSG_LEN(sizeof(struct timeval))) { + memcpy(&(reportstruct->packetTime), CMSG_DATA(cmsg), sizeof(struct timeval)); + tsdone = 1; + } + } + } +#else + currLen = recv(mSettings->mSock, mSettings->mBuf, mSettings->mBufLen, mSettings->recvflags); +#endif + if (currLen <=0) { + // Socket read timeout or read error + reportstruct->emptyreport=1; + if (currLen == 0) { + peerclose = true; + } else if (FATALUDPREADERR(errno)) { + WARN_errno(1, "recvmsg"); + currLen = 0; + peerclose = true; + } + } else if (TimeZero(myReport->info.ts.prevpacketTime)) { + myReport->info.ts.prevpacketTime = reportstruct->packetTime; + } + if (!tsdone) { + now.setnow(); + reportstruct->packetTime.tv_sec = now.getSecs(); + reportstruct->packetTime.tv_usec = now.getUsecs(); + } + return currLen; +} + +// Returns true if the client has indicated this is the final packet +inline bool Server::ReadPacketID (int offset_adjust) { + bool terminate = false; + struct UDP_datagram* mBuf_UDP = reinterpret_cast<struct UDP_datagram*>(mSettings->mBuf + offset_adjust); + // terminate when datagram begins with negative index + // the datagram ID should be correct, just negated + + if (isSeqNo64b(mSettings)) { + // New client - Signed PacketID packed into unsigned id2,id + reportstruct->packetID = (static_cast<uint32_t>(ntohl(mBuf_UDP->id))) | (static_cast<uintmax_t>(ntohl(mBuf_UDP->id2)) << 32); + +#ifdef HAVE_PACKET_DEBUG + printf("id 0x%x, 0x%x -> %" PRIdMAX " (0x%" PRIxMAX ")\n", + ntohl(mBuf_UDP->id), ntohl(mBuf_UDP->id2), reportstruct->packetID, reportstruct->packetID); +#endif + } else { + // Old client - Signed PacketID in Signed id + reportstruct->packetID = static_cast<int32_t>(ntohl(mBuf_UDP->id)); +#ifdef HAVE_PACKET_DEBUG + printf("id 0x%x -> %" PRIdMAX " (0x%" PRIxMAX ")\n", + ntohl(mBuf_UDP->id), reportstruct->packetID, reportstruct->packetID); +#endif + } + if (reportstruct->packetID < 0) { + reportstruct->packetID = - reportstruct->packetID; + terminate = true; + } + // read the sent timestamp from the rx packet + reportstruct->sentTime.tv_sec = ntohl(mBuf_UDP->tv_sec); + reportstruct->sentTime.tv_usec = ntohl(mBuf_UDP->tv_usec); + return terminate; +} + +void Server::L2_processing () { +#if (HAVE_LINUX_FILTER_H) && (HAVE_AF_PACKET) + eth_hdr = reinterpret_cast<struct ether_header *>(mSettings->mBuf); + ip_hdr = reinterpret_cast<struct iphdr *>(mSettings->mBuf + sizeof(struct ether_header)); + // L4 offest is set by the listener and depends upon IPv4 or IPv6 + udp_hdr = reinterpret_cast<struct udphdr *>(mSettings->mBuf + mSettings->l4offset); + // Read the packet to get the UDP length + int udplen = ntohs(udp_hdr->len); + // + // in the event of an L2 error, double check the packet before passing it to the reporter, + // i.e. no reason to run iperf accounting on a packet that has no reasonable L3 or L4 headers + // + reportstruct->packetLen = udplen - sizeof(struct udphdr); + reportstruct->expected_l2len = reportstruct->packetLen + mSettings->l4offset + sizeof(struct udphdr); + if (reportstruct->l2len != reportstruct->expected_l2len) { + reportstruct->l2errors |= L2LENERR; + if (L2_quintuple_filter() != 0) { + reportstruct->l2errors |= L2UNKNOWN; + reportstruct->l2errors |= L2CSUMERR; + reportstruct->emptyreport = 1; + } + } + if (!(reportstruct->l2errors & L2UNKNOWN)) { + // perform UDP checksum test, returns zero on success + int rc; + rc = udpchecksum((void *)ip_hdr, (void *)udp_hdr, udplen, (isIPV6(mSettings) ? 1 : 0)); + if (rc) { + reportstruct->l2errors |= L2CSUMERR; + if ((!(reportstruct->l2errors & L2LENERR)) && (L2_quintuple_filter() != 0)) { + reportstruct->emptyreport = 1; + reportstruct->l2errors |= L2UNKNOWN; + } + } + } +#endif // HAVE_AF_PACKET +} + +// Run the L2 packet through a quintuple check, i.e. proto/ip src/ip dst/src port/src dst +// and return zero is there is a match, otherwize return nonzero +int Server::L2_quintuple_filter () { +#if defined(HAVE_LINUX_FILTER_H) && defined(HAVE_AF_PACKET) + +#define IPV4SRCOFFSET 12 // the ipv4 source address offset from the l3 pdu +#define IPV6SRCOFFSET 8 // the ipv6 source address offset + + // Get the expected values from the sockaddr structures + // Note: it's expected the initiating socket has aready "connected" + // and the sockaddr structs have been populated + // 2nd Note: sockaddr structs are in network byte order + struct sockaddr *p = reinterpret_cast<sockaddr *>(&mSettings->peer); + struct sockaddr *l = reinterpret_cast<sockaddr *>(&mSettings->local); + // make sure sa_family is coherent for both src and dst + if (!(((l->sa_family == AF_INET) && (p->sa_family == AF_INET)) || ((l->sa_family == AF_INET6) && (p->sa_family == AF_INET6)))) { + return -1; + } + + // check the L2 ethertype + struct ether_header *l2hdr = reinterpret_cast<struct ether_header *>(mSettings->mBuf); + + if (!isIPV6(mSettings)) { + if (ntohs(l2hdr->ether_type) != ETHERTYPE_IP) + return -1; + } else { + if (ntohs(l2hdr->ether_type) != ETHERTYPE_IPV6) + return -1; + } + // check the ip src/dst + const uint32_t *data; + udp_hdr = reinterpret_cast<struct udphdr *>(mSettings->mBuf + mSettings->l4offset); + + // Check plain old v4 using v4 addr structs + if (l->sa_family == AF_INET) { + data = reinterpret_cast<const uint32_t *>(mSettings->mBuf + sizeof(struct ether_header) + IPV4SRCOFFSET); + if ((reinterpret_cast<struct sockaddr_in *>(p))->sin_addr.s_addr != *data++) + return -1; + if ((reinterpret_cast<struct sockaddr_in *>(l))->sin_addr.s_addr != *data) + return -1; + if (udp_hdr->source != (reinterpret_cast<struct sockaddr_in *>(p))->sin_port) + return -1; + if (udp_hdr->dest != (reinterpret_cast<struct sockaddr_in *>(l))->sin_port) + return -1; + } else { + // Using the v6 addr structures +# if HAVE_IPV6 + struct in6_addr *v6peer = SockAddr_get_in6_addr(&mSettings->peer); + struct in6_addr *v6local = SockAddr_get_in6_addr(&mSettings->local); + if (isIPV6(mSettings)) { + int i; + data = reinterpret_cast<const uint32_t *>(mSettings->mBuf + sizeof(struct ether_header) + IPV6SRCOFFSET); + // check for v6 src/dst address match + for (i = 0; i < 4; i++) { + if (v6peer->s6_addr32[i] != *data++) + return -1; + } + for (i = 0; i < 4; i++) { + if (v6local->s6_addr32[i] != *data++) + return -1; + } + } else { // v4 addr in v6 family struct + data = reinterpret_cast<const uint32_t *>(mSettings->mBuf + sizeof(struct ether_header) + IPV4SRCOFFSET); + if (v6peer->s6_addr32[3] != *data++) + return -1; + if (v6peer->s6_addr32[3] != *data) + return -1; + } + // check udp ports + if (udp_hdr->source != (reinterpret_cast<struct sockaddr_in6 *>(p))->sin6_port) + return -1; + if (udp_hdr->dest != (reinterpret_cast<struct sockaddr_in6 *>(l))->sin6_port) + return -1; +# endif // HAVE_IPV6 + } +#endif // HAVE_AF_PACKET + // made it through all the checks + return 0; +} + +inline void Server::udp_isoch_processing (int rxlen) { + reportstruct->transit_ready = 0; + // Ignore runt sized isoch packets + if (rxlen < static_cast<int>(sizeof(struct UDP_datagram) + sizeof(struct client_hdr_v1) + sizeof(struct client_hdrext) + sizeof(struct isoch_payload))) { + reportstruct->burstsize = 0; + reportstruct->remaining = 0; + reportstruct->frameID = 0; + } else { + struct client_udp_testhdr *udp_pkt = reinterpret_cast<struct client_udp_testhdr *>(mSettings->mBuf); + reportstruct->isochStartTime.tv_sec = ntohl(udp_pkt->isoch.start_tv_sec); + reportstruct->isochStartTime.tv_usec = ntohl(udp_pkt->isoch.start_tv_usec); + reportstruct->frameID = ntohl(udp_pkt->isoch.frameid); + reportstruct->prevframeID = ntohl(udp_pkt->isoch.prevframeid); + reportstruct->burstsize = ntohl(udp_pkt->isoch.burstsize); + assert(reportstruct->burstsize > 0); + reportstruct->burstperiod = ntohl(udp_pkt->isoch.burstperiod); + reportstruct->remaining = ntohl(udp_pkt->isoch.remaining); + if ((reportstruct->remaining == (uint32_t) rxlen) && ((reportstruct->frameID - reportstruct->prevframeID) == 1)) { + reportstruct->transit_ready = 1; + } + } +} + +/* ------------------------------------------------------------------- + * Receive UDP data from the (connected) socket. + * Sends termination flag several times at the end. + * Does not close the socket. + * ------------------------------------------------------------------- */ +void Server::RunUDP () { + int rxlen; + bool isLastPacket = false; + + if (InitTrafficLoop()) { + // Exit loop on three conditions + // 1) Fatal read error + // 2) Last packet of traffic flow sent by client + // 3) -t timer expires + while (InProgress() && !isLastPacket) { + // The emptyreport flag can be set + // by any of the packet processing routines + // If it's set the iperf reporter won't do + // bandwidth accounting, basically it's indicating + // that the reportstruct itself couldn't be + // completely filled out. + reportstruct->emptyreport=1; + reportstruct->packetLen=0; + // read the next packet with timestamp + // will also set empty report or not + rxlen=ReadWithRxTimestamp(); + if (!peerclose && (rxlen > 0)) { + reportstruct->emptyreport = 0; + reportstruct->packetLen = rxlen; + if (isL2LengthCheck(mSettings)) { + reportstruct->l2len = rxlen; + // L2 processing will set the reportstruct packet length with the length found in the udp header + // and also set the expected length in the report struct. The reporter thread + // will do the compare and account and print l2 errors + reportstruct->l2errors = 0x0; + L2_processing(); + } + if (!(reportstruct->l2errors & L2UNKNOWN)) { + // ReadPacketID returns true if this is the last UDP packet sent by the client + // also sets the packet rx time in the reportstruct + reportstruct->prevSentTime = myReport->info.ts.prevsendTime; + reportstruct->prevPacketTime = myReport->info.ts.prevpacketTime; + isLastPacket = ReadPacketID(mSettings->l4payloadoffset); + myReport->info.ts.prevsendTime = reportstruct->sentTime; + myReport->info.ts.prevpacketTime = reportstruct->packetTime; + if (isIsochronous(mSettings)) { + udp_isoch_processing(rxlen); + } + } + } + ReportPacket(myReport, reportstruct); + } + } + disarm_itimer(); + int do_close = EndJob(myJob, reportstruct); + if (!isMulticast(mSettings) && !isNoUDPfin(mSettings)) { + // send a UDP acknowledgement back except when: + // 1) we're NOT receiving multicast + // 2) the user requested no final exchange + // 3) this is a full duplex test + write_UDP_AckFIN(&myReport->info, mSettings->mBufLen); + } + if (do_close) { +#if HAVE_THREAD_DEBUG + thread_debug("udp close sock=%d", mySocket); +#endif + int rc = close(mySocket); + WARN_errno(rc == SOCKET_ERROR, "server close"); + } + Iperf_remove_host(mSettings); + FreeReport(myJob); +} + +// end Recv diff --git a/src/Settings.cpp b/src/Settings.cpp new file mode 100644 index 0000000..39229f5 --- /dev/null +++ b/src/Settings.cpp @@ -0,0 +1,2577 @@ +/*--------------------------------------------------------------- + * Copyright (c) 1999,2000,2001,2002,2003 + * The Board of Trustees of the University of Illinois + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software (Iperf) and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the names of the University of Illinois, NCSA, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * National Laboratory for Applied Network Research + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * http://www.ncsa.uiuc.edu + * ________________________________________________________________ + * + * Settings.cpp + * by Mark Gates <mgates@nlanr.net> + * & Ajay Tirumala <tirumala@ncsa.uiuc.edu> + * ------------------------------------------------------------------- + * Stores and parses the initial values for all the global variables. + * ------------------------------------------------------------------- + * headers + * uses + * <stdlib.h> + * <stdio.h> + * <string.h> + * + * <unistd.h> + * ------------------------------------------------------------------- */ + +#define HEADERS() + +#include "headers.h" +#include "Settings.hpp" +#include "Locale.h" +#include "SocketAddr.h" +#include "util.h" +#include "version.h" +#include "gnu_getopt.h" +#include "isochronous.hpp" +#include "pdfs.h" +#include "payloads.h" +#include "PerfSocket.hpp" +#include "dscp.h" +#include "iperf_formattime.h" +#include <math.h> + +static int reversetest = 0; +static int fullduplextest = 0; +static int histogram = 0; +static int jitter_histogram = 0; +static int l2checks = 0; +static int incrdstip = 0; +static int incrsrcip = 0; +static int incrdstport = 0; +static int incrsrcport = 0; +static int sumdstip = 0; +static int txstarttime = 0; +static int noconnectsync = 0; +static int txholdback = 0; +static int fqrate = 0; +static int triptime = 0; +static int infinitetime = 0; +static int connectonly = 0; +static int connectretry = 0; +static int burstipg = 0; +static int burstsize = 0; +static int burstperiodic = 0; +static int isochronous = 0; +static int noudpfin = 0; +static int numreportstructs = 0; +static int sumonly = 0; +static int so_dontroute = 0; +static int nearcongest = 0; +static int permitkey = 0; +static int permitkeytimeout = 0; +static int rxwinclamp = 0; +static int txnotsentlowwater = 0; +static int tapif = 0; +static int tunif = 0; +static int hideips = 0; +static int bounceback = 0; +static int bouncebackhold = 0; +static int bouncebackperiod = 0; +static int overridetos = 0; +static int notcpbbquickack = 0; +static int tcpquickack = 0; +static int notcpbbquickack_cliset = 0; +static int workingload = 0; +static int utctimes = 0; +static int bouncebackdelaystart = 0; +static int tcpwritetimes = 0; + +void Settings_Interpret(char option, const char *optarg, struct thread_Settings *mExtSettings); +// apply compound settings after the command line has been fully parsed +void Settings_ModalOptions(struct thread_Settings *mExtSettings); + +static void generate_permit_key(struct thread_Settings *mExtSettings); + +/* ------------------------------------------------------------------- + * command line options + * + * The option struct essentially maps a long option name (--foobar) + * or environment variable ($FOOBAR) to its short option char (f). + * ------------------------------------------------------------------- */ +#define LONG_OPTIONS() + +const struct option long_options[] = +{ +{"singleclient", no_argument, NULL, '1'}, +#if 0 +{"v4", no_argument, NULL, '4'}, +{"v6", no_argument, NULL, '6'}, +#endif +{"bandwidth", required_argument, NULL, 'b'}, +{"client", required_argument, NULL, 'c'}, +{"dualtest", no_argument, NULL, 'd'}, +{"enhanced", no_argument, NULL, 'e'}, +{"format", required_argument, NULL, 'f'}, +{"help", no_argument, NULL, 'h'}, +{"interval", required_argument, NULL, 'i'}, +{"len", required_argument, NULL, 'l'}, +{"print_mss", no_argument, NULL, 'm'}, +{"num", required_argument, NULL, 'n'}, +{"output", required_argument, NULL, 'o'}, +{"port", required_argument, NULL, 'p'}, +{"tradeoff", no_argument, NULL, 'r'}, +{"server", no_argument, NULL, 's'}, +{"time", required_argument, NULL, 't'}, +{"udp", no_argument, NULL, 'u'}, +{"version", no_argument, NULL, 'v'}, +{"window", required_argument, NULL, 'w'}, +{"reportexclude", required_argument, NULL, 'x'}, +{"reportstyle",required_argument, NULL, 'y'}, +{"realtime", no_argument, NULL, 'z'}, + +// more esoteric options +{"awdl", no_argument, NULL, 'A'}, +{"bind", required_argument, NULL, 'B'}, +{"bounceback", optional_argument, &bounceback, 1}, +{"bounceback-txdelay", required_argument, &bouncebackdelaystart, 1}, +{"bounceback-hold", required_argument, &bouncebackhold, 1}, +{"bounceback-no-quickack", no_argument, ¬cpbbquickack, 1}, +{"bounceback-period", required_argument, &bouncebackperiod, 1}, +{"compatibility", no_argument, NULL, 'C'}, +{"daemon", no_argument, NULL, 'D'}, +{"file_input", required_argument, NULL, 'F'}, +{"ssm-host", required_argument, NULL, 'H'}, +{"stdin_input", no_argument, NULL, 'I'}, +{"mss", required_argument, NULL, 'M'}, +{"nodelay", no_argument, NULL, 'N'}, +{"listenport", required_argument, NULL, 'L'}, +{"parallel", required_argument, NULL, 'P'}, +#ifdef WIN32 +{"remove", no_argument, NULL, 'R'}, +#else +{"reverse", no_argument, NULL, 'R'}, +#endif +{"tos", required_argument, NULL, 'S'}, +{"ttl", required_argument, NULL, 'T'}, +{"single_udp", no_argument, NULL, 'U'}, +{"ipv6_domain", no_argument, NULL, 'V'}, +{"suggest_win_size", no_argument, NULL, 'W'}, +{"peer-detect", no_argument, NULL, 'X'}, +{"tcp-congestion", required_argument, NULL, 'Z'}, +{"histograms", optional_argument, &histogram, 1}, +{"hide-ips", no_argument, &hideips, 1}, +{"jitter-histograms", optional_argument, &jitter_histogram, 1}, +{"udp-histograms", optional_argument, &histogram, 1}, // keep support per 2.0.13 usage +{"l2checks", no_argument, &l2checks, 1}, +{"incr-dstip", no_argument, &incrdstip, 1}, +{"incr-srcip", no_argument, &incrsrcip, 1}, +{"incr-dstport", no_argument, &incrdstport, 1}, +{"incr-srcport", no_argument, &incrsrcport, 1}, +{"sum-dstip", no_argument, &sumdstip, 1}, +{"txstart-time", required_argument, &txstarttime, 1}, +{"txdelay-time", required_argument, &txholdback, 1}, +{"fq-rate", required_argument, &fqrate, 1}, +{"trip-times", no_argument, &triptime, 1}, +{"no-udp-fin", no_argument, &noudpfin, 1}, +{"connect-only", optional_argument, &connectonly, 1}, +{"connect-retries", required_argument, &connectretry, 1}, +{"no-connect-sync", no_argument, &noconnectsync, 1}, +{"full-duplex", no_argument, &fullduplextest, 1}, +{"ipg", required_argument, &burstipg, 1}, +{"isochronous", optional_argument, &isochronous, 1}, +{"sum-only", no_argument, &sumonly, 1}, +{"local-only", optional_argument, &so_dontroute, 1}, +{"near-congestion", optional_argument, &nearcongest, 1}, +{"permit-key", optional_argument, &permitkey, 1}, +{"permit-key-timeout", required_argument, &permitkeytimeout, 1}, +{"burst-size", required_argument, &burstsize, 1}, +{"burst-period", required_argument, &burstperiodic, 1}, +{"tos-override", required_argument, &overridetos, 1}, +{"tcp-rx-window-clamp", required_argument, &rxwinclamp, 1}, +{"tcp-quickack", no_argument, &tcpquickack, 1}, +{"tcp-write-prefetch", required_argument, &txnotsentlowwater, 1}, // see doc/DESIGN_NOTES +{"tcp-write-times", no_argument, &tcpwritetimes, 1}, +{"tap-dev", optional_argument, &tapif, 1}, +{"tun-dev", optional_argument, &tunif, 1}, +{"working-load", optional_argument, &workingload, 1}, +{"utc", no_argument, &utctimes, 1}, +{"NUM_REPORT_STRUCTS", required_argument, &numreportstructs, 1}, +#ifdef WIN32 +{"reverse", no_argument, &reversetest, 1}, +#endif +{0, 0, 0, 0} +}; + +#define ENV_OPTIONS() + +const struct option env_options[] = +{ +{"IPERF_IPV6_DOMAIN", no_argument, NULL, 'V'}, +{"IPERF_SINGLECLIENT", no_argument, NULL, '1'}, +{"IPERF_BANDWIDTH", required_argument, NULL, 'b'}, +{"IPERF_CLIENT", required_argument, NULL, 'c'}, +{"IPERF_DUALTEST", no_argument, NULL, 'd'}, +{"IPERF_ENHANCEDREPORTS", no_argument, NULL, 'e'}, +{"IPERF_FORMAT", required_argument, NULL, 'f'}, +// skip help +{"IPERF_INTERVAL", required_argument, NULL, 'i'}, +{"IPERF_LEN", required_argument, NULL, 'l'}, +{"IPERF_PRINT_MSS", no_argument, NULL, 'm'}, +{"IPERF_NUM", required_argument, NULL, 'n'}, +{"IPERF_PORT", required_argument, NULL, 'p'}, +{"IPERF_TRADEOFF", no_argument, NULL, 'r'}, +{"IPERF_SERVER", no_argument, NULL, 's'}, +{"IPERF_TIME", required_argument, NULL, 't'}, +{"IPERF_UDP", no_argument, NULL, 'u'}, +// skip version +{"TCP_WINDOW_SIZE", required_argument, NULL, 'w'}, +{"IPERF_REPORTEXCLUDE", required_argument, NULL, 'x'}, +{"IPERF_REPORTSTYLE",required_argument, NULL, 'y'}, + +// more esoteric options +{"IPERF_BIND", required_argument, NULL, 'B'}, +{"IPERF_COMPAT", no_argument, NULL, 'C'}, +{"IPERF_DAEMON", no_argument, NULL, 'D'}, +{"IPERF_FILE_INPUT", required_argument, NULL, 'F'}, +{"IPERF_STDIN_INPUT", no_argument, NULL, 'I'}, +{"IPERF_MSS", required_argument, NULL, 'M'}, +{"IPERF_NODELAY", no_argument, NULL, 'N'}, +{"IPERF_LISTENPORT", required_argument, NULL, 'L'}, +{"IPERF_PARALLEL", required_argument, NULL, 'P'}, +{"IPERF_TOS", required_argument, NULL, 'S'}, +{"IPERF_TTL", required_argument, NULL, 'T'}, +{"IPERF_SINGLE_UDP", no_argument, NULL, 'U'}, +{"IPERF_SUGGEST_WIN_SIZE", required_argument, NULL, 'W'}, +{"IPERF_PEER_DETECT", no_argument, NULL, 'X'}, +{"IPERF_CONGESTION_CONTROL", required_argument, NULL, 'Z'}, +{0, 0, 0, 0} +}; + +#define SHORT_OPTIONS() + +const char short_options[] = "146b:c:def:hi:l:mn:o:p:rst:uvw:x:y:zAB:CDF:H:IL:M:NP:RS:T:UVWXZ:"; + +/* ------------------------------------------------------------------- + * defaults + * ------------------------------------------------------------------- */ +#define DEFAULTS() + +const long kDefault_UDPRate = 1024 * 1024; // -u if set, 1 Mbit/sec +const int kDefault_TCPBufLen = 128 * 1024; // TCP default read/write size +const int kDefault_BBTCPBufLen = 100; // default bounce-back size in bytes + + +/* ------------------------------------------------------------------- + * Initialize all settings to defaults. + * ------------------------------------------------------------------- */ +void Settings_Initialize (struct thread_Settings *main) { + // Everything defaults to zero or NULL with + // this memset. Only need to set non-zero values + // below. + memset(main, 0, sizeof(struct thread_Settings)); + main->mSock = INVALID_SOCKET; + main->mReportMode = kReport_Default; + // option, defaults + main->flags = FLAG_MODETIME | FLAG_STDOUT; // Default time and stdout + main->flags_extend = 0x0; // Default all extend flags to off + main->flags_extend2 = 0x0; // Default all extend flags to off + //main->mAppRate = 0; // -b, offered (or rate limited) load (both UDP and TCP) + main->mAppRateUnits = kRate_BW; + //main->mHost = NULL; // -c, none, required for client + main->mMode = kTest_Normal; // -d, mMode == kTest_DualTest + main->mFormat = 'a'; // -f, adaptive bits + // skip help // -h, + //main->mBufLenSet = false; // -l, + main->mBufLen = kDefault_TCPBufLen; // -l, Default to TCP read/write size + //main->mInterval = 0; // -i, ie. no periodic bw reports + //main->mPrintMSS = false; // -m, don't print MSS + // mAmount is time also // -n, N/A + //main->mOutputFileName = NULL; // -o, filename + main->mPort = 5001; // -p, ttcp port + main->mBindPort = 0; // -B, default port for bind + // mMode = kTest_Normal; // -r, mMode == kTest_TradeOff + main->mThreadMode = kMode_Unknown; // -s, or -c, none + main->mAmount = 1000; // -t, 10 seconds, units is 10 ms + main->mIntervalMode = kInterval_None;// -i none, time, packets, or bursts + // skip version // -v, + //main->mTCPWin = 0; // -w, ie. don't set window + + // more esoteric options + //main->mLocalhost = NULL; // -B, none + //main->mCompat = false; // -C, run in Compatibility mode + //main->mDaemon = false; // -D, run as a daemon + //main->mFileInput = false; // -F, + //main->mFileName = NULL; // -F, filename + //main->mStdin = false; // -I, default not stdin + //main->mListenPort = 0; // -L, listen port + //main->mMSS = 0; // -M, ie. don't set MSS + //main->mNodelay = false; // -N, don't set nodelay + //main->mThreads = 0; // -P, + //main->mRemoveService = false; // -R, + //main->mTOS = 0; // -S, ie. don't set type of service + main->mTTL = -1; // -T, link-local TTL + //main->mDomain = kMode_IPv4; // -V, + //main->mSuggestWin = false; // -W, Suggest the window size. + main->mListenerTimeout = -1; // + main->mKeyCheck = true; +#if defined(HAVE_DECL_SO_DONTROUTE) && defined(HAVE_DEFAULT_DONTROUTE_ON) + setDontRoute(main); +#endif + main->mFPS = 1; +} // end Settings + +void Settings_Copy (struct thread_Settings *from, struct thread_Settings **into, int copyall) { + *into = new struct thread_Settings; + memset(*into, 0, sizeof(struct thread_Settings)); + memcpy(*into, from, sizeof(struct thread_Settings)); + (*into)->mSumReport = NULL; + (*into)->mTransferIDStr = NULL; + +#ifdef HAVE_THREAD_DEBUG + thread_debug("Copy thread settings (malloc) from/to=%p/%p report/sum/fullduplex %p/%p/%p", \ + (void *)from, (void *)*into, (void *)(*into)->reporthdr, (void *)(*into)->mSumReport, (void *)(*into)->mFullDuplexReport); +#endif + // Some settings don't need to be copied and will confuse things. Don't copy them unless copyall is set + if (copyall) { + // Don't allocate memory for these if this is a reverse client + if (from->mHost != NULL) { + (*into)->mHost = new char[strlen(from->mHost) + 1]; + strcpy((*into)->mHost, from->mHost); + } + if (from->mOutputFileName != NULL) { + (*into)->mOutputFileName = new char[strlen(from->mOutputFileName) + 1]; + strcpy((*into)->mOutputFileName, from->mOutputFileName); + } + if (from->mLocalhost != NULL) { + (*into)->mLocalhost = new char[strlen(from->mLocalhost) + 1]; + strcpy((*into)->mLocalhost, from->mLocalhost); + } + if (from->mFileName != NULL) { + (*into)->mFileName = new char[strlen(from->mFileName) + 1]; + strcpy((*into)->mFileName, from->mFileName); + } + if (from->mHistogramStr != NULL) { + (*into)->mHistogramStr = new char[strlen(from->mHistogramStr) + 1]; + strcpy((*into)->mHistogramStr, from->mHistogramStr); + } + if (from->mSSMMulticastStr != NULL) { + (*into)->mSSMMulticastStr = new char[strlen(from->mSSMMulticastStr) + 1]; + strcpy((*into)->mSSMMulticastStr, from->mSSMMulticastStr); + } + if (from->mIfrname != NULL) { + (*into)->mIfrname = static_cast<char *>(calloc(strlen(from->mIfrname) + 1, sizeof(char))); + strcpy((*into)->mIfrname, from->mIfrname); + } + if (from->mIfrnametx != NULL) { + (*into)->mIfrnametx = static_cast<char *>(calloc(strlen(from->mIfrnametx) + 1, sizeof(char))); + strcpy((*into)->mIfrnametx, from->mIfrnametx); + } + if (from->mIsochronousStr != NULL) { + (*into)->mIsochronousStr = new char[strlen(from->mIsochronousStr) + 1]; + strcpy((*into)->mIsochronousStr, from->mIsochronousStr); + } + if (from->mHideHost != NULL) { + (*into)->mHideHost = new char[strlen(from->mHideHost) + 1]; + strcpy((*into)->mHideHost, from->mHideHost); + } + if (from->mCongestion != NULL) { + (*into)->mCongestion = new char[strlen(from->mCongestion) + 1]; + strcpy((*into)->mCongestion, from->mCongestion); + } + } else { + (*into)->mHost = NULL; + (*into)->mOutputFileName = NULL; + (*into)->mLocalhost = NULL; + (*into)->mFileName = NULL; + (*into)->mHistogramStr = NULL; + (*into)->mSSMMulticastStr = NULL; + (*into)->mIfrname = NULL; + (*into)->mIfrnametx = NULL; + (*into)->mIsochronousStr = NULL; + (*into)->mCongestion = NULL; + // apply the server side congestion setting to reverse clients + if (from->mIsochronousStr != NULL) { + (*into)->mIsochronousStr = new char[strlen(from->mIsochronousStr) + 1]; + strcpy((*into)->mIsochronousStr, from->mIsochronousStr); + } + } + + (*into)->txstart_epoch = from->txstart_epoch; + (*into)->mSumReport = from->mSumReport; + (*into)->mFullDuplexReport = from->mFullDuplexReport; + + // Zero out certain entries + (*into)->mTID = thread_zeroid(); + (*into)->runNext = NULL; + (*into)->runNow = NULL; +#if defined(HAVE_LINUX_FILTER_H) && defined(HAVE_AF_PACKET) + (*into)->mSockDrop = INVALID_SOCKET; +#endif + int mbuflen = (from->mBufLen > MINMBUFALLOCSIZE) ? from->mBufLen : MINMBUFALLOCSIZE; // defined in payloads.h +#if (((HAVE_TUNTAP_TUN) || (HAVE_TUNTAP_TAP)) && (AF_PACKET)) + mbuflen += TAPBYTESSLOP; +#endif + (*into)->mBuf = new char[mbuflen]; + memset((*into)->mBuf, 0, mbuflen); + +#ifdef HAVE_THREAD_DEBUG + thread_debug("Copy Settings: MBUF malloc %d bytes (%p)", mbuflen, (void *) (*into)->mBuf); +#endif + Condition_Initialize(&(*into)->awake_me); + // default copied settings to no reporter reporting + unsetReport((*into)); +} + +/* ------------------------------------------------------------------- + * Delete memory: Does not clean up open file pointers or ptr_parents + * ------------------------------------------------------------------- */ + +void Settings_Destroy (struct thread_Settings *mSettings) { +#if HAVE_THREAD_DEBUG + thread_debug("Free thread settings=%p", mSettings); +#endif + if (mSettings->tuntapdev) + close(mSettings->tuntapdev); + Condition_Destroy(&mSettings->awake_me); + DELETE_ARRAY(mSettings->mHost); + DELETE_ARRAY(mSettings->mHideHost); + DELETE_ARRAY(mSettings->mLocalhost); + DELETE_ARRAY(mSettings->mFileName); + DELETE_ARRAY(mSettings->mOutputFileName); + DELETE_ARRAY(mSettings->mHistogramStr); + DELETE_ARRAY(mSettings->mSSMMulticastStr); + DELETE_ARRAY(mSettings->mCongestion); + FREE_ARRAY(mSettings->mIfrname); + FREE_ARRAY(mSettings->mIfrnametx); + FREE_ARRAY(mSettings->mTransferIDStr); + DELETE_ARRAY(mSettings->mIsochronousStr); + DELETE_ARRAY(mSettings->mBuf); + DELETE_PTR(mSettings); +} // end ~Settings + +/* ------------------------------------------------------------------- + * Parses settings from user's environment variables. + * ------------------------------------------------------------------- */ +void Settings_ParseEnvironment (struct thread_Settings *mSettings) { + char *theVariable; + + int i = 0; + while (env_options[i].name != NULL) { + theVariable = getenv(env_options[i].name); + if (theVariable != NULL) { + Settings_Interpret(env_options[i].val, theVariable, mSettings); + } + i++; + } +} // end ParseEnvironment + +/* ------------------------------------------------------------------- + * Parse settings from app's command line. + * ------------------------------------------------------------------- */ + +void Settings_ParseCommandLine (int argc, char **argv, struct thread_Settings *mSettings) { + int option; + gnu_opterr = 1; // Fail on an unrecognized command line option + while ((option = + gnu_getopt_long(argc, argv, short_options, + long_options, NULL)) != EOF) { + Settings_Interpret(option, gnu_optarg, mSettings); + } + + for (int i = gnu_optind; i < argc; i++) { + fprintf(stderr, "%s: ignoring extra argument -- %s\n", argv[0], argv[i]); + } + // Determine the modal or compound settings now that the full command line has been parsed + Settings_ModalOptions(mSettings); + +} // end ParseCommandLine + +/* ------------------------------------------------------------------- + * Interpret individual options, either from the command line + * or from environment variables. + * ------------------------------------------------------------------- */ + +void Settings_Interpret (char option, const char *optarg, struct thread_Settings *mExtSettings) { + char *results; + switch (option) { + case '1': // Single Client + setSingleClient(mExtSettings); + break; + + case '4': // v4 only + setIPV4(mExtSettings); + break; + + case '6': // v6 only + setIPV6(mExtSettings); + break; + + case 'b': // UDP bandwidth + { + char *tmp= new char [strlen(optarg) + 1]; + strcpy(tmp, optarg); + // scan for PPS units, just look for 'p' as that's good enough + if ((((results = strtok(tmp, "p")) != NULL) && strcmp(results,optarg) != 0) \ + || (((results = strtok(tmp, "P")) != NULL) && strcmp(results,optarg) != 0)) { + mExtSettings->mAppRateUnits = kRate_PPS; + mExtSettings->mAppRate = byte_atoi(results); + } else { + mExtSettings->mAppRateUnits = kRate_BW; + mExtSettings->mAppRate = byte_atoi(optarg); + if (((results = strtok(tmp, ",")) != NULL) && strcmp(results,optarg) != 0) { + setVaryLoad(mExtSettings); + mExtSettings->mVariance = byte_atoi(optarg); + } + } + delete [] tmp; + } + setBWSet(mExtSettings); + break; + case 'c': // client mode w/ server host to connect to + mExtSettings->mHost = new char[strlen(optarg) + 1 ]; + strcpy(mExtSettings->mHost, optarg); + + if (mExtSettings->mThreadMode == kMode_Unknown) { + mExtSettings->mThreadMode = kMode_Client; + mExtSettings->mThreads = 1; + } + break; + + case 'd': // Dual-test Mode + if (mExtSettings->mThreadMode != kMode_Client) { + fprintf(stderr, warn_invalid_server_option, option); + break; + } + if (isCompat(mExtSettings)) { + fprintf(stderr, warn_invalid_compatibility_option, option); + } +#ifdef HAVE_THREAD + mExtSettings->mMode = kTest_DualTest; +#else + fprintf(stderr, warn_invalid_single_threaded, option); + mExtSettings->mMode = kTest_TradeOff; +#endif + break; + case 'e': // Use enhanced reports + setEnhanced(mExtSettings); + break; + case 'f': // format to print in + mExtSettings->mFormat = (*optarg); + break; + + case 'h': // print help and exit + fprintf(stdout, "%s", usage_long1); + fprintf(stdout, "%s", usage_long2); + exit(0); + break; + + case 'i': // specify interval between periodic bw reports + { + char framechar; + char *tmp= new char [strlen(optarg) + 1]; + strcpy(tmp, optarg); + // scan for frames as units + if ((sscanf(optarg,"%c", &framechar)) && ((framechar == 'f') || (framechar == 'F'))) { + mExtSettings->mIntervalMode = kInterval_Frames; + setEnhanced(mExtSettings); + setFrameInterval(mExtSettings); + } else { + char *end; + strcpy(tmp, optarg); + double itime = strtof(optarg, &end); + if (*end != '\0') { + fprintf (stderr, "Invalid value of '%s' for -i interval\n", optarg); + exit(1); + } + if (itime > (UINT_MAX / 1e6)) { + fprintf (stderr, "Too large value of '%s' for -i interval, max is %f\n", optarg, (UINT_MAX / 1e6)); + exit(1); + } + mExtSettings->mInterval = static_cast<unsigned int>(ceil(itime * 1e6)); + mExtSettings->mIntervalMode = kInterval_Time; + if (mExtSettings->mInterval <= 0) { + mExtSettings->mInterval = -1; + } else if (mExtSettings->mInterval < SMALLEST_INTERVAL) { + mExtSettings->mInterval = SMALLEST_INTERVAL; + fprintf (stderr, report_interval_small, (double) mExtSettings->mInterval / 1e3); + } + } + delete [] tmp; + } + break; + + case 'l': // length of each buffer + mExtSettings->mBufLen = byte_atoi(optarg); + setBuflenSet(mExtSettings); + break; + + case 'm': // print TCP MSS +#if HAVE_DECL_TCP_MAXSEG + setPrintMSS(mExtSettings); +#endif + break; + + case 'n': // bytes of data + // amount mode (instead of time mode) + unsetModeTime(mExtSettings); + mExtSettings->mAmount = byte_atoi(optarg); + if (!(mExtSettings->mAmount > 0)) { + fprintf (stderr, "Invalid value for -n amount of '%s'\n", optarg); + exit(1); + } + break; + + case 'o' : // output the report and other messages into the file + unsetSTDOUT(mExtSettings); + mExtSettings->mOutputFileName = new char[strlen(optarg)+1]; + strcpy(mExtSettings->mOutputFileName, optarg); + break; + + case 'p': // server port + { + char *tmp= new char [strlen(optarg) + 1]; + strcpy(tmp, optarg); + if ((results = strtok(tmp, "-")) != NULL) { + mExtSettings->mPort = atoi(results); + if (strcmp(results,optarg)) { + mExtSettings->mPortLast = atoi(strtok(NULL, "-")); + setIncrDstPort(mExtSettings); + } + } + delete [] tmp; + break; + } + case 'r': // test mode tradeoff + if (mExtSettings->mThreadMode != kMode_Client) { + fprintf(stderr, warn_invalid_server_option, option); + break; + } + if (isCompat(mExtSettings)) { + fprintf(stderr, warn_invalid_compatibility_option, option); + } + mExtSettings->mMode = kTest_TradeOff; + break; + + case 's': // server mode + if (mExtSettings->mThreadMode != kMode_Unknown) { + fprintf(stderr, warn_invalid_client_option, option); + break; + } + + mExtSettings->mThreadMode = kMode_Listener; + break; + + case 't': // seconds to run the client, server, listener + if (!optarg) { + fprintf(stderr, "ERROR: option -t requires value\n"); + exit(1); + } + { + double val; +#if HAVE_STRTOD + char *end; + errno = 0; + val = strtod(optarg, &end); + if (errno || (*end != '\0')) { + fprintf(stderr, "ERROR: -t value of '%s' not recognized\n", optarg); + exit(1); + } +#else + val = atof(optarg); +#endif + if (val > 0.0) + mExtSettings->mAmount = static_cast<size_t>(val * 100.0); + else + infinitetime = 1; + // time mode (instead of amount mode), units is 10 ms + setModeTime(mExtSettings); + setServerModeTime(mExtSettings); + } + break; + case 'u': // UDP instead of TCP + setUDP(mExtSettings); + break; + + case 'v': // print version and exit + fprintf(stdout, "%s", version); + exit(0); + break; + + case 'w': // TCP window size (socket buffer size) + mExtSettings->mTCPWin = byte_atoi(optarg); + if (mExtSettings->mTCPWin < 2048) { + fprintf(stderr, warn_window_small, mExtSettings->mTCPWin); + } + break; + + case 'x': // Limit Reports + while (*optarg != '\0') { + switch (*optarg) { + case 's': + case 'S': + setNoSettReport(mExtSettings); + break; + case 'c': + case 'C': + setNoConnReport(mExtSettings); + break; + case 'd': + case 'D': + setNoDataReport(mExtSettings); + break; + case 'v': + case 'V': + setNoServReport(mExtSettings); + break; + case 'm': + case 'M': + setNoMultReport(mExtSettings); + break; + default: + fprintf(stderr, warn_invalid_report, *optarg); + } + optarg++; + } + break; +#if HAVE_SCHED_SETSCHEDULER + case 'z': // Use realtime scheduling + setRealtime(mExtSettings); + break; +#endif + + case 'y': // Reporting Style + switch (*optarg) { + case 'c': + case 'C': + mExtSettings->mReportMode = kReport_CSV; + setNoSettReport(mExtSettings); + setNoConnReport(mExtSettings); + break; + default: + fprintf(stderr, warn_invalid_report_style, optarg); + } + break; + + // more esoteric options + + case 'B': // specify bind address + if (mExtSettings->mLocalhost == NULL) { + mExtSettings->mLocalhost = new char[strlen(optarg) + 1 ]; + strcpy(mExtSettings->mLocalhost, optarg); + } + break; + + case 'C': // Run in Compatibility Mode, i.e. no intial nor final header messaging + setCompat(mExtSettings); + if (mExtSettings->mMode != kTest_Normal) { + fprintf(stderr, warn_invalid_compatibility_option, + (mExtSettings->mMode == kTest_DualTest ? + 'd' : 'r')); + mExtSettings->mMode = kTest_Normal; + } + break; + + case 'D': // Run as a daemon + setDaemon(mExtSettings); + break; + + case 'F' : // Get the input for the data stream from a file + if (mExtSettings->mThreadMode != kMode_Client) { + fprintf(stderr, warn_invalid_server_option, option); + break; + } + + setFileInput(mExtSettings); + mExtSettings->mFileName = new char[strlen(optarg)+1]; + strcpy(mExtSettings->mFileName, optarg); + break; + + case 'H' : // Get the SSM host (or Source per the S,G) + if (mExtSettings->mThreadMode == kMode_Client) { + fprintf(stderr, warn_invalid_client_option, option); + break; + } + mExtSettings->mSSMMulticastStr = new char[strlen(optarg)+1]; + strcpy(mExtSettings->mSSMMulticastStr, optarg); + setSSMMulticast(mExtSettings); + break; + + case 'I' : // Set the stdin as the input source + if (mExtSettings->mThreadMode != kMode_Client) { + fprintf(stderr, warn_invalid_server_option, option); + break; + } + + setFileInput(mExtSettings); + setSTDIN(mExtSettings); + mExtSettings->mFileName = new char[strlen("<stdin>")+1]; + strcpy(mExtSettings->mFileName,"<stdin>"); + break; + + case 'L': // Listen Port (bidirectional testing client-side) + if (mExtSettings->mThreadMode != kMode_Client) { + fprintf(stderr, warn_invalid_server_option, option); + break; + } + mExtSettings->mListenPort = atoi(optarg); + break; + + case 'M': // specify TCP MSS (maximum segment size) +#if HAVE_DECL_TCP_MAXSEG + mExtSettings->mMSS = byte_atoi(optarg); + setTCPMSS(mExtSettings); + setPrintMSS(mExtSettings); +#endif + break; + + case 'N': // specify TCP nodelay option (disable Jacobson's Algorithm) + setNoDelay(mExtSettings); + break; + + case 'P': // number of client threads +#ifdef HAVE_THREAD + mExtSettings->mThreads = atoi(optarg); +#else + if (mExtSettings->mThreadMode != kMode_Server) { + fprintf(stderr, warn_invalid_single_threaded, option); + } else { + mExtSettings->mThreads = atoi(optarg); + } +#endif + break; +#ifdef WIN32 + case 'R': + setRemoveService(mExtSettings); + break; +#else + case 'R': + setReverse(mExtSettings); + break; +#endif + case 'S': // IP type-of-service + // TODO use a function that understands base-2 + // the zero base here allows the user to specify + // "0x#" hex, "0#" octal, and "#" decimal numbers + if ((mExtSettings->mTOS = parse_ipqos(optarg)) == -1) { + fprintf(stderr, "Invalid --tos value of %s\n", optarg); + mExtSettings->mTOS = 0; + } + break; + + case 'T': // time-to-live for both unicast and multicast + mExtSettings->mTTL = atoi(optarg); + break; + + case 'U': // single threaded UDP server + setUDP(mExtSettings); + setSingleUDP(mExtSettings); + setSingleClient(mExtSettings); + break; + + case 'V': // IPv6 Domain +#if HAVE_IPV6 + setIPV6(mExtSettings); +#else + fprintf(stderr, "The --ipv6_domain (-V) option is not enabled in this build.\n"); + exit(1); +#endif + break; + + case 'W' : + setSuggestWin(mExtSettings); + fprintf(stderr, "The -W option is not available in this release\n"); + break; + + case 'X' : + setPeerVerDetect(mExtSettings); + break; + + case 'Z': +#ifdef TCP_CONGESTION + setCongestionControl(mExtSettings); + mExtSettings->mCongestion = new char[strlen(optarg)+1]; + strcpy(mExtSettings->mCongestion, optarg); +#else + fprintf(stderr, "The -Z option is not available on this operating system\n"); +#endif + break; + + case 0: + if (incrdstip) { + incrdstip = 0; + setIncrDstIP(mExtSettings); + } + if (incrdstport) { + incrdstport = 0; + setIncrDstPort(mExtSettings); + } + if (incrsrcip) { + incrsrcip = 0; + setIncrSrcIP(mExtSettings); + } + if (incrsrcport) { + incrsrcport = 0; + setIncrSrcPort(mExtSettings); + } + if (sumdstip) { + sumdstip = 0; + setSumServerDstIP(mExtSettings); + } + if (txstarttime) { + long seconds; + long usecs; + int match = 0; + txstarttime = 0; + setTxStartTime(mExtSettings); + setEnhanced(mExtSettings); + match = sscanf(optarg,"%ld.%6ld", &seconds, &usecs); + mExtSettings->txstart_epoch.tv_usec = 0; + switch (match) { + case 2: + mExtSettings->txstart_epoch.tv_usec = usecs; + case 1: + mExtSettings->txstart_epoch.tv_sec = seconds; + break; + default: + unsetTxStartTime(mExtSettings); + fprintf(stderr, "WARNING: invalid --txstart-time format\n"); + } + } + if (noconnectsync) { +#ifdef HAVE_THREAD + noconnectsync = 0; + setNoConnectSync(mExtSettings); +#else + fprintf(stderr, "WARNING: --no-connect-sync requires thread support and not supported\n"); +#endif + } + if (txholdback) { + txholdback = 0; + char *end; + Timestamp holdbackdelay; + double delay = strtof(optarg, &end); + if (*end != '\0') { + fprintf (stderr, "Invalid value of '%s' for --txdelay-time time\n", optarg); + } else { + holdbackdelay.set(delay); + mExtSettings->txholdback_timer.tv_sec = holdbackdelay.getSecs(); + mExtSettings->txholdback_timer.tv_usec = (holdbackdelay.getUsecs()); + setTxHoldback(mExtSettings); + } + } + if (triptime) { + triptime = 0; + setTripTime(mExtSettings); + } + if (noudpfin) { + noudpfin = 0; + setNoUDPfin(mExtSettings); + } + if (connectonly) { + connectonly = 0; + setConnectOnly(mExtSettings); + unsetNoConnReport(mExtSettings); + if (optarg) { + mExtSettings->connectonly_count = atoi(optarg); + } else { + mExtSettings->connectonly_count = -1; + } + } + if (connectretry) { + connectretry = 0; + mExtSettings->mConnectRetries = atoi(optarg); + } + if (sumonly) { + sumonly = 0; + setSumOnly(mExtSettings); + } + if (so_dontroute) { + so_dontroute = 0; +#if HAVE_DECL_SO_DONTROUTE + setDontRoute(mExtSettings); + if (optarg) { + if (atoi(optarg)) + setDontRoute(mExtSettings); + else + unsetDontRoute(mExtSettings); + } +#else + fprintf(stderr, "WARNING: The --local-only option is not supported on this platform\n"); +#endif + } + if (nearcongest) { + nearcongest = 0; + setNearCongest(mExtSettings); + if (optarg && (atof(optarg) >= 0.0)) { + mExtSettings->rtt_nearcongest_weight_factor = atof(optarg); + } else { + mExtSettings->rtt_nearcongest_weight_factor = NEARCONGEST_DEFAULT; + } + } + if (permitkey) { + permitkey = 0; + if (optarg) { + strncpy(mExtSettings->mPermitKey, optarg, MAX_PERMITKEY_LEN); + mExtSettings->mPermitKey[MAX_PERMITKEY_LEN] = '\0'; + } else { + mExtSettings->mPermitKey[0] = '\0'; + } + setPermitKey(mExtSettings); + } + if (permitkeytimeout) { + permitkeytimeout = 0; + if (atof(optarg) >= 0.0) + mExtSettings->mListenerTimeout = static_cast<size_t>(atof(optarg)); + } + if (histogram) { + histogram = 0; + setHistogram(mExtSettings); + setEnhanced(mExtSettings); + if (optarg) { + mExtSettings->mHistogramStr = new char[strlen(optarg) + 1 ]; + strcpy(mExtSettings->mHistogramStr, optarg); + } else { + mExtSettings->mHistogramStr = NULL; + } + } + if (jitter_histogram) { + jitter_histogram = 0; + setJitterHistogram(mExtSettings); + setEnhanced(mExtSettings); + if (optarg) { + mExtSettings->jitter_binwidth = atoi(optarg); + } else { + mExtSettings->jitter_binwidth = JITTER_BINWIDTH; // units are usecs + } + } + if (reversetest) { + reversetest = 0; + setReverse(mExtSettings); + } + if (fullduplextest) { + fullduplextest = 0; + setFullDuplex(mExtSettings); + } + if (overridetos) { + overridetos = 0; + if ((mExtSettings->mRTOS = parse_ipqos(optarg)) == -1) { + fprintf(stderr, "Invalid --tos-overide value of %s\n", optarg); + } else { + setOverrideTOS(mExtSettings); + } + } + if (fqrate) { +#if defined(HAVE_DECL_SO_MAX_PACING_RATE) + fqrate=0; + setFQPacing(mExtSettings); + mExtSettings->mFQPacingRate = static_cast<uintmax_t>(bitorbyte_atoi(optarg) / 8); +#else + fprintf(stderr, "WARNING: The --fq-rate option is not supported\n"); +#endif + } + if (isochronous) { + isochronous = 0; + setEnhanced(mExtSettings); + setIsochronous(mExtSettings); + // The following are default values which + // may be overwritten during modal parsing + mExtSettings->mFPS = 60.0; + mExtSettings->mMean = 20000000.0; + mExtSettings->mVariance = 0.0; + mExtSettings->mBurstIPG = 5e-6; + if (optarg) { + mExtSettings->mIsochronousStr = new char[strlen(optarg) + 1 ]; + strcpy(mExtSettings->mIsochronousStr, optarg); + } + } + if (burstipg) { + burstipg = 0; + setIPG(mExtSettings); + char *end; + mExtSettings->mBurstIPG = strtof(optarg,&end); + if (*end != '\0') { + fprintf (stderr, "ERRPORE: Invalid value of '%s' for --ipg\n", optarg); + exit(1); + } + } + if (rxwinclamp) { + rxwinclamp = 0; +#if HAVE_DECL_TCP_WINDOW_CLAMP + mExtSettings->mClampSize = byte_atoi(optarg); + setRxClamp(mExtSettings); +#else + fprintf(stderr, "--tcp-rx-window-clamp not supported on this platform\n"); +#endif + } + if (tcpwritetimes) { + tcpwritetimes = 0; + setTcpWriteTimes(mExtSettings); + } + if (notcpbbquickack) { + notcpbbquickack = 0; + notcpbbquickack_cliset = 1; + } + if (tcpquickack) { + tcpquickack = 0; +#if HAVE_DECL_TCP_QUICKACK + setTcpQuickAck(mExtSettings); +#endif + } + if (utctimes) { + setUTC(mExtSettings); + } + if (workingload) { + workingload = 0; +#ifdef HAVE_THREAD + setWorkingLoadUp(mExtSettings); + setWorkingLoadDown(mExtSettings); + if (optarg) { + char *tmp= new char [strlen(optarg) + 1]; + if (tmp) { + strcpy(tmp, optarg); + if ((results = strtok(tmp, ",")) != NULL) { + if (strcasecmp(results, "up") == 0) { + unsetWorkingLoadDown(mExtSettings); + } else if (strcasecmp(results, "down") == 0) { + unsetWorkingLoadUp(mExtSettings); + } else if (strcasecmp(results, "bidir") == 0) { + setWorkingLoadUp(mExtSettings); + setWorkingLoadDown(mExtSettings); + } else { + fprintf(stderr, "Unrecoginized value of %s for --working-load, use 'up', 'down' or 'bidir'\n", results); + } + if ((results = strtok(NULL, ",")) != NULL) { + mExtSettings->mWorkingLoadThreads = atoi(results); + } + delete [] tmp; + } + } + } +#else + fprintf(stderr, "bounceback-congest option requires a platform that supports threads\n"); +#endif + } + if (bouncebackdelaystart) { + bouncebackdelaystart = 0; + char *end; + Timestamp holdbackdelay; + double delay = strtof(optarg, &end); + if (*end != '\0') { + fprintf (stderr, "Invalid value of '%s' for --bounceback-txdelay time\n", optarg); + } else { + holdbackdelay.set(delay); + mExtSettings->txholdback_timer.tv_sec = holdbackdelay.getSecs(); + mExtSettings->txholdback_timer.tv_usec = (holdbackdelay.getUsecs()); + setTxHoldback(mExtSettings); + } + } + if (txnotsentlowwater) { + txnotsentlowwater = 0; +#if HAVE_DECL_TCP_NOTSENT_LOWAT + mExtSettings->mWritePrefetch = byte_atoi(optarg); + setWritePrefetch(mExtSettings); + setEnhanced(mExtSettings); +#else + fprintf(stderr, "--tcp-write-prefetch not supported on this platform\n"); +#endif + } + if (burstperiodic) { + burstperiodic = 0; + setPeriodicBurst(mExtSettings); + if (optarg && (atof(optarg) > 1e-5)) { // limit to 10 usecs + mExtSettings->mFPS = 1.0/atof(optarg); + } else { + if (atof(optarg) != 0) + fprintf(stderr, "WARN: burst-period too small, must be greater than 10 usecs\n"); + unsetPeriodicBurst(mExtSettings); + } + } + if (burstsize) { + burstsize = 0; + setPeriodicBurst(mExtSettings); + if (optarg) { + mExtSettings->mBurstSize = byte_atoi(optarg); + } + } + if (numreportstructs) { + numreportstructs = 0; + mExtSettings->numreportstructs = byte_atoi(optarg); + } + if (tapif) { + tapif = 0; +#if HAVE_TUNTAP_TAP + if (optarg) { + mExtSettings->mIfrname = static_cast<char *>(calloc(strlen(optarg) + 1, sizeof(char))); + strcpy(mExtSettings->mIfrname, optarg); + } + setTapDev(mExtSettings); + setEnhanced(mExtSettings); + setL2LengthCheck(mExtSettings); +#else + fprintf(stderr, "ERROR: tap devices not supported\n"); + exit(1); +#endif + } + if (tunif) { + tunif = 0; + fprintf(stderr, "ERROR: tun devices not yet supported\n"); + exit(1); +#if HAVE_TUNTAP_TUN + if (optarg) { + mExtSettings->mIfrname = static_cast<char *>(calloc(strlen(optarg) + 1, sizeof(char))); + strcpy(mExtSettings->mIfrname, optarg); + } + setTunDev(mExtSettings); + setEnhanced(mExtSettings); +#endif + } + if (hideips) { + hideips = 0; + setHideIPs(mExtSettings); + } + if (bounceback) { + bounceback = 0; + setBounceBack(mExtSettings); + setNoDelay(mExtSettings); + setEnhanced(mExtSettings); + if (optarg) { + mExtSettings->mBounceBackBurst = atoi(optarg); + if (mExtSettings->mBounceBackBurst <= 0) { + fprintf(stderr, "WARN: invalid bounceback value, setting it to 10\n"); + mExtSettings->mBounceBackBurst = 10; + } + } else { + mExtSettings->mBounceBackBurst = -1; + } + } + if (bouncebackhold) { + bouncebackhold = 0; + if (optarg) + //cli units is ms, working units is us + mExtSettings->mBounceBackHold = int(atof(optarg) * 1e3); + else + mExtSettings->mBounceBackHold = 0; + } + if (bouncebackperiod) { + bouncebackperiod = 0; + setPeriodicBurst(mExtSettings); + if (optarg) { + float value = atof(optarg); + if (value > 1e-5) { // limit to 10 usecs + mExtSettings->mFPS = 1.0/atof(optarg); + } else { + mExtSettings->mFPS = -1; + } + } + } + break; + default: // ignore unknown + break; + } +} // end Interpret + + +static void generate_permit_key (struct thread_Settings *mExtSettings) { + Timestamp now; + mExtSettings->mPermitKeyTime.tv_sec = now.getSecs(); + mExtSettings->mPermitKeyTime.tv_usec = now.getUsecs(); + int usecs = mExtSettings->mPermitKeyTime.tv_usec; + int timestrlength = snprintf(NULL, 0, "%ld.%06d-", static_cast<long>(mExtSettings->mPermitKeyTime.tv_sec), usecs); + snprintf(mExtSettings->mPermitKey, (timestrlength+1), "%ld.%06d-", static_cast<long>(mExtSettings->mPermitKeyTime.tv_sec), usecs); + srand(static_cast<unsigned int>(time(NULL))); + int index; + char characters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + for(index = timestrlength; index < (DEFAULT_PERMITKEY_LEN + timestrlength); index++) { + int len = snprintf(mExtSettings->mPermitKey + index, sizeof(char) + 1, "%c", \ + characters[rand() % (static_cast<int>(sizeof(characters)) - 1)]); + FAIL_errno ((len < 0), "permit-key gen", mExtSettings); + } + mExtSettings->mPermitKey[DEFAULT_PERMITKEY_LEN + timestrlength] = '\0'; + if (strlen(mExtSettings->mPermitKey) > MAX_PERMITKEY_LEN) { + fprintf(stderr, "ERROR: permit key too long\n"); + exit(1); + } +} + +static void strip_v6_brackets (char *v6addr) { + char * results; + if (v6addr && (*v6addr == '[') && ((results = strtok(v6addr, "]")) != NULL)) { + int len = strlen(v6addr); + for (int jx = 0; jx < len; jx++) { + v6addr[jx]= v6addr[jx + 1]; + } + } +} + +static char * isv6_bracketed_port (char *v6addr) { + char *results = NULL; + if (v6addr && (*v6addr == '[') && ((results = strtok(v6addr, "]")) != NULL)) { + results = strtok(NULL, ":"); + strip_v6_brackets(v6addr); + return results; + } + return NULL; +} +static char * isv4_port (char *v4addr) { + char *results = NULL; + if (((results = strtok(v4addr, ":")) != NULL) && ((results = strtok(NULL, ":")) != NULL)) { + return results; + } + return NULL; +} + + +// The commmand line options are position independent and hence some settings become "modal" +// i.e. two passes are required to get all the final settings correct. +// For example, -V indicates use IPv6 and -u indicates use UDP, and the default socket +// read/write (UDP payload) size is different for ipv4 and ipv6. +// So in the Settings_Interpret pass there is no guarantee to know all three of (-u and -V and not -l) +// while parsing them individually. +// +// Since Settings_Interpret() will set all the *individual* options and flags +// then the below code (per the example UDP, v4 or v6, and not -l) can set final +// values, e.g. a correct default mBufLen. Other examples that need this are multicast +// socket or not,-B local bind port parsing, and when to use the default UDP offered load +// +// Also apply the bail out or exit conditions if the user requested mutually exclusive +// or incompatabile options +void Settings_ModalOptions (struct thread_Settings *mExtSettings) { + char *results; + // Handle default read/write sizes based on v4, v6, UDP or TCP + if (!isBuflenSet(mExtSettings)) { + if (isUDP(mExtSettings)) { + if (isIPV6(mExtSettings) && mExtSettings->mThreadMode == kMode_Client) { + mExtSettings->mBufLen = kDefault_UDPBufLenV6; + } else { + mExtSettings->mBufLen = kDefault_UDPBufLen; + } + } else { + if (isBounceBack(mExtSettings)) + mExtSettings->mBufLen = kDefault_BBTCPBufLen; + else + mExtSettings->mBufLen = kDefault_TCPBufLen; + } + } + if (!mExtSettings->mPortLast) + mExtSettings->mPortLast = mExtSettings->mPort; + + // Handle default UDP offered load (TCP will be max, i.e. no read() or write() rate limiting) + if (!isBWSet(mExtSettings) && isUDP(mExtSettings)) { + mExtSettings->mAppRate = kDefault_UDPRate; + } + if (isTripTime(mExtSettings) && (isReverse(mExtSettings) || \ + isFullDuplex(mExtSettings) || \ + (mExtSettings->mMode != kTest_Normal))) { + setEnhanced(mExtSettings); + } + // Warnings + if (mExtSettings->mThreadMode == kMode_Client) { + if (isModeTime(mExtSettings) && infinitetime) { + unsetModeTime(mExtSettings); + setModeInfinite(mExtSettings); + fprintf(stderr, "WARNING: client will send traffic forever or until an external signal (e.g. SIGINT or SIGTERM) occurs to stop it\n"); + } + if (isFullDuplex(mExtSettings) && isCongestionControl(mExtSettings)) { + fprintf(stderr, "WARNING: tcp congestion control will only be applied on transmit traffic, use -Z on the server\n"); + } + } + if (isHideIPs(mExtSettings)) { + char hide_string[] = "(**hidden**)"; + mExtSettings->mHideHost = new char[strlen(hide_string) + 1]; + if (mExtSettings->mHideHost) + strcpy(mExtSettings->mHideHost, &hide_string[0]); + } + + // Bail outs + bool bail = false; + // compat mode doesn't support these test settings + int compat_nosupport = (isReverse(mExtSettings) | isFullDuplex(mExtSettings) | isTripTime(mExtSettings) | isVaryLoad(mExtSettings) \ + | isHistogram(mExtSettings) | isIsochronous(mExtSettings) \ + | isEnhanced(mExtSettings) | (mExtSettings->mMode != kTest_Normal)); + if (isCompat(mExtSettings) && compat_nosupport) { + fprintf(stderr, "ERROR: compatibility mode not supported with the requested with options\n"); + bail = true; + } +#if !(HAVE_DECL_IP_TOS) + if (isOverrideTOS(mExtSettings) || mExtSettings->mTOS) { + unsetOverrideTOS(mExtSettings); + fprintf(stderr, "WARN: IP_TOS not supported\n"); + } +#endif + if (isPermitKey(mExtSettings)) { + if (isUDP(mExtSettings)) { + fprintf(stderr, "ERROR: Option of --permit-key not supported with UDP\n"); + bail = true; + } else if (mExtSettings->mPermitKey[0] != '\0') { + int keylen = strnlen(mExtSettings->mPermitKey, MAX_PERMITKEY_LEN + 1); + if (keylen < MIN_PERMITKEY_LEN) { + fprintf(stderr, "ERROR: value for --permit-key must have at least %d characters\n", MIN_PERMITKEY_LEN); + bail = true; + } else if (keylen > MAX_PERMITKEY_LEN) { + fprintf(stderr, "ERROR: value for --permit-key can't be more than %d characters \n", MAX_PERMITKEY_LEN); + bail = true; + } + } + } +#if !HAVE_IPV6 + if (isIPV6(mExtSettings)) { + fprintf(stderr, "ERROR: ipv6 not supported\n"); + bail = true; + } +#endif + if (isIPV4(mExtSettings) && isIPV6(mExtSettings)) { + fprintf(stderr, "WARN: both ipv4 and ipv6 set\n"); + unsetIPV6(mExtSettings); + unsetIPV4(mExtSettings); + } + if (mExtSettings->mThreadMode == kMode_Client) { + if (isRemoveService(mExtSettings)) { + // -R on the client is overloaded and is the + // short option for --reverse, fix it now + setReverse(mExtSettings); + unsetRemoveService(mExtSettings); + } + if (isIncrSrcIP(mExtSettings) && (mExtSettings->mLocalhost==NULL)) { + fprintf(stderr, "ERROR: option of --incr-srcip requires -B bind option to be set\n"); + bail = true; + } + if (isSumServerDstIP(mExtSettings)) { + fprintf(stderr, "WARN: option of --sum-dstip not supported on the client\n"); + } + if (isOverrideTOS(mExtSettings)) { + unsetOverrideTOS(mExtSettings); + fprintf(stderr, "WARN: option of --tos-override not supported on the client\n"); + } + if (isRxClamp(mExtSettings)) { + fprintf(stderr, "WARN: option of --tcp-rx-window-clamp not supported on the client\n"); + unsetRxClamp(mExtSettings); + } + if (isJitterHistogram(mExtSettings)) { + fprintf(stderr, "WARN: option of --jitter-histogram not supported on the client\n"); + unsetJitterHistogram(mExtSettings); + } + if (isIncrSrcPort(mExtSettings) && !mExtSettings->mBindPort) { + fprintf(stderr, "WARN: option of --incr-srcport requires -B bind option w/port to be set\n"); + unsetIncrSrcPort(mExtSettings); + } + if (isPeriodicBurst(mExtSettings)) { + setEnhanced(mExtSettings); + setFrameInterval(mExtSettings); + } + if (mExtSettings->mTTL > MAXTTL) { + fprintf(stderr, "ERROR: option of -ttl (-T) must be less than %d\n", MAXTTL); + bail = true; + } + if (isPermitKey(mExtSettings) && (mExtSettings->mPermitKey[0] == '\0')) { + fprintf(stderr, "ERROR: option of --permit-key requires a value on the client\n"); + bail = true; + } + if (!isUDP(mExtSettings) && isTxHoldback(mExtSettings) && isTxStartTime(mExtSettings)) { + fprintf(stderr,"ERROR: options of --txstart-time and --txdelay-time are mutually exclusive\n"); + bail = true; + } else if (isTxStartTime(mExtSettings) || isTxHoldback(mExtSettings)) { + Timestamp now; + if (isTxStartTime(mExtSettings)) { + if (mExtSettings->txstart_epoch.tv_sec < 0) { + fprintf(stderr, "ERROR: --txstart-time must be a positive value\n"); + unsetTxStartTime(mExtSettings); + bail = true; + } else if ((mExtSettings->txstart_epoch.tv_sec - now.getSecs()) > MAXDIFFTXSTART) { + char timestr[120]; + struct timeval t; + t.tv_sec = now.getSecs(); + t.tv_usec = now.getUsecs(); + iperf_formattime(timestr, sizeof(timestr), t, isEnhanced(mExtSettings), isUTC(mExtSettings), YearThruSecTZ); + printf(error_starttime_exceeds, mExtSettings->txstart_epoch.tv_sec, mExtSettings->txstart_epoch.tv_usec, \ + timestr, MAXDIFFTXSTART); + bail = true; + } + } else if (mExtSettings->txholdback_timer.tv_sec > MAXDIFFTXDELAY) { + printf(error_delaytime_exceeds, mExtSettings->txholdback_timer.tv_sec, MAXDIFFTXDELAY); + bail = true; + } + } + if (isBounceBack(mExtSettings)) { + if (static_cast<int> (mExtSettings->mBurstSize) > 0) { + fprintf(stderr, "WARN: options of --burst-size for bounce-back ignored, use -l sets size\n"); + } + mExtSettings->mBounceBackBytes = mExtSettings->mBufLen; + mExtSettings->mBurstSize = mExtSettings->mBufLen; +#if HAVE_DECL_TCP_QUICKACK + if (notcpbbquickack_cliset && isTcpQuickAck(mExtSettings)) { + fprintf(stderr, "ERROR: --tcp-quickack and --bounceback-no-quickack are mutually exclusive\n"); + bail = true; + } + // be wary of double negatives here + if (!notcpbbquickack_cliset) { + setTcpQuickAck(mExtSettings); + } +#endif + // default bounceback period to 1 second + if (!isPeriodicBurst(mExtSettings)) { + mExtSettings->mFPS = 1.0; + setPeriodicBurst(mExtSettings); + if (mExtSettings->mIntervalMode == kInterval_None) { + mExtSettings->mIntervalMode = kInterval_Time; + mExtSettings->mInterval = 1000000; // units is us + } + } else if (mExtSettings->mFPS <= 1e-5) { + unsetPeriodicBurst(mExtSettings); + } + if (isPeriodicBurst(mExtSettings) && (mExtSettings->mBounceBackBurst == -1)) { + mExtSettings->mBounceBackBurst = 10; + } + } +#if HAVE_DECL_TCP_NOTSENT_LOWAT + if (isTripTime(mExtSettings) && !isUDP(mExtSettings)) { + if (isWritePrefetch(mExtSettings)) { + if (mExtSettings->mWritePrefetch <= 0) { + unsetWritePrefetch(mExtSettings); + } + } else { + mExtSettings->mWritePrefetch = SMALL_WRITE_PREFETCH; + setWritePrefetch(mExtSettings); + setEnhanced(mExtSettings); + } + } +#endif + if (isPeriodicBurst(mExtSettings)) { + if (isIsochronous(mExtSettings)) { + fprintf(stderr, "ERROR: options of --burst-period and --isochronous cannot be applied together\n"); + bail = true; + } else if (isNearCongest(mExtSettings)) { + fprintf(stderr, "ERROR: options of --burst-period and --near-congestion cannot be applied together\n"); + bail = true; + } else if (static_cast<int> (mExtSettings->mBurstSize) == 0) { + mExtSettings->mBurstSize = byte_atoi("1M"); //default to 1 Mbyte + } + if (static_cast<int> (mExtSettings->mBurstSize) < mExtSettings->mBufLen) { + fprintf(stderr, "ERROR: option of --burst-size %d must be equal or larger to write length (-l) %d\n", mExtSettings->mBurstSize, mExtSettings->mBufLen); + bail = true; + } + } else if (!isBounceBack(mExtSettings) && (static_cast<int> (mExtSettings->mBurstSize) > 0)) { + setPeriodicBurst(mExtSettings); + mExtSettings->mFPS = 1.0; + fprintf(stderr, "WARN: option of --burst-size without --burst-period defaults --burst-period to 1 second\n"); + } + if (isUDP(mExtSettings)) { + if (isPeerVerDetect(mExtSettings)) { + fprintf(stderr, "ERROR: option of -X or --peer-detect not supported with -u UDP\n"); + bail = true; + } + if (isConnectOnly(mExtSettings)) { + fprintf(stderr, "ERROR: option of --connect-only not supported with -u UDP\n"); + bail = true; + } + if (isBounceBack(mExtSettings)) { + fprintf(stderr, "ERROR: option of -X or --bounceback not supported with -u UDP\n"); + bail = true; + } + if (isNearCongest(mExtSettings)) { + fprintf(stderr, "ERROR: option of --near-congestion not supported with -u UDP\n"); + bail = true; + } + if (isIPG(mExtSettings) && isBWSet(mExtSettings)) { + fprintf(stderr, "ERROR: options of --b and --ipg cannot be applied together\n"); + bail = true; + } + if (mExtSettings->mBurstIPG < 0.0) { + fprintf(stderr, "ERROR: option --ipg must be a positive value\n"); + bail = true; + } + if (mExtSettings->mConnectRetries > 0) { + fprintf(stderr, "ERROR: option --connect-retries not supported with -u UDP\n"); + bail = true; + } + if (isWritePrefetch(mExtSettings)) { + fprintf(stderr, "WARN: setting of option --tcp-write-prefetch is not supported with -u UDP\n"); + unsetWritePrefetch(mExtSettings); + } + if (isTcpQuickAck(mExtSettings)) { + fprintf(stderr, "WARN: setting of option --tcp-quickack is not supported with -u UDP\n"); + unsetWritePrefetch(mExtSettings); + } + + { + double delay_target; + if (isIPG(mExtSettings)) { + delay_target = mExtSettings->mBurstIPG * 1e9; // convert from seconds to nanoseconds + } else { + // compute delay target in units of nanoseconds + if (mExtSettings->mAppRateUnits == kRate_BW) { + // compute delay for bandwidth restriction, constrained to [0,max] seconds + delay_target = (mExtSettings->mBufLen * 8e9) / mExtSettings->mAppRate; + } else { + delay_target = 1e9 / mExtSettings->mAppRate; + } + } + if (delay_target < 0 || + delay_target > MAXIPGSECS * 1e9) { + fprintf(stderr, "ERROR: IPG delay target of %.1f secs too large (max value is %d secs)\n", (delay_target / 1e9), MAXIPGSECS); + bail = true; + } + } + if (isTripTime(mExtSettings)) { + if (mExtSettings->mBufLen < MINTRIPTIMEPLAYOAD) { + if (isReverse(mExtSettings) || isFullDuplex(mExtSettings) || (mExtSettings->mMode != kTest_Normal)) { + fprintf(stderr, "ERROR: payload (-l) size of %d too small for --trip-times, must be %d or greater\n", mExtSettings->mBufLen, MINTRIPTIMEPLAYOAD); + bail = true; + } else { + setSmallTripTime(mExtSettings); + } + } + } + } else { + if ((mExtSettings->mAppRate > 0) && isNearCongest(mExtSettings)) { + fprintf(stderr, "ERROR: option of --near-congestion and -b rate limited are mutually exclusive\n"); + bail = true; + } + if (isBWSet(mExtSettings) && !(mExtSettings->mAppRateUnits == kRate_PPS) \ + && ((mExtSettings->mAppRate / 8) < static_cast<uintmax_t>(mExtSettings->mBufLen))) { + fprintf(stderr, "ERROR: option -b and -l of %d are incompatible, consider setting -l to %d or lower\n", \ + mExtSettings->mBufLen, static_cast<int>(mExtSettings->mAppRate / 8)); + bail = true; + } + if (isIPG(mExtSettings)) { + fprintf(stderr, "ERROR: option --ipg requires -u UDP\n"); + bail = true; + } + if (isNoUDPfin(mExtSettings)) { + fprintf(stderr, "ERROR: option --no-udp-fin requires -u UDP\n"); + bail = true; + } + if (isTxHoldback(mExtSettings) && isConnectOnly(mExtSettings)) { + fprintf(stderr,"ERROR: Fail because --txdelay-time and --connect-only cannot be applied together\n"); + bail = true; ; + } + if (mExtSettings->mAppRateUnits == kRate_PPS) { + fprintf(stderr, "ERROR: units of pps not supported with TCP\n"); + bail = true; + } + if (isJitterHistogram(mExtSettings)) { + fprintf(stderr, "ERROR: option of --jitter-histogram not supported with TCP\n"); + bail = true; + } + } + if (!isReverse(mExtSettings) && !isFullDuplex(mExtSettings) && isHistogram(mExtSettings)){ + setTcpWriteTimes(mExtSettings); + mExtSettings->mHistBins = 100000; // 10 seconds wide + mExtSettings->mHistBinsize = 100; // 100 usec bins + mExtSettings->mHistUnits = 6; // usecs 10 pow(x) + mExtSettings->mHistci_lower = 5; + mExtSettings->mHistci_upper = 95; + } + if (isCongestionControl(mExtSettings) && isReverse(mExtSettings)) { + fprintf(stderr, "ERROR: tcp congestion control -Z and --reverse cannot be applied together\n"); + bail = true; + } + { + int one_only = 0; + if (isFullDuplex(mExtSettings)) + one_only++; + if (isReverse(mExtSettings)) + one_only++; + if (mExtSettings->mMode != kTest_Normal) + one_only++; + if (one_only > 1) { + fprintf(stderr, "ERROR: options of --full-duplex, --reverse, -d and -r are mutually exclusive\n"); + bail = true; + } + } + if (isBWSet(mExtSettings) && isIsochronous(mExtSettings)) { + fprintf(stderr, "ERROR: options of --b and --isochronous cannot be applied together\n"); + bail = true; + } + } else { + if (mExtSettings->mPortLast && (!(mExtSettings->mPortLast >= mExtSettings->mPort))) { + fprintf(stderr, "ERROR: invalid port range of %d-%d\n",mExtSettings->mPort, mExtSettings->mPortLast); + bail = true; + } + if (isPermitKey(mExtSettings)) { + if (mExtSettings->mPermitKey[0]=='\0') { + generate_permit_key(mExtSettings); + } + if (mExtSettings->mListenerTimeout < 0) { + mExtSettings->mListenerTimeout = DEFAULT_PERMITKEY_LIFE; + } + } + if (isBounceBack(mExtSettings)) { + fprintf(stderr, "ERROR: setting of option --bounce-back is not supported on the server\n"); + bail = true; + } + if (isTripTime(mExtSettings)) { + fprintf(stderr, "WARN: setting of option --trip-times is not supported on the server\n"); + } + if (isWritePrefetch(mExtSettings)) { + fprintf(stderr, "WARN: setting of option --tcp-write-prefetch is not supported on the server\n"); + unsetWritePrefetch(mExtSettings); + } + if (isIncrSrcIP(mExtSettings)) { + fprintf(stderr, "WARN: setting of option --incr-srcip is not supported on the server\n"); + } + if (isVaryLoad(mExtSettings)) { + fprintf(stderr, "WARN: option of variance per -b is not supported on the server\n"); + } + if (isTxStartTime(mExtSettings)) { + fprintf(stderr, "WARN: option of --txstart-time is not supported on the server\n"); + } + if (isTxHoldback(mExtSettings)) { + fprintf(stderr, "WARN: option of --txdelay-time is not supported on the server\n"); + } + if (isIPG(mExtSettings)) { + fprintf(stderr, "WARN: option of --ipg is not supported on the server\n"); + } + if (isIsochronous(mExtSettings)) { + fprintf(stderr, "WARN: option of --isochronous is not supported on the server\n"); + } + if (isFullDuplex(mExtSettings)) { + fprintf(stderr, "WARN: option of --full-duplex is not supported on the server\n"); + } + if (isReverse(mExtSettings)) { + fprintf(stderr, "WARN: option of --reverse is not supported on the server\n"); + } + if (isIncrDstIP(mExtSettings)) { + fprintf(stderr, "WARN: option of --incr-dstip is not supported on the server\n"); + } + if (isFQPacing(mExtSettings)) { + fprintf(stderr, "WARN: option of --fq-rate is not supported on the server\n"); + } + if (isNoUDPfin(mExtSettings)) { + fprintf(stderr, "WARN: option of --no-udp-fin is not supported on the server\n"); + } + if (isPeerVerDetect(mExtSettings)) { + fprintf(stderr, "WARN: option of -X or --peer-detect not supported on the server\n"); + } + if (mExtSettings->mConnectRetries > 0) { + fprintf(stderr, "WARN: option --connect-retries not supported on the server\n"); + } + if (isNearCongest(mExtSettings)) { + fprintf(stderr, "WARN: option of --near-congestion not supported on the server\n"); + } + if (isPeriodicBurst(mExtSettings)) { + fprintf(stderr, "WARN: option of --burst-period can only be set on the client\n"); + } + if (mExtSettings->mBurstSize != 0) { + fprintf(stderr, "WARN: option of --burst-size not supported on the server\n"); + } + if (isUDP(mExtSettings) && isRxClamp(mExtSettings)) { + fprintf(stderr, "WARN: option of --tcp-rx-window-clamp not supported using -u UDP \n"); + unsetRxClamp(mExtSettings); + } + } + if (bail) + exit(1); + + // Histogram optional settings + if (isHistogram(mExtSettings)) { + if (!mExtSettings->mHistogramStr) { + if (mExtSettings->mThreadMode == kMode_Server) { + // set default rx histogram settings, milliseconds bins between 0 and 1 secs + mExtSettings->mHistBins = 1000; + mExtSettings->mHistBinsize = 1; + mExtSettings->mHistUnits = 3; + mExtSettings->mHistci_lower = 5; + mExtSettings->mHistci_upper = 95; + } else { + // set default tx histogram settings, microseconds with 100 us bins + mExtSettings->mHistBins = 10000; + mExtSettings->mHistBinsize = 100; + mExtSettings->mHistUnits = 6; + mExtSettings->mHistci_lower = 5; + mExtSettings->mHistci_upper = 95; + } + } else { + // check for optional arguments to change histogram settings + if (((results = strtok(mExtSettings->mHistogramStr, ",")) != NULL) && !strcmp(results,mExtSettings->mHistogramStr)) { + // scan for unit specifier + char *tmp = new char [strlen(results) + 1]; + strcpy(tmp, results); + if ((strtok(tmp, "u") != NULL) && strcmp(results,tmp) != 0) { + mExtSettings->mHistUnits = 6; // units is microseconds + } else { + strcpy(tmp, results); + if ((strtok(tmp, "m") != NULL) && strcmp(results,tmp) != 0) { + mExtSettings->mHistUnits = 3; // units is milliseconds + } + } + mExtSettings->mHistBinsize = atoi(tmp); + delete [] tmp; + mExtSettings->mHistci_lower = 5; + mExtSettings->mHistci_upper = 95; + if ((results = strtok(results+strlen(results)+1, ",")) != NULL) { + mExtSettings->mHistBins = byte_atoi(results); + if ((results = strtok(NULL, ",")) != NULL) { + mExtSettings->mHistci_lower = atof(results); + if ((results = strtok(NULL, ",")) != NULL) { + mExtSettings->mHistci_upper = atof(results); + } + } + } + } + } + } + if (isUDP(mExtSettings)) { + if (isFullDuplex(mExtSettings)) { + setNoUDPfin(mExtSettings); + } + if (mExtSettings->mThreadMode == kMode_Client) { + // L2 settings + if (l2checks && isUDP(mExtSettings)) { + l2checks = 0; +#if defined(HAVE_LINUX_FILTER_H) && defined(HAVE_AF_PACKET) + // Request server to do length checks + setL2LengthCheck(mExtSettings); +#else + fprintf(stderr, "WARNING: option --l2checks not supported on this platform\n"); +#endif + } + } + } else { + if (mExtSettings->mBurstSize && (static_cast<int>(mExtSettings->mBurstSize) < mExtSettings->mBufLen)) { + fprintf(stderr, "WARN: Setting --burst-size to %d because value given is smaller than -l value\n", \ + mExtSettings->mBufLen); + mExtSettings->mBurstSize = mExtSettings->mBufLen; + } else if (isTripTime(mExtSettings) && !(mExtSettings->mBurstSize > 0)) { + mExtSettings->mBurstSize = mExtSettings->mBufLen; + } + } + if (isIsochronous(mExtSettings) && mExtSettings->mIsochronousStr) { + // parse client isochronous field, + // format is --isochronous <int>:<float>,<float> and supports + // human suffixes, e.g. --isochronous 60:100m,5m + // which is frames per second, mean and variance + if (mExtSettings->mThreadMode == kMode_Client) { + if (((results = strtok(mExtSettings->mIsochronousStr, ":")) != NULL) && !strcmp(results,mExtSettings->mIsochronousStr)) { + mExtSettings->mFPS = atof(results); + if ((results = strtok(NULL, ",")) != NULL) { + mExtSettings->mMean = bitorbyte_atof(results); + if (mExtSettings->mMean == 0.0) { + fprintf(stderr, "ERROR: Invalid --isochronous mean value, must be greater than zero\n"); + exit(1); + } + if (!isUDP(mExtSettings)) { + if (mExtSettings->mMean < 0) { + fprintf(stderr, "ERROR: Invalid --isochronous units of 'p' with TCP must be bytes\n"); + exit(1); + } + } else { // UDP + if (mExtSettings->mMean < 0) { + mExtSettings->mMean *= -8 * mExtSettings->mBufLen * mExtSettings->mFPS; + } + } + if ((results = strtok(NULL, ",")) != NULL) { + mExtSettings->mVariance = bitorbyte_atof(results); + } + } else { + mExtSettings->mMean = 20000000.0; + mExtSettings->mVariance = 0.0; + } + } else { + fprintf(stderr, "WARNING: Invalid --isochronous value, format is <fps>:<mean>,<variance> (e.g. 60:18M,1m)\n"); + } + } + } + + // Check for further mLocalhost (-B) and <dev> requests + // full addresses look like 192.168.1.1:6001%eth0 or [2001:e30:1401:2:d46e:b891:3082:b939]:6001%eth0 + iperf_sockaddr tmp; + // Parse -B addresses + if (mExtSettings->mLocalhost) { + if (((results = strtok(mExtSettings->mLocalhost, "%")) != NULL) && ((results = strtok(NULL, "%")) != NULL)) { + mExtSettings->mIfrname = static_cast<char *>(calloc(strlen(results) + 1, sizeof(char))); + strcpy(mExtSettings->mIfrname, results); + if (mExtSettings->mThreadMode == kMode_Client) { + fprintf(stderr, "WARNING: Client cannot set bind device %s via -B consider using -c\n", mExtSettings->mIfrname); + free(mExtSettings->mIfrname); + mExtSettings->mIfrname = NULL; + } + } + if (isIPV6(mExtSettings)) { + results = isv6_bracketed_port(mExtSettings->mLocalhost); + } else { + results = isv4_port(mExtSettings->mLocalhost); + } + if (results) { + if (mExtSettings->mThreadMode == kMode_Client) { + mExtSettings->mBindPort = atoi(results); + } else { + fprintf(stderr, "WARNING: port %s ignored - set receive port on server via -p or -L\n", results); + } + } + // Check for multicast per the -B + SockAddr_setHostname(mExtSettings->mLocalhost, &tmp, + (isIPV6(mExtSettings) ? 1 : 0)); + if ((mExtSettings->mThreadMode != kMode_Client) && SockAddr_isMulticast(&tmp)) { + setMulticast(mExtSettings); + } else if (SockAddr_isMulticast(&tmp)) { + if (mExtSettings->mIfrname) { + free(mExtSettings->mIfrname); + mExtSettings->mIfrname = NULL; + } + fprintf(stderr, "WARNING: Client src addr (per -B) must be ip unicast\n"); + } + } + // Parse client (-c) addresses for multicast, link-local and bind to device, port incr + if (mExtSettings->mThreadMode == kMode_Client) { + if (mExtSettings->mPortLast > mExtSettings->mPort) { + int prcnt = ((mExtSettings->mPortLast - mExtSettings->mPort) + 1); + int threads_needed = (prcnt > mExtSettings->mThreads) ? prcnt : mExtSettings->mThreads; + if (mExtSettings->mThreads < prcnt) { + fprintf(stderr, "WARNING: port-range and -P mismatch (adjusting -P to %d)\n", threads_needed); + mExtSettings->mThreads = threads_needed; + } else if ((mExtSettings->mThreads > 1) && (threads_needed > prcnt)) { + fprintf(stderr, "WARNING: port-range and -P mismatch (adjusting port-range to %d-%d)\n", \ + mExtSettings->mPort, mExtSettings->mPort + threads_needed); + } + } + mExtSettings->mIfrnametx = NULL; // default off SO_BINDTODEVICE + if (((results = strtok(mExtSettings->mHost, "%")) != NULL) && ((results = strtok(NULL, "%")) != NULL)) { + size_t len = strlen(results) + 1; + mExtSettings->mIfrnametx = static_cast<char *>(calloc(len, sizeof(char))); + strncpy(mExtSettings->mIfrnametx, results, len); + mExtSettings->mIfrnametx[len] = '\0'; + } + if (isIPV6(mExtSettings)) + strip_v6_brackets(mExtSettings->mHost); + // get the socket address settings from the host, needed for link-local and multicast tests + SockAddr_zeroAddress(&mExtSettings->peer); + SockAddr_remoteAddr(mExtSettings); + if (isIPV6(mExtSettings) && SockAddr_isLinklocal(&mExtSettings->peer)) { + // link-local doesn't use SO_BINDTODEVICE but includes it in the host string + // so stitch things back together and null the bind to name + if (mExtSettings->mIfrnametx) { + strcat(mExtSettings->mHost, "%"); + strcat(mExtSettings->mHost, mExtSettings->mIfrnametx); + free(mExtSettings->mIfrnametx); + mExtSettings->mIfrnametx = NULL; + } else { + fprintf(stderr, "WARNING: usage of ipv6 link-local requires a device specifier, e.g. %s%%eth0\n", mExtSettings->mHost); + } + SockAddr_zeroAddress(&mExtSettings->peer); // for link-local, force getaddrinfo() in the connect + } + if (SockAddr_isMulticast(&mExtSettings->peer)) { + bail = false; + if ((mExtSettings->mThreads > 1) && !isIncrDstIP(mExtSettings)) { + fprintf(stderr, "ERROR: client option of -P greater than 1 not supported with multicast address\n"); + bail = true; + } else if (isFullDuplex(mExtSettings) || isReverse(mExtSettings) || (mExtSettings->mMode != kTest_Normal)) { + fprintf(stderr, "ERROR: options of --full-duplex, --reverse, -d and -r not supported with multicast addresses\n"); + bail = true; + } + if (bail) + exit(1); + else + setMulticast(mExtSettings); + } +#ifndef HAVE_DECL_SO_BINDTODEVICE + if (mExtSettings->mIfrnametx) { + fprintf(stderr, "bind to device will be ignored because not supported\n"); + free(mExtSettings->mIfrnametx); + mExtSettings->mIfrnametx=NULL; + } +#endif + } + if ((mExtSettings->mIntervalMode == kInterval_Time) && (mExtSettings->mIntervalMode <= 0)) { + mExtSettings->mIntervalMode = kInterval_None; + mExtSettings->mInterval = 0; + } +} + +void Settings_GetUpperCaseArg (const char *inarg, char *outarg) { + int len = strlen(inarg); + strcpy(outarg,inarg); + + if ((len > 0) && (inarg[len-1] >='a') + && (inarg[len-1] <= 'z')) + outarg[len-1]= outarg[len-1]+'A'-'a'; +} + +void Settings_GetLowerCaseArg (const char *inarg, char *outarg) { + int len = strlen(inarg); + strcpy(outarg,inarg); + + if ((len > 0) && (inarg[len-1] >='A') + && (inarg[len-1] <= 'Z')) + outarg[len-1]= outarg[len-1]-'A'+'a'; +} + +/* + * Settings_GenerateListenerSettings + * Called to generate the settings to be passed to the Listener + * instance that will handle dual testings from the client side + * this should only return an instance if it was called on + * the struct thread_settings instance generated from the command line + * for client side execution + */ +#define DUALTIMER_MS 300 +void Settings_GenerateListenerSettings (struct thread_Settings *client, struct thread_Settings **listener) { + if ((client->mMode == kTest_DualTest) || (client->mMode == kTest_TradeOff)) { + Settings_Copy(client, listener, SHALLOW_COPY); + unsetDaemon((*listener)); + setCompat((*listener)); + if (client->mListenPort != 0) { + (*listener)->mPort = client->mListenPort; + } else { + (*listener)->mPort = client->mPort; + } + if (client->mMode == kTest_TradeOff) { + (*listener)->mAmount = client->mAmount + DUALTIMER_MS; + } else if (client->mMode == kTest_DualTest) { + (*listener)->mAmount = client->mAmount + (SLOPSECS * 100); + } + if ((client->mMode != kTest_Normal) && ((*listener)->mAmount < DUALTIMER_MS)) { + (*listener)->mAmount = DUALTIMER_MS; + } + (*listener)->mFileName = NULL; + (*listener)->mHost = NULL; + (*listener)->mLocalhost = NULL; + (*listener)->mOutputFileName = NULL; + (*listener)->mMode = kTest_Normal; + (*listener)->mThreadMode = kMode_Listener; + if (client->mHost != NULL) { + (*listener)->mHost = new char[strlen(client->mHost) + 1]; + strcpy((*listener)->mHost, client->mHost); + } + if (client->mLocalhost != NULL) { + (*listener)->mLocalhost = new char[strlen(client->mLocalhost) + 1]; + strcpy((*listener)->mLocalhost, client->mLocalhost); + } + if (client->mBufLen <= 0) { + if (isUDP((*listener))) { + (*listener)->mBufLen = kDefault_UDPBufLen; + } else { + (*listener)->mBufLen = kDefault_TCPBufLen; + } + } else { + (*listener)->mBufLen = client->mBufLen; + } + setReport((*listener)); + } else { + *listener = NULL; + } +} + +void Settings_ReadClientSettingsIsoch (struct thread_Settings **client, struct client_hdrext_isoch_settings *hdr) { + (*client)->mFPS = ntohl(hdr->FPSl); + (*client)->mFPS += ntohl(hdr->FPSu) / static_cast<double>(rMillion); + (*client)->mMean = ntohl(hdr->Meanl); + (*client)->mMean += ntohl(hdr->Meanu) / static_cast<double>(rMillion); + (*client)->mVariance = ntohl(hdr->Variancel); + (*client)->mVariance += ntohl(hdr->Varianceu) / static_cast<double>(rMillion); + (*client)->mBurstIPG = ntohl(hdr->BurstIPGl); + (*client)->mBurstIPG += ntohl(hdr->BurstIPGu) / static_cast<double>(rMillion); +} + +void Settings_ReadClientSettingsBurst (struct thread_Settings **client, struct client_hdrext_isoch_settings *hdr) { + (*client)->mFPS = ntohl(hdr->FPSl); + (*client)->mFPS += ntohl(hdr->FPSu) / static_cast<double>(rMillion); +} + +void Settings_ReadClientSettingsV1 (struct thread_Settings **client, struct client_hdr_v1 *hdr) { + (*client)->mTID = thread_zeroid(); + (*client)->mPort = static_cast<unsigned short>(ntohl(hdr->mPort)); + (*client)->mThreads = 1; + struct thread_Settings *tmpSettings = *client; + if (hdr->mBufLen != 0) { + (*client)->mBufLen = ntohl(hdr->mBufLen); + setBuflenSet(tmpSettings); + } else { +#ifdef DEFAULT_PAYLOAD_LEN_PER_MTU_DISCOVERY + checksock_max_udp_payload(tmpSettings); +#endif + } + (*client)->mAmount = ntohl(hdr->mAmount); + if (((*client)->mAmount & 0x80000000) > 0) { + setModeTime((*client)); +#ifndef WIN32 + (*client)->mAmount |= 0xFFFFFFFF00000000LL; +#else + (*client)->mAmount |= 0xFFFFFFFF00000000; +#endif + (*client)->mAmount = -(*client)->mAmount; + } else { + unsetModeTime((*client)); + } +} + +/* + * Settings_GenerateClientSettings + * + * Called by the Listener to generate the settings to be used by clients + * per things like dual tests. Set client pointer to null if a client isn't needed + * + * Note: mBuf should already be filled out per the Listener's apply_client_settings + */ +void Settings_GenerateClientSettings (struct thread_Settings *server, struct thread_Settings **client, void *mBuf) { + assert(server != NULL); + assert(mBuf != NULL); + uint32_t flags = isUDP(server) ? ntohl(*(uint32_t *)((char *)mBuf + sizeof(struct UDP_datagram))) : ntohl(*(uint32_t *)mBuf); + uint16_t upperflags = 0; + thread_Settings *reversed_thread = NULL; + *client = NULL; + bool v1test = (flags & HEADER_VERSION1) && !(flags & HEADER_VERSION2); +#ifdef HAVE_THREAD_DEBUG + if (v1test) + thread_debug("header set for a version 1 test"); +#endif + if (isFullDuplex(server) || isServerReverse(server)) + setTransferID(server, 1); + if (isFullDuplex(server) || v1test) { + Settings_Copy(server, client, SHALLOW_COPY); + reversed_thread = *client; + if (isFullDuplex(server) && !(flags & HEADER_VERSION1)) { + setFullDuplex(reversed_thread); + } else { + unsetFullDuplex(reversed_thread); + } + } else if (isServerReverse(server)) { + reversed_thread = server; + } else { + assert(0); + return; + } + reversed_thread->mThreadMode = kMode_Client; + + if (isUDP(server)) { // UDP test information passed in every packet per being stateless + struct client_udp_testhdr *hdr = static_cast<struct client_udp_testhdr *>(mBuf); + Settings_ReadClientSettingsV1(&reversed_thread, &hdr->base); + if (isFullDuplex(server) || v1test) { + server->mAmount = reversed_thread->mAmount + (SLOPSECS * 100); + } + if (v1test) { + setServerReverse(reversed_thread); + if (flags & RUN_NOW) { + reversed_thread->mMode = kTest_DualTest; + } else { + reversed_thread->mMode = kTest_TradeOff; + } + } + if (flags & HEADER_EXTEND) { + reversed_thread->mAppRate = ntohl(hdr->extend.lRate); +#ifdef HAVE_INT64_T + reversed_thread->mAppRate |= (static_cast<uint64_t>(ntohl(hdr->extend.uRate) >> 8) << 32); +#endif + upperflags = ntohs(hdr->extend.upperflags); + if (upperflags & HEADER_NOUDPFIN) { + setNoUDPfin(reversed_thread); + } + if ((upperflags & HEADER_UNITS_PPS) == HEADER_UNITS_PPS) { + reversed_thread->mAppRateUnits = kRate_PPS; + } else { + reversed_thread->mAppRateUnits = kRate_BW; + } + reversed_thread->mTOS = ntohs(hdr->extend.tos); + if (isIsochronous(server)) { + Settings_ReadClientSettingsIsoch(&reversed_thread, &hdr->isoch_settings); + } + if (upperflags & HEADER_FQRATESET) { + setFQPacing(reversed_thread); + reversed_thread->mFQPacingRate = ntohl(hdr->start_fq.fqratel); +#ifdef HAVE_INT64_T + reversed_thread->mFQPacingRate |= (static_cast<uint64_t>(ntohl(hdr->start_fq.fqrateu)) << 32); +#endif + } + } + } else { //tcp first payload + struct client_tcp_testhdr *hdr = static_cast<struct client_tcp_testhdr *>(mBuf); + Settings_ReadClientSettingsV1(&reversed_thread, &hdr->base); + + if (isFullDuplex(server) || v1test) { + server->mAmount = reversed_thread->mAmount + (SLOPSECS * 100); + } + if (v1test) { + setServerReverse(reversed_thread); + if (flags & RUN_NOW) { + reversed_thread->mMode = kTest_DualTest; + } else { + reversed_thread->mMode = kTest_TradeOff; + } + } + if (flags & HEADER_EXTEND) { + reversed_thread->mAppRate = ntohl(hdr->extend.lRate); +#ifdef HAVE_INT64_T + reversed_thread->mAppRate |= (static_cast<uint64_t>(ntohl(hdr->extend.uRate) >> 8) << 32); +#endif + upperflags = ntohs(hdr->extend.upperflags); + reversed_thread->mTOS = ntohs(hdr->extend.tos); + + if (isIsochronous(server)) { + Settings_ReadClientSettingsIsoch(&reversed_thread, &hdr->isoch_settings); + } else if (isPeriodicBurst(server)) { + Settings_ReadClientSettingsBurst(&reversed_thread, &hdr->isoch_settings); + } + if (upperflags & HEADER_FQRATESET) { + setFQPacing(reversed_thread); + reversed_thread->mFQPacingRate = ntohl(hdr->start_fq.fqratel); +#ifdef HAVE_INT64_T + reversed_thread->mFQPacingRate |= (static_cast<uint64_t>(ntohl(hdr->start_fq.fqrateu)) << 32); +#endif + } + } + } + unsetTxHoldback(reversed_thread); + setNoSettReport(reversed_thread); + setNoConnectSync(reversed_thread); + // for legacy -d and -r need so set the reversed threads mHost + if (v1test) { + reversed_thread->mHost = new char[REPORT_ADDRLEN]; + if ((reinterpret_cast<sockaddr*>(&server->peer))->sa_family == AF_INET) { + inet_ntop(AF_INET, &(reinterpret_cast<sockaddr_in*>(&server->peer))->sin_addr, + reversed_thread->mHost, REPORT_ADDRLEN); + } +#if HAVE_IPV6 + else { + inet_ntop(AF_INET6, &(reinterpret_cast<sockaddr_in6*>(&server->peer))->sin6_addr, + reversed_thread->mHost, REPORT_ADDRLEN); + } +#endif + } else { + reversed_thread->mMode = kTest_Normal; +#if HAVE_DECL_SO_MAX_PACING_RATE + if (isFQPacing(reversed_thread)) { + int rc = setsockopt(reversed_thread->mSock, SOL_SOCKET, SO_MAX_PACING_RATE, \ + &reversed_thread->mFQPacingRate, sizeof(reversed_thread->mFQPacingRate)); + WARN_errno(rc == SOCKET_ERROR, "setsockopt SO_MAX_PACING_RATE"); + #ifdef HAVE_THREAD_DEBUG + #ifdef HAVE_INT64_T + thread_debug("Set socket %d pacing rate to %ld byte/sec", reversed_thread->mSock, reversed_thread->mFQPacingRate); + #else + thread_debug("Set socket %d pacing rate to %d byte/sec", reversed_thread->mSock, reversed_thread->mFQPacingRate); + #endif + #endif + } +#endif // MAX_PACING_RATE + } +} + +int Settings_GenerateClientHdrV1 (struct thread_Settings *client, struct client_hdr_v1 *hdr) { + if (isBuflenSet(client)) { + hdr->mBufLen = htonl(client->mBufLen); + } else { + hdr->mBufLen = 0; + } + if (client->mListenPort != 0) { + hdr->mPort = htonl(client->mListenPort); + } else { + hdr->mPort = htonl(client->mPort); + } + hdr->numThreads = htonl(client->mThreads); + if (isModeTime(client)) { + hdr->mAmount = htonl(-(long)client->mAmount); + } else { + hdr->mAmount = htonl((long)client->mAmount); + hdr->mAmount &= htonl(0x7FFFFFFF); + } + return (sizeof(struct client_hdr_v1)); +} + +/* + * Settings_GenerateClientHdr + * + * Called to generate the client header to be passed to the listener/server + * + * This will handle: + * o) dual testings from the listener/server side + * o) advanced udp test settings + * + * Returns size of header in bytes + */ +int Settings_GenerateClientHdr (struct thread_Settings *client, void *testhdr, struct timeval startTime) { + uint16_t len = 0; + uint16_t upperflags = 0; + uint16_t lowerflags = 0; + uint32_t flags = 0; + + // Check the corner case of small packets and trip times + if (isUDP(client) && isSmallTripTime(client)) { + int buflen = (client->mBufLen < (int) sizeof(struct client_udpsmall_testhdr)) ? client->mBufLen \ + : sizeof(struct client_udpsmall_testhdr); + struct client_udpsmall_testhdr *hdr = static_cast<struct client_udpsmall_testhdr *>(testhdr); + memset(hdr, 0, buflen); + hdr->flags = htons(HEADER16_SMALL_TRIPTIMES); +#ifdef HAVE_THREAD_DEBUG + thread_debug("UDP small trip times flags = %X", ntohs(hdr->flags)); +#endif + return (MINIPERFPAYLOAD); + } + // flags common to both TCP and UDP + if (isReverse(client) && !isCompat(client)) { + upperflags |= HEADER_REVERSE; + if (isTxStartTime(client) && !TimeZero(startTime)) { + upperflags |= HEADER_EPOCH_START; + } + } + if (isFullDuplex(client) && !isCompat(client)) { + upperflags |= HEADER_FULLDUPLEX; + if (isTxStartTime(client) && !TimeZero(startTime)) { + upperflags |= HEADER_EPOCH_START; + } + } + if (isTxStartTime(client) && isTripTime(client) && !TimeZero(startTime)) { + upperflags |= HEADER_EPOCH_START; + } + + // Now setup UDP and TCP specific passed settings from client to server + if (isUDP(client)) { // UDP test information passed in every packet per being stateless + struct client_udp_testhdr *hdr = static_cast<struct client_udp_testhdr *>(testhdr); + int buflen = (client->mBufLen < (int) sizeof(struct client_udp_testhdr)) ? client->mBufLen \ + : sizeof(struct client_udp_testhdr); + memset(hdr, 0, buflen); + flags |= HEADER_SEQNO64B; // use 64 bit by default + flags |= HEADER_EXTEND; + hdr->extend.version_u = htonl(IPERF_VERSION_MAJORHEX); + hdr->extend.version_l = htonl(IPERF_VERSION_MINORHEX); + hdr->extend.tos = htons(client->mTOS & 0xFF); + if (isBWSet(client) && (client->mAppRate > 0)) { + uint64_t bw = 0; + if ((client->mAppRateUnits == kRate_PPS) && (isFullDuplex(client) || isReverse(client) || (client->mMode != kTest_Normal))) { + bw = client->mAppRate * 8 * client->mBufLen; + } else { + bw = client->mAppRate; + } + hdr->extend.lRate = htonl((uint32_t)(bw)); +#ifdef HAVE_INT64_T + hdr->extend.uRate = htonl(((uint32_t)(bw >> 32)) << 8); +#endif + } else { + hdr->extend.lRate = htonl(kDefault_UDPRate); + hdr->extend.uRate = 0x0; + } + len += sizeof(struct client_hdrext); + len += Settings_GenerateClientHdrV1(client, &hdr->base); + if (!isCompat(client) && (client->mMode != kTest_Normal)) { + flags |= HEADER_VERSION1; + if (client->mMode == kTest_DualTest) + flags |= RUN_NOW; + hdr->base.flags = htonl(flags); + } + /* + * set the default offset where underlying "inline" subsystems can write into the udp payload + */ + if (isL2LengthCheck(client)) { + flags |= HEADER_UDPTESTS; + if (isL2LengthCheck(client)) { + upperflags |= HEADER_L2LENCHECK; + if (isIPV6(client)) + upperflags |= HEADER_L2ETHPIPV6; + } + } + if (isIsochronous(client)) { + flags |= (HEADER_UDPTESTS | HEADER_EXTEND) ; + upperflags |= HEADER_ISOCH; + if (isFullDuplex(client) || isReverse(client)) { + upperflags |= HEADER_ISOCH_SETTINGS; + hdr->isoch_settings.FPSl = htonl((long)(client->mFPS)); + hdr->isoch_settings.FPSu = htonl((long)((client->mFPS - (long)(client->mFPS)) * rMillion)); + hdr->isoch_settings.Meanl = htonl((long)(client->mMean)); + hdr->isoch_settings.Meanu = htonl((long)(((client->mMean) - (long)(client->mMean)) * rMillion)); + hdr->isoch_settings.Variancel = htonl((long)(client->mVariance)); + hdr->isoch_settings.Varianceu = htonl((long)((client->mVariance - (long)(client->mVariance)) * rMillion)); + hdr->isoch_settings.BurstIPGl = htonl((long)(client->mBurstIPG)); + hdr->isoch_settings.BurstIPGu = htonl((long)((client->mBurstIPG - (long)(client->mBurstIPG)) * rMillion)); + len += sizeof(struct client_hdrext_isoch_settings); + } + } + if (isReverse(client) || isFullDuplex(client)) { + flags |= (HEADER_UDPTESTS | HEADER_VERSION2); + } + if (isNoUDPfin(client)) { + flags |= (HEADER_UDPTESTS | HEADER_EXTEND); + upperflags |= HEADER_NOUDPFIN; + } + if (isTripTime(client) || isFQPacing(client) || isTxStartTime(client)) { + flags |= HEADER_UDPTESTS; + if (isTripTime(client) || isTxStartTime(client)) { + hdr->start_fq.start_tv_sec = htonl(startTime.tv_sec); + hdr->start_fq.start_tv_usec = htonl(startTime.tv_usec); + if (isTripTime(client)) + upperflags |= HEADER_TRIPTIME; + } + if (isFQPacing(client)) { + upperflags |= HEADER_FQRATESET; + hdr->start_fq.fqratel = htonl((uint32_t) client->mFQPacingRate); +#ifdef HAVE_INT64_T + hdr->start_fq.fqrateu = htonl((uint32_t) (client->mFQPacingRate >> 32)); +#endif + } + } + // Write flags to header so the listener can determine the tests requested + hdr->extend.upperflags = htons(upperflags); + hdr->extend.lowerflags = htons(lowerflags); + + // isoch payload is an enclave field between v 0.13 and v0.14 + // so figure out if it's there now - UDP only + // will be filled in by the client write + if (isTripTime(client) || isFQPacing(client) || isIsochronous(client)) + len += sizeof (struct isoch_payload); + + if (len > 0) { + len += sizeof(struct UDP_datagram); + flags |= ((len << 1) & HEADER_KEYLEN_MASK) | HEADER_LEN_BIT; + } + hdr->base.flags = htonl(flags); +#ifdef HAVE_THREAD_DEBUG + thread_debug("UDPflags = %X", ntohl(hdr->base.flags)); +#endif + } else { // TCP first write with test information + struct client_tcp_testhdr *hdr = static_cast<struct client_tcp_testhdr *>(testhdr); +#ifdef HAVE_THREAD_DEBUG + thread_debug("Client header init size %d (%p)", sizeof(struct client_tcp_testhdr), (void *) hdr); +#endif + if (isBounceBack(client)) { + flags = HEADER_BOUNCEBACK; + len = sizeof(struct bounceback_hdr); + } else { + int buflen = (client->mBufLen < (int) sizeof(struct client_tcp_testhdr)) ? client->mBufLen \ + : sizeof(struct client_tcp_testhdr); + memset(hdr, 0, buflen); + flags |= HEADER_EXTEND; + hdr->extend.version_u = htonl(IPERF_VERSION_MAJORHEX); + hdr->extend.version_l = htonl(IPERF_VERSION_MINORHEX); + hdr->extend.tos = htons(client->mTOS & 0xFF); + if (isBWSet(client)) { + hdr->extend.lRate = htonl((uint32_t)(client->mAppRate)); +#ifdef HAVE_INT64_T + hdr->extend.uRate = htonl(((uint32_t)(client->mAppRate >> 32)) << 8); +#endif + } + len += sizeof(struct client_hdrext); + len += Settings_GenerateClientHdrV1(client, &hdr->base); + if (!isCompat(client) && (client->mMode != kTest_Normal)) { + flags |= HEADER_VERSION1; + if (client->mMode == kTest_DualTest) + flags |= RUN_NOW; + } + if (isPeerVerDetect(client)) { + flags |= (HEADER_V2PEERDETECT | HEADER_VERSION2); + } + if (isTripTime(client) || isFQPacing(client) || isIsochronous(client) || isTxStartTime(client)) { + hdr->start_fq.start_tv_sec = htonl(startTime.tv_sec); + hdr->start_fq.start_tv_usec = htonl(startTime.tv_usec); + hdr->start_fq.fqratel = htonl((uint32_t) client->mFQPacingRate); +#ifdef HAVE_INT64_T + hdr->start_fq.fqrateu = htonl((uint32_t) (client->mFQPacingRate >> 32)); +#endif + len += sizeof(struct client_hdrext_starttime_fq); + // Set flags on + if (isTripTime(client)) { + upperflags |= HEADER_TRIPTIME; + } + if (isFQPacing(client)) { + upperflags |= HEADER_FQRATESET; + } + } +#if HAVE_DECL_TCP_NOTSENT_LOWAT + if (isWritePrefetch(client) && (isReverse(client) || isFullDuplex(client))) { + upperflags |= HEADER_WRITEPREFETCH; + hdr->extend.TCPWritePrefetch = htonl((long)client->mWritePrefetch); + } +#endif +#if HAVE_DECL_TCP_QUICKACK + if (isTcpQuickAck(client) && (!isReverse(client) || isFullDuplex(client))) { + upperflags |= HEADER_TCPQUICKACK; + } +#endif + if (isIsochronous(client) || isPeriodicBurst(client)) { + if (isPeriodicBurst(client)) { + upperflags |= HEADER_PERIODICBURST; // overload the isoch settings + } else { + upperflags |= HEADER_ISOCH; + } + if (isFullDuplex(client) || isReverse(client) || isPeriodicBurst(client)) { + hdr->isoch_settings.FPSl = htonl((long)client->mFPS); + hdr->isoch_settings.FPSu = htonl((long)((client->mFPS - (long)(client->mFPS)) * rMillion)); + hdr->isoch_settings.Variancel = htonl((long)(client->mVariance)); + hdr->isoch_settings.Varianceu = htonl((long)((client->mVariance - (long)(client->mVariance)) * rMillion)); + if (!isPeriodicBurst(client)) { + hdr->isoch_settings.Meanl = htonl((long)(client->mMean)); + hdr->isoch_settings.Meanu = htonl((long)(((client->mMean) - (long)(client->mMean)) * rMillion)); + hdr->isoch_settings.BurstIPGl = htonl((long)client->mBurstIPG); + hdr->isoch_settings.BurstIPGu = htonl(((long)(client->mBurstIPG) - (long)client->mBurstIPG * rMillion)); + } else { + hdr->isoch_settings.Meanl = htonl((long)(client->mBurstSize)); + } + len += sizeof(struct client_hdrext_isoch_settings); + } + } + if (isReverse(client) || isFullDuplex(client)) { + flags |= HEADER_VERSION2; + } + hdr->extend.upperflags = htons(upperflags); + hdr->extend.lowerflags = htons(lowerflags); + if (len > 0) { + flags |= HEADER_LEN_BIT; + int keylen = 0; + if (!isServerReverse(client) && isPermitKey(client) && (client->mPermitKey[0] != '\0')) { + keylen = static_cast<int>(strnlen(client->mPermitKey, MAX_PERMITKEY_LEN)); + flags |= HEADER_KEYCHECK; + struct permitKey *thiskey = reinterpret_cast<struct permitKey *>(static_cast<char *>(testhdr) + len); + thiskey->length = htons((uint16_t)keylen); + memcpy(thiskey->value, client->mPermitKey, keylen); + len += sizeof(thiskey->length); + } + flags |= ((len << 1) & HEADER_KEYLEN_MASK); // this is the key value offset passed to the server + len += keylen; + } + } + hdr->base.flags = htonl(flags); + } + return (len); +} + +int Settings_ClientTestHdrLen (uint32_t flags, struct thread_Settings *inSettings) { + int peeklen = 0; + if ((flags & HEADER_VERSION1) || (flags & HEADER_VERSION2) || (flags & HEADER_EXTEND) || isPermitKey(inSettings)) { + if (flags & HEADER_LEN_BIT) { + peeklen = static_cast<int>((flags & HEADER_LEN_MASK) >> 1); + if (peeklen > MAX_HEADER_LEN) { + fprintf(stderr, "WARN: header of %d length too large\n", peeklen); + peeklen = -1; + } + } else { + if (flags & (HEADER_VERSION1 | HEADER_EXTEND)) { + peeklen = sizeof(struct client_hdr_v1); + } + if (flags & (HEADER_VERSION2 | HEADER_EXTEND)) { + peeklen += sizeof(struct client_hdrext); + } + } + } + return peeklen; +} diff --git a/src/SocketAddr.c b/src/SocketAddr.c new file mode 100644 index 0000000..4322475 --- /dev/null +++ b/src/SocketAddr.c @@ -0,0 +1,941 @@ +/*--------------------------------------------------------------- + * Copyright (c) 1999,2000,2001,2002,2003 + * The Board of Trustees of the University of Illinois + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software (Iperf) and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the names of the University of Illinois, NCSA, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * National Laboratory for Applied Network Research + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * http://www.ncsa.uiuc.edu + * ________________________________________________________________ + * + * Socket.cpp + * by Ajay Tirumala <tirumala@ncsa.uiuc.edu> + * and Mark Gates <mgates@nlanr.net> + * ------------------------------------------------------------------- */ + +#define HEADERS() + +#include "headers.h" + +#include "SocketAddr.h" +#ifdef HAVE_IFADDRS_H +#include <ifaddrs.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* ------------------------------------------------------------------- + * Create a socket address. If inHostname is not null, resolve that + * address and fill it in. Fill in the port number. Use IPv6 ADDR_ANY + * if that is what is desired. + * ------------------------------------------------------------------- */ +void SockAddr_remoteAddr (struct thread_Settings *inSettings) { + if (SockAddr_isZeroAddress(&inSettings->peer) == 0) { + if (inSettings->mHost != NULL) { + SockAddr_setHostname(inSettings->mHost, &inSettings->peer, isIPV6(inSettings)); + if (inSettings->incrdstip) + SockAddr_incrAddress(&inSettings->peer, inSettings->incrdstip); + } else { +#if HAVE_IPV6 + if (isIPV6(inSettings)) { + ((struct sockaddr*)&inSettings->peer)->sa_family = AF_INET6; + } else { + ((struct sockaddr*)&inSettings->peer)->sa_family = AF_INET; + } + } + if (SockAddr_isIPv6(&inSettings->peer)) { + inSettings->size_peer = sizeof(struct sockaddr_in6); + } else { + inSettings->size_peer = sizeof(struct sockaddr_in); + } +#else + } + ((struct sockaddr*)&inSettings->peer)->sa_family = AF_INET; + inSettings->size_peer = sizeof(struct sockaddr_in); +#endif + SockAddr_setPort(&inSettings->peer, inSettings->mPort); + } +} +// end SocketAddr + +void SockAddr_localAddr (struct thread_Settings *inSettings) { + SockAddr_zeroAddress(&inSettings->local); + + if (inSettings->mLocalhost != NULL) { + SockAddr_setHostname(inSettings->mLocalhost, &inSettings->local, + isIPV6(inSettings)); + if (inSettings->incrsrcip) + SockAddr_incrAddress(&inSettings->local, inSettings->incrsrcip); + + } else { +#if HAVE_IPV6 + if (isIPV6(inSettings)) { + ((struct sockaddr*)&inSettings->local)->sa_family = AF_INET6; + } else { + ((struct sockaddr*)&inSettings->local)->sa_family = AF_INET; + } + } + + if (SockAddr_isIPv6(&inSettings->local)) { + inSettings->size_local = sizeof(struct sockaddr_in6); + } else { + inSettings->size_local = sizeof(struct sockaddr_in); + } +#else + ((struct sockaddr*)&inSettings->local)->sa_family = AF_INET; + } + inSettings->size_local = sizeof(struct sockaddr_in); +#endif + /* + * This section handles the *local* port binding (which is messy) + * Quintuple is Proto:LocalIP:LocalPort:DstIP:DstPort + * + * There are three threads being Client, Listener and Server + * mPort comes from the -p command (which defaults to 5001) + * mLocalhost indicates -B set requesting a local binding + * mBindPort comes from -B IP:<port> (where port defaults to 0) + * Multicast IP address, e.g. 239.1.1.1, is set per a -B + * Zero will cause the OS to auto assign a LocalPort + * For iperf -s; Windows uses listener thread, *nix a server thread + * (so, effectively, Listener and Server threads are the same) + * Client threads support either auto assignment (default) or + * user specified (via -B) + */ + if (inSettings->mLocalhost == NULL) { + if (inSettings->mThreadMode == kMode_Client) { + /* + * Client thread, -p and no -B, + * OS will auto assign a free local port + */ + SockAddr_setPortAny (&inSettings->local); + } else { + /* Server or Listener thread, -p and no -B */ + SockAddr_setPort(&inSettings->local, inSettings->mPort); + } + } else { + // -B was set + if (inSettings->mThreadMode == kMode_Client) { + /* Client thread */ + if (inSettings->mBindPort) { + /* + * User specified port so use it + */ +#if HAVE_DECL_SO_REUSEPORT + int boolean = 1; + Socklen_t len = sizeof(boolean); + setsockopt(inSettings->mSock, SOL_SOCKET, SO_REUSEPORT, (char*) &boolean, len); +#endif + SockAddr_setPort(&inSettings->local, (inSettings->mBindPort + inSettings->incrsrcport)); + } else { + /* + * No user specified port, let OS assign a free one + */ + SockAddr_setPortAny (&inSettings->local); + } + } else { + /* + * Server or Listener thread, both always use -p port + * any -B port will be ignored + */ + SockAddr_setPort(&inSettings->local, inSettings->mPort); + } + } +} +// end SocketAddr + +/* ------------------------------------------------------------------- + * Resolve the hostname address and fill it in. + * ------------------------------------------------------------------- */ +void SockAddr_setHostname (const char* inHostname, iperf_sockaddr *inSockAddr, int isIPv6) { + // ..I think this works for both ipv6 & ipv4... we'll see + bool found = false; + int ret_ga; + struct addrinfo *res = NULL, *itr; + struct addrinfo hints; + memset(&hints, 0, sizeof(hints)); + if (!isIPv6) { + hints.ai_family = AF_INET; + ret_ga = getaddrinfo(inHostname, NULL, &hints, &res); + if (ret_ga == 0) { + if (res && res->ai_addr) { + itr = res; + // Now search for a IPv4 Address + while (itr != NULL) { + if (itr->ai_family == AF_INET) { + memcpy(inSockAddr, (itr->ai_addr), (itr->ai_addrlen)); + freeaddrinfo(res); + found = true; + break; + } else { + itr = itr->ai_next; + } + } + } + } + } +#if HAVE_IPV6 + if (!found) { + hints.ai_family = AF_INET6; + ret_ga = getaddrinfo(inHostname, NULL, &hints, &res); + if (ret_ga == 0) { + if (res && res->ai_addr) { + // Now search for a IPv6 Address + itr = res; + while (itr != NULL) { + if (itr->ai_family == AF_INET6) { + memcpy(inSockAddr, (itr->ai_addr), (itr->ai_addrlen)); + freeaddrinfo(res); + found = true; + break; + } else { + itr = itr->ai_next; + } + } + } + } + } +#endif // IPV6 + // getaddrinfo didn't find an address, fallback to gethostbyname for v4 + if (!found && !isIPv6) { + // first try just converting dotted decimal + // on Windows gethostbyname doesn't understand dotted decimal + struct sockaddr_in *sockaddr = (struct sockaddr_in *)inSockAddr; + int rc = inet_pton(AF_INET, inHostname, &sockaddr->sin_addr); + sockaddr->sin_family = AF_INET; + if (rc == 0) { + struct hostent *hostP = gethostbyname(inHostname); + if (hostP == NULL) { + /* this is the same as herror() but works on more systems */ + const char* format; + switch (h_errno) { + case HOST_NOT_FOUND: + format = "%s: Unknown host\n"; + break; + case NO_ADDRESS: + format = "%s: No address associated with name\n"; + break; + case NO_RECOVERY: + format = "%s: Unknown server error\n"; + break; + case TRY_AGAIN: + format = "%s: Host name lookup failure\n"; + break; + default: + format = "%s: Unknown resolver error\n"; + break; + } + fprintf(stderr, format, inHostname); + exit(1); + return; // TODO throw + } + found = true; + memcpy(&sockaddr->sin_addr, *(hostP->h_addr_list), (hostP->h_length)); + } + } + if (!found) { + fprintf(stderr, "ERROR: failed to find an ip address for host '%s'\n", inHostname); + exit(1); + } +} +// end setHostname + +/* ------------------------------------------------------------------- + * Copy the IP address into the string. + * ------------------------------------------------------------------- */ +void SockAddr_getHostAddress (iperf_sockaddr *inSockAddr, char* outAddress, + size_t len) { + if (((struct sockaddr*)inSockAddr)->sa_family == AF_INET) { + inet_ntop(AF_INET, &(((struct sockaddr_in*) inSockAddr)->sin_addr), + outAddress, len); + } +#if HAVE_IPV6 + else { + inet_ntop(AF_INET6, &(((struct sockaddr_in6*) inSockAddr)->sin6_addr), + outAddress, len); + } +#endif +} +// end getHostAddress + +/* ------------------------------------------------------------------- + * Set the address to any (generally all zeros). + * ------------------------------------------------------------------- */ +void SockAddr_setAddressAny (iperf_sockaddr *inSockAddr) { + if (((struct sockaddr*)inSockAddr)->sa_family == AF_INET) + memset(&(((struct sockaddr_in*) inSockAddr)->sin_addr), 0, + sizeof(struct in_addr)); +#if HAVE_IPV6 + else + memset(&(((struct sockaddr_in6*) inSockAddr)->sin6_addr), 0, + sizeof(struct in6_addr)); +#endif +} +// end setAddressAny + +/* ------------------------------------------------------------------- + * Incr the address by value + * ------------------------------------------------------------------- */ +void SockAddr_incrAddress (iperf_sockaddr *inSockAddr, int value) { + if (((struct sockaddr*)inSockAddr)->sa_family == AF_INET) + ((struct sockaddr_in *)inSockAddr)->sin_addr.s_addr += htonl(value); +#if HAVE_IPV6 + else { + uint32_t *lower = (uint32_t *)&((struct sockaddr_in6 *)inSockAddr)->sin6_addr.s6_addr[12]; + *lower += htonl(value); + } +#endif +} +// end setAddressAny + + +/* ------------------------------------------------------------------- + * Set the port to the given port. Handles the byte swapping. + * ------------------------------------------------------------------- */ +void SockAddr_setPort (iperf_sockaddr *inSockAddr, unsigned short inPort) { + if (((struct sockaddr*)inSockAddr)->sa_family == AF_INET) + ((struct sockaddr_in*) inSockAddr)->sin_port = htons(inPort); +#if HAVE_IPV6 + else + ((struct sockaddr_in6*) inSockAddr)->sin6_port = htons(inPort); +#endif + +} +// end setPort + +/* ------------------------------------------------------------------- + * Set the port to zero, which lets the OS pick the port. + * ------------------------------------------------------------------- */ +void SockAddr_setPortAny (iperf_sockaddr *inSockAddr) { + SockAddr_setPort(inSockAddr, 0); +} +// end setPortAny + +/* ------------------------------------------------------------------- + * Return the port. Handles the byte swapping. + * ------------------------------------------------------------------- */ +unsigned short SockAddr_getPort (iperf_sockaddr *inSockAddr) { + if (((struct sockaddr*)inSockAddr)->sa_family == AF_INET) + return ntohs(((struct sockaddr_in*) inSockAddr)->sin_port); +#if HAVE_IPV6 + else + return ntohs(((struct sockaddr_in6*) inSockAddr)->sin6_port); +#endif + return 0; + +} +// end getPort + +/* ------------------------------------------------------------------- + * Return the IPv4 Internet Address from the sockaddr_in structure + * ------------------------------------------------------------------- */ +struct in_addr* SockAddr_get_in_addr (iperf_sockaddr *inSockAddr) { + if (((struct sockaddr*)inSockAddr)->sa_family == AF_INET) + return &(((struct sockaddr_in*) inSockAddr)->sin_addr); + + fprintf(stderr, "FATAL: get_in_addr called on IPv6 address\n"); + return NULL; +} + +/* ------------------------------------------------------------------- + * Return the IPv6 Internet Address from the sockaddr_in6 structure + * ------------------------------------------------------------------- */ +#if HAVE_IPV6 +struct in6_addr* SockAddr_get_in6_addr (iperf_sockaddr *inSockAddr) { + if (((struct sockaddr*)inSockAddr)->sa_family == AF_INET6) + return &(((struct sockaddr_in6*) inSockAddr)->sin6_addr); + + fprintf(stderr, "FATAL: get_in6_addr called on IPv4 address\n"); + return NULL; +} +#endif + + +/* ------------------------------------------------------------------- + * Return the size of the appropriate address structure. + * ------------------------------------------------------------------- */ +Socklen_t SockAddr_get_sizeof_sockaddr (iperf_sockaddr *inSockAddr) { +#if HAVE_IPV6 + if (((struct sockaddr*)inSockAddr)->sa_family == AF_INET6) { + return(sizeof(struct sockaddr_in6)); + } +#endif + return(sizeof(struct sockaddr_in)); +} +// end get_sizeof_sockaddr + + +/* ------------------------------------------------------------------- + * Return if IPv6 socket + * ------------------------------------------------------------------- */ +int SockAddr_isIPv6 (iperf_sockaddr *inSockAddr) { +#if HAVE_IPV6 + if (((struct sockaddr*)inSockAddr)->sa_family == AF_INET6) { + return 1; + } +#endif + return 0; +} +// end get_sizeof_sockaddr + +/* ------------------------------------------------------------------- + * Return true if the address is multicast ip address. + * ------------------------------------------------------------------- */ +int SockAddr_isMulticast (iperf_sockaddr *inSockAddr) { +#if HAVE_IPV6 + if (((struct sockaddr*)inSockAddr)->sa_family == AF_INET6) { + return(IN6_IS_ADDR_MULTICAST(&(((struct sockaddr_in6*) inSockAddr)->sin6_addr))); + } else +#endif + { + +#ifdef IN_MULTICAST + // 224.0.0.0 to 239.255.255.255 (e0.00.00.00 to ef.ff.ff.ff) + // convert from network to host byte order + uint32_t maddr = ntohl((uint32_t)(((struct sockaddr_in*) inSockAddr)->sin_addr.s_addr)); + return (IN_MULTICAST(maddr)); +#else + const unsigned long kClassD_Mask = 0xf0000000L; + const unsigned long kMulticast = 0xe0000000L; + return((((ntohl(((struct sockaddr_in*) inSockAddr)->sin_addr.s_addr)) & kClassD_Mask) == kMulticast)); +#endif + } +} +// end isMulticast + +/* ------------------------------------------------------------------- + * Return true if the address is multicast ip address. + * ------------------------------------------------------------------- */ +int SockAddr_isLinklocal (iperf_sockaddr *inSockAddr) { +#if HAVE_IPV6 + if (((struct sockaddr*)inSockAddr)->sa_family == AF_INET6) { + return(IN6_IS_ADDR_LINKLOCAL(&(((struct sockaddr_in6*) inSockAddr)->sin6_addr))); + } else +#endif + { + return 0; + } +} + +/* ------------------------------------------------------------------- + * Zero out the address structure. + * ------------------------------------------------------------------- */ +void SockAddr_zeroAddress (iperf_sockaddr *inSockAddr) { + memset(inSockAddr, 0, sizeof(iperf_sockaddr)); +} + +int SockAddr_isZeroAddress (iperf_sockaddr *inSockAddr) { + iperf_sockaddr zeroSockAddr; + memset(&zeroSockAddr, 0, sizeof(iperf_sockaddr)); + return(memcmp((void *)inSockAddr, (void *)&zeroSockAddr, sizeof(iperf_sockaddr))); +} + +/* ------------------------------------------------------------------- + * Compare two sockaddrs and return true if they are equal + * ------------------------------------------------------------------- */ +int SockAddr_are_Equal (iperf_sockaddr *first, iperf_sockaddr *second) { + if (((struct sockaddr*)first)->sa_family == AF_INET && ((struct sockaddr*)second)->sa_family == AF_INET) { + // compare IPv4 adresses + return(((long) ((struct sockaddr_in*)first)->sin_addr.s_addr == (long) ((struct sockaddr_in*)second)->sin_addr.s_addr) + && (((struct sockaddr_in*)first)->sin_port == ((struct sockaddr_in*)second)->sin_port)); + } +#if HAVE_IPV6 + if (((struct sockaddr*)first)->sa_family == AF_INET6 && ((struct sockaddr*)second)->sa_family == AF_INET6) { + // compare IPv6 addresses + return(!memcmp(((struct sockaddr_in6*)first)->sin6_addr.s6_addr, ((struct sockaddr_in6*)second)->sin6_addr.s6_addr, sizeof(struct in6_addr)) + && (((struct sockaddr_in6*)first)->sin6_port == ((struct sockaddr_in6*)second)->sin6_port)); + } +#endif + return 0; +} + +/* ------------------------------------------------------------------- + * Compare two sockaddrs and return true if the hosts are equal + * ------------------------------------------------------------------- */ +int SockAddr_Hostare_Equal (iperf_sockaddr* first, iperf_sockaddr *second) { + if (((struct sockaddr*)first)->sa_family == AF_INET && ((struct sockaddr*)second)->sa_family == AF_INET) { + // compare IPv4 adresses + return((long) ((struct sockaddr_in*)first)->sin_addr.s_addr == + (long) ((struct sockaddr_in*)second)->sin_addr.s_addr); + } +#if HAVE_IPV6 + if (((struct sockaddr*)first)->sa_family == AF_INET6 && ((struct sockaddr*)second)->sa_family == AF_INET6) { + // compare IPv6 addresses + return(!memcmp(((struct sockaddr_in6*)first)->sin6_addr.s6_addr, + ((struct sockaddr_in6*)second)->sin6_addr.s6_addr, sizeof(struct in6_addr))); + } +#endif + return 0; +} + +/* ------------------------------------------------------------------- + * Find the interface name of a connected socket (when not already set) + * Can be forced with -B <ip>%<name> (server), -c <ip>%<name> (client) + * Note that kernel maps, e.g. via routing tables, to the actual device + * so these can change. Assume they won't change during the life + * of a thread. + * + * Store (and cache) the results in the thread settings structure + * Return 0 if set, -1 if not + * ------------------------------------------------------------------- */ +int SockAddr_Ifrname (struct thread_Settings *inSettings) { +#ifdef HAVE_IFADDRS_H + if (inSettings->mIfrname == NULL) { + struct sockaddr_storage myaddr; + struct ifaddrs* ifaddr; + struct ifaddrs* ifa; + socklen_t addr_len; + addr_len = sizeof(struct sockaddr_storage); + getsockname(inSettings->mSock, (struct sockaddr*)&myaddr, &addr_len); + getifaddrs(&ifaddr); + + // look which interface contains the desired IP per getsockname() which sets myaddr + // When found, ifa->ifa_name contains the name of the interface (eth0, eth1, ppp0...) + if (myaddr.ss_family == AF_INET) { + // v4 socket family (supports v4 only) + struct sockaddr_in* addr = (struct sockaddr_in*)&myaddr; + for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { + if ((ifa->ifa_addr) && (ifa->ifa_addr->sa_family == AF_INET)) { + struct sockaddr_in* inaddr = (struct sockaddr_in*)ifa->ifa_addr; + if ((inaddr->sin_addr.s_addr == addr->sin_addr.s_addr) && (ifa->ifa_name)) { + // Found v4 address in v4 addr family, copy it to thread settings structure + inSettings->mIfrname = calloc (strlen(ifa->ifa_name) + 1, sizeof(char)); + strcpy(inSettings->mIfrname, ifa->ifa_name); + break; + } + } + } + } else if (myaddr.ss_family == AF_INET6) { + // v6 socket family (supports both v4 and v6) + struct sockaddr_in6* addr = (struct sockaddr_in6*)&myaddr; + // Link local address are shared amongst all devices + // Try to pull the interface from the destination + if ((inSettings->mThreadMode == kMode_Client) && (IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr))) { + char *results; + char *copy = (char *)malloc(strlen(inSettings->mHost)+1); + strcpy(copy,(const char *)inSettings->mHost); + if (((results = strtok(copy, "%")) != NULL) && ((results = strtok(NULL, "%")) != NULL)) { + inSettings->mIfrname = calloc (strlen(results) + 1, sizeof(char)); + strcpy(inSettings->mIfrname, results); + } + free(copy); + } else if ((inSettings->mThreadMode == kMode_Server) && (IN6_IS_ADDR_V4MAPPED (&addr->sin6_addr))) { + for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { + if ((ifa->ifa_addr) && (ifa->ifa_addr->sa_family == AF_INET)) { + struct sockaddr_in* inaddr = (struct sockaddr_in*)ifa->ifa_addr; + uint32_t v4; + memcpy(&v4, &addr->sin6_addr.s6_addr[12], 4); + if ((ifa->ifa_name) && (inaddr->sin_addr.s_addr == v4)) { + // Found v4 address in v4 addr family, copy it to thread settings structure + inSettings->mIfrname = calloc (strlen(ifa->ifa_name) + 1, sizeof(char)); + strcpy(inSettings->mIfrname, ifa->ifa_name); + break; + } + } + } + } else { + // Hunt the v6 interfaces + for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { + if ((ifa->ifa_addr) && (ifa->ifa_addr->sa_family == AF_INET6)) { + struct sockaddr_in6* inaddr = (struct sockaddr_in6*)ifa->ifa_addr; + if ((ifa->ifa_name) && (IN6_ARE_ADDR_EQUAL(&addr->sin6_addr, &inaddr->sin6_addr))) { + // Found v6 address in v6 addr family, copy it to thread settings structure + inSettings->mIfrname = calloc (strlen(ifa->ifa_name) + 1, sizeof(char)); + strcpy(inSettings->mIfrname, ifa->ifa_name); + break; + } + } + } + } + } + freeifaddrs(ifaddr); + } +#endif + return ((inSettings->mIfrname == NULL) ? -1 : 0); +} + + +#if defined(HAVE_LINUX_FILTER_H) && defined(HAVE_AF_PACKET) +int SockAddr_Drop_All_BPF (int sock) { + struct sock_filter udp_filter[] = { + { 0x6, 0, 0, 0x00000000 }, + }; + struct sock_fprog bpf = { + .len = (sizeof(udp_filter) / sizeof(struct sock_filter)), + .filter = udp_filter, + }; + return(setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof(bpf))); +} + +// +// [root@ryzen3950 iperf2-code]# tcpdump ip and udp dst port 5001 -e -dd -i any +// tcpdump: data link type LINUX_SLL2 +// { 0x28, 0, 0, 0x00000000 }, +// { 0x15, 0, 8, 0x00000800 }, +// { 0x30, 0, 0, 0x0000001d }, +// { 0x15, 0, 6, 0x00000011 }, +// { 0x28, 0, 0, 0x0000001a }, +// { 0x45, 4, 0, 0x00001fff }, +// { 0xb1, 0, 0, 0x00000014 }, +// { 0x48, 0, 0, 0x00000016 }, +// { 0x15, 0, 1, 0x00001389 }, +// { 0x6, 0, 0, 0x00040000 }, +// { 0x6, 0, 0, 0x00000000 }, + +// { 0x28, 0, 0, 0x00000014 }, +// { 0x45, 4, 0, 0x00001fff }, +// { 0xb1, 0, 0, 0x0000001e }, +// { 0x48, 0, 0, 0x00000010 }, +// { 0x15, 0, 1, 0x00001389 }, + + +int SockAddr_v4_Accept_BPF (int sock, uint16_t port) { + // tcpdump udp dst port 5001 -dd to get c code filter + // UDP port is the 5 and 13 bytecodes (5001 = 0x1389) + // see linux/filter.h + struct sock_filter udp_filter[] = { + { 0x28, 0, 0, 0x0000000c }, + { 0x15, 0, 8, 0x00000800 }, + { 0x30, 0, 0, 0x00000017 }, + { 0x15, 0, 6, 0x00000011 }, + { 0x28, 0, 0, 0x00000014 }, + { 0x45, 4, 0, 0x00001fff }, + { 0xb1, 0, 0, 0x0000000e }, + { 0x48, 0, 0, 0x00000010 }, + { 0x15, 0, 1, 0x00001389 }, + { 0x6, 0, 0, 0x00040000 }, + { 0x6, 0, 0, 0x00000000 }, + }; + udp_filter[8].k = port; + struct sock_fprog bpf = { + .len = (sizeof(udp_filter) / sizeof(struct sock_filter)), + .filter = udp_filter, + }; + return(setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof(bpf))); +} + +//[root@ryzen3950 iperf2-code]# tcpdump udp dst port 5001 and dst host 1.1.1.1 -dd +//Warning: assuming Ethernet +//{ 0x28, 0, 0, 0x0000000c }, +//{ 0x15, 11, 0, 0x000086dd }, +//{ 0x15, 0, 10, 0x00000800 }, +//{ 0x30, 0, 0, 0x00000017 }, +//{ 0x15, 0, 8, 0x00000011 }, +//{ 0x28, 0, 0, 0x00000014 }, +//{ 0x45, 6, 0, 0x00001fff }, +//{ 0xb1, 0, 0, 0x0000000e }, +//{ 0x48, 0, 0, 0x00000010 }, +//{ 0x15, 0, 3, 0x00001389 }, +//{ 0x20, 0, 0, 0x0000001e }, +//{ 0x15, 0, 1, 0x01010101 }, +//{ 0x6, 0, 0, 0x00040000 }, +//{ 0x6, 0, 0, 0x00000000 }, +// +// BPF for TAP interaces with explicit v4 IP and UDP dst port +int SockAddr_Accept_V4_TAP_BPF (int sock, uint32_t dstip, uint16_t port) { + struct sock_filter udp_filter[] = { + { 0x28, 0, 0, 0x0000000c }, + { 0x15, 11, 0, 0x000086dd }, + { 0x15, 0, 10, 0x00000800 }, + { 0x30, 0, 0, 0x00000017 }, + { 0x15, 0, 8, 0x00000011 }, + { 0x28, 0, 0, 0x00000014 }, + { 0x45, 6, 0, 0x00001fff }, + { 0xb1, 0, 0, 0x0000000e }, + { 0x48, 0, 0, 0x00000010 }, + { 0x15, 0, 3, 0x00001389 }, + { 0x20, 0, 0, 0x0000001e }, + { 0x15, 0, 1, 0x00000000 }, + { 0x6, 0, 0, 0x00040000 }, + { 0x6, 0, 0, 0x00000000 }, + }; + udp_filter[12].k = htonl(dstip); + udp_filter[9].k = htons(port); + struct sock_fprog bpf = { + .len = (sizeof(udp_filter) / sizeof(struct sock_filter)), + .filter = udp_filter, + }; + return(setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof(bpf))); +} + +// Simulate the UDP connect for the AF_PACKET (or PF_PACKET) +// +int SockAddr_v4_Connect_BPF (int sock, uint32_t dstip, uint32_t srcip, uint16_t dstport, uint16_t srcport) { + // Use full quintuple, proto, src ip, dst ip, src port, dst port + // ip proto is already set per the PF_PACKET ETH_P_IP + // tcpdump udp and ip src 127.0.0.1 and ip dst 127.0.0.2 and src port 5001 and dst port 5002 -dd + // + // tcpdump udp and ip src 127.0.0.1 and ip dst 127.0.0.2 and src port 5001 and dst port 5002 -d + // (000) ldh [12] + // (001) jeq #0x86dd jt 17 jf 2 + // (002) jeq #0x800 jt 3 jf 17 + // (003) ldb [23] + // (004) jeq #0x11 jt 5 jf 17 + // (005) ld [26] + // (006) jeq #0x7f000001 jt 7 jf 17 + // (007) ld [30] + // (008) jeq #0x7f000002 jt 9 jf 17 + // (009) ldh [20] + // (010) jset #0x1fff jt 17 jf 11 + // (011) ldxb 4*([14]&0xf) + // (012) ldh [x + 14] + // (013) jeq #0x1389 jt 14 jf 17 + // (014) ldh [x + 16] + // (015) jeq #0x138a jt 16 jf 17 + // (016) ret #262144 + // (017) ret #0 + // + struct sock_filter udp_filter[] = { + { 0x28, 0, 0, 0x0000000c }, + { 0x15, 15, 0, 0x000086dd }, + { 0x15, 0, 14, 0x00000800 }, + { 0x30, 0, 0, 0x00000017 }, + { 0x15, 0, 12, 0x00000011 }, + { 0x20, 0, 0, 0x0000001a }, + { 0x15, 0, 10, 0x7f000001 }, + { 0x20, 0, 0, 0x0000001e }, + { 0x15, 0, 8, 0x7f000002 }, + { 0x28, 0, 0, 0x00000014 }, + { 0x45, 6, 0, 0x00001fff }, + { 0xb1, 0, 0, 0x0000000e }, + { 0x48, 0, 0, 0x0000000e }, + { 0x15, 0, 3, 0x00001389 }, + { 0x48, 0, 0, 0x00000010 }, + { 0x15, 0, 1, 0x0000138a }, + { 0x6, 0, 0, 0x00040000 }, + { 0x6, 0, 0, 0x00000000 }, + }; + udp_filter[6].k = htonl(srcip); + udp_filter[8].k = htonl(dstip); + udp_filter[13].k = htons(srcport); + udp_filter[15].k = htons(dstport); + struct sock_fprog bpf = { + .len = (sizeof(udp_filter) / sizeof(struct sock_filter)), + .filter = udp_filter, + }; + return(setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof(bpf))); +} +int SockAddr_v4_Connect_TAP_BPF (int sock, uint32_t dstip, uint32_t srcip, uint16_t dstport, uint16_t srcport) { + // [root@ryzen3950 iperf2-code]# tcpdump ip and src 127.0.0.1 and dst 127.0.0.2 and udp src port 5001 and dst port 5002 -d + // Warning: assuming Ethernet + // (000) ldh [12] + // (001) jeq #0x800 jt 2 jf 16 + // (002) ld [26] + // (003) jeq #0x7f000001 jt 4 jf 16 + // (004) ld [30] + // (005) jeq #0x7f000002 jt 6 jf 16 + // (006) ldb [23] + // (007) jeq #0x11 jt 8 jf 16 + // (008) ldh [20] + // (009) jset #0x1fff jt 16 jf 10 + // (010) ldxb 4*([14]&0xf) + // (011) ldh [x + 14] + // (012) jeq #0x1389 jt 13 jf 16 + // (013) ldh [x + 16] + // (014) jeq #0x138a jt 15 jf 16 + // (015) ret #262144 + // (016) ret #0 + // [root@ryzen3950 iperf2-code]# tcpdump ip and src 127.0.0.1 and dst 127.0.0.2 and udp src port 5001 and dst port 5002 -dd + // Warning: assuming Ethernet + struct sock_filter udp_filter[] = { + { 0x28, 0, 0, 0x0000000c }, + { 0x15, 0, 14, 0x00000800 }, + { 0x20, 0, 0, 0x0000001a }, + { 0x15, 0, 12, 0x7f000001 }, + { 0x20, 0, 0, 0x0000001e }, + { 0x15, 0, 10, 0x7f000002 }, + { 0x30, 0, 0, 0x00000017 }, + { 0x15, 0, 8, 0x00000011 }, + { 0x28, 0, 0, 0x00000014 }, + { 0x45, 6, 0, 0x00001fff }, + { 0xb1, 0, 0, 0x0000000e }, + { 0x48, 0, 0, 0x0000000e }, + { 0x15, 0, 3, 0x00001389 }, + { 0x48, 0, 0, 0x00000010 }, + { 0x15, 0, 1, 0x0000138a }, + { 0x6, 0, 0, 0x00040000 }, + { 0x6, 0, 0, 0x00000000 }, + }; + udp_filter[3].k = htonl(srcip); + udp_filter[5].k = htonl(dstip); + udp_filter[12].k = htons(srcport); + udp_filter[14].k = htons(dstport); + struct sock_fprog bpf = { + .len = (sizeof(udp_filter) / sizeof(struct sock_filter)), + .filter = udp_filter, + }; + return(setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof(bpf))); +} + +int SockAddr_v4_Connect_BPF_Drop (int sock, uint32_t dstip, uint32_t srcip, uint16_t dstport, uint16_t srcport) { + // Use full quintuple, proto, src ip, dst ip, src port, dst port + // ip proto is already set per the PF_PACKET ETH_P_IP + // tcpdump udp and ip src 127.0.0.1 and ip dst 127.0.0.2 and src port 5001 and dst port 5002 -dd + + struct sock_filter udp_filter[] = { + { 0x28, 0, 0, 0x0000000c }, + { 0x15, 15, 0, 0x000086dd }, + { 0x15, 0, 14, 0x00000800 }, + { 0x30, 0, 0, 0x00000017 }, + { 0x15, 0, 12, 0x00000011 }, + { 0x20, 0, 0, 0x0000001a }, + { 0x15, 0, 10, 0x7f000001 }, + { 0x20, 0, 0, 0x0000001e }, + { 0x15, 0, 8, 0x7f000002 }, + { 0x28, 0, 0, 0x00000014 }, + { 0x45, 6, 0, 0x00001fff }, + { 0xb1, 0, 0, 0x0000000e }, + { 0x48, 0, 0, 0x0000000e }, + { 0x15, 0, 3, 0x00001389 }, + { 0x48, 0, 0, 0x00000010 }, + { 0x15, 0, 1, 0x0000138a }, + { 0x6, 0, 0, 0x00000000 }, + { 0x6, 0, 0, 0x00000000 }, + }; + udp_filter[6].k = htonl(srcip); + udp_filter[8].k = htonl(dstip); + udp_filter[13].k = htons(srcport); + udp_filter[15].k = htons(dstport); + struct sock_fprog bpf = { + .len = (sizeof(udp_filter) / sizeof(struct sock_filter)), + .filter = udp_filter, + }; + return(setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof(bpf))); +} +#if HAVE_IPV6 +// +// v6 Connected BPF, use 32 bit values +// +int SockAddr_v6_Connect_BPF (int sock, struct in6_addr *dst, struct in6_addr *src, uint16_t dstport, uint16_t srcport) { + // Use full quintuple, proto, src ip, dst ip, src port, dst port + // tcpdump udp and ip6 src fe80::428d:5cff:fe6a:2d85 and ip6 dst fe80::428d:5cff:fe6a:2d86 and src port 5001 and dst port 5002 -dd + // + //tcpdump udp and ip6 src fe80::428d:5cff:fe6a:2d85 and ip6 dst fe80::428d:5cff:fe6a:2d86 and src port 5001 and dst port 5002 -d + // (000) ldh [12] + // (001) jeq #0x86dd jt 2 jf 32 + // (002) ldb [20] + // (003) jeq #0x11 jt 7 jf 4 + // (004) jeq #0x2c jt 5 jf 32 + // (005) ldb [54] + // (006) jeq #0x11 jt 7 jf 32 + // (007) ld [22] + // (008) jeq #0xfe800000 jt 9 jf 32 + // (009) ld [26] + // (010) jeq #0x0 jt 11 jf 32 + // (011) ld [30] + // (012) jeq #0x428d5cff jt 13 jf 32 + // (013) ld [34] + // (014) jeq #0xfe6a2d85 jt 15 jf 32 + // (015) ld [38] + // (016) jeq #0xfe800000 jt 17 jf 32 + // (017) ld [42] + // (018) jeq #0x0 jt 19 jf 32 + // (019) ld [46] + // (020) jeq #0x428d5cff jt 21 jf 32 + // (021) ld [50] + // (022) jeq #0xfe6a2d86 jt 23 jf 32 + // (023) ldb [20] + // (024) jeq #0x84 jt 27 jf 25 + // (025) jeq #0x6 jt 27 jf 26 + // (026) jeq #0x11 jt 27 jf 32 + // (027) ldh [54] + // (028) jeq #0x1389 jt 29 jf 32 + // (029) ldh [56] + // (030) jeq #0x138a jt 31 jf 32 + // (031) ret #262144 + // (032) ret #0 + // + struct sock_filter udp_filter[] = { + { 0x28, 0, 0, 0x0000000c }, + { 0x15, 0, 30, 0x000086dd }, + { 0x30, 0, 0, 0x00000014 }, + { 0x15, 3, 0, 0x00000011 }, + { 0x15, 0, 27, 0x0000002c }, + { 0x30, 0, 0, 0x00000036 }, + { 0x15, 0, 25, 0x00000011 }, + { 0x20, 0, 0, 0x00000016 }, + { 0x15, 0, 23, 0xfe800000 }, + { 0x20, 0, 0, 0x0000001a }, + { 0x15, 0, 21, 0x00000000 }, + { 0x20, 0, 0, 0x0000001e }, + { 0x15, 0, 19, 0x428d5cff }, + { 0x20, 0, 0, 0x00000022 }, + { 0x15, 0, 17, 0xfe6a2d85 }, + { 0x20, 0, 0, 0x00000026 }, + { 0x15, 0, 15, 0xfe800000 }, + { 0x20, 0, 0, 0x0000002a }, + { 0x15, 0, 13, 0x00000000 }, + { 0x20, 0, 0, 0x0000002e }, + { 0x15, 0, 11, 0x428d5cff }, + { 0x20, 0, 0, 0x00000032 }, + { 0x15, 0, 9, 0xfe6a2d86 }, + { 0x30, 0, 0, 0x00000014 }, + { 0x15, 2, 0, 0x00000084 }, + { 0x15, 1, 0, 0x00000006 }, + { 0x15, 0, 5, 0x00000011 }, + { 0x28, 0, 0, 0x00000036 }, + { 0x15, 0, 3, 0x00001389 }, + { 0x28, 0, 0, 0x00000038 }, + { 0x15, 0, 1, 0x0000138a }, + { 0x6, 0, 0, 0x00040000 }, + { 0x6, 0, 0, 0x00000000 }, + }; + udp_filter[8].k = htonl((*src).s6_addr32[0]); + udp_filter[10].k = htonl((*src).s6_addr32[1]); + udp_filter[12].k = htonl((*src).s6_addr32[2]); + udp_filter[14].k = htonl((*src).s6_addr32[3]); + udp_filter[16].k = htonl((*dst).s6_addr32[0]); + udp_filter[18].k = htonl((*dst).s6_addr32[1]); + udp_filter[20].k = htonl((*dst).s6_addr32[2]); + udp_filter[22].k = htonl((*dst).s6_addr32[3]); + udp_filter[28].k = htons(srcport); + udp_filter[30].k = htons(dstport); + struct sock_fprog bpf = { + .len = (sizeof(udp_filter) / sizeof(struct sock_filter)), + .filter = udp_filter, + }; + return(setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof(bpf))); +} +# endif // HAVE_V6 +#endif // HAVE_LINUX_FILTER + +#ifdef __cplusplus +} /* end extern "C" */ +#endif diff --git a/src/active_hosts.cpp b/src/active_hosts.cpp new file mode 100644 index 0000000..a3455ab --- /dev/null +++ b/src/active_hosts.cpp @@ -0,0 +1,261 @@ +/*--------------------------------------------------------------- + * Copyrig h(c) 1999,2000,2001,2002,2003 + * The Board of Trustees of the University of Illinois + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software (Iperf) and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the names of the University of Illinois, NCSA, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * National Laboratory for Applied Network Research + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * http://www.ncsa.uiuc.edu + * ________________________________________________________________ + * + * active_hosts.c (was List.cpp) + * rewrite by Robert McMahon + * + * This is a list to hold active traffic and create sum groups + * sum groups are traffic sessions from the same client host + * ------------------------------------------------------------------- + */ + +#include "active_hosts.h" +#include "Mutex.h" +#include "SocketAddr.h" +#include "Reporter.h" + +/* + * Global table with active hosts, their sum reports and active thread counts + */ +static struct Iperf_Table active_table; +static bool Iperf_host_port_present (iperf_sockaddr *find); +static struct Iperf_ListEntry* Iperf_host_present (iperf_sockaddr *find); + +#if HAVE_THREAD_DEBUG +static void active_table_show_entry(const char *action, Iperf_ListEntry *entry, int found) { + assert(action != NULL); + assert(entry != NULL); + char tmpaddr[200]; + size_t len=200; + unsigned short port = SockAddr_getPort(&(entry->host)); + SockAddr_getHostAddress(&(entry->host), tmpaddr, len); + thread_debug("active table: %s %s port %d (flag=%d) rootp=%p entryp=%p totcnt/activecnt/hostcnt = %d/%d/%d", \ + action, tmpaddr, port, found, (void *) active_table.root, (void *) entry, active_table.total_count, \ + active_table.count, entry->thread_count); +} +static void active_table_show_compare(const char *action, Iperf_ListEntry *entry, iperf_sockaddr *host, const char *type) { + assert(action != NULL); + assert(entry != NULL); + char lookupaddr[200]; + char findaddr[200]; + size_t len=200; + unsigned short port = SockAddr_getPort(&(entry->host)); + unsigned short findport = SockAddr_getPort(host); + SockAddr_getHostAddress(&(entry->host), lookupaddr, len); + SockAddr_getHostAddress(host, findaddr, len); + thread_debug("active table: compare table entry %s %s/%d against host %s/%d (%s)", type, lookupaddr, port, findaddr, findport, action); +} +#endif + +void Iperf_initialize_active_table () { + Mutex_Initialize(&active_table.my_mutex); + active_table.root = NULL; + active_table.groupid = 0; +} + +/* + * Add Entry add to the list or update thread count + */ +static void active_table_update (iperf_sockaddr *host, struct thread_Settings *agent) { + assert(host != NULL); + assert(agent != NULL); + Iperf_ListEntry *this_entry = Iperf_host_present(host); + active_table.total_count++; + if (this_entry == NULL) { + this_entry = new Iperf_ListEntry(); + assert(this_entry != NULL); + this_entry->host = *host; + this_entry->next = active_table.root; + this_entry->thread_count = 1; + this_entry->socket = agent->mSock; + active_table.count++; + active_table.groupid++; + active_table.root = this_entry; + this_entry->sum_report = InitSumReport(agent, active_table.total_count, 0); + IncrSumReportRefCounter(this_entry->sum_report); + agent->mSumReport = this_entry->sum_report; + this_entry->sum_report->info.common->transferID = -active_table.groupid; // sum ids are negative +#if HAVE_THREAD_DEBUG + active_table_show_entry("new entry", this_entry, ((SockAddr_are_Equal(&this_entry->host, host) && SockAddr_Hostare_Equal(&this_entry->host, host)))); +#endif + } else { + this_entry->thread_count++; + agent->mSumReport = this_entry->sum_report; + IncrSumReportRefCounter(this_entry->sum_report); +#if HAVE_THREAD_DEBUG + active_table_show_entry("incr entry", this_entry, 1); +#endif + } +} + +static inline iperf_sockaddr *active_table_get_host_key (struct thread_Settings *agent) { + iperf_sockaddr *key = (isSumServerDstIP(agent) ? &agent->local : &agent->peer); + return key; +} + +// Thread access to store a host +int Iperf_push_host (struct thread_Settings *agent) { + iperf_sockaddr *host = active_table_get_host_key(agent); + Mutex_Lock(&active_table.my_mutex); + active_table_update(host, agent); + int groupid = active_table.groupid; + Mutex_Unlock(&active_table.my_mutex); + return groupid; +} + +// Used for UDP push of a new host, returns negative value if the host/port is already present +// This is critical because UDP is connectionless and designed to be stateless +int Iperf_push_host_port_conditional (struct thread_Settings *agent) { + iperf_sockaddr *host = active_table_get_host_key(agent); + int rc = -1; + Mutex_Lock(&active_table.my_mutex); + if (!Iperf_host_port_present(host)) { + active_table_update(host, agent); + rc = active_table.groupid; + } + Mutex_Unlock(&active_table.my_mutex); + return (rc); +} + +/* + * Remove a host from the table + */ +void Iperf_remove_host (struct thread_Settings *agent) { + iperf_sockaddr *del = active_table_get_host_key(agent); + // remove_list_entry(entry) { + // indirect = &head; + // while ((*indirect) != entry) { + // indirect = &(*indirect)->next; + // } + // *indirect = entry->next + Mutex_Lock(&active_table.my_mutex); + Iperf_ListEntry **tmp = &active_table.root; + while ((*tmp) && !(SockAddr_Hostare_Equal(&(*tmp)->host, del))) { +#if HAVE_THREAD_DEBUG + active_table_show_compare("miss", *tmp, del, "client ip"); +#endif + tmp = &(*tmp)->next; + } + if (*tmp) { + if (--(*tmp)->thread_count == 0) { + Iperf_ListEntry *remove = (*tmp); + active_table.count--; + agent->mSumReport = NULL; +#if HAVE_THREAD_DEBUG + active_table_show_entry("delete", remove, 1); +#endif + *tmp = remove->next; + FreeSumReport(remove->sum_report); + delete remove; + } else { + DecrSumReportRefCounter((*tmp)->sum_report); +#if HAVE_THREAD_DEBUG + active_table_show_entry("decr", (*tmp), 1); +#endif + } + } + Mutex_Unlock(&active_table.my_mutex); +} + +/* + * Destroy the table + */ +void Iperf_destroy_active_table () { + Iperf_ListEntry *itr1 = active_table.root, *itr2; + while (itr1 != NULL) { + itr2 = itr1->next; + delete itr1; + itr1 = itr2; + } + Mutex_Destroy(&active_table.my_mutex); + active_table.root = NULL; + active_table.count = 0; + active_table.total_count = 0; +} + +/* + * Check if the host and port are present in the active table + */ +bool Iperf_host_port_present (iperf_sockaddr *find) { + Iperf_ListEntry *itr = active_table.root; + bool rc = false; + while (itr != NULL) { + if (SockAddr_are_Equal(&itr->host, find)) { +#if HAVE_THREAD_DEBUG + active_table_show_compare("match", itr, find, "client ip/port"); +#endif + rc = true; + break; + } else { +#if HAVE_THREAD_DEBUG + active_table_show_compare("miss", itr, find, "client ip/port"); +#endif + itr = itr->next; + } + } + return rc; +} + +/* + * Check if the host is present in the active table + */ +static Iperf_ListEntry* Iperf_host_present (iperf_sockaddr *find) { + Iperf_ListEntry *itr = active_table.root; + while (itr != NULL) { + if (SockAddr_Hostare_Equal(&itr->host, find)) { +#if HAVE_THREAD_DEBUG + active_table_show_compare("match", itr, find, "client ip"); +#endif + break; + } else { +#if HAVE_THREAD_DEBUG + active_table_show_compare("miss", itr, find, "client ip"); +#endif + itr = itr->next; + } + } + return itr; +} diff --git a/src/checkdelay.c b/src/checkdelay.c new file mode 100644 index 0000000..1c35d64 --- /dev/null +++ b/src/checkdelay.c @@ -0,0 +1,203 @@ +/*--------------------------------------------------------------- + * Copyright (c) 2014 + * Broadcom Corporation + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the name of Broadcom Coporation, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * + * checkdelay.c + * Simple tool to measure mean/min/max of nanosleep + * by Robert J. McMahon (rjmcmahon@rjmcmahon.com, rmcmahon@broadcom.com) + * ------------------------------------------------------------------- */ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <ctype.h> +#include <unistd.h> +#include "headers.h" +#include "util.h" +#include "delay.h" +#if HAVE_SCHED_SETSCHEDULER +#include <sched.h> +#ifdef HAVE_MLOCKALL +#include <sys/mman.h> +#endif +#endif + + + +#define BILLION 1000000000 +#define MILLION 1000000 + +int main (int argc, char **argv) { + double sum=0; + double time1, time2; + double delta, max=0, min=-1; + int ix, delay=1,loopcount=1000; + int c; + int clockgettime = 0, kalman = 0; +#if HAVE_DECL_CPU_SET + int affinity = 0; +#endif +#if HAVE_SCHED_SETSCHEDULER + int realtime = 0; + struct sched_param sp; +#endif +#ifdef HAVE_CLOCK_GETTIME + struct timespec t1; +#else + struct timeval t1; +#endif + + while ((c=getopt(argc, argv, "a:bkd:i:r")) != -1) + switch (c) { + case 'b': + clockgettime = 1; + break; + case 'k': + kalman = 1; + break; + case 'd': + delay = atoi(optarg); + break; + case 'i': + loopcount = atoi(optarg); + break; +#if HAVE_DECL_CPU_SET + case 'a': + affinity=atoi(optarg); + break; +#endif +#if HAVE_SCHED_SETSCHEDULER + case 'r': + realtime = 1; + break; +#endif + case '?': + fprintf(stderr,"Usage -b busyloop, -d usec delay, -i iterations" +#if HAVE_DECL_CPU_SET + ", -a affinity" +#endif +#if HAVE_SCHED_SETSCHEDULER + ", -r realtime" +#endif + "\n"); + return 1; + default: + abort(); + } + +#ifndef HAVE_NANOSLEEP + clockgettime = 1; +#endif + +#if HAVE_SCHED_SETSCHEDULER + if (realtime) { + fprintf(stdout,"Setting scheduler to realtime via SCHED_RR\n"); + // SCHED_OTHER, SCHED_FIFO, SCHED_RR + sp.sched_priority = sched_get_priority_max(SCHED_RR); + WARN_errno(sched_setscheduler(0, SCHED_RR, &sp) < 0, + "Client set scheduler"); +#ifdef HAVE_MLOCKALL + // lock the threads memory + WARN_errno(mlockall(MCL_CURRENT | MCL_FUTURE) != 0, "mlockall"); +#endif + } +#if HAVE_DECL_CPU_SET + if (affinity) { + fprintf(stdout,"CPU affinity set to %d\n", affinity); + cpu_set_t myset; + CPU_ZERO(&myset); + CPU_SET(affinity,&myset); + } +#endif +#endif + if (loopcount > 1000) + fprintf(stdout,"Measuring %s over %.0e iterations using %d usec delay\n", + kalman ? "kalman" : + clockgettime ? "clock_gettime" : "nanosleep", + (double) loopcount, delay); + else + fprintf(stdout,"Measuring %s over %d iterations using %d usec delay\n", + kalman ? "kalman" : + clockgettime ? "clock_gettime" : "nanosleep", + loopcount, delay); + fflush(stdout); + for (ix=0; ix < loopcount; ix++) { + // Find the max jitter for delay call +#ifdef HAVE_CLOCK_GETTIME + clock_gettime(CLOCK_REALTIME, &t1); + time1 = t1.tv_sec + (t1.tv_nsec / 1000000000.0); +#else + gettimeofday( &t1, NULL ); + time1 = t1.tv_sec + (t1.tv_usec / 1000000.0); +#endif +#ifdef HAVE_KALMAN + if (kalman) { + delay_kalman(delay); + } else +#endif + if (clockgettime) { + delay_busyloop(delay); + } else { +#ifdef HAVE_NANOSLEEP + delay_nanosleep(delay); +#endif + } +#ifdef HAVE_CLOCK_GETTIME + clock_gettime(CLOCK_REALTIME, &t1); + time2 = t1.tv_sec + (t1.tv_nsec / 1000000000.0); +#else + gettimeofday( &t1, NULL ); + time2 = t1.tv_sec + (t1.tv_usec / 1000000.0); +#endif + delta = (time2 - time1) * 1e6; + if (delta > max) { + max = delta; + } + if (delta < min || min < 0) { + min = delta; + } + sum += (double) delta; + } + fprintf(stdout,"delay=%.03f/%.03f/%.03f usec (mean/min/max)\n", + (sum / loopcount), min, max); + return(0); +} diff --git a/src/checkisoch.cpp b/src/checkisoch.cpp new file mode 100644 index 0000000..a770e6d --- /dev/null +++ b/src/checkisoch.cpp @@ -0,0 +1,129 @@ +/*--------------------------------------------------------------- + * Copyright (c) 2017 + * Broadcom Corporation + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the name of Broadcom Coporation, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * + * checkisoch.cpp + * + * Test routine to test the isochronous functions + * + * by Robert J. McMahon (rjmcmahon@rjmcmahon.com, bob.mcmahon@broadcom.com) + * ------------------------------------------------------------------- */ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <errno.h> +#include <string.h> +#include <math.h> +#include <unistd.h> +#include "headers.h" +#include "isochronous.hpp" +#include "delay.h" +#include "pdfs.h" +#include "util.h" + +static void posttimestamp(int, int); + +int main (int argc, char **argv) { + int c, count=100, frequency=100; + float mean=1e8; + float variance=3e7; + bool forceslip = false; + + Isochronous::FrameCounter *fc = NULL; + + while ((c = getopt(argc, argv, "c:f:m:sv:")) != -1) { + switch (c) { + case 'c': + count = atoi(optarg); + break; + case 'f': + frequency = atoi(optarg); + break; + case 'm': + mean=byte_atof(optarg); + break; + case 's': + forceslip = true; + break; + case 'v': + variance=byte_atof(optarg); + break; + case '?': + fprintf (stderr, "usage: -c <count> -f <frames per second> -m <mean> -v <variance>\n"); + return 1; + default: + abort (); + } + } + fc = new Isochronous::FrameCounter(frequency); + + fprintf(stdout,"Timestamping %d times at %d fps\n", count, frequency); + fflush(stdout); + while (count-- > 0) { + if (forceslip && count == 8) { + delay_loop (1000000/frequency + 10); + } + fc->wait_tick(); + posttimestamp(count, (round(lognormal(mean,variance)) / (frequency * 8))); + if (fc->slip) { + fprintf(stdout,"Slip occurred\n"); + fc->slip = 0; + } + } + DELETE_PTR(fc); +} + +void posttimestamp (int count, int bytes) { + struct timespec t1; + double timestamp; + int err; + + err = clock_gettime(CLOCK_REALTIME, &t1); + if (err < 0) { + perror("clock_getttime"); + } else { + timestamp = t1.tv_sec + (t1.tv_nsec / 1000000000.0); + fprintf(stdout,"%f counter(%d), sending %d bytes\n", timestamp, count, bytes); + } + fflush(stdout); +} diff --git a/src/checkpdfs.c b/src/checkpdfs.c new file mode 100644 index 0000000..87577c7 --- /dev/null +++ b/src/checkpdfs.c @@ -0,0 +1,217 @@ +/*--------------------------------------------------------------- + * Copyright (c) 2017 + * Broadcom Corporation + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the name of Broadcom Coporation, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * + * pdfs.c + * Produce probability distribution functions, expected to be used + * for iperf client traffic emulations + * + * by Robert J. McMahon (rjmcmahon@rjmcmahon.com, bob.mcmahon@broadcom.com) + * ------------------------------------------------------------------- */ + +/* Produce normal and log normal + * + * Implements the Polar form of the Box-Muller Transformation + * + * +*/ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <math.h> +#include <unistd.h> +#include "headers.h" +#include "util.h" +#include "pdfs.h" + +#define MAXBINS 1024 +#define TRUE 1 +#define FALSE 0 +#define MILLION 1000000 +#define BILLION 1000000000 + +#ifdef HAVE_CLOCK_GETTIME +static double timespec_diff(struct timespec tv1, struct timespec tv0); +#else +static double timeval_diff (struct timeval tv1, struct timeval tv0); +#endif + +int main (int argc, char **argv) { + int c, i; + int minbin = MAXBINS; + int maxbin = 0; + int bincount=MAXBINS; + time_t t; + int histogram[MAXBINS]; + float mean=100.0; + float variance=30.0; + int count = 10000; + int gaussian = TRUE; + int printout = FALSE; + int speedonly = FALSE; + int exectime; + int random = FALSE; + double total; + double binwidth=1.0; + + while ((c=getopt(argc, argv, "b:c:lm:prsv:w:")) != -1) + switch (c) { + case 'b': + bincount = atoi(optarg); + break; + case 'c': + count = atoi(optarg); + break; + case 'l': + gaussian = FALSE; + break; + case 'm': + mean = bitorbyte_atof(optarg); + break; + case 'p': + printout = TRUE; + break; + case 'r': + random = TRUE; + break; + case 's': + speedonly = TRUE; + break; + case 'v': + variance = bitorbyte_atof(optarg); + break; + case 'w': + binwidth = bitorbyte_atof(optarg); + break; + case '?': + default: + fprintf(stderr,"Usage -b bins, -c count, -l log normal, -m mean, -p print, -s speed only, -v variance"); + exit(-1); + } + if (bincount > MAXBINS) { + int max = MAXBINS; + fprintf(stderr, "Maximum number of bins is %d while %d requested\n", max, bincount); + abort(); + } + /* Intializes random number generator */ + if (random) { + srand((unsigned) time(&t)); + printf("seed = %ld\n", t); + } + memset(histogram, 0, sizeof(histogram)); +#ifdef HAVE_CLOCK_GETTIME + struct timespec t1; + clock_gettime(CLOCK_REALTIME, &t1); +#else + struct timeval t1; + gettimeofday( &t1, NULL ); +#endif + if (gaussian) { + for( i = 0 ; i < count ; i++ ) { + int result = round(normal(mean,variance)/binwidth); + if (!speedonly) { + if (result >= 0 && result < (MAXBINS - 1)) { + histogram[result]++; + if (result < minbin) + minbin = result; + if (result > maxbin) + maxbin = result; + } + } + } + } else { + for( i = 0 ; i < count ; i++ ) { + int result = round(lognormal(mean,variance)/binwidth); + if (!speedonly) { + if (result >= 0 && result < (MAXBINS - 1)) { + histogram[result]++; + if (result < minbin) + minbin = result; + if (result > maxbin) + maxbin = result; + } + } + } + } +#ifdef HAVE_CLOCK_GETTIME + struct timespec t2; + clock_gettime(CLOCK_REALTIME, &t2); + total = timespec_diff(t2, t1); +#else + struct timeval t2; + gettimeofday( &t2, NULL ); + total = timeval_diff(t2, t1); +#endif + if (printout) { + for( i = minbin ; i <= maxbin ; i++ ) + printf("%.0f %d\n", i * binwidth, histogram[i]); + } + exectime = round(1e9 * total / count); + if (!printout) { + printf("Total time=%f secs, count= %d, average generate time of %d nanoseconds\n", total, count, exectime); + } + return(0); +} +#ifdef HAVE_CLOCK_GETTIME +// tv1 assumed greater than tv0 +static double timespec_diff (struct timespec tv1, struct timespec tv0) { + double result; + if (tv1.tv_nsec < tv0.tv_nsec) { + tv1.tv_nsec += BILLION; + tv1.tv_sec--; + } + result = (double) (((tv1.tv_sec - tv0.tv_sec) * BILLION) + (tv1.tv_nsec - tv0.tv_nsec)); + return (result / 1e9); +} +#else +// tv1 assumed greater than tv0 +static double timeval_diff (struct timeval tv1, struct timeval tv0) { + double result; + if (tv1.tv_usec < tv0.tv_usec) { + tv1.tv_usec += MILLION; + tv1.tv_sec--; + } + result = (double) (((tv1.tv_sec - tv0.tv_sec) * MILLION) + (tv1.tv_usec - tv0.tv_usec)); + return (result / 1e6); +} +#endif diff --git a/src/checksums.c b/src/checksums.c new file mode 100644 index 0000000..852f195 --- /dev/null +++ b/src/checksums.c @@ -0,0 +1,229 @@ +/*--------------------------------------------------------------- + * Copyright (c) 2018 + * Broadcom Corporation + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the name of Broadcom Coporation, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * + * UDP checksums v4 and v6 + * + * The checksum calculation is defined in RFC 768 + * hints as to how to calculate it efficiently are in RFC 1071 + * + * by Robert J. McMahon (rjmcmahon@rjmcmahon.com, bob.mcmahon@broadcom.com) + * ------------------------------------------------------------------- + */ +#include "headers.h" + +/* + * + * Compute Internet Checksum for UDP packets (assumes 32 bit system) + * + * IPV4 Notes: + * + * User Datagram Header Format + * 0 7 8 15 16 23 24 31 + * +--------+--------+--------+--------+ + * | Source | Destination | + * | Port | Port | + * +--------+--------+--------+--------+ + * | | | + * | Length | Checksum | + * +--------+--------+--------+--------+ + * | + * | data octets ... + * +---------------- ... + * + * + * Checksum is the 16-bit one's complement of the one's complement sum of a + * pseudo header of information from the IP header, the UDP header, and the + * data, padded with zero octets at the end (if necessary) to make a + * multiple of two octets. + * + * The ipv4 pseudo header conceptually prefixed to the UDP header contains the + * source address, the destination address, the protocol, and the UDP + * length. This information gives protection against misrouted datagrams. + * This checksum procedure is the same as is used in TCP. + * + * 0 7 8 15 16 23 24 31 + * +--------+--------+--------+--------+ + * | source address | + * +--------+--------+--------+--------+ + * | destination address | + * +--------+--------+--------+--------+ + * | zero |protocol| UDP length | + * +--------+--------+--------+--------+ + * + * If the computed checksum is zero, it is transmitted as all ones (the + * equivalent in one's complement arithmetic). An all zero transmitted + * checksum value means that the transmitter generated no checksum (for + * debugging or for higher level protocols that don't care). + * + * + * IPV6 Notes: + * + * Any transport or other upper-layer protocol that includes the + * addresses from the IP header in its checksum computation must be + * modified for use over IPv6, to include the 128-bit IPv6 addresses + * instead of 32-bit IPv4 addresses. In particular, the following + * illustration shows the TCP and UDP "pseudo-header" for IPv6: + * + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | + * + + + * | | + * + Source Address + + * | | + * + + + * | | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | + * + + + * | | + * + Destination Address + + * | | + * + + + * | | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Upper-Layer Packet Length | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | zero | Next Header | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * o If the IPv6 packet contains a Routing header, the Destination + * Address used in the pseudo-header is that of the final + * destination. At the originating node, that address will be in + * the last element of the Routing header; at the recipient(s), + * that address will be in the Destination Address field of the + * IPv6 header. + * + * o The Next Header value in the pseudo-header identifies the + * upper-layer protocol (e.g., 6 for TCP, or 17 for UDP). It will + * differ from the Next Header value in the IPv6 header if there + * are extension headers between the IPv6 header and the upper- + * layer header. + * + * o The Upper-Layer Packet Length in the pseudo-header is the + * length of the upper-layer header and data (e.g., TCP header + * plus TCP data). Some upper-layer protocols carry their own + * length information (e.g., the Length field in the UDP header); + * for such protocols, that is the length used in the pseudo- + * header. Other protocols (such as TCP) do not carry their own + * length information, in which case the length used in the + * pseudo-header is the Payload Length from the IPv6 header, minus + * the length of any extension headers present between the IPv6 + * header and the upper-layer header. + * + * o Unlike IPv4, when UDP packets are originated by an IPv6 node, + * the UDP checksum is not optional. That is, whenever + * originating a UDP packet, an IPv6 node must compute a UDP + * checksum over the packet and the pseudo-header, and, if that + * computation yields a result of zero, it must be changed to hex + * FFFF for placement in the UDP header. IPv6 receivers must + * discard UDP packets containing a zero checksum, and should log + * the error. + * + * + * Returns zero on checksum success, non zero otherwise + */ + +#define IPV4SRCOFFSET 12 // the ipv4 source address offset from the l3 pdu +#define IPV6SRCOFFSET 8 // the ipv6 source address offset +#define IPV6SIZE 8 // units is number of 16 bits, i.e. 128 bits is eight 16 bits +#define IPV4SIZE 2 // v4 is two 16 bits (32 bits) +#define UDPPROTO 17 // UDP protocol value for psuedo header +uint32_t udpchecksum(const void *l3pdu, const void *l4pdu, int udplen, int v6) { + register uint32_t sum = 0; + const uint16_t *data; + int i; + + const struct udphdr *udp_hdr = (const struct udphdr *)l4pdu; + if (!udp_hdr->check) { + if (v6) + // v6 requires checksums + return -1; + else + // v4 checksums are optional + return 0; + } + + /* + * Build pseudo headers, partially from the packet + * (which are in network byte order) and + * the protocol of UDP (value of 17). Also, the IP dst + * addr immediately follows the src so double the size + * per each loop to cover both addrs + */ + if (v6) { + // skip to the ip header v6 src field, offset 8 (see ipv6 header) + data = (const uint16_t *)((char *)l3pdu + IPV6SRCOFFSET); + for (i = 0; i < (2 * IPV6SIZE); i++) { + sum += *data++; + } + } else { + // skip to the ip header v4 src field, offset 12 (see ipv4 header) + data = (const uint16_t *)((char *)l3pdu + IPV4SRCOFFSET); + for (i = 0; i < (2 * IPV4SIZE); i++) { + sum += *data++; + } + } + // These should work for both v4 and v6 even though + // v6 psuedo header uses 32 bit values because the + // uppers in v6 will be zero + sum += htons(UDPPROTO); // proto of UDP is 17 + sum += htons(udplen); // For UDP, the pseudo hdr len equals udp len + + /* + * UDP hdr + payload + */ + data = (const uint16_t *) l4pdu; + while( udplen > 1 ) { + sum += *data++; + udplen -= 2; + } + /* Add left-over byte, if any */ + if( udplen > 0 ) + sum += * (uint8_t *) data; + + /* Fold 32-bit sum to 16 bits */ + while (sum>>16) + sum = (sum & 0xffff) + (sum >> 16); + + /* return ones complement */ + sum = (sum ^ 0xffff); + return sum; +} diff --git a/src/dscp.c b/src/dscp.c new file mode 100644 index 0000000..de691a7 --- /dev/null +++ b/src/dscp.c @@ -0,0 +1,180 @@ +/* DSCP lookup routines lifted from openssh, modified a bit for WiFi WMMM + * + * Copyright (c) 2000 Markus Friedl. All rights reserved. + * Copyright (c) 2005,2006 Damien Miller. All rights reserved. + * Copyright (c) 2022 Robert McMahon. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#if HAVE_STRING_H +#include <string.h> +#endif +#if HAVE_STDLIB_H +#include <stdlib.h> +#endif + +#if HAVE_INTTYPES_H +#include <inttypes.h> +#endif + +#ifdef WIN32 +#define strcasecmp(a,b) _stricmp(a,b) +#define snprintf _snprintf +#endif + +#include "dscp.h" + +/* + * Definitions for IP type of service (ip_tos) + */ + +#if HAVE_NETINET_IN_SYSTM_H +#if defined(__FreeBSD__) +#include <sys/types.h> +#endif +#include <netinet/in_systm.h> +#endif +#if HAVE_NETINET_IP_H +#include <netinet/ip.h> +#endif + +#ifndef IPTOS_LOWDELAY +# define IPTOS_LOWDELAY 0x10 +# define IPTOS_THROUGHPUT 0x08 +# define IPTOS_RELIABILITY 0x04 +# define IPTOS_LOWCOST 0x02 +# define IPTOS_MINCOST IPTOS_LOWCOST +#endif /* IPTOS_LOWDELAY */ + +/* + * Definitions for DiffServ Codepoints as per RFC2474, rfc8622, rfc8325 + */ +#ifndef IPTOS_DSCP_AF11 +# define IPTOS_DSCP_AF11 0x28 +# define IPTOS_DSCP_AF12 0x30 +# define IPTOS_DSCP_AF13 0x38 +# define IPTOS_DSCP_AF21 0x48 +# define IPTOS_DSCP_AF22 0x50 +# define IPTOS_DSCP_AF23 0x58 +# define IPTOS_DSCP_AF31 0x68 +# define IPTOS_DSCP_AF32 0x70 +# define IPTOS_DSCP_AF33 0x78 +# define IPTOS_DSCP_AF41 0x88 +# define IPTOS_DSCP_AF42 0x90 +# define IPTOS_DSCP_AF43 0x98 +# define IPTOS_DSCP_EF 0xb8 +# define IPTOS_DSCP_LE 0x01 // rfc8622 +# define IPTOS_DSCP_NQB 0x05 // rfc8325 +# define IPTOS_DSCP_NQB2 0x2D // rfc8325 45 decimal + +#endif /* IPTOS_DSCP_AF11 */ + +#ifndef IPTOS_DSCP_CS0 +# define IPTOS_DSCP_CS0 0x00 +# define IPTOS_DSCP_CS1 0x20 +# define IPTOS_DSCP_CS2 0x40 +# define IPTOS_DSCP_CS3 0x60 +# define IPTOS_DSCP_CS4 0x80 +# define IPTOS_DSCP_CS5 0xa0 +# define IPTOS_DSCP_CS6 0xc0 +# define IPTOS_DSCP_CS7 0xe0 +#endif /* IPTOS_DSCP_CS0 */ +#ifndef IPTOS_DSCP_EF +# define IPTOS_DSCP_EF 0xb8 +#endif /* IPTOS_DSCP_EF */ + +static const struct { + const char *name; + int value; +} ipqos[] = { + { "af11", IPTOS_DSCP_AF11 }, + { "af12", IPTOS_DSCP_AF12 }, + { "af13", IPTOS_DSCP_AF13 }, + { "af21", IPTOS_DSCP_AF21 }, + { "af22", IPTOS_DSCP_AF22 }, + { "af23", IPTOS_DSCP_AF23 }, + { "af31", IPTOS_DSCP_AF31 }, + { "af32", IPTOS_DSCP_AF32 }, + { "af33", IPTOS_DSCP_AF33 }, + { "af41", IPTOS_DSCP_AF41 }, + { "af42", IPTOS_DSCP_AF42 }, + { "af43", IPTOS_DSCP_AF43 }, + { "cs0", IPTOS_DSCP_CS0 }, + { "cs1", IPTOS_DSCP_CS1 }, + { "cs2", IPTOS_DSCP_CS2 }, + { "cs3", IPTOS_DSCP_CS3 }, + { "cs4", IPTOS_DSCP_CS4 }, + { "cs5", IPTOS_DSCP_CS5 }, + { "cs6", IPTOS_DSCP_CS6 }, + { "cs7", IPTOS_DSCP_CS7 }, + { "ef", IPTOS_DSCP_EF }, + { "le", IPTOS_DSCP_LE }, + { "nqb", IPTOS_DSCP_NQB }, + { "nqb2", IPTOS_DSCP_NQB2 }, + { "ac_be", IPTOS_DSCP_CS0 }, + { "ac_bk", IPTOS_DSCP_CS1 }, + { "ac_vi", IPTOS_DSCP_CS4 }, + { "ac_vo", IPTOS_DSCP_EF }, + { "lowdelay", IPTOS_LOWDELAY }, + { "throughput", IPTOS_THROUGHPUT }, + { "reliability", IPTOS_RELIABILITY }, + { NULL, -1 } +}; + +int +parse_ipqos(const char *cp) +{ + unsigned int i; + char *ep = NULL; + long val; + + if (cp == NULL) + return -1; + for (i = 0; ipqos[i].name != NULL; i++) { + if (strcasecmp(cp, ipqos[i].name) == 0) + return ipqos[i].value; + } + /* Try parsing as an integer */ + val = strtol(cp, &ep, 0); + if (*cp == '\0' || *ep != '\0' || val < 0 || val > 255) + return -1; + return val; +} + +const char * +iptos2str(int iptos) +{ + int i; + static char iptos_str[sizeof "0xff"]; + if (iptos < 0 || iptos > 64) iptos = 0; + for (i = 0; ipqos[i].name != NULL; i++) { + if (ipqos[i].value == iptos) + return ipqos[i].name; + } + snprintf(iptos_str, sizeof iptos_str, "0x%02x", iptos); + return iptos_str; +} diff --git a/src/gnu_getopt.c b/src/gnu_getopt.c new file mode 100644 index 0000000..6905278 --- /dev/null +++ b/src/gnu_getopt.c @@ -0,0 +1,818 @@ +/* Getopt for GNU. + NOTE: gnu_getopt is now part of the C library, so if you don't know what + "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu + before changing it! + + Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97 + Free Software Foundation, Inc. + + This file is part of the GNU C Library. Its master source is NOT part of + the C library, however. The master source lives in /gd/gnu/lib. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* + * modified July 9, 1999 by mark gates <mgates@nlanr.net> + * Dec 17, 1999 + * + * renamed all functions and variables by prepending "gnu_" + * removed/redid a bunch of stuff under the assumption we're + * using a modern standard C compiler. + * add #include <string.h> here for strncmp(). Originally + * it was included only under special conditions. + * + * $Id: gnu_getopt.c,v 1.1.1.1 2004/05/18 01:50:44 kgibbs Exp $ + */ + + + +#include <stdio.h> +#include <stdlib.h> +#ifndef _MSC_VER /* Visual C++ doesn't have unistd.h */ + #include <unistd.h> +#endif +#include <string.h> + +#ifndef _ +/* This is for other GNU distributions with internationalized messages. + When compiling libc, the _ macro is predefined. */ + #ifdef HAVE_LIBINTL_H + #include <libintl.h> + #define _(msgid) gettext (msgid) + #else + #define _(msgid) (msgid) + #endif +#endif + +/* This version of `gnu_getopt' appears to the caller like standard + Unix `getopt' but it behaves differently for the user, since it + allows the user to intersperse the options with the other + arguments. + + As `gnu_getopt' works, it permutes the elements of ARGV so that, + when it is done, all the options precede everything else. Thus + all application programs are extended to handle flexible argument order. + + Setting the environment variable POSIXLY_CORRECT disables permutation. + Then the behavior is completely standard. + + GNU application programs can use a third alternative mode in which + they can distinguish the relative order of options and other arguments. */ + +#include "gnu_getopt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* For communication from `gnu_getopt' to the caller. + When `gnu_getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +char *gnu_optarg = NULL; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `gnu_getopt'. + + On entry to `gnu_getopt', zero means this is the first call; initialize. + + When `gnu_getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `gnu_optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +/* 1003.2 says this must be 1 before any call. */ +int gnu_optind = 1; + +/* Formerly, initialization of gnu_getopt depended on gnu_optind==0, which + causes problems with re-calling gnu_getopt as programs generally don't + know that. */ + +int __gnu_getopt_initialized = 0; + +/* The next char to be scanned in the option-element + in which the last option character we returned was found. + This allows us to pick up the scan where we left off. + + If this is zero, or a null string, it means resume the scan + by advancing to the next ARGV-element. */ + +static char *nextchar; + +/* Callers store zero here to inhibit the error message + for unrecognized options. */ + +int gnu_opterr = 1; + +/* Set to an option character which was unrecognized. + This must be initialized on some systems to avoid linking in the + system's own gnu_getopt implementation. */ + +int gnu_optopt = '?'; + +/* Describe how to deal with options that follow non-option ARGV-elements. + + If the caller did not specify anything, + the default is REQUIRE_ORDER if the environment variable + POSIXLY_CORRECT is defined, PERMUTE otherwise. + + REQUIRE_ORDER means don't recognize them as options; + stop option processing when the first non-option is seen. + This is what Unix does. + This mode of operation is selected by either setting the environment + variable POSIXLY_CORRECT, or using `+' as the first character + of the list of option characters. + + PERMUTE is the default. We permute the contents of ARGV as we scan, + so that eventually all the non-options are at the end. This allows options + to be given in any order, even with programs that were not written to + expect this. + + RETURN_IN_ORDER is an option available to programs that were written + to expect options and other ARGV-elements in any order and that care about + the ordering of the two. We describe each non-option ARGV-element + as if it were the argument of an option with character code 1. + Using `-' as the first character of the list of option characters + selects this mode of operation. + + The special argument `--' forces an end of option-scanning regardless + of the value of `ordering'. In the case of RETURN_IN_ORDER, only + `--' can cause `gnu_getopt' to return -1 with `gnu_optind' != ARGC. */ + +static enum { + REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER +} ordering; + +/* Value of POSIXLY_CORRECT environment variable. */ +static char *posixly_correct; + + +/* Avoid depending on library functions or files + whose names are inconsistent. */ + +static char * +my_index( const char* str, int chr ) { + while ( *str ) { + if ( *str == chr ) + return(char *) str; + str++; + } + return 0; +} + + +/* Handle permutation of arguments. */ + +/* Describe the part of ARGV that contains non-options that have + been skipped. `first_nonopt' is the index in ARGV of the first of them; + `last_nonopt' is the index after the last of them. */ + +static int first_nonopt; +static int last_nonopt; + +/* Exchange two adjacent subsequences of ARGV. + One subsequence is elements [first_nonopt,last_nonopt) + which contains all the non-options that have been skipped so far. + The other is elements [last_nonopt,gnu_optind), which contains all + the options processed since those non-options were skipped. + + `first_nonopt' and `last_nonopt' are relocated so that they describe + the new indices of the non-options in ARGV after they are moved. */ + +static void exchange( char **argv ); + +static void +exchange( char **argv ) { + int bottom = first_nonopt; + int middle = last_nonopt; + int top = gnu_optind; + char *tem; + + /* Exchange the shorter segment with the far end of the longer segment. + That puts the shorter segment into the right place. + It leaves the longer segment in the right place overall, + but it consists of two parts that need to be swapped next. */ + + while ( top > middle && middle > bottom ) { + if ( top - middle > middle - bottom ) { + /* Bottom segment is the short one. */ + int len = middle - bottom; + register int i; + + /* Swap it with the top part of the top segment. */ + for ( i = 0; i < len; i++ ) { + tem = argv[bottom + i]; + argv[bottom + i] = argv[top - (middle - bottom) + i]; + argv[top - (middle - bottom) + i] = tem; + } + /* Exclude the moved bottom segment from further swapping. */ + top -= len; + } else { + /* Top segment is the short one. */ + int len = top - middle; + register int i; + + /* Swap it with the bottom part of the bottom segment. */ + for ( i = 0; i < len; i++ ) { + tem = argv[bottom + i]; + argv[bottom + i] = argv[middle + i]; + argv[middle + i] = tem; + } + /* Exclude the moved top segment from further swapping. */ + bottom += len; + } + } + + /* Update records for the slots the non-options now occupy. */ + + first_nonopt += (gnu_optind - last_nonopt); + last_nonopt = gnu_optind; +} + +/* Initialize the internal data when the first call is made. */ + +static const char * +_gnu_getopt_initialize( int argc, + char *const * argv, + const char *optstring ); + +static const char * +_gnu_getopt_initialize( int argc, + char *const * argv, + const char *optstring ) { + /* Start processing options with ARGV-element 1 (since ARGV-element 0 + is the program name); the sequence of previously skipped + non-option ARGV-elements is empty. */ + + first_nonopt = last_nonopt = gnu_optind = 1; + + nextchar = NULL; + + posixly_correct = getenv ("POSIXLY_CORRECT"); + + /* Determine how to handle the ordering of options and nonoptions. */ + + if ( optstring[0] == '-' ) { + ordering = RETURN_IN_ORDER; + ++optstring; + } else if ( optstring[0] == '+' ) { + ordering = REQUIRE_ORDER; + ++optstring; + } else if ( posixly_correct != NULL ) + ordering = REQUIRE_ORDER; + else + ordering = PERMUTE; + + return optstring; +} + +/* Scan elements of ARGV (whose length is ARGC) for option characters + given in OPTSTRING. + + If an element of ARGV starts with '-', and is not exactly "-" or "--", + then it is an option element. The characters of this element + (aside from the initial '-') are option characters. If `gnu_getopt' + is called repeatedly, it returns successively each of the option characters + from each of the option elements. + + If `gnu_getopt' finds another option character, it returns that character, + updating `gnu_optind' and `nextchar' so that the next call to `gnu_getopt' can + resume the scan with the following option character or ARGV-element. + + If there are no more option characters, `gnu_getopt' returns -1. + Then `gnu_optind' is the index in ARGV of the first ARGV-element + that is not an option. (The ARGV-elements have been permuted + so that those that are not options now come last.) + + OPTSTRING is a string containing the legitimate option characters. + If an option character is seen that is not listed in OPTSTRING, + return '?' after printing an error message. If you set `gnu_opterr' to + zero, the error message is suppressed but we still return '?'. + + If a char in OPTSTRING is followed by a colon, that means it wants an arg, + so the following text in the same ARGV-element, or the text of the following + ARGV-element, is returned in `gnu_optarg'. Two colons mean an option that + wants an optional arg; if there is text in the current ARGV-element, + it is returned in `gnu_optarg', otherwise `gnu_optarg' is set to zero. + + If OPTSTRING starts with `-' or `+', it requests different methods of + handling the non-option ARGV-elements. + See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. + + Long-named options begin with `--' instead of `-'. + Their names may be abbreviated as long as the abbreviation is unique + or is an exact match for some defined option. If they have an + argument, it follows the option name in the same ARGV-element, separated + from the option name by a `=', or else the in next ARGV-element. + When `gnu_getopt' finds a long-named option, it returns 0 if that option's + `flag' field is nonzero, the value of the option's `val' field + if the `flag' field is zero. + + The elements of ARGV aren't really const, because we permute them. + But we pretend they're const in the prototype to be compatible + with other systems. + + LONGOPTS is a vector of `struct option' terminated by an + element containing a name which is zero. + + LONGIND returns the index in LONGOPT of the long-named option found. + It is only valid when a long-named option has been found by the most + recent call. + + If LONG_ONLY is nonzero, '-' as well as '--' can introduce + long-named options. */ + +int +_gnu_getopt_internal( int argc, + char *const *argv, + const char *optstring, + const struct option *longopts, + int *longind, + int long_only ) { + gnu_optarg = NULL; + + if ( !__gnu_getopt_initialized || gnu_optind == 0 ) { + optstring = _gnu_getopt_initialize (argc, argv, optstring); + gnu_optind = 1; /* Don't scan ARGV[0], the program name. */ + __gnu_getopt_initialized = 1; + } + + /* Test whether ARGV[gnu_optind] points to a non-option argument. + Either it does not have option syntax, or there is an environment flag + from the shell indicating it is not an option. The later information + is only used when the used in the GNU libc. */ + +#define NONOPTION_P (argv[gnu_optind][0] != '-' || argv[gnu_optind][1] == '\0') + + if ( nextchar == NULL || *nextchar == '\0' ) { + /* Advance to the next ARGV-element. */ + + /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been + moved back by the user (who may also have changed the arguments). */ + if ( last_nonopt > gnu_optind ) + last_nonopt = gnu_optind; + if ( first_nonopt > gnu_optind ) + first_nonopt = gnu_optind; + + if ( ordering == PERMUTE ) { + /* If we have just processed some options following some non-options, + exchange them so that the options come first. */ + + if ( first_nonopt != last_nonopt && last_nonopt != gnu_optind ) + exchange ((char **) argv); + else if ( last_nonopt != gnu_optind ) + first_nonopt = gnu_optind; + + /* Skip any additional non-options + and extend the range of non-options previously skipped. */ + + while ( gnu_optind < argc && NONOPTION_P ) + gnu_optind++; + last_nonopt = gnu_optind; + } + + /* The special ARGV-element `--' means premature end of options. + Skip it like a null option, + then exchange with previous non-options as if it were an option, + then skip everything else like a non-option. */ + + if ( gnu_optind != argc && !strcmp (argv[gnu_optind], "--") ) { + gnu_optind++; + + if ( first_nonopt != last_nonopt && last_nonopt != gnu_optind ) + exchange ((char **) argv); + else if ( first_nonopt == last_nonopt ) + first_nonopt = gnu_optind; + last_nonopt = argc; + + gnu_optind = argc; + } + + /* If we have done all the ARGV-elements, stop the scan + and back over any non-options that we skipped and permuted. */ + + if ( gnu_optind == argc ) { + /* Set the next-arg-index to point at the non-options + that we previously skipped, so the caller will digest them. */ + if ( first_nonopt != last_nonopt ) + gnu_optind = first_nonopt; + return -1; + } + + /* If we have come to a non-option and did not permute it, + either stop the scan or describe it to the caller and pass it by. */ + + if ( NONOPTION_P ) { + if ( ordering == REQUIRE_ORDER ) + return -1; + gnu_optarg = argv[gnu_optind++]; + return 1; + } + + /* We have found another option-ARGV-element. + Skip the initial punctuation. */ + + nextchar = (argv[gnu_optind] + 1 + + (longopts != NULL && argv[gnu_optind][1] == '-')); + } + + /* Decode the current option-ARGV-element. */ + + /* Check whether the ARGV-element is a long option. + + If long_only and the ARGV-element has the form "-f", where f is + a valid short option, don't consider it an abbreviated form of + a long option that starts with f. Otherwise there would be no + way to give the -f short option. + + On the other hand, if there's a long option "fubar" and + the ARGV-element is "-fu", do consider that an abbreviation of + the long option, just like "--fu", and not "-f" with arg "u". + + This distinction seems to be the most useful approach. */ + + if ( longopts != NULL + && (argv[gnu_optind][1] == '-' + || (long_only && (argv[gnu_optind][2] || !my_index (optstring, argv[gnu_optind][1])))) ) { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = -1; + int option_index; + + for ( nameend = nextchar; *nameend && *nameend != '='; nameend++ ) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for ( p = longopts, option_index = 0; p->name; p++, option_index++ ) + if ( !strncmp (p->name, nextchar, nameend - nextchar) ) { + if ( (unsigned int) (nameend - nextchar) + == (unsigned int) strlen (p->name) ) { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } else if ( pfound == NULL ) { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } else + /* Second or later nonexact match found. */ + ambig = 1; + } + + if ( ambig && !exact ) { + if ( gnu_opterr ) + fprintf (stderr, _("%s: option `%s' is ambiguous\n"), + argv[0], argv[gnu_optind]); + nextchar += strlen (nextchar); + gnu_optind++; + gnu_optopt = 0; + return '?'; + } + + if ( pfound != NULL ) { + option_index = indfound; + gnu_optind++; + if ( *nameend ) { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if ( pfound->has_arg ) + gnu_optarg = nameend + 1; + else { + if ( gnu_opterr ) { + if ( argv[gnu_optind - 1][1] == '-' ) { + /* --option */ + fprintf (stderr, + _("%s: option `--%s' doesn't allow an argument\n"), + argv[0], pfound->name); + } else { + /* +option or -option */ + fprintf (stderr, + _("%s: option `%c%s' doesn't allow an argument\n"), + argv[0], argv[gnu_optind - 1][0], pfound->name); + } + } + + nextchar += strlen (nextchar); + + gnu_optopt = pfound->val; + return '?'; + } + } else if ( pfound->has_arg == 1 ) { + if ( gnu_optind < argc ) + gnu_optarg = argv[gnu_optind++]; + else { + if ( gnu_opterr ) + fprintf (stderr, + _("%s: option `%s' requires an argument\n"), + argv[0], argv[gnu_optind - 1]); + nextchar += strlen (nextchar); + gnu_optopt = pfound->val; + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen (nextchar); + if ( longind != NULL ) + *longind = option_index; + if ( pfound->flag ) { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + + /* Can't find it as a long option. If this is not gnu_getopt_long_only, + or the option starts with '--' or is not a valid short + option, then it's an error. + Otherwise interpret it as a short option. */ + if ( !long_only || argv[gnu_optind][1] == '-' + || my_index (optstring, *nextchar) == NULL ) { + if ( gnu_opterr ) { + if ( argv[gnu_optind][1] == '-' ) + /* --option */ + fprintf (stderr, _("%s: unrecognized option `--%s'\n"), + argv[0], nextchar); + else + /* +option or -option */ + fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), + argv[0], argv[gnu_optind][0], nextchar); + } + nextchar = (char *) ""; + gnu_optind++; + gnu_optopt = 0; + return '?'; + } + } + + /* Look at and handle the next short option-character. */ + + { + char c = *nextchar++; + char *temp = my_index (optstring, c); + + /* Increment `gnu_optind' when we start to process its last character. */ + if ( *nextchar == '\0' ) + ++gnu_optind; + + if ( temp == NULL || c == ':' ) { + if ( gnu_opterr ) { + if ( posixly_correct ) + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, _("%s: illegal option -- %c\n"), + argv[0], c); + else + fprintf (stderr, _("%s: invalid option -- %c\n"), + argv[0], c); + } + gnu_optopt = c; + return '?'; + } + /* Convenience. Treat POSIX -W foo same as long option --foo */ + if ( temp[0] == 'W' && temp[1] == ';' ) { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = 0; + int option_index; + + /* This is an option that requires an argument. */ + if ( *nextchar != '\0' ) { + gnu_optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + gnu_optind++; + } else if ( gnu_optind == argc ) { + if ( gnu_opterr ) { + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, _("%s: option requires an argument -- %c\n"), + argv[0], c); + } + gnu_optopt = c; + if ( optstring[0] == ':' ) + c = ':'; + else + c = '?'; + return c; + } else + /* We already incremented `gnu_optind' once; + increment it again when taking next ARGV-elt as argument. */ + gnu_optarg = argv[gnu_optind++]; + + /* gnu_optarg is now the argument, see if it's in the + table of longopts. */ + + for ( nextchar = nameend = gnu_optarg; *nameend && *nameend != '='; nameend++ ) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for ( p = longopts, option_index = 0; p->name; p++, option_index++ ) + if ( !strncmp (p->name, nextchar, nameend - nextchar) ) { + if ( (unsigned int) (nameend - nextchar) == strlen (p->name) ) { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } else if ( pfound == NULL ) { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } else + /* Second or later nonexact match found. */ + ambig = 1; + } + if ( ambig && !exact ) { + if ( gnu_opterr ) + fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), + argv[0], argv[gnu_optind]); + nextchar += strlen (nextchar); + gnu_optind++; + return '?'; + } + if ( pfound != NULL ) { + option_index = indfound; + if ( *nameend ) { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if ( pfound->has_arg ) + gnu_optarg = nameend + 1; + else { + if ( gnu_opterr ) + fprintf (stderr, _("\ +%s: option `-W %s' doesn't allow an argument\n"), + argv[0], pfound->name); + + nextchar += strlen (nextchar); + return '?'; + } + } else if ( pfound->has_arg == 1 ) { + if ( gnu_optind < argc ) + gnu_optarg = argv[gnu_optind++]; + else { + if ( gnu_opterr ) + fprintf (stderr, + _("%s: option `%s' requires an argument\n"), + argv[0], argv[gnu_optind - 1]); + nextchar += strlen (nextchar); + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen (nextchar); + if ( longind != NULL ) + *longind = option_index; + if ( pfound->flag ) { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + nextchar = NULL; + return 'W'; /* Let the application handle it. */ + } + if ( temp[1] == ':' ) { + if ( temp[2] == ':' ) { + /* This is an option that accepts an argument optionally. */ + if ( *nextchar != '\0' ) { + gnu_optarg = nextchar; + gnu_optind++; + } else + gnu_optarg = NULL; + nextchar = NULL; + } else { + /* This is an option that requires an argument. */ + if ( *nextchar != '\0' ) { + gnu_optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + gnu_optind++; + } else if ( gnu_optind == argc ) { + if ( gnu_opterr ) { + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, + _("%s: option requires an argument -- %c\n"), + argv[0], c); + } + gnu_optopt = c; + if ( optstring[0] == ':' ) + c = ':'; + else + c = '?'; + } else + /* We already incremented `gnu_optind' once; + increment it again when taking next ARGV-elt as argument. */ + gnu_optarg = argv[gnu_optind++]; + nextchar = NULL; + } + } + return c; + } +} + +int +gnu_getopt ( int argc, + char *const *argv, + const char *optstring ) { + return _gnu_getopt_internal (argc, argv, optstring, + (const struct option *) 0, + (int *) 0, + 0); +} + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + + +#ifdef TEST + +/* Compile with -DTEST to make an executable for use in testing + the above definition of `gnu_getopt'. */ + +int +main (argc, argv) +int argc; +char **argv; +{ +int c; +int digit_optind = 0; + +while ( 1 ) { + int this_option_optind = gnu_optind ? gnu_optind : 1; + + c = gnu_getopt (argc, argv, "abc:d:0123456789"); + if ( c == -1 ) + break; + + switch ( c ) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if ( digit_optind != 0 && digit_optind != this_option_optind ) + fprintf ( stderr, "digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + fprintf ( stderr, "option %c\n", c); + break; + + case 'a': + fprintf ( stderr, "option a\n"); + break; + + case 'b': + fprintf ( stderr, "option b\n"); + break; + + case 'c': + fprintf ( stderr, "option c with value `%s'\n", gnu_optarg); + break; + + case '?': + break; + + default: + fprintf ( stderr, "?? gnu_getopt returned character code 0%o ??\n", c); + } +} + +if ( gnu_optind < argc ) { + fprintf (stderr, "non-option ARGV-elements: "); + while ( gnu_optind < argc ) + fprintf ( stderr, "%s ", argv[gnu_optind++]); + fprintf ( stderr, "\n"); +} + +exit (0); +} + +#endif /* TEST */ diff --git a/src/gnu_getopt_long.c b/src/gnu_getopt_long.c new file mode 100644 index 0000000..9049feb --- /dev/null +++ b/src/gnu_getopt_long.c @@ -0,0 +1,162 @@ +/* gnu_getopt_long and getopt_long_only entry points for GNU getopt. + Copyright (C) 1987,88,89,90,91,92,93,94,96,97 Free Software Foundation, Inc. + + This file is part of the GNU C Library. Its master source is NOT part of + the C library, however. The master source lives in /gd/gnu/lib. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* + * modified July 9, 1999 by mark gates <mgates@nlanr.net> + * Dec 17, 1999 + * + * renamed all functions and variables by prepending "gnu_" + * removed/redid a bunch of stuff under the assumption we're + * using a modern standard C compiler. + * renamed file to gnu_getopt_long.c (from gnu_getopt1.c) + * + * $Id: gnu_getopt_long.c,v 1.1.1.1 2004/05/18 01:50:44 kgibbs Exp $ + */ + + + +#include "gnu_getopt.h" + +#include <stdio.h> +#include <stdlib.h> + +#ifdef __cplusplus +extern "C" { +#endif + +int +gnu_getopt_long( int argc, + char *const *argv, + const char *options, + const struct option *long_options, + int *opt_index ) { + return _gnu_getopt_internal (argc, argv, options, long_options, opt_index, 0); +} + +/* Like gnu_getopt_long, but '-' as well as '--' can indicate a long option. + If an option that starts with '-' (not '--') doesn't match a long option, + but does match a short option, it is parsed as a short option + instead. */ + +int +gnu_getopt_long_only( int argc, + char *const *argv, + const char *options, + const struct option *long_options, + int *opt_index ) { + return _gnu_getopt_internal (argc, argv, options, long_options, opt_index, 1); +} + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + + +#ifdef TEST + + #include <stdio.h> + +int +main (argc, argv) +int argc; +char **argv; +{ +int c; +int digit_optind = 0; + +while ( 1 ) { + int this_option_optind = gnu_optind ? gnu_optind : 1; + int option_index = 0; + static struct option long_options[] = + { + {"add", 1, 0, 0}, + {"append", 0, 0, 0}, + {"delete", 1, 0, 0}, + {"verbose", 0, 0, 0}, + {"create", 0, 0, 0}, + {"file", 1, 0, 0}, + {0, 0, 0, 0} + }; + + c = gnu_getopt_long (argc, argv, "abc:d:0123456789", + long_options, &option_index); + if ( c == -1 ) + break; + + switch ( c ) { + case 0: + fprintf ( stderr, "option %s", long_options[option_index].name); + if ( gnu_optarg ) + fprintf ( stderr, " with arg %s", gnu_optarg); + fprintf ( stderr, "\n"); + break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if ( digit_optind != 0 && digit_optind != this_option_optind ) + fprintf ( stderr, "digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + fprintf ( stderr, "option %c\n", c); + break; + + case 'a': + fprintf ( stderr, "option a\n"); + break; + + case 'b': + fprintf ( stderr, "option b\n"); + break; + + case 'c': + fprintf ( stderr, "option c with value `%s'\n", gnu_optarg); + break; + + case 'd': + fprintf ( stderr, "option d with value `%s'\n", gnu_optarg); + break; + + case '?': + break; + + default: + fprintf ( stderr, "?? gnu_getopt returned character code 0%o ??\n", c); + } +} + +if ( gnu_optind < argc ) { + fprintf ( stderr, "non-option ARGV-elements: "); + while ( gnu_optind < argc ) + fprintf ( stderr, "%s ", argv[gnu_optind++]); + fprintf ( stderr, "\n"); +} + +exit (0); +} + +#endif /* TEST */ diff --git a/src/histogram.c b/src/histogram.c new file mode 100644 index 0000000..3a9b82c --- /dev/null +++ b/src/histogram.c @@ -0,0 +1,269 @@ +/*--------------------------------------------------------------- + * Copyright (c) 2017 + * Broadcom Corporation + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the name of Broadcom Coporation, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * + * histograms.c + * Suppport for histograms + * + * by Robert J. McMahon (rjmcmahon@rjmcmahon.com, bob.mcmahon@broadcom.com) + * ------------------------------------------------------------------- + */ +#include "headers.h" +#include "histogram.h" +#ifdef HAVE_THREAD_DEBUG +// needed for thread_debug +#include "Thread.h" +#endif +struct histogram *histogram_init(unsigned int bincount, unsigned int binwidth, float offset, float units,\ + double ci_lower, double ci_upper, unsigned int id, char *name) { + struct histogram *this = (struct histogram *) malloc(sizeof(struct histogram)); + if (!this) { + fprintf(stderr,"Malloc failure in histogram init\n"); + return(NULL); + } + if (!bincount) + bincount = 1000; + this->mybins = (unsigned int *) malloc(sizeof(unsigned int) * bincount); + if (!this->mybins) { + fprintf(stderr,"Malloc failure in histogram init b\n"); + free(this); + return(NULL); + } + this->myname = (char *) malloc(sizeof(strlen(name))); + if (!this->myname) { + fprintf(stderr,"Malloc failure in histogram init n\n"); + free(this->mybins); + free(this); + return(NULL); + } + this->outbuf = (char *) malloc(120 + (32*bincount) + strlen(name)); + if (!this->outbuf) { + fprintf(stderr,"Malloc failure in histogram init o\n"); + free(this->myname); + free(this->mybins); + free(this); + return(NULL); + } + memset(this->mybins, 0, bincount * sizeof(unsigned int)); + strcpy(this->myname, name); + this->id = id; + this->bincount = bincount; + this->binwidth = binwidth; + this->populationcnt = 0; + this->offset=offset; + this->units=units; + this->cntloweroutofbounds=0; + this->cntupperoutofbounds=0; + this->ci_lower = ci_lower; + this->ci_upper = ci_upper; + this->prev = NULL; + this->maxbin = -1; + this->fmaxbin = -1; + this->maxts.tv_sec = 0; + this->maxts.tv_usec = 0; + this->fmaxts.tv_sec = 0; + this->fmaxts.tv_usec = 0; +#ifdef HAVE_THREAD_DEBUG + thread_debug("histo create %p", (void *) this); +#endif + return this; +} + +void histogram_delete(struct histogram *h) { +#ifdef HAVE_THREAD_DEBUG + thread_debug("histo delete %p", (void *) h); +#endif + if (h) { + if (h->prev) + histogram_delete(h->prev); + if (h->mybins) + free(h->mybins); + if (h->myname) + free(h->myname); + free(h); + } +} + +// value is units seconds +int histogram_insert(struct histogram *h, float value, struct timeval *ts) { + int bin; + // calculate the bin, convert the value units from seconds to units of interest + bin = (int) (h->units * (value - h->offset) / h->binwidth); + h->populationcnt++; + if (ts && (value > h->maxval)) { + h->maxbin = bin; + h->maxval = value; + h->maxts.tv_sec = ts->tv_sec; + h->maxts.tv_usec = ts->tv_usec; + // printf("imax=%ld.%ld %f\n",h->maxts.tv_sec, h->maxts.tv_usec, value); + if (value > h->fmaxval) { + h->fmaxbin = bin; + h->fmaxval = value; + h->fmaxts.tv_sec = ts->tv_sec; + h->fmaxts.tv_usec = ts->tv_usec; + // printf("fmax=%ld.%ld %f\n",h->fmaxts.tv_sec, h->fmaxts.tv_usec, value); + } + } + if (bin < 0) { + h->cntloweroutofbounds++; + return(-1); + } else if (bin > (int) h->bincount) { + h->cntupperoutofbounds++; + return(-2); + } + else { + h->mybins[bin]++; + return(h->mybins[bin]); + } +} + +void histogram_clear(struct histogram *h) { + memset(h->mybins, 0, (h->bincount * sizeof(unsigned int))); + h->populationcnt = 0; + h->cntloweroutofbounds=0; + h->cntupperoutofbounds=0; + h->maxbin = 0; + h->maxts.tv_sec = 0; + h->maxts.tv_usec = 0; + if (h->prev) + histogram_clear(h->prev); + h->prev = NULL; +} + +void histogram_add(struct histogram *to, struct histogram *from) { + int ix; + assert(to != NULL); + assert(from != NULL); + if (to->bincount <= from->bincount) { + for (ix=0; ix < to->bincount; ix ++) { + to->mybins[ix] += from->mybins[ix]; + } + to->populationcnt += from->populationcnt; + to->cntloweroutofbounds += from->cntloweroutofbounds; + to->cntupperoutofbounds += from->cntupperoutofbounds; + if (from->maxbin > to->maxbin) { + to->maxbin = from->maxbin; + } + if (from->maxts.tv_sec > to->maxts.tv_sec) { + to->maxts.tv_sec = from->maxts.tv_sec; + to->maxts.tv_usec = from->maxts.tv_usec; + } else if ((from->maxts.tv_sec == to->maxts.tv_sec) && \ + (from->maxts.tv_usec > to->maxts.tv_usec)) { + to->maxts.tv_usec = from->maxts.tv_usec; + } + } +} + +void histogram_print(struct histogram *h, double start, double end) { + if (h->final && h->prev) { + histogram_clear(h->prev); + } + if (!h->prev) { + h->prev = histogram_init(h->bincount, h->binwidth, h->offset, h->units, h->ci_lower, h->ci_upper, h->id, h->myname); + } + int n = 0, ix, delta, lowerci, upperci, outliercnt, fence_lower, fence_upper, upper3stdev; + int running=0; + int intervalpopulation, oob_u, oob_l; + intervalpopulation = h->populationcnt - h->prev->populationcnt; + strcpy(h->outbuf, h->myname); + sprintf(h->outbuf, "[%3d] " IPERFTimeFrmt " sec %s%s%s bin(w=%d%s):cnt(%d)=", h->id, start, end, h->myname, (h->final ? "(f)" : ""), "-PDF:",h->binwidth, ((h->units == 1e3) ? "ms" : "us"), intervalpopulation); + n = strlen(h->outbuf); + lowerci=0; + upperci=0; + upper3stdev = 0; + outliercnt=0; + fence_lower = 0; + fence_upper = 0; + int outside3fences = 0; + h->prev->populationcnt = h->populationcnt; + oob_l = h->cntloweroutofbounds - h->prev->cntloweroutofbounds; + h->prev->cntloweroutofbounds = h->cntloweroutofbounds; + oob_u = h->cntupperoutofbounds - h->prev->cntupperoutofbounds; + h->prev->cntupperoutofbounds = h->cntupperoutofbounds; + + for (ix = 0; ix < h->bincount; ix++) { + delta = h->mybins[ix] - h->prev->mybins[ix]; + if (delta > 0) { + running+=delta; + if (!lowerci && ((float)running/intervalpopulation > h->ci_lower/100.0)) { + lowerci = ix+1; + } + // use 10% and 90% for inner fence post, then 3 times for outlier + if ((float)running/intervalpopulation < 0.1) { + fence_lower=ix+1; + } + if ((float)running/intervalpopulation < 0.9) { + fence_upper=ix+1; + } else if (!outside3fences) { + outside3fences = fence_upper + (3 * (fence_upper - fence_lower)); + } else if (ix > outside3fences) { + outliercnt += delta; + } + if (!upperci && ((float)running/intervalpopulation > h->ci_upper/100.0)) { + upperci = ix+1; + } + if (!upper3stdev && ((float)running/intervalpopulation > 99.7/100.0)) { + upper3stdev = ix+1; + } + n += sprintf(h->outbuf + n,"%d:%d,", ix+1, delta); + h->prev->mybins[ix] = h->mybins[ix]; + } + } + h->outbuf[strlen(h->outbuf)-1] = '\0'; + if (!upperci) + upperci=h->bincount; + if (!upper3stdev) + upper3stdev=h->bincount; + if (h->ci_upper > 99.7) + fprintf(stdout, "%s (%.2f/99.7/%.2f/%%=%d/%d/%d,Outliers=%d,obl/obu=%d/%d)", \ + h->outbuf, h->ci_lower, h->ci_upper, lowerci, upper3stdev, upperci, outliercnt, oob_l, oob_u); + else + fprintf(stdout, "%s (%.2f/%.2f/99.7%%=%d/%d/%d,Outliers=%d,obl/obu=%d/%d)", \ + h->outbuf, h->ci_lower, h->ci_upper, lowerci, upperci, upper3stdev, outliercnt, oob_l, oob_u); + if (!h->final && (h->maxval > 0) && ((h->maxts.tv_sec > 0) || h->maxts.tv_usec > 0)) { + fprintf(stdout, " (%0.3f ms/%ld.%ld)\n", (h->maxval * 1e3), (long) h->maxts.tv_sec, (long) h->maxts.tv_usec); + h->maxbin = -1; + h->maxval = 0; + } else if (h->final && (h->fmaxval > 0) && ((h->maxts.tv_sec > 0) || h->maxts.tv_usec > 0)) { + fprintf(stdout, " (%0.3f ms/%ld.%ld)\n", (h->fmaxval * 1e3), (long) h->fmaxts.tv_sec, (long) h->fmaxts.tv_usec); + } else { + fprintf(stdout, "\n"); + } +} diff --git a/src/igmp_querier.c b/src/igmp_querier.c new file mode 100644 index 0000000..d18af5b --- /dev/null +++ b/src/igmp_querier.c @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2018 + * Broadcom Corporation + * All Rights Reserved. + * Redistribution and use in source and binary forms, with or without modification, are permitted + * provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this list of conditions + * and the following disclaimer. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. Neither the name of the Broadcom nor the names of + * contributors may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USEn, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author Robert J. McMahon, Broadcom LTD + * Date April 2016 + * + * IGMP 2 querier that can be controlled remotely + * + * Author Robert J. McMahon (rmcmahon) + * Last modified: 06/25/2010 + * + * $Copyright Open Broadcom Corporation$ + * + */ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#include <stdio.h> +#include <signal.h> +#include <unistd.h> +#include <stdlib.h> +#include <time.h> +#include <netinet/in.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <strings.h> +#include <string.h> +#include <errno.h> +#include <ctype.h> +#include <arpa/inet.h> +#include "headers.h" + +#define IGMP_HEADER_SIZE 8 + +void sigint(); +void siguser(); +void sigalrm(); +static int querier_sent_count = 0; +static int sendcount = 0; +static short daemonmode = 0; +static char mcast_queryaddr[20] = "224.0.0.1"; +static int send_igmp_allhosts_querier (char *); + + +int main (int argc, char **argv) { + char *tvalue = NULL; + char *cvalue = NULL; + int c; + int queryinterval; + int pid; + + opterr = 0; + while ((c = getopt (argc, argv, "c:dg:t:")) != -1) { + switch (c) { + case 'c': + cvalue = optarg; + break; + case 'g' : + strcpy(mcast_queryaddr, optarg); + break; + case 't': + tvalue = optarg; + break; + case 'd': + daemonmode = 1; + break; + case '?': + if (optopt == 't') + fprintf (stderr, "Option -%c requires an integer argument.\n", optopt); + else if (optopt == 'c') + fprintf (stderr, "Option -%c requires an integer argument.\n", optopt); + else if (isprint (optopt)) + fprintf (stderr, "Unknown option `-%c'.\n", optopt); + else + fprintf (stderr, + "Unknown option character `\\x%x'.\n", + optopt); + default: + fprintf(stderr,"Usage -c <count>, -d daemon, -g <group>, -t <period in seconds>\n"); + exit(-1); + } + } + if (tvalue != NULL) { + queryinterval = atoi(tvalue); + } else { + queryinterval = 0; + } + if (cvalue != NULL) { + sendcount = atoi(cvalue); + if (tvalue == NULL) + queryinterval = 0; + } else { + sendcount = 1; + } + signal(SIGINT, sigint); + signal(SIGUSR1, siguser); + signal(SIGALRM, sigalrm); + pid = (int) getpid(); + if (daemonmode) { + if (tvalue != NULL) { + sendcount = 1; + printf("IGMP All Hosts Querier (pid=%d) started as a daemon with interval of %d seconds to %s\n", pid, queryinterval, mcast_queryaddr); + } else { + sendcount = 0; + printf("IGMP All Hosts Querier (pid=%d) to %s started as a daemon only\n", pid, mcast_queryaddr); + } + } else { + printf("IGMP All Hosts Querier (pid=%d) sending %d reports with interval of %d seconds\n", pid, sendcount, queryinterval); + } + fflush(stdout); + while (daemonmode || sendcount) { + if (sendcount-- > 0) { + send_igmp_allhosts_querier(mcast_queryaddr); + } + if (queryinterval) { + alarm(queryinterval); + pause(); + } + if (daemonmode && sendcount <= 0) + pause(); + } +} + +void sigint (void) { + exit(0); +} + +void siguser (void) { + if (!send_igmp_allhosts_querier(mcast_queryaddr)) { + exit (-1); + } +} + +void sigalrm (void) { + if (daemonmode) + sendcount++; +} + +static int send_igmp_allhosts_querier (char *mcast_queryaddr) { + int sid=0; + int rc; + char buf[IGMP_HEADER_SIZE]; + unsigned int ttl=1; + char type = 17; + char maxresptime = 1; + // unsigned int groupaddr = 0; + char checksum_upper = 0xee; + char checksum_lower = 0xfe; + struct sockaddr_in msock; + const time_t timer = time(NULL); + + bzero (&buf, sizeof(buf)); + /* + * Note: with byte writes shouldn't need to worry about network/host + * byte ordering, though should double check on non intel system + */ + buf[0] = type; + buf[1] = maxresptime; + buf[2] = checksum_upper; + buf[3] = checksum_lower; + + bzero (&msock, sizeof(msock)); + msock.sin_family = AF_INET; + + inet_pton(AF_INET, mcast_queryaddr, &msock.sin_addr); + setuid(geteuid()); + sid = socket(AF_INET, SOCK_RAW, IPPROTO_IGMP); + if (sid != -1) { + rc = setsockopt(sid, IPPROTO_IP, IP_TTL, (char *) &ttl, sizeof(ttl)); + if (rc != -1) { + rc = sendto(sid, &buf, IGMP_HEADER_SIZE, 0, (const struct sockaddr *) &msock, sizeof(msock)); + if (rc == -1) { + fprintf(stderr, "IGMP Query sendto error = %s\n", strerror(errno)); + } + } else { + fprintf(stderr, "IGMP Query setsockopt error = %s\n", strerror(errno)); + } + } else { + fprintf(stderr, "IGMP Query, socket error = %s\n", strerror(errno)); + } + if (sid > 0) { + close(sid); + rc=1; + } else { + rc = 0; + } + setuid(getuid()); + if (rc) { + printf("Sent IGMP all hosts querier to %s (count = %d) at %s",mcast_queryaddr, ++querier_sent_count, ctime(&timer)); + fflush(stdout); + } + return rc; +} diff --git a/src/iperf_formattime.c b/src/iperf_formattime.c new file mode 100644 index 0000000..df65650 --- /dev/null +++ b/src/iperf_formattime.c @@ -0,0 +1,100 @@ +/*--------------------------------------------------------------- + * Copyright (c) 2023 + * Broadcom Corporation + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the name of Broadcom Coporation, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * + * iperf_formattime + * wrapper around strftime.c for iperf supported formatting + * + * by Robert J. McMahon (rjmcmahon@rjmcmahon.com, bob.mcmahon@broadcom.com) + * ------------------------------------------------------------------- + */ +#include "headers.h" +#include "util.h" +#include "iperf_formattime.h" + +inline void iperf_formattime (char *timestr, int buflen, struct timeval timestamp, bool prec_ms, bool utc_time, enum TimeFormatType ftype) { + struct tm ts ; + ts = (utc_time ? *gmtime(×tamp.tv_sec) : *localtime(×tamp.tv_sec)); + switch (ftype) { + case YearThruSec: + strftime(timestr, buflen, "%Y-%m-%d %H:%M:%S", &ts); + if (prec_ms) { + int currlen = strlen(timestr); + if (currlen > 5) { + snprintf((timestr + currlen), 5, ".%.3d", (int) (timestamp.tv_usec/1000)); + } + } + break; + case YearThruSecTZ: + strftime(timestr, buflen, "%Y-%m-%d %H:%M:%S", &ts); + int currlen = strlen(timestr); + if (prec_ms) { + if (currlen > 5) { + snprintf((timestr + currlen), 5, ".%.3d", (int) (timestamp.tv_usec/1000)); + currlen = strlen(timestr); + } + } + if ((buflen - currlen) > 5) { + strftime((timestr + currlen), (buflen - currlen), " (%Z)", &ts); + } + break; + case CSV: + strftime(timestr, buflen, "%Y%m%d%H%M%S", &ts); + if (prec_ms) { + int currlen = strlen(timestr); + if (currlen > 5) { + snprintf((timestr + currlen), 5, ".%.3d", (int) (timestamp.tv_usec/1000)); + } + } + break; + case CSVTZ: + strftime(timestr, buflen, "%z:%Y%m%d%H%M%S", &ts); + if (prec_ms) { + int currlen = strlen(timestr); + if (currlen > 5) { + snprintf((timestr + currlen), 5, ".%.3d", (int) (timestamp.tv_usec/1000)); + } + } + break; + default: + FAIL_exit(1, "iperf_formattime program error"); + } + timestr[buflen - 1] = '\0'; // make sure string is null terminated +} diff --git a/src/isochronous.cpp b/src/isochronous.cpp new file mode 100644 index 0000000..573f05a --- /dev/null +++ b/src/isochronous.cpp @@ -0,0 +1,275 @@ +/*--------------------------------------------------------------- + * Copyright (c) 2017-2021 + * Broadcom Corporation + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the name of Broadcom Coporation, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * + * isochronous.c + * Suppport for isochonronous traffic testing + * + * by Robert J. McMahon (rjmcmahon@rjmcmahon.com, bob.mcmahon@broadcom.com) + * ------------------------------------------------------------------- + */ +#include "headers.h" +#include "Timestamp.hpp" +#include "isochronous.hpp" +#include "delay.h" + +#define BILLION 1000000000 + +using namespace Isochronous; + +FrameCounter::FrameCounter (double value, const Timestamp& start) : frequency(value) { + period = static_cast<unsigned int>(1000000 / frequency); + startTime = start; + nextslotTime=start; + lastcounter = 0; + slot_counter = 0; + slip = 0; +} +FrameCounter::FrameCounter (double value) : frequency(value) { +#ifdef WIN32 + /* Create timer */ + my_timer = CreateWaitableTimer(NULL, TRUE, NULL); + if (!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL)) + WARN_errno(1, "SetThreadPriority"); +#endif + period = static_cast<unsigned int>(1000000 / frequency); // unit us + lastcounter = 0; + slot_counter = 0; + slip = 0; +} + + +FrameCounter::~FrameCounter () { +#ifdef WIN32 + /* Clean resources */ + if (my_timer) + CloseHandle(my_timer); +#endif +} + +#ifdef WIN32 +/* Windows sleep in 100ns units returns 0 on success as does clock_nanosleep*/ +int FrameCounter::mySetWaitableTimer (long delay_time) { + int rc = -1; + if (!my_timer) { + if ((my_timer = CreateWaitableTimer(NULL, TRUE, NULL))) { + /* Set timer properties */ + delay.QuadPart = -delay_time; + } else { + WARN_errno(1, "CreateWaitable"); + my_timer = NULL; + } + } + if (my_timer) { + /* Set timer properties */ + /* negative values are relative, positive absolute UTC time */ + delay.QuadPart = -delay_time; + if(!SetWaitableTimer(my_timer, &delay, 0, NULL, NULL, FALSE)) { + WARN_errno(1, "SetWaitableTimer"); + CloseHandle(my_timer); + my_timer = NULL; + } else { + // Wait for timer + if (WaitForSingleObject(my_timer, INFINITE)) { + WARN_errno(1, "WaitForSingleObject"); + } else { + rc = 0; + } + } + } + return rc; +} +#endif + +#if HAVE_CLOCK_NANOSLEEP +unsigned int FrameCounter::wait_tick (long *sched_err) { + Timestamp now; + int rc = true; + if (!slot_counter) { + slot_counter = 1; + now.setnow(); + nextslotTime = now; + } else { + while (!now.before(nextslotTime)) { + now.setnow(); + nextslotTime.add(period); +// printf("***** next slot %ld.%ld\n",nextslotTime.getSecs(), nextslotTime.getUsecs()); + slot_counter++; + } + if (lastcounter && ((slot_counter - lastcounter) > 1)) { + slip++; + } + } + #ifndef WIN32 + timespec txtime_ts; + txtime_ts.tv_sec = nextslotTime.getSecs(); + txtime_ts.tv_nsec = nextslotTime.getUsecs() * 1000; + rc = clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &txtime_ts, NULL); + #else + long duration = nextslotTime.subUsec(now); + rc = mySetWaitableTimer(10 * duration); // convert us to 100 ns + //int rc = clock_nanosleep(0, TIMER_ABSTIME, &txtime_ts, NULL); + #endif + if (sched_err) { + // delay_loop(2020); + Timestamp actual; + *sched_err = actual.subUsec(nextslotTime); +// printf("**** sched err %ld\n", *sched_err); + if (*sched_err < 0) { + *sched_err = -(*sched_err); // err is an absolute value + // Per windows docs, this timer can go off early per: + // APIs that deal with timers use various different hardware clocks. These clocks may have resolutions + // significantly different from what you expect: some may be measured in milliseconds (for those that + // use an RTC-based timer chip), to those measured in nanoseconds (for those that use ACPI or TSC counters). + // You can change the resolution of your API with a call to the timeBeginPeriod and timeEndPeriod functions. + // How precise you can change the resolution depends on which hardware clock the particular API uses. + // For more information, check your hardware documentation. + // + // I noticed the timer going off up to 8 ms early on a Windows 11 cross compile - yikes. + // Do a WAR hack here to add delay if & when that occurs +#ifdef WIN32 + if (*sched_err > 1000) { + delay_loop(*sched_err); + } +#endif + } + } + WARN_errno((rc!=0), "wait_tick failed"); + #ifdef HAVE_THREAD_DEBUG + // thread_debug("Client tick occurred per %ld.%ld", txtime_ts.tv_sec, txtime_ts.tv_nsec / 1000); + #endif + lastcounter = slot_counter; + return(slot_counter); +} +#else +unsigned int FrameCounter::wait_tick (long *sched_err) { + long remaining; + unsigned int framecounter; + + if (!lastcounter) { + reset(); + framecounter = 1; + } else { + framecounter = get(&remaining); + if ((framecounter - lastcounter) > 1) + slip++; +// delay_loop(remaining); + remaining *= 1000; + struct timespec tv0={0,0}, tv1; + tv0.tv_sec = (remaining / BILLION); + tv0.tv_nsec += (remaining % BILLION); + if (tv0.tv_nsec >= BILLION) { + tv0.tv_sec++; + tv0.tv_nsec -= BILLION; + } + Timestamp slotstart = startTime; + slot_counter = get(); + // period unit is in microseconds, convert to seconds + slotstart.add(slot_counter * period * 1e-6); + int rc = nanosleep(&tv0, &tv1); + if (sched_err) { + Timestamp actual; + *sched_err = actual.subUsec(slotstart); +// printf("**** slot %ld.%ld actual %ld.%ld %ld\n", slotstart.getSecs(), slotstart.getUsecs(), actual.getSecs(), actual.getUsecs(), *sched_err); + } + WARN_errno((rc != 0), "nanosleep wait_tick"); ; +// printf("****** rc = %d, remain %ld.%ld\n", rc, tv1.tv_sec, tv1.tv_nsec); + framecounter ++; + } + lastcounter = framecounter; + return(framecounter); +} +#endif +inline unsigned int FrameCounter::get () const { + Timestamp now; + return slot_counter + 1; +} + +inline unsigned int FrameCounter::get (const Timestamp& slot) const { + return(slot_counter + 1); // Frame counter for packets starts at 1 +} + +inline unsigned int FrameCounter::get (long *ticks_remaining) { + assert(ticks_remaining != NULL); + Timestamp sampleTime; // Constructor will initialize timestamp to now + long usecs = -startTime.subUsec(sampleTime); + unsigned int counter = static_cast<unsigned int>(usecs / period) + 1; + // figure out how many usecs before the next frame counter tick + // the caller can use this to delay until the next tick + *ticks_remaining = (counter * period) - usecs; + return(counter + 1); // Frame counter for packets starts at 1 +} + +inline Timestamp FrameCounter::next_slot () { + Timestamp next = startTime; + slot_counter = get(); + // period unit is in microseconds, convert to seconds + next.add(slot_counter * (period / 1e6)); + return next; +} + +unsigned int FrameCounter::period_us () { + return(period); +} + +void FrameCounter::reset () { + period = (1000000 / frequency); + startTime.setnow(); +} + +unsigned int FrameCounter::wait_sync (long sec, long usec) { + long remaining; + unsigned int framecounter; + startTime.set(sec, usec); + framecounter = get(&remaining); + delay_loop(remaining); + reset(); + framecounter = 1; + lastcounter = 1; + return(framecounter); +} + +long FrameCounter::getSecs () { + return startTime.getSecs(); +} + +long FrameCounter::getUsecs () { + return startTime.getUsecs(); +} diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..7038faa --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,479 @@ +/*--------------------------------------------------------------- + * Copyright (c) 1999,2000,2001,2002,2003 + * The Board of Trustees of the University of Illinois + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software (Iperf) and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the names of the University of Illinois, NCSA, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * National Laboratory for Applied Network Research + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * http://www.ncsa.uiuc.edu + * ________________________________________________________________ + * main.cpp + * by Mark Gates <mgates@nlanr.net> + * & Ajay Tirumala <tirumala@ncsa.uiuc.edu> + * ------------------------------------------------------------------- + * main does initialization and creates the various objects that will + * actually run the iperf program, then waits in the Joinall(). + * ------------------------------------------------------------------- + * headers + * uses + * <stdlib.h> + * <string.h> + * + * <signal.h> + * ------------------------------------------------------------------- */ + +#define HEADERS() + +#include "headers.h" +#include "Settings.hpp" +#include "PerfSocket.hpp" +#include "Locale.h" +#include "Condition.h" +#include "Timestamp.hpp" +#include "Listener.hpp" +#include "active_hosts.h" +#include "util.h" +#include "Reporter.h" +#include "payloads.h" + +#ifdef WIN32 +#include "service.h" +#endif + +/* ------------------------------------------------------------------- + * prototypes + * ------------------------------------------------------------------- */ +// Function called at exit to clean up as much as possible +void cleanup(); +// signal handlers +static void Sig_Interupt(int inSigno); + +/* ------------------------------------------------------------------- + * global variables + * ------------------------------------------------------------------- */ +extern "C" { + // Global flag to signal a user interrupt + int sInterupted = 0; + // Global ID that we increment to be used + // as identifier for SUM reports + int groupID = 0; + // Mutex to protect access to the above ID + Mutex transferid_mutex; + // Condition used to signal the reporter thread + // when a packet ring is full. Shouldn't really + // be needed but is "belts and suspeners" + struct Condition ReportCond; + // Initialize reporter thread mutex + struct AwaitMutex reporter_state; + struct AwaitMutex threads_start; + struct BarrierMutex transmits_start; +} + + +// global variables only accessed within this file + +// Thread that received the SIGTERM or SIGINT signal +// Used to ensure that if multiple threads receive the +// signal we do not prematurely exit +nthread_t sThread; +static thread_Settings* ext_gSettings; +// The main thread uses this function to wait +// for all other threads to complete +void waitUntilQuit(); + +/* ------------------------------------------------------------------- + * main() + * Entry point into Iperf + * + * sets up signal handlers + * initialize global locks and conditions + * parses settings from environment and command line + * starts up server or client thread + * waits for all threads to complete + * ------------------------------------------------------------------- */ +int main(int argc, char **argv) { + + // Set SIGTERM and SIGINT to call our user interrupt function + my_signal(SIGTERM, Sig_Interupt); + my_signal(SIGINT, Sig_Interupt); +#ifndef WIN32 + my_signal(SIGALRM, Sig_Interupt); + // Ignore broken pipes + signal(SIGPIPE,SIG_IGN); +#else + // Start winsock + WSADATA wsaData; + int rc = WSAStartup(0x202, &wsaData); + WARN_errno(rc == SOCKET_ERROR, "WSAStartup"); + if (rc == SOCKET_ERROR) + return 0; + // Tell windows we want to handle our own signals + SetConsoleCtrlHandler(sig_dispatcher, true); +#endif + + // Initialize global mutexes and conditions + Iperf_initialize_active_table(); + Condition_Initialize (&ReportCond); + +#ifdef HAVE_THREAD_DEBUG + Mutex_Initialize(&packetringdebug_mutex); + Mutex_Initialize(&thread_debug_mutex); +#endif + Mutex_Initialize(&transferid_mutex); + + // Initialize reporter thread mutex + reporter_state.ready = 0; + threads_start.ready = 0; + transmits_start.count = 0; + Condition_Initialize(&reporter_state.await); + Condition_Initialize(&threads_start.await); + Condition_Initialize(&transmits_start.await); + + // Initialize the thread subsystem + thread_init(); + + // Initialize the interrupt handling thread to 0 + sThread = thread_zeroid(); + + // perform any cleanup when quitting Iperf + atexit(cleanup); + + // Allocate the "global" settings + ext_gSettings = new thread_Settings; + // Default reporting mode here to avoid unitialized warnings + // this won't be the actual mode + ThreadMode ReporterThreadMode = kMode_Reporter; + // Initialize settings to defaults + Settings_Initialize(ext_gSettings); + // read settings from environment variables + Settings_ParseEnvironment(ext_gSettings); + // read settings from command-line parameters + Settings_ParseCommandLine(argc, argv, ext_gSettings); + + // Check for either having specified client or server + if ((ext_gSettings->mThreadMode != kMode_Client) && (ext_gSettings->mThreadMode != kMode_Listener)) { + // neither server nor client mode was specified + // print usage and exit + +#ifdef WIN32 + // In Win32 we also attempt to start a previously defined service + // Starting in 2.0 to restart a previously defined service + // you must call iperf with "iperf -D" or using the environment variable + SERVICE_TABLE_ENTRY dispatchTable[] = + { + { (LPSTR)TEXT(SZSERVICENAME), (LPSERVICE_MAIN_FUNCTION)service_main}, + { NULL, NULL} + }; + + // starting the service by SCM, there is no arguments will be passed in. + // the arguments will pass into Service_Main entry. + if (!StartServiceCtrlDispatcher(dispatchTable)) + // If the service failed to start then print usage +#endif + fprintf(stderr, usage_short, argv[0], argv[0]); + return 0; + } + + if (!isSTDOUT(ext_gSettings)) { +#ifdef HAVE_FREOPEN + FILE *fd; + fprintf(stdout, "Output from stdout (but not from stderr) will be redirected to file %s\n", ext_gSettings->mOutputFileName); + fflush(stdout); + fd = freopen(ext_gSettings->mOutputFileName, "w", stdout); + FAIL_errno(fd == NULL, "freopen stdout\n", ext_gSettings); +#else + fprintf(stderr, "Output to file not supported\n"); +#endif + + } + + int mbuflen = (ext_gSettings->mBufLen > MINMBUFALLOCSIZE) ? ext_gSettings->mBufLen : MINMBUFALLOCSIZE; +#if (((HAVE_TUNTAP_TUN) || (HAVE_TUNTAP_TAP)) && (AF_PACKET)) + mbuflen += TAPBYTESSLOP; +#endif + ext_gSettings->mBuf = new char[mbuflen]; + memset(ext_gSettings->mBuf, 0, mbuflen); + + + unsetReport(ext_gSettings); + switch (ext_gSettings->mThreadMode) { + case kMode_Client : + if (isDaemon(ext_gSettings)) { + fprintf(stderr, "Iperf client cannot be run as a daemon\n"); + return 0; + } + // initialize client(s) + transmits_start.count = ext_gSettings->mThreads; + ext_gSettings->connects_done = &transmits_start; + client_init(ext_gSettings); + ReporterThreadMode = kMode_ReporterClient; + break; + case kMode_Listener : +#ifdef WIN32 + // Remove the Windows service if requested + if (isRemoveService(ext_gSettings)) { + // remove the service + if (CmdRemoveService()) { + fprintf(stderr, "IPerf Service is removed.\n"); + } + } + if (isDaemon(ext_gSettings)) { + CmdInstallService(argc, argv); + } else if (isRemoveService(ext_gSettings)) { + return 0; + } +#else // *nix system + if (isDaemon(ext_gSettings)) { + fprintf(stderr, "Running Iperf Server as a daemon\n"); + // Start the server as a daemon + // redirect stdin, stdout and sterr to /dev/null (see dameon and no close flag) + if (daemon(1, 0) < 0) { + perror("daemon"); + } + } +#endif + // Start up any parallel listener threads + if (ext_gSettings->mPortLast) { + listeners_init(ext_gSettings); + } + break; + default : + fprintf(stderr, "unknown mode"); + break; + } +#ifdef HAVE_THREAD + // Last step is to initialize the reporter then start all threads + { + thread_Settings *into = NULL; + // Create the settings structure for the reporter thread + Settings_Copy(ext_gSettings, &into, DEEP_COPY); + into->mThreadMode = ReporterThreadMode; + into->mSumReport = NULL; + into->mFullDuplexReport = NULL; + // Have the reporter launch the client or listener + into->runNow = ext_gSettings; + // Start all the threads that are ready to go + thread_start_all(into); + Condition_Lock(threads_start.await); + threads_start.ready = 1; + Condition_Signal(&threads_start.await); + Condition_Unlock(threads_start.await); + } +#else + // No need to make a reporter thread because we don't have threads + thread_start(ext_gSettings); +#endif + // wait for other (client, server) threads to complete + thread_joinall(); + // all done! + return 0; +} // end main + +/* ------------------------------------------------------------------- + * Signal handler sets the sInterupted flag, so the object can + * respond appropriately.. [static] + * ------------------------------------------------------------------- */ + +void Sig_Interupt (int inSigno) { +#ifdef HAVE_THREAD + // We try to not allow a single interrupt handled by multiple threads + // to completely kill the app so we save off the first thread ID + // then that is the only thread that can supply the next interrupt + if ((inSigno == SIGINT) && thread_equalid(sThread, thread_zeroid())) { + sThread = thread_getid(); + } else if (thread_equalid(sThread, thread_getid())) { + sig_exit(inSigno); + } + // global variable used by threads to see if they were interrupted + sInterupted = inSigno; + + // Note: ignore alarms per setitimer +#if HAVE_DECL_SIGALRM + if (inSigno != SIGALRM) +#endif + // with threads, stop waiting for non-terminating threads + // (ie Listener Thread) + thread_release_nonterm(inSigno); + +#else + // without threads, just exit quietly, same as sig_exit() + sig_exit(inSigno); +#endif +} + +/* ------------------------------------------------------------------- + * Any necesary cleanup before Iperf quits. Called at program exit, + * either by exit() or terminating main(). + * ------------------------------------------------------------------- */ + +void cleanup () { +#ifdef WIN32 + // Shutdown Winsock + WSACleanup(); +#endif + // clean up the list of active clients + Iperf_destroy_active_table(); + // done actions + // Destroy global mutexes and conditions + + Condition_Destroy (&ReportCond); + Condition_Destroy(&reporter_state.await); + Condition_Destroy(&threads_start.await); + Condition_Destroy(&transmits_start.await); +#ifdef HAVE_THREAD_DEBUG + Mutex_Destroy(&packetringdebug_mutex); + Mutex_Destroy(&thread_debug_mutex); +#endif + Mutex_Destroy(&transferid_mutex); + // shutdown the thread subsystem + thread_destroy(); +} // end cleanup + +#ifdef WIN32 +/*-------------------------------------------------------------------- + * ServiceStart + * + * each time starting the service, this is the entry point of the service. + * Start the service, certainly it is on server-mode + * + *-------------------------------------------------------------------- */ +VOID ServiceStart (DWORD dwArgc, LPTSTR *lpszArgv) { + thread_Settings* ext_gSettings; + + // report the status to the service control manager. + // + if (!ReportStatusToSCMgr( + SERVICE_START_PENDING, // service state + NO_ERROR, // exit code + 3000)) // wait hint + goto clean; + + ext_gSettings = new thread_Settings; + + // Initialize settings to defaults + Settings_Initialize(ext_gSettings); + // read settings from environment variables + Settings_ParseEnvironment(ext_gSettings); + // read settings from command-line parameters + Settings_ParseCommandLine(dwArgc, lpszArgv, ext_gSettings); + + // Arguments will be lost when the service is started by SCM, but + // we need to be at least a listener + ext_gSettings->mThreadMode = kMode_Listener; + + // report the status to the service control manager. + // + if (!ReportStatusToSCMgr( + SERVICE_START_PENDING, // service state + NO_ERROR, // exit code + 3000)) // wait hint + goto clean; + + // if needed, redirect the output into a specified file + if (!isSTDOUT(ext_gSettings)) { + redirect(ext_gSettings->mOutputFileName); + } + + // report the status to the service control manager. + // + if (!ReportStatusToSCMgr( + SERVICE_START_PENDING, // service state + NO_ERROR, // exit code + 3000)) // wait hint + goto clean; + + // initialize client(s) + if (ext_gSettings->mThreadMode == kMode_Client) { + client_init(ext_gSettings); + } + + // start up the reporter and client(s) or listener + { + thread_Settings *into = NULL; +#ifdef HAVE_THREAD + Settings_Copy(ext_gSettings, &into, DEEP_COPY); + into->mThreadMode = kMode_Reporter; + into->runNow = ext_gSettings; +#else + into = ext_gSettings; +#endif + thread_start_all(into); + } + + // report the status to the service control manager. + // + if (!ReportStatusToSCMgr( + SERVICE_RUNNING, // service state + NO_ERROR, // exit code + 0)) // wait hint + goto clean; + + clean: + // wait for other (client, server) threads to complete + thread_joinall(); +} + +// +// FUNCTION: ServiceStop +// +// PURPOSE: Stops the service +// +// PARAMETERS: +// none +// +// RETURN VALUE: +// none +// +// COMMENTS: +// If a ServiceStop procedure is going to +// take longer than 3 seconds to execute, +// it should spawn a thread to execute the +// stop code, and return. Otherwise, the +// ServiceControlManager will believe that +// the service has stopped responding. +// +VOID ServiceStop() { +#ifdef HAVE_THREAD + Sig_Interupt(1); +#else + sig_exit(1); +#endif +} + +#endif diff --git a/src/packet_ring.c b/src/packet_ring.c new file mode 100644 index 0000000..93e7578 --- /dev/null +++ b/src/packet_ring.c @@ -0,0 +1,219 @@ +/*--------------------------------------------------------------- + * Copyright (c) 2019 + * Broadcom Corporation + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the name of Broadcom Coporation, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * + * Suppport for packet rings between threads + * + * by Robert J. McMahon (rjmcmahon@rjmcmahon.com, bob.mcmahon@broadcom.com) + * ------------------------------------------------------------------- + */ +#include "headers.h" +#include "packet_ring.h" +#include "Condition.h" +#include "Thread.h" + +#ifdef HAVE_THREAD_DEBUG +#include "Mutex.h" +static int totalpacketringcount = 0; +Mutex packetringdebug_mutex; +#endif + +struct PacketRing * packetring_init (int count, struct Condition *awake_consumer, struct Condition *awake_producer) { + assert(awake_consumer != NULL); + struct PacketRing *pr = NULL; + if ((pr = (struct PacketRing *) calloc(1, sizeof(struct PacketRing)))) { + pr->bytes = sizeof(struct PacketRing); + pr->data = (struct ReportStruct *) calloc(count, sizeof(struct ReportStruct)); + pr->bytes += count * sizeof(struct ReportStruct); + } + if (!pr || !pr->data) { + fprintf(stderr, "ERROR: no memory for packet ring of size %d count, try to reduce with option --NUM_REPORT_STRUCTS\n", count); + exit(1); + } + pr->producer = 0; + pr->consumer = 0; + pr->maxcount = count; + pr->awake_producer = awake_producer; + pr->awake_consumer = awake_consumer; + if (!awake_producer) + pr->mutex_enable=0; + else + pr->mutex_enable=1; + pr->consumerdone = 0; + pr->awaitcounter = 0; +#ifdef HAVE_THREAD_DEBUG + Mutex_Lock(&packetringdebug_mutex); + totalpacketringcount++; + thread_debug("Init %d element packet ring=%p consumer=%p producer=%p total rings=%d enable=%d", count, \ + (void *)pr, (void *) pr->awake_consumer, (void *) pr->awake_producer, totalpacketringcount, pr->mutex_enable); + Mutex_Unlock(&packetringdebug_mutex); +#endif + return (pr); +} + +inline void packetring_enqueue (struct PacketRing *pr, struct ReportStruct *metapacket) { + while (((pr->producer == pr->maxcount) && (pr->consumer == 0)) || \ + ((pr->producer + 1) == pr->consumer)) { + // Signal the consumer thread to process a full queue + if (pr->mutex_enable) { + assert(pr->awake_consumer != NULL); + Condition_Signal(pr->awake_consumer); + // Wait for the consumer to create some queue space + assert(pr->awake_producer != NULL); + Condition_Lock((*(pr->awake_producer))); + pr->awaitcounter++; +#ifdef HAVE_THREAD_DEBUG_PERF + { + struct timeval now; + static struct timeval prev={0, 0}; + gettimeofday( &now, NULL ); + if (!prev.tv_sec || (TimeDifference(now, prev) > 1.0)) { + prev = now; + thread_debug( "Not good, traffic's packet ring %p stalled per %p", (void *)pr, (void *)&pr->awake_producer); + } + } +#endif + Condition_TimedWait(pr->awake_producer, 1); + Condition_Unlock((*(pr->awake_producer))); + } + } + int writeindex; + if ((pr->producer + 1) == pr->maxcount) + writeindex = 0; + else + writeindex = (pr->producer + 1); + + /* Next two lines must be maintained as is */ + memcpy((pr->data + writeindex), metapacket, sizeof(struct ReportStruct)); + pr->producer = writeindex; +} + +inline struct ReportStruct *packetring_dequeue (struct PacketRing *pr) { + struct ReportStruct *packet = NULL; + if (pr->producer == pr->consumer) + return NULL; + + int readindex; + if ((pr->consumer + 1) == pr->maxcount) + readindex = 0; + else + readindex = (pr->consumer + 1); + packet = (pr->data + readindex); + // advance the consumer pointer last + pr->consumer = readindex; + if (pr->mutex_enable) { + // Signal the traffic thread assigned to this ring + // when the ring goes from having something to empty + if (pr->producer == pr->consumer) { +#ifdef HAVE_THREAD_DEBUG + // thread_debug( "Consumer signal packet ring %p empty per %p", (void *)pr, (void *)&pr->awake_producer); +#endif + assert(pr->awake_producer); + Condition_Signal(pr->awake_producer); + } + } + return packet; +} + +inline void enqueue_ackring (struct PacketRing *pr, struct ReportStruct *metapacket) { + packetring_enqueue(pr, metapacket); + // Keep the latency low by signaling the consumer thread + // per each enqueue +#ifdef HAVE_THREAD_DEBUG + // thread_debug( "Producer signal consumer ackring=%p per %p", (void *)pr, (void *)&pr->awake_consumer); +#endif + Condition_Signal(pr->awake_consumer); +} + +inline struct ReportStruct *dequeue_ackring (struct PacketRing *pr) { + struct ReportStruct *packet = NULL; + Condition_Lock((*(pr->awake_consumer))); + while ((packet = packetring_dequeue(pr)) == NULL) { + Condition_TimedWait(pr->awake_consumer, 1); + } + Condition_Unlock((*(pr->awake_consumer))); + if (packet) { + // Signal the producer thread for low latency + // indication of space available + Condition_Signal(pr->awake_producer); + } + return packet; +} + +void packetring_free (struct PacketRing *pr) { + if (pr) { + if (pr->awaitcounter > 1000) fprintf(stderr, "WARN: Reporter thread may be too slow, await counter=%d, " \ + "consider increasing NUM_REPORT_STRUCTS\n", pr->awaitcounter); + if (pr->data) { +#ifdef HAVE_THREAD_DEBUG + Mutex_Lock(&packetringdebug_mutex); + totalpacketringcount--; + thread_debug("Free packet ring=%p producer=%p (consumer=%p) awaits = %d total rings = %d", \ + (void *)pr, (void *) pr->awake_producer, (void *) pr->awake_consumer, pr->awaitcounter, totalpacketringcount); + Mutex_Unlock(&packetringdebug_mutex); +#endif + free(pr->data); + } + free(pr); + } +} + +void free_ackring(struct PacketRing *pr) { + packetring_free(pr); + Condition_Destroy(pr->awake_consumer); +} + +/* + * This is an estimate and can be incorrect as these counters + * done like this is not thread safe. Use with care as there + * is no guarantee the return value is accurate + */ +#ifdef HAVE_THREAD_DEBUG +inline int packetring_getcount (struct PacketRing *pr) { + int depth = 0; + if (pr->producer != pr->consumer) { + depth = (pr->producer > pr->consumer) ? \ + (pr->producer - pr->consumer) : \ + ((pr->maxcount - pr->consumer) + pr->producer); + // printf("DEBUG: Depth=%d for packet ring %p\n", depth, (void *)pr); + } + return depth; +} +#endif diff --git a/src/pdfs.c b/src/pdfs.c new file mode 100644 index 0000000..a1e0382 --- /dev/null +++ b/src/pdfs.c @@ -0,0 +1,100 @@ +/*--------------------------------------------------------------- + * Copyright (c) 2017 + * Broadcom Corporation + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the name of Broadcom Coporation, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * + * pdfs.c + * Produce probability distribution functions, expected to be used + * for iperf client traffic emulations + * + * Implements the Polar form of the Box-Muller Transformation + * + * by Robert J. McMahon (rjmcmahon@rjmcmahon.com, bob.mcmahon@broadcom.com) + * & Tim Auckland + * ------------------------------------------------------------------- + */ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <math.h> +#include "headers.h" +#include "pdfs.h" + +#define FALSE 0 +#define TRUE 1 +float box_muller(void) { + float x1, x2, w, y1; + static float y2; + static int generate = FALSE; + /* Each iteration produces two values, if one exists use the value from previous call */ + generate = !generate; + if (!generate) { + y1 = y2; + } else { + int loopcontrol=100; + do { + x1 = 2.0 * (float)rand()/(float)(RAND_MAX) - 1.0; + x2 = 2.0 * (float)rand()/(float)(RAND_MAX) - 1.0; + w = x1 * x1 + x2 * x2; + } while ( w >= 1.0 && --loopcontrol > 0); + if (w >= 1.0) { + fprintf(stderr, "pdf box_muller() rand() error\n"); + return 0; + } else { + w = sqrt( (-2.0 * logf( w ) ) / w ); + y1 = x1 * w; + y2 = x2 * w; + } + } + return(y1); +} + +float normal(float mean, float variance) { + return (box_muller() * variance + mean); +} + +float lognormal(float mu, float sigma) { + float phi = sqrtf((mu * mu) + (sigma * sigma)); + float mu_prime = logf(((mu * mu)/phi)); + float sigma_prime = sqrtf(logf((phi * phi)/(mu * mu))); + return (expf(normal(mu_prime,sigma_prime))); +} diff --git a/src/socket_io.c b/src/socket_io.c new file mode 100644 index 0000000..0475310 --- /dev/null +++ b/src/socket_io.c @@ -0,0 +1,239 @@ +/*--------------------------------------------------------------- + * Copyright (c) 1999,2000,2001,2002,2003 + * The Board of Trustees of the University of Illinois + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software (Iperf) and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the names of the University of Illinois, NCSA, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * National Laboratory for Applied Network Research + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * http://www.ncsa.uiuc.edu + * ________________________________________________________________ + * + * socket.c + * by Mark Gates <mgates@nlanr.net> + * ------------------------------------------------------------------- + * set/getsockopt and read/write wrappers + * ------------------------------------------------------------------- */ + +#include "headers.h" +#include "util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* ------------------------------------------------------------------- + * Attempts to reads n bytes from a socket. + * Returns number actually read, or -1 on error. + * If number read < inLen then we reached EOF. + * + * from Stevens, 1998, section 3.9 + * ------------------------------------------------------------------- */ +ssize_t readn (int inSock, void *outBuf, size_t inLen) { + size_t nleft; + ssize_t nread; + char *ptr; + + assert(inSock >= 0); + assert(outBuf != NULL); + assert(inLen > 0); + + ptr = (char*) outBuf; + nleft = inLen; + + while (nleft > 0) { + nread = read(inSock, ptr, nleft); + if (nread < 0) { + if (errno == EINTR) + nread = 0; /* interupted, call read again */ + else + return -1; /* error */ + } else if (nread == 0) + break; /* EOF */ + + nleft -= nread; + ptr += nread; + } + + return(inLen - nleft); +} /* end readn */ + +/* ------------------------------------------------------------------- + * Similar to read but supports recv flags + * Returns number actually read, or -1 on error. + * If number read < inLen then we reached EOF. + * from Stevens, 1998, section 3.9 + * ------------------------------------------------------------------- */ +int recvn (int inSock, char *outBuf, int inLen, int flags) { + int nleft; + int nread = 0; + char *ptr; + + assert(inSock >= 0); + assert(outBuf != NULL); + assert(inLen > 0); + + ptr = outBuf; + nleft = inLen; +#if (HAVE_DECL_MSG_PEEK) + if (flags & MSG_PEEK) { + while ((nleft != nread) && !sInterupted) { + nread = recv(inSock, ptr, nleft, flags); + switch (nread) { + case SOCKET_ERROR : + // Note: use TCP fatal error codes even for UDP + if (FATALTCPREADERR(errno)) { + WARN_errno(1, "recvn peek"); + nread = -1; + sInterupted = 1; + goto DONE; + } +#ifdef HAVE_THREAD_DEBUG + WARN_errno(1, "recvn peek non-fatal"); +#endif + break; + case 0: +#ifdef HAVE_THREAD_DEBUG + WARN(1, "recvn peek peer close"); +#endif + goto DONE; + break; + default : + break; + } + } + } else +#endif + { + while ((nleft > 0) && !sInterupted) { +#if (HAVE_DECL_MSG_WAITALL) + nread = recv(inSock, ptr, nleft, MSG_WAITALL); +#else + nread = recv(inSock, ptr, nleft, 0); +#endif + switch (nread) { + case SOCKET_ERROR : + // Note: use TCP fatal error codes even for UDP + if (FATALTCPREADERR(errno)) { + WARN_errno(1, "recvn"); + nread = -1; + sInterupted = 1; + goto DONE; + } else { + nread = -2; + goto DONE; + } +#ifdef HAVE_THREAD_DEBUG + WARN_errno(1, "recvn non-fatal"); +#endif + break; + case 0: +#ifdef HAVE_THREAD_DEBUG + WARN(1, "recvn peer close"); +#endif + nread = inLen - nleft; + goto DONE; + break; + default : + nleft -= nread; + ptr += nread; + break; + } + nread = inLen - nleft; + } + } + DONE: + return(nread); +} /* end readn */ + +/* ------------------------------------------------------------------- + * Attempts to write n bytes to a socket. + * returns number actually written, or -1 on error. + * number written is always inLen if there is not an error. + * + * from Stevens, 1998, section 3.9 + * ------------------------------------------------------------------- */ + +int writen (int inSock, const void *inBuf, int inLen, int *count) { + int nleft; + int nwritten; + const char *ptr; + + assert(inSock >= 0); + assert(inBuf != NULL); + assert(inLen > 0); + assert(count != NULL); + + ptr = (char*) inBuf; + nleft = inLen; + nwritten = 0; + *count = 0; + + while ((nleft > 0) && !sInterupted) { + nwritten = write(inSock, ptr, nleft); + (*count)++; + switch (nwritten) { + case SOCKET_ERROR : + // check for a fatal error vs an error that should retry + if ((errno != EINTR) && (errno != EAGAIN) && (errno != EWOULDBLOCK)) { + nwritten = inLen - nleft; + fprintf(stdout, "FAIL: writen errno = %d\n", errno); + WARN_errno(1, "writen fatal"); + sInterupted = 1; + goto DONE; + } + break; + case 0: + // write timeout - retry + break; + default : + nleft -= nwritten; + ptr += nwritten; + break; + } + nwritten = inLen - nleft; + } + DONE: + return (nwritten); +} /* end writen */ + + + +#ifdef __cplusplus +} /* end extern "C" */ +#endif diff --git a/src/stdio.c b/src/stdio.c new file mode 100644 index 0000000..3bdf668 --- /dev/null +++ b/src/stdio.c @@ -0,0 +1,355 @@ +/*--------------------------------------------------------------- + * Copyright (c) 1999,2000,2001,2002,2003 + * The Board of Trustees of the University of Illinois + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software (Iperf) and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the names of the University of Illinois, NCSA, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * National Laboratory for Applied Network Research + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * http://www.ncsa.uiuc.edu + * ________________________________________________________________ + * + * stdio.c + * by Mark Gates <mgates@nlanr.net> + * and Ajay Tirumalla <tirumala@ncsa.uiuc.edu> + * ------------------------------------------------------------------- + * input and output numbers, converting with kilo, mega, giga + * ------------------------------------------------------------------- */ + +#include "headers.h" +#include "util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +const long kKilo_to_Unit = 1024; +const long kMega_to_Unit = 1024 * 1024; +const long kGiga_to_Unit = 1024 * 1024 * 1024; + +const long kkilo_to_Unit = 1000; +const long kmega_to_Unit = 1000 * 1000; +const long kgiga_to_Unit = 1000 * 1000 * 1000; + +/* ------------------------------------------------------------------- + * byte_atof + * + * Given a string of form #x where # is a number and x is a format + * character listed below, this returns the interpreted integer. + * Gg, Mm, Kk are giga, mega, kilo respectively + * ------------------------------------------------------------------- */ + +double byte_atof(const char *inString) { + double theNum; + char suffix = '\0'; + + assert(inString != NULL); + + /* scan the number and any suffices */ + sscanf(inString, "%lf%c", &theNum, &suffix); + + /* convert according to [Gg Mm Kk] */ + switch (suffix) { + case 'G': theNum *= kGiga_to_Unit; break; + case 'M': theNum *= kMega_to_Unit; break; + case 'K': theNum *= kKilo_to_Unit; break; + case 'g': theNum *= kgiga_to_Unit; break; + case 'm': theNum *= kmega_to_Unit; break; + case 'k': theNum *= kkilo_to_Unit; break; + default: break; + } + return theNum; +} /* end byte_atof */ + +/* ------------------------------------------------------------------- + * byte_atoi + * + * Given a string of form #x where # is a number and x is a format + * character listed below, this returns the interpreted integer. + * Gg, Mm, Kk are giga, mega, kilo respectively + * ------------------------------------------------------------------- */ + +intmax_t byte_atoi(const char *inString) { + double theNum; + char suffix = '\0'; + + assert(inString != NULL); + + /* scan the number and any suffices */ + sscanf(inString, "%lf%c", &theNum, &suffix); + + /* convert according to [Gg Mm Kk] */ + switch (suffix) { + case 'G': theNum *= kGiga_to_Unit; break; + case 'M': theNum *= kMega_to_Unit; break; + case 'K': theNum *= kKilo_to_Unit; break; + case 'g': theNum *= kgiga_to_Unit; break; + case 'm': theNum *= kmega_to_Unit; break; + case 'k': theNum *= kkilo_to_Unit; break; + default: break; + } + return (intmax_t) theNum; +} /* end byte_atof */ + +/* ------------------------------------------------------------------- + * bitorbyte_atoi + * + * Given a string of form #x where # is a number and x is a format + * character listed below, this returns the interpreted integer. + * Gg, Mm, Kk are giga, mega, kilo respectively + * ------------------------------------------------------------------- */ +uintmax_t bitorbyte_atoi(const char *inString) { + double theNum; + char suffix = '\0'; + + assert(inString != NULL); + + /* scan the number and any suffices */ + sscanf(inString, "%lf%c", &theNum, &suffix); + + /* convert according to [Gg Mm Kk] */ + switch (suffix) { + case 'G': theNum *= (kgiga_to_Unit * 8.0); break; + case 'M': theNum *= (kmega_to_Unit * 8.0); break; + case 'K': theNum *= (kkilo_to_Unit * 8.0); break; + case 'g': theNum *= kgiga_to_Unit; break; + case 'm': theNum *= kmega_to_Unit; break; + case 'k': theNum *= kkilo_to_Unit; break; + default: break; + } + return (uintmax_t) theNum; +} /* end byte_atof */ + +/* ------------------------------------------------------------------- + * bitorbyte_atof + * + * Given a string of form #x where # is a number and x is a format + * character listed below, this returns the interpreted integer. + * Gg, Mm, Kk are giga, mega, kilo respectively + * ------------------------------------------------------------------- */ +double bitorbyte_atof(const char *inString) { + double theNum; + char suffix = '\0'; + + assert(inString != NULL); + + /* scan the number and any suffices */ + sscanf(inString, "%lf%c", &theNum, &suffix); + + /* convert according to [Gg Mm Kk] */ + switch (suffix) { + case 'G': theNum *= (kgiga_to_Unit * 8.0); break; + case 'M': theNum *= (kmega_to_Unit * 8.0); break; + case 'K': theNum *= (kkilo_to_Unit * 8.0); break; + case 'g': theNum *= kgiga_to_Unit; break; + case 'm': theNum *= kmega_to_Unit; break; + case 'k': theNum *= kkilo_to_Unit; break; + case 'p': + case 'P': theNum *= -1; break; + default: break; + } + return theNum; +} /* end byte_atof */ + +/* ------------------------------------------------------------------- + * constants for byte_printf + * ------------------------------------------------------------------- */ + +/* used as indices into kConversion[], kLabel_Byte[], and kLabel_bit[] */ +enum { + kConv_Unit, + kConv_Kilo, + kConv_Mega, + kConv_Giga, + kConv_Tera, + kConv_Peta +}; + +/* factor to multiply the number by */ +const double kConversion[] = +{ + 1.0, /* unit */ + 1.0 / 1024, /* kilo */ + 1.0 / 1024 / 1024, /* mega */ + 1.0 / 1024 / 1024 / 1024, /* giga */ + 1.0 / 1024 / 1024 / 1024 / 1024, /* tera */ + 1.0 / 1024 / 1024 / 1024 / 1024 / 1024 /* peta */ +}; + +/* factor to multiply the number by for bits*/ +const double kConversionForBits[] = +{ + 1.0, /* unit */ + 1.0 / 1000, /* kilo */ + 1.0 / 1000 / 1000, /* mega */ + 1.0 / 1000 / 1000 / 1000, /* giga */ + 1.0 / 1000 / 1000 / 1000 / 1000, /* tera */ + 1.0 / 1000 / 1000 / 1000 / 1000/ 1000 /* peta */ +}; + + +/* labels for Byte formats [KMG] */ +const char* kLabel_Byte[] = +{ + "Byte", + "KByte", + "MByte", + "GByte", + "TByte", + "PByte" +}; + +/* labels for bit formats [kmg] */ +const char* kLabel_bit[] = +{ + "bit", + "Kbit", + "Mbit", + "Gbit", + "Tbit", + "Pbit" +}; + +/* ------------------------------------------------------------------- + * byte_snprintf + * + * Given a number in bytes and a format, converts the number and + * prints it out with a bits or bytes label. + * B, K, M, G, A, P, T for Byte, Kbyte, Mbyte, Gbyte, Tbyte, Pbyte adaptive byte + * b, k, m, g, a, p, t for bit, Kbit, Mbit, Gbit, Tbit, Pbit, adaptive bit + * adaptive picks the "best" one based on the number. + * outString should be at least 11 chars long + * (4 digits + space + 5 chars max + null) + * ------------------------------------------------------------------- */ + +void byte_snprintf(char* outString, int inLen, double inNum, char inFormat) { + int conv = 0; + const char* suffix; + const char* format; + double tmpNum; + + /* convert to bits for [bkmga] */ + if (!isupper((int)inFormat)) { + inNum *= 8; + } + + switch (toupper((int)inFormat)) { + case 'B': conv = kConv_Unit; break; + case 'K': conv = kConv_Kilo; break; + case 'M': conv = kConv_Mega; break; + case 'G': conv = kConv_Giga; break; + case 'T': conv = kConv_Tera; break; + case 'P': conv = kConv_Peta; break; + + default: + case 'A': { + tmpNum = (inNum < 0.0 ? (-1 * inNum) : inNum); + conv = kConv_Unit; + + if (isupper((int)inFormat)) { + while (tmpNum >= 1024.0 && conv < kConv_Peta) { + tmpNum /= 1024.0; + conv++; + } + } else { + while (tmpNum >= 1000.0 && conv < kConv_Peta) { + tmpNum /= 1000.0; + conv++; + } + } + break; + } + } + + if (!isupper((int)inFormat)) { + inNum *= kConversionForBits[conv]; + suffix = kLabel_bit[conv]; + } else { + inNum *= kConversion[conv]; + suffix = kLabel_Byte[conv]; + } + + /* print such that we always fit in 4 places */ + tmpNum = (inNum < 0.0 ? (-1 * inNum) : inNum); + if (tmpNum < 0.9995) { /* 0.995 would be rounded to 1.000 */ + format = "%4.3f %s"; /* #.## */ + } else if (tmpNum < 9.995) { /* 9.995 would be rounded to 10.00 */ + format = "%4.2f %s"; /* #.## */ + } else if (tmpNum < 99.95) { /* 99.95 would be rounded to 100.0 */ + format = "%4.1f %s"; /* ##.# */ + } else if (tmpNum < 999.5) { /* 999.5 would be rounded to 1000 */ + format = "%4.0f %s"; /* ### */ + } else { /* 1000-1024 fits in 4 places + * If not using Adaptive sizes then + * this code will not control spaces*/ + format = "%4.0f %s"; /* #### */ + } + snprintf(outString, inLen, format, inNum, suffix); +} /* end byte_snprintf */ + +/* ------------------------------------------------------------------- + * redirect + * + * redirect the stdout into a specified file + * return: none + * ------------------------------------------------------------------- */ + +void redirect(const char *inOutputFileName) { +#ifdef WIN32 + + FILE *fp; + + if (inOutputFileName == NULL) { + fprintf(stderr, "should specify the output file name.\n"); + return; + } + + fp = freopen(inOutputFileName, "a+", stdout); + if (fp == NULL) { + fprintf(stderr, "redirect stdout failed!\n"); + return; + } + +#endif + +} + + +#ifdef __cplusplus +} /* end extern "C" */ +#endif diff --git a/src/tcp_window_size.c b/src/tcp_window_size.c new file mode 100644 index 0000000..4b5d79b --- /dev/null +++ b/src/tcp_window_size.c @@ -0,0 +1,227 @@ +/*--------------------------------------------------------------- + * Copyright (c) 1999,2000,2001,2002,2003 + * The Board of Trustees of the University of Illinois + * All Rights Reserved. + *--------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software (Iperf) and associated + * documentation files (the "Software"), to deal in the Software + * without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit + * persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and + * the following disclaimers. + * + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimers in the documentation and/or other materials + * provided with the distribution. + * + * + * Neither the names of the University of Illinois, NCSA, + * nor the names of its contributors may be used to endorse + * or promote products derived from this Software without + * specific prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ________________________________________________________________ + * National Laboratory for Applied Network Research + * National Center for Supercomputing Applications + * University of Illinois at Urbana-Champaign + * http://www.ncsa.uiuc.edu + * ________________________________________________________________ + * + * tcp_window_size.c + * by Mark Gates <mgates@nlanr.net> + * ------------------------------------------------------------------- + * set/getsockopt + * ------------------------------------------------------------------- */ + +#include "headers.h" + +#include "util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* ------------------------------------------------------------------- + * If inTCPWin > 0, set the TCP window size (via the socket buffer + * sizes) for inSock. Otherwise leave it as the system default. + * + * This must be called prior to calling listen() or connect() on + * the socket, for TCP window sizes > 64 KB to be effective. + * + * This now works on UNICOS also, by setting TCP_WINSHIFT. + * This now works on AIX, by enabling RFC1323. + * returns -1 on error, 0 on no error. + * ------------------------------------------------------------------- */ + +int setsock_tcp_windowsize (int inSock, int inTCPWin, int inSend) { +#ifdef SO_SNDBUF + int rc; + int newTCPWin; + + assert(inSock >= 0); + if (inTCPWin > 0) { +#ifdef TCP_WINSHIFT + /* UNICOS requires setting the winshift explicitly */ + if (inTCPWin > 65535) { + int winShift = 0; + int scaledWin = inTCPWin >> 16; + while (scaledWin > 0) { + scaledWin >>= 1; + winShift++; + } + + /* set TCP window shift */ + rc = setsockopt(inSock, IPPROTO_TCP, TCP_WINSHIFT, + (char*) &winShift, sizeof(winShift)); + if (rc < 0) { + return rc; + } + + /* Note: you cannot verify TCP window shift, since it returns + * a structure and not the same integer we use to set it. (ugh) */ + } +#endif /* TCP_WINSHIFT */ + +#ifdef TCP_RFC1323 + /* On AIX, RFC 1323 extensions can be set system-wide, + * using the 'no' network options command. But we can also set them + * per-socket, so let's try just in case. */ + if (inTCPWin > 65535) { + /* enable RFC 1323 */ + int on = 1; + rc = setsockopt(inSock, IPPROTO_TCP, TCP_RFC1323, + (char*) &on, sizeof(on)); + if (rc < 0) { + return rc; + } + } +#endif /* TCP_RFC1323 */ + + if (!inSend) { + /* receive buffer -- set + * note: results are verified after connect() or listen(), + * since some OS's don't show the corrected value until then. */ + newTCPWin = inTCPWin; + rc = setsockopt(inSock, SOL_SOCKET, SO_RCVBUF, + (char*) &newTCPWin, sizeof(newTCPWin)); + } else { + /* send buffer -- set + * note: results are verified after connect() or listen(), + * since some OS's don't show the corrected value until then. */ + newTCPWin = inTCPWin; + rc = setsockopt(inSock, SOL_SOCKET, SO_SNDBUF, + (char*) &newTCPWin, sizeof(newTCPWin)); + } + if (rc < 0) { + return rc; + } + } +#endif /* SO_SNDBUF */ + return 0; +} /* end setsock_tcp_windowsize */ + +/* ------------------------------------------------------------------- + * returns the TCP window size (on the sending buffer, SO_SNDBUF), + * or -1 on error. + * ------------------------------------------------------------------- */ + +int getsock_tcp_windowsize (int inSock, int inSend) { + int rc = -1; +#ifdef SO_SNDBUF + Socklen_t len; + int theTCPWin = 0; + /* send buffer -- query for buffer size */ + len = sizeof(theTCPWin); + if (inSend) { + rc = getsockopt(inSock, SOL_SOCKET, SO_SNDBUF, + (char*) &theTCPWin, &len); + } else { + rc = getsockopt(inSock, SOL_SOCKET, SO_RCVBUF, + (char*) &theTCPWin, &len); + } + if (rc == 0) { + rc = theTCPWin; + } +#endif + return rc; +} /* end getsock_tcp_windowsize */ + +#if HAVE_DECL_TCP_WINDOW_CLAMP +int setsock_tcp_windowclamp (int inSock, int clampsize) { + assert(inSock >= 0); + assert(clampsize > 0); + int rc; + Socklen_t len; + + len = sizeof(clampsize); + rc = setsockopt(inSock, IPPROTO_TCP, TCP_WINDOW_CLAMP, (char*)(&clampsize), len); + WARN_errno(rc == SOCKET_ERROR, "setsockopt TCP_WINDOW_CLAMP"); + return rc; +} + +int getsock_tcp_windowclamp (int inSock) { + assert(inSock >= 0); + int clamp = 0; + int rc; + Socklen_t len; + + /* send buffer -- query for buffer size */ + len = sizeof(clamp); + rc = getsockopt(inSock, IPPROTO_TCP, TCP_WINDOW_CLAMP, (char*)(&clamp), &len); + WARN_errno(rc == SOCKET_ERROR, "getsockopt TCP_WINDOW_CLAMP"); + if (rc < 0) { + return rc; + } + return clamp; +} +#endif + +#if HAVE_DECL_TCP_NOTSENT_LOWAT +int setsock_tcp_notsent_low_watermark (int inSock, int watermark) { + assert(inSock >= 0); + assert(watermark > 0); + int rc; + Socklen_t len; + + len = sizeof(watermark); + rc = setsockopt(inSock, IPPROTO_TCP, TCP_NOTSENT_LOWAT, (char*)(&watermark), len); + WARN_errno(rc == SOCKET_ERROR, "setsockopt TCP_NOTSENT_LOWAT"); + return rc; +} + +int getsock_tcp_notsent_low_watermark (int inSock) { + assert(inSock >= 0); + int watermark = 0; + int rc; + Socklen_t len; + + /* send buffer -- query for buffer size */ + len = sizeof(watermark); + rc = getsockopt(inSock, IPPROTO_TCP, TCP_NOTSENT_LOWAT, (char*)(&watermark), &len); + WARN_errno(rc == SOCKET_ERROR, "getsockopt TCP_NOTSENT_LOWAT"); + if (rc < 0) { + return rc; + } + return watermark; +} +#endif +#ifdef __cplusplus +} /* end extern "C" */ +#endif diff --git a/t/base.sh b/t/base.sh new file mode 100644 index 0000000..097a995 --- /dev/null +++ b/t/base.sh @@ -0,0 +1,47 @@ +# common test setup +set -o pipefail +#set -x + +lo=localhost +ip=127.0.0.1 +ip6=::1 + +# Some versions of expr can't handle can't mix regexp and math +test=$(expr $0 : '.*/t\([0-9]*\)_') +port=$(expr 5000 + $test) +lport=$(expr 6000 - $test) + +@() { echo "+ $@"; "$@"; } + +run_iperf() { + mode=server + server=(-s) + client=(-c) + # Split server and client args lists + for a; do + case $a in + (-c) mode=client;; + (-s) mode=server;; + (*) + case $mode in + (server) server+=($a);; + (client) client+=($a);; + esac + esac + done + # Start server + # Wait for "listening" + # Start client + # Merge server and client output + # Store results for additional processing and also copy to stderr for progress + results=$(@ src/iperf -p $port "${server[@]}" 2>&1 | { + awk '{print};/listening/{exit 0}'; + @ src/iperf -p $port "${client[@]}"; cat; + } 2>&1 | tee /dev/stderr) + + # Check for known error messages + if [[ "$results" =~ unrecognized|ignoring|failed|not\ valid ]]; then + exit 1 + fi +} + diff --git a/t/t10_dualtest.sh b/t/t10_dualtest.sh new file mode 100755 index 0000000..cc370d1 --- /dev/null +++ b/t/t10_dualtest.sh @@ -0,0 +1,12 @@ +#!/bin/bash -e +. $(dirname $0)/base.sh + +# usage: +# run_iperf -s server args -c client args +# +# client args should contain $ip or -V $ip6 +# results returned in $results + +run_iperf \ + -s -P 1 -i 1 -t 3 \ + -c $ip -P 1 --dualtest -L $lport -i 1 -t 2 diff --git a/t/t11_tradeoff.sh b/t/t11_tradeoff.sh new file mode 100755 index 0000000..b962371 --- /dev/null +++ b/t/t11_tradeoff.sh @@ -0,0 +1,12 @@ +#!/bin/bash -e +. $(dirname $0)/base.sh + +# usage: +# run_iperf -s server args -c client args +# +# client args should contain $ip or -V $ip6 +# results returned in $results + +run_iperf \ + -s -P 1 -i 1 -t 3 \ + -c $ip -P 1 --tradeoff -L $lport -i 1 -t 2 diff --git a/t/t12_full_duplex.sh b/t/t12_full_duplex.sh new file mode 100755 index 0000000..f159921 --- /dev/null +++ b/t/t12_full_duplex.sh @@ -0,0 +1,13 @@ +#!/bin/bash -e +. $(dirname $0)/base.sh + +# usage: +# run_iperf -s server args -c client args +# +# client args should contain $ip or -V $ip6 +# results returned in $results + +run_iperf \ + -s -P 1 -i 1 -t 3 \ + -c $ip -P 1 --full-duplex -i 1 -t 2 + diff --git a/t/t13_reverse.sh b/t/t13_reverse.sh new file mode 100755 index 0000000..8b0292a --- /dev/null +++ b/t/t13_reverse.sh @@ -0,0 +1,13 @@ +#!/bin/bash -e +. $(dirname $0)/base.sh + +# usage: +# run_iperf -s server args -c client args +# +# client args should contain $ip or -V $ip6 +# results returned in $results + +run_iperf \ + -s -P 1 -i 1 -t 3 \ + -c $ip -P 1 --reverse -i 1 -t 2 + diff --git a/t/t1_tcp.sh b/t/t1_tcp.sh new file mode 100755 index 0000000..965f15e --- /dev/null +++ b/t/t1_tcp.sh @@ -0,0 +1,14 @@ +#!/bin/bash -e +. $(dirname $0)/base.sh + +# usage: +# run_iperf -s server args -c client args +# +# client args should contain $ip or -V $ip6 +# results returned in $results + +run_iperf \ + -s -P 1 -i 1 -t 3 \ + -c $ip -P 1 -i 1 -t 2 + + diff --git a/t/t2_tcp6.sh b/t/t2_tcp6.sh new file mode 100755 index 0000000..802b2d8 --- /dev/null +++ b/t/t2_tcp6.sh @@ -0,0 +1,14 @@ +#!/bin/bash -e +. $(dirname $0)/base.sh + +# usage: +# run_iperf -s server args -c client args +# +# client args should contain $ip or -V $ip6 +# results returned in $results + +run_iperf \ + -s --ipv6_domain -P 1 -i 1 -t 3 \ + -c $ip6 -V -P 1 -i 1 -t 2 + + diff --git a/t/t3_udp.sh b/t/t3_udp.sh new file mode 100755 index 0000000..4374253 --- /dev/null +++ b/t/t3_udp.sh @@ -0,0 +1,12 @@ +#!/bin/bash -e +. $(dirname $0)/base.sh + +# usage: +# run_iperf -s server args -c client args +# +# client args should contain $ip or -V $ip6 +# results returned in $results + +run_iperf \ + -s -P 1 -u -i 1 -t 3 \ + -c $ip -P 1 -u -b 10m -i 1 -t 2 diff --git a/t/t4_udp6.sh b/t/t4_udp6.sh new file mode 100755 index 0000000..698020f --- /dev/null +++ b/t/t4_udp6.sh @@ -0,0 +1,12 @@ +#!/bin/bash -e +. $(dirname $0)/base.sh + +# usage: +# run_iperf -s server args -c client args +# +# client args should contain $ip or -V $ip6 +# results returned in $results + +run_iperf \ + -s -V -P 1 -u -i 1 -t 3 \ + -c $ip6 -V -P 1 -u -b 10m -i 1 -t 2 diff --git a/t/t5_f.sh b/t/t5_f.sh new file mode 100755 index 0000000..b5232d4 --- /dev/null +++ b/t/t5_f.sh @@ -0,0 +1,12 @@ +#!/bin/bash -e +. $(dirname $0)/base.sh + +# usage: +# run_iperf -s server args -c client args +# +# client args should contain $ip or -V $ip6 +# results returned in $results + +run_iperf \ + -s -P 1 -u -i 1 -t 3 \ + -c $ip -P 1 -u -b 1m -i 1 -F Makefile diff --git a/t/t6_filelong.sh b/t/t6_filelong.sh new file mode 100755 index 0000000..e83efa7 --- /dev/null +++ b/t/t6_filelong.sh @@ -0,0 +1,12 @@ +#!/bin/bash -e +. $(dirname $0)/base.sh + +# usage: +# run_iperf -s server args -c client args +# +# client args should contain $ip or -V $ip6 +# results returned in $results + +run_iperf \ + -s -P 1 -u -i 1 -t 3 \ + -c $ip -P 1 -u -b 1m -i 1 -t 2 --file_input Makefile diff --git a/t/t7_n.sh b/t/t7_n.sh new file mode 100755 index 0000000..c6547d8 --- /dev/null +++ b/t/t7_n.sh @@ -0,0 +1,12 @@ +#!/bin/bash -e +. $(dirname $0)/base.sh + +# usage: +# run_iperf -s server args -c client args +# +# client args should contain $ip or -V $ip6 +# results returned in $results + +run_iperf \ + -s -P 1 -i 1 -t 8 \ + -c $ip -P 1 -i 1 -n 1G diff --git a/t/t8_num.sh b/t/t8_num.sh new file mode 100755 index 0000000..f041cdf --- /dev/null +++ b/t/t8_num.sh @@ -0,0 +1,12 @@ +#!/bin/bash -e +. $(dirname $0)/base.sh + +# usage: +# run_iperf -s server args -c client args +# +# client args should contain $ip or -V $ip6 +# results returned in $results + +run_iperf \ + -s -P 1 -i 1 -t 8 \ + -c $ip -P 1 -i 1 --num 1G diff --git a/t/t9_parallel.sh b/t/t9_parallel.sh new file mode 100755 index 0000000..4dcab5d --- /dev/null +++ b/t/t9_parallel.sh @@ -0,0 +1,12 @@ +#!/bin/bash -e +. $(dirname $0)/base.sh + +# usage: +# run_iperf -s server args -c client args +# +# client args should contain $ip or -V $ip6 +# results returned in $results + +run_iperf \ + -s --parallel 4 -i 1 -t 3 \ + -c $ip -P 4 -i 1 -t 2 diff --git a/test-driver b/test-driver new file mode 100755 index 0000000..b8521a4 --- /dev/null +++ b/test-driver @@ -0,0 +1,148 @@ +#! /bin/sh +# test-driver - basic testsuite driver script. + +scriptversion=2018-03-07.03; # UTC + +# Copyright (C) 2011-2018 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to <bug-automake@gnu.org> or send patches to +# <automake-patches@gnu.org>. + +# Make unconditional expansion of undefined variables an error. This +# helps a lot in preventing typo-related bugs. +set -u + +usage_error () +{ + echo "$0: $*" >&2 + print_usage >&2 + exit 2 +} + +print_usage () +{ + cat <<END +Usage: + test-driver --test-name=NAME --log-file=PATH --trs-file=PATH + [--expect-failure={yes|no}] [--color-tests={yes|no}] + [--enable-hard-errors={yes|no}] [--] + TEST-SCRIPT [TEST-SCRIPT-ARGUMENTS] +The '--test-name', '--log-file' and '--trs-file' options are mandatory. +END +} + +test_name= # Used for reporting. +log_file= # Where to save the output of the test script. +trs_file= # Where to save the metadata of the test run. +expect_failure=no +color_tests=no +enable_hard_errors=yes +while test $# -gt 0; do + case $1 in + --help) print_usage; exit $?;; + --version) echo "test-driver $scriptversion"; exit $?;; + --test-name) test_name=$2; shift;; + --log-file) log_file=$2; shift;; + --trs-file) trs_file=$2; shift;; + --color-tests) color_tests=$2; shift;; + --expect-failure) expect_failure=$2; shift;; + --enable-hard-errors) enable_hard_errors=$2; shift;; + --) shift; break;; + -*) usage_error "invalid option: '$1'";; + *) break;; + esac + shift +done + +missing_opts= +test x"$test_name" = x && missing_opts="$missing_opts --test-name" +test x"$log_file" = x && missing_opts="$missing_opts --log-file" +test x"$trs_file" = x && missing_opts="$missing_opts --trs-file" +if test x"$missing_opts" != x; then + usage_error "the following mandatory options are missing:$missing_opts" +fi + +if test $# -eq 0; then + usage_error "missing argument" +fi + +if test $color_tests = yes; then + # Keep this in sync with 'lib/am/check.am:$(am__tty_colors)'. + red='[0;31m' # Red. + grn='[0;32m' # Green. + lgn='[1;32m' # Light green. + blu='[1;34m' # Blue. + mgn='[0;35m' # Magenta. + std='[m' # No color. +else + red= grn= lgn= blu= mgn= std= +fi + +do_exit='rm -f $log_file $trs_file; (exit $st); exit $st' +trap "st=129; $do_exit" 1 +trap "st=130; $do_exit" 2 +trap "st=141; $do_exit" 13 +trap "st=143; $do_exit" 15 + +# Test script is run here. +"$@" >$log_file 2>&1 +estatus=$? + +if test $enable_hard_errors = no && test $estatus -eq 99; then + tweaked_estatus=1 +else + tweaked_estatus=$estatus +fi + +case $tweaked_estatus:$expect_failure in + 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;; + 0:*) col=$grn res=PASS recheck=no gcopy=no;; + 77:*) col=$blu res=SKIP recheck=no gcopy=yes;; + 99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;; + *:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;; + *:*) col=$red res=FAIL recheck=yes gcopy=yes;; +esac + +# Report the test outcome and exit status in the logs, so that one can +# know whether the test passed or failed simply by looking at the '.log' +# file, without the need of also peaking into the corresponding '.trs' +# file (automake bug#11814). +echo "$res $test_name (exit status: $estatus)" >>$log_file + +# Report outcome to console. +echo "${col}${res}${std}: $test_name" + +# Register the test result, and other relevant metadata. +echo ":test-result: $res" > $trs_file +echo ":global-test-result: $res" >> $trs_file +echo ":recheck: $recheck" >> $trs_file +echo ":copy-in-global-log: $gcopy" >> $trs_file + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC0" +# time-stamp-end: "; # UTC" +# End: |