pax_global_header00006660000000000000000000000064133663067220014522gustar00rootroot0000000000000052 comment=737d1e3e5576ce5499c24002f847d3d743e6663b sockperf-3.6/000077500000000000000000000000001336630672200132065ustar00rootroot00000000000000sockperf-3.6/.gitignore000066400000000000000000000001771336630672200152030ustar00rootroot00000000000000Makefile aclocal.m4 config.h config.h.in config.log config.status config/aux/ configure doc/Doxyfile sockperf src/.dirstamp *~ sockperf-3.6/Makefile.am000077500000000000000000000024631336630672200152520ustar00rootroot00000000000000if TEST TEST_SUBDIR = tests endif if TOOL TOOL_SUBDIR = tools endif SUBDIRS = ${TEST_SUBDIR} ${TOOL_SUBDIR} ACLOCAL_AMFLAGS = -I config/m4 AM_LDFLAGS = -rdynamic AM_CPPFLAGS = -imacros $(builddir)/config.h AM_CXXFLAGS = $(OUR_CXXFLAGS) bin_PROGRAMS = sockperf sockperf_SOURCES = \ src/aopt.cpp \ src/aopt.h \ src/client.cpp \ src/client.h \ src/clock.h \ src/common.cpp \ src/common.h \ src/defs.cpp \ src/defs.h \ src/iohandlers.cpp \ src/iohandlers.h \ src/message.cpp \ src/message.h \ src/os_abstract.cpp \ src/os_abstract.h \ src/packet.cpp \ src/packet.h \ src/playback.cpp \ src/playback.h \ src/server.cpp \ src/server.h \ src/sockperf.cpp \ src/switches.h \ src/ticks.cpp \ src/ticks.h \ src/ticks_os.h \ src/vma-redirect.cpp \ src/vma-redirect.h dist_doc_DATA = \ readme \ authors \ news \ version \ copying EXTRA_DIST = \ build \ contrib \ debian \ doc/Doxyfile.in \ doc/main.dox if DOC .PHONY: doxygen doxygen: doc/man/man/man3/sockperf.3 doc/man/man/man3/sockperf.3: doc/Doxyfile $(srcdir)/doc/main.dox doxygen doc/Doxyfile install-data-local: $(mkinstalldirs) ${DESTDIR}$(docdir) cp -rf doc/man/html/ ${DESTDIR}$(docdir) uninstall-local: rm -rf ${DESTDIR}$(docdir)/html clean-local: rm -rf doc/man doc/doxygen.log man_MANS = doc/man/man/man3/sockperf.3 endif sockperf-3.6/README.md000066400000000000000000000046701336630672200144740ustar00rootroot00000000000000**sockperf** is a network benchmarking utility over socket API that was designed for testing performance (latency and throughput) of high-performance systems (it is also good for testing performance of regular networking systems as well). It covers most of the socket API calls and options. Specifically, in addition to the standard throughput tests, **sockperf**, does the following: * measure latency of each discrete packet at sub-nanosecond resolution (using TSC register that counts CPU ticks with very low overhead). * Does the above for both ping-pong mode and for latency under load mode. This means that we measure latency of single packets even under load of millions Packets Per Second (without waiting for reply of packet before sending subsequent packet on time) * Enable spike analysis by providing histogram, with various percentiles of the packets’ latencies (for example: median, min, max, 99% percentile, and more), (this is in addition to average and standard deviation). Also, **sockperf** provides full log with all packet’s tx/rx times that can be further analyzed with external tools, such as MS-Excel or matplotlib - All this without affecting the benchmark itself. * Support MANY optional settings for good coverage of socket API and network configurations, while still keeping very low overhead in the fast path to allow cleanest results. * Licensing * What you will need to compile aLic on Unix systems perl 5.8+ (used by the automake tools) GNU make tools: automake 1.7+, autoconf 2.57+, m4 1.4+ and libtool 1.4+ A Compiler, among those tested are: . gcc4 (Ubuntu 9) * How to install: The sockperf package uses the GNU autotools compilation and installation framework. $ ./autogen.sh $ ./configure --prefix= $ make $ make install To enable test scripts $ ./configure --prefix= --enable-test To enable the documentation $ ./configure --prefix= --enable-doc To enable the special scripts $ ./configure --prefix= --enable-tool To compile with debug symbols and information: $ ./configure --prefix= --enable-debug This will define the DEBUG variable at compile time. Type './configure --help' for a list of all the configure options. Some of the options are generic autoconf options, while the aLic specific options are prefixed with "SOCKPERF:" in the help text. Good luck! sockperf-3.6/authors000066400000000000000000000001171336630672200146150ustar00rootroot00000000000000Avner BenHanoch Igor Ivanov sockperf-3.6/autogen.sh000077500000000000000000000010501336630672200152030ustar00rootroot00000000000000#!/bin/sh set -ex oldpwd=$(pwd) topdir=$(dirname "$0") cd "$topdir" CURRENT_VERSION_FILE=./build/current-version . ./build/versioning.sh echo ${VERSION}-${RELEASE} > $CURRENT_VERSION_FILE echo $GIT_REF >> $CURRENT_VERSION_FILE rm -rf autom4te.cache mkdir -p config/m4 config/aux autoreconf -v --install || exit 1 rm -rf autom4te.cache cd "$oldpwd" if [ "x$1" = "xc" ]; then shift $topdir/configure CXXFLAGS='-g -O0 -Wall -Werror' $@ make clean else printf "\nNow run '$topdir/configure' and 'make'.\n\n" fi rm -f $CURRENT_VERSION_FILE exit 0 sockperf-3.6/build/000077500000000000000000000000001336630672200143055ustar00rootroot00000000000000sockperf-3.6/build/build-rpm-to-deb.sh000077500000000000000000000022211336630672200177040ustar00rootroot00000000000000#!/bin/bash -e ############################################################################## # this script will extract content of a given *.src.rpm file (that its tarball # contains ./debian/ subfolder) and will compile it into *.deb binary ############################################################################## APP_NAME=sockperf SRCRPM_EXT=.src.rpm TARBALL_EXT=.tar.gz BASE_DIR=`pwd` if [ $# -lt 1 ]; then echo -e "Usage is:\n\t $0 " > /dev/stderr exit 1 fi SRCRPM_FILE=`readlink -f $1` APP_NAME_VER=`basename $SRCRPM_FILE $SRCRPM_EXT` # sockperf-2.7-13.gitd8618862f05d.dirty FULL_VER=${APP_NAME_VER#$APP_NAME-} # 2.7-13.gitd8618862f05d.dirty VERSION=${FULL_VER%%-*} # 2.7 TEMP_DIR=/tmp/for-deb-$APP_NAME_VER rm -rf $TEMP_DIR; mkdir $TEMP_DIR; cd $TEMP_DIR rpm2cpio $SRCRPM_FILE | cpio -i 2> /dev/null # extract *.src.rpm OLD_NAME=`basename $APP_NAME-*$TARBALL_EXT $TARBALL_EXT` ln -s $OLD_NAME$TARBALL_EXT ${APP_NAME}_${VERSION}.orig$TARBALL_EXT tar xf $OLD_NAME$TARBALL_EXT cd $OLD_NAME dpkg-buildpackage -us -uc # actual build of *.deb cd $BASE_DIR cp --verbose $TEMP_DIR/*.deb . rm -rf $TEMP_DIR sockperf-3.6/build/build-rpm.sh000077500000000000000000000033251336630672200165420ustar00rootroot00000000000000#!/bin/bash -e ################################################################# ######## create *.src.rpm based on specfile template ############ ################################################################# BASE_DIR=`pwd` script_dir=`dirname $(readlink -f $0)` cd $script_dir/.. source ./build/versioning.sh APP_NAME=sockperf MAINTAINER="Mellanox Technologies Ltd. " DATE=`date -R` GITHUB_REF=$APP_NAME-$GIT_REF FULL_VER=${VERSION}-${RELEASE} echo $FULL_VER > ./build/current-version echo $GIT_REF >> ./build/current-version APP_NAME_VER=$APP_NAME-$FULL_VER #DIRNAME=$GITHUB_REF # match Fedora original style DIRNAME=$APP_NAME_VER # better MOFED DIRNAME=$APP_NAME-$VERSION TEMP_DIR=/tmp/$DIRNAME rm -rf $TEMP_DIR; mkdir $TEMP_DIR cp -a * $TEMP_DIR/ # do not copy hidden files like .git cd $TEMP_DIR if [ $# -lt 1 ]; then RPM_DIR=`rpm --eval '%{_topdir}'` else RPM_DIR=$1 fi mkdir -p --verbose $RPM_DIR/{BUILD,RPMS,SOURCES,SPECS,SRPMS,tmp} APP_SPEC=$RPM_DIR/SPECS/$APP_NAME_VER.spec sed -e s/__GIT_REF__/$GIT_REF/g -e s/__VERSION__/$VERSION/g -e s/__RELEASE__/$RELEASE/g ./build/$APP_NAME.spec.in > $APP_SPEC sed -i -e s/__VERSION__/$VERSION/g -e s/__RELEASE__/$RELEASE/g -e s/__APP_NAME__/$APP_NAME/g -e "s/__DATE__/$DATE/g" -e "s/__MAINTAINER__/$MAINTAINER/g" debian/* 2> /dev/null || true ./autogen.sh tar -zcf $RPM_DIR/SOURCES/$DIRNAME.tar.gz --exclude .git -C .. $DIRNAME rpmbuild -bs --define 'dist %{nil}' --define '_source_filedigest_algorithm md5' --define '_binary_filedigest_algorithm md5' --rmsource --rmspec --define "_topdir $RPM_DIR" $APP_SPEC cd $BASE_DIR rm -rf $TEMP_DIR # mv XXX.src.rpm from $RPM_DIR/SRPMS -> /.autodirect/mswg/release/sockperf/ and update ./latest.txt sockperf-3.6/build/sockperf.spec.in000066400000000000000000000060631336630672200174070ustar00rootroot00000000000000%global version __VERSION__ %global git_ref __GIT_REF__ %global release __RELEASE__ %global full_ver %{version}-%{release} Name: sockperf Version: %{version} Release: %{release}%{?dist} Summary: Network benchmarking utility for testing latency and throughput Group: Applications/Internet License: BSD URL: https://github.com/mellanox/%{name} #Source0: https://github.com/mellanox/%{name}/archive/%{git_ref}.tar.gz#/%{name}-%{git_ref}.tar.gz Source0: %{name}-%{version}.tar.gz BuildRequires: doxygen # can't use _pkgdocdir neither _docdir since it is not the same even where it is defined %global _my_pkgdocdir /usr/share/doc/%{name} %description sockperf is a network benchmarking utility over socket API that was designed for testing performance (latency and throughput) of high-performance systems (it is also good for testing performance of regular networking systems as well). It covers most of the socket API calls and options. Specifically, in addition to the standard throughput tests, sockperf, does the following: * Measure latency of each discrete packet at sub-nanosecond resolution (using TSC register that counts CPU ticks with very low overhead). * Does the above for both ping-pong mode and for latency under load mode. This means that we measure latency of single packets even under load of millions Packets Per Second (without waiting for reply of packet before sending subsequent packet on time) * Enable spike analysis by providing histogram, with various percentiles of the packets' latencies (for example: median, min, max, 99% percentile, and more), (this is in addition to average and standard deviation). Also, sockperf provides full log with all packet's tx/rx times that can be further analyzed with external tools, such as MS-Excel or matplotlib - All this without affecting the benchmark itself. * Support MANY optional settings for good coverage of socket API and network configurations, while still keeping very low overhead in the fast path to allow cleanest results. %prep #%setup -q -n %{name}-%{git_ref} %setup -q -n %{name}-%{version} %build # Upstream wants and defaults to "-O3 --param inline-unit-growth=200". # The Fedora optflags would override the former, so let's put it back. # Avner wrote: # > I reached that in the past after fine tuning the performance of sockperf. # > We used sockperf for measuring latency of extremely fast networks. # > Sometimes at sub microsecond resolution. This parameter helps us keeping # > the entire fast path of the application as "one big function" with no # > calls to other functions because it helps the compiler to respect all our # > "inline" directive for other functions that we call (while still keeping # > the "one big function" at a reasonable size for good performance at run # > time). export CXXFLAGS='%{optflags} -O3' %configure --enable-doc # --enable-tool --enable-test make %{?_smp_mflags} %install make install DESTDIR="%{?buildroot}" %files %defattr(-,root,root,-) %{_bindir}/%{name} %{_mandir}/man3/%{name}.3.* %{_my_pkgdocdir} sockperf-3.6/build/versioning.sh000077500000000000000000000005601336630672200170300ustar00rootroot00000000000000#!/bin/bash -e VERSION=`cat version | tr -d '\n'` GIT_REF=`git rev-parse HEAD 2> /dev/null || echo "no.git"` x=`git describe --long --abbrev=12 --dirty 2> /dev/null || echo ""` if [ -n "$x" ]; then x=`echo $x | sed -e 's/-g/.git/' -e 's/-dirty/.dirty/' | sed s/.*-//`; else x="no.git"; fi RELEASE=$x #RELEASE=20 # TEMP !!! #GIT_REF=${VERSION}-${RELEASE} # TEMP !!! sockperf-3.6/config/000077500000000000000000000000001336630672200144535ustar00rootroot00000000000000sockperf-3.6/config/m4/000077500000000000000000000000001336630672200147735ustar00rootroot00000000000000sockperf-3.6/config/m4/arg-bool.m4000066400000000000000000000007101336630672200167350ustar00rootroot00000000000000dnl Kind of like AC_ARG_ENABLE, but enforces that the optional argument is dnl either "yes" or "no". Returns the result in a variable called have_NAME. dnl dnl SP_ARG_ENABLE_BOOL(NAME, HELP-STRING) AC_DEFUN([SP_ARG_ENABLE_BOOL], [ have_$1=no AC_ARG_ENABLE([$1], [$2], [ AS_IF([test "x$enableval" = "xno"], [have_$1=no], [test "x$enableval" = "xyes"], [have_$1=yes], [AC_MSG_ERROR([bad value $enableval for --enable-$1])])]) ]) sockperf-3.6/config/m4/checkflags.m4000066400000000000000000000023601336630672200173300ustar00rootroot00000000000000dnl Check if compiler accepts FLAG in CXXFLAGS. If accepted, do dnl ACTION-IF-FLAG-WORKS. Otherwise do ACTION-IF-FLAG-DOES-NOT-WORK. dnl dnl SP_CHECK_CXXFLAG(FLAG, [ACTION-IF-FLAG-WORKS], [ACTION-IF-FLAG-DOES-NOT-WORK]) AC_DEFUN([SP_CHECK_CXXFLAG], [ AS_VAR_PUSHDEF([sp_cxxflag], [sockperf_cv_cxxflags_$1]) AC_CACHE_CHECK([whether $CXX supports $1 in CXXFLAGS], [sp_cxxflag], [ saved_cxxflags="$CXXFLAGS" CXXFLAGS="$1" AC_LINK_IFELSE([AC_LANG_PROGRAM()], [AS_VAR_SET([sp_cxxflag], [yes])], [AS_VAR_SET([sp_cxxflag], [no])]) CXXFLAGS="$saved_cxxflags"]) AS_VAR_IF([sp_cxxflag], [yes], [$2], [$3]) AS_VAR_POPDEF([sp_cxxflag]) ]) dnl Check if compiler accepts FLAG in CXXFLAGS. If accepted, append the flag dnl to environment variable ENV-VAR. Otherwise do ACTION-IF-FLAG-DOES-NOT-WORK. dnl dnl SP_CHECK_CXXFLAG_APPEND(ENV-VAR, FLAG, [ACTION-IF-FLAG-DOES-NOT-WORK]) AC_DEFUN([SP_CHECK_CXXFLAG_APPEND], [SP_CHECK_CXXFLAG([$2], [$1="${$1} $2"], [$3]) ]) dnl Check if compiler accepts FLAGS in CXXFLAGS. Append accepted flags to dnl environment variable ENV-VAR. Ignore rejected flags. dnl dnl SP_CHECK_CXXFLAGS_APPEND(ENV-VAR, FLAGS) AC_DEFUN([SP_CHECK_CXXFLAGS_APPEND], [ for flag in $2; do SP_CHECK_CXXFLAG_APPEND([$1], [$flag]) done]) sockperf-3.6/configure.ac000066400000000000000000000132561336630672200155030ustar00rootroot00000000000000define([sockperf_version], esyscmd([sh -c "head -1 ./build/current-version | tr -d '\n'"])) AC_INIT([SOCKPERF], [sockperf_version], [http://github.com/mellanox/sockperf/issues]) AC_CONFIG_HEADER([config.h]) AC_CONFIG_MACRO_DIR([config/m4]) AC_CONFIG_AUX_DIR([config/aux]) # Determine the host system AC_CANONICAL_SYSTEM TARGETDIR="unknown" case "$host" in i?86-*-*) TARGET=X86; TARGETDIR=x86;; ia64*-*-*) TARGET=IA64; TARGETDIR=ia64;; powerpc*-*-linux* | powerpc-*-sysv*) TARGET=POWERPC; TARGETDIR=powerpc;; arm*-*-linux*) TARGET=ARM; TARGETDIR=arm;; powerpc-*-beos*) TARGET=POWERPC; TARGETDIR=powerpc;; powerpc-*-darwin*) TARGET=POWERPC_DARWIN; TARGETDIR=powerpc;; powerpc-*-aix* | rs6000-*-aix*) TARGET=POWERPC_AIX; TARGETDIR=powerpc;; powerpc-*-freebsd*) TARGET=POWERPC_FREEBSD; TARGETDIR=powerpc;; powerpc*-*-rtems*) TARGET=POWERPC; TARGETDIR=powerpc;; x86_64-*-*) TARGET=X86_64; TARGETDIR=x86;; amd64-*-freebsd*) TARGET=FREEBSD; TARGETDIR=x86;; i386-*-freebsd*) TARGET=FREEBSD; TARGETDIR=x86;; aarch64-*-*) TARGET=AARCH64; TARGETDIR=aarch64;; s390*-*-*) TARGET=S390; TARGETDIR=s390;; esac AC_SUBST(AM_RUNTESTFLAGS) AC_SUBST(AM_LTLDFLAGS) if test $TARGETDIR = unknown; then AC_MSG_ERROR(["it has not been ported to $host."]) fi AM_CONDITIONAL(X86, test x$TARGET = xX86) AM_CONDITIONAL(IA64, test x$TARGET = xIA64) AM_CONDITIONAL(POWERPC, test x$TARGET = xPOWERPC) AM_CONDITIONAL(ARM, test x$TARGET = xARM) AM_CONDITIONAL(POWERPC_AIX, test x$TARGET = xPOWERPC_AIX) AM_CONDITIONAL(POWERPC_DARWIN, test x$TARGET = xPOWERPC_DARWIN) AM_CONDITIONAL(POWERPC_FREEBSD, test x$TARGET = xPOWERPC_FREEBSD) AM_CONDITIONAL(FREEBSD, test x$TARGET = xFREEBSD) AM_CONDITIONAL(AARCH64, test x$TARGET = xAARCH64) AM_CONDITIONAL(S390, test x$TARGET = xS390) AC_SUBST(TARGET) AC_SUBST(TARGETDIR) ######### # Locate a compiler for the build machine. This compiler should # generate command-line programs that run on the build machine. # if test x"$cross_compiling" = xyes; then AC_MSG_NOTICE([Enable cross compiling on ${build_cpu} for ${host_cpu}]) #prefix=${prefix}/${host_cpu} fi AM_INIT_AUTOMAKE([foreign subdir-objects -Wall]) AM_MAINTAINER_MODE ##################################### # check for C++ preprocessor and compiler # : ${CXXFLAGS="-O3 -g"} AC_PROG_CXX AC_LANG(C++) #AC_PROG_LIBTOOL SP_CHECK_CXXFLAGS_APPEND([OUR_CXXFLAGS], [\ -Wall \ "--param inline-unit-growth=200"]) ########################################################################## # check VMA extra API # AC_ARG_ENABLE( [vma-api], AC_HELP_STRING([--enable-vma-api], [SOCKPERF: enable vma extra api support (default=no)]), [have_vma_api=$enableval], [have_vma_api=no]) AS_IF([test "x${have_vma_api}" == "xyes"], [AC_CHECK_HEADER([mellanox/vma_extra.h], [AC_DEFINE([USING_VMA_EXTRA_API],[1],[[Enable using VMA extra API]])], [AC_MSG_ERROR([vma_extra.h file not found])] [have_vma_api=no])]) AC_MSG_CHECKING( [for vma extra api]) AC_MSG_RESULT([${have_vma_api}]) ########################## # Documentation # SP_ARG_ENABLE_BOOL( [doc], AC_HELP_STRING([--enable-doc], [SOCKPERF: create documentation with doxygen in html and unix-man (default=no)])) AS_IF([test "x$have_doc" = "xyes"], [ # Checks for doxygen AC_PATH_PROG(DOXYGEN, doxygen, ,$PATH:/usr/local/bin:/usr/bin) AS_IF([test -z "$DOXYGEN"], [AC_MSG_ERROR([Building of doc requested, but doxygen not found])])]) AM_CONDITIONAL(DOC, test "x$have_doc" = "xyes") ########################## # Enable tests # SP_ARG_ENABLE_BOOL( [test], AC_HELP_STRING([--enable-test], [SOCKPERF: compile tests (default=no)])) AM_CONDITIONAL(TEST, test "x$have_test" = "xyes") ########################## # Enable tools # SP_ARG_ENABLE_BOOL( [tool], AC_HELP_STRING([--enable-tool], [SOCKPERF: compile utilities (default=no)])) AM_CONDITIONAL(TOOL, test "x$have_tool" = "xyes") ########################## # Enable debug build # SP_ARG_ENABLE_BOOL( [debug], AC_HELP_STRING([--enable-debug], [SOCKPERF: turn on debugging (default=no)])) AS_IF([test "x$have_debug" = "xyes"], [AC_DEFINE([DEBUG], [], [Enable debugging])], [AC_DEFINE([NDEBUG], [], [Disable debugging])]) ########################## # Enable build 32bit # SP_ARG_ENABLE_BOOL( [build32], AC_HELP_STRING([--enable-build32], [SOCKPERF: force build 32bit (default=no)])) AS_IF([test "x$have_build32" = "xyes"], [ SP_CHECK_CXXFLAG_APPEND([OUR_CXXFLAGS], [-m32], [AC_MSG_ERROR([32bit build requested, but -m32 compiler flag does not work])])]) AC_SUBST([OUR_CXXFLAGS]) ##################################### # Checks for header files. # AC_HEADER_STDC AC_CHECK_HEADERS( [arpa/inet.h fcntl.h netinet/in.h stdint.h stdlib.h \ string.h sys/ioctl.h sys/socket.h sys/time.h syslog.h \ termios.h unistd.h]) ##################################### # Checks for libraries. # AC_HEADER_STDC AC_SEARCH_LIBS([clock_gettime], [rt], [], AC_MSG_ERROR([librt not found])) AC_SEARCH_LIBS([pthread_create], [pthread], [], AC_MSG_ERROR([libpthread not found])) AC_SEARCH_LIBS([backtrace], [execinfo], [], AC_MSG_ERROR([libexecinfo not found])) AC_SEARCH_LIBS([dlsym], [dl], [], AC_MSG_ERROR([libdl not found])) AC_CONFIG_FILES([Makefile tools/Makefile tests/Makefile doc/Doxyfile build/sockperf.spec]) AC_OUTPUT AC_MSG_RESULT([ ${PACKAGE} ${VERSION} prefix: ${prefix} compiler: ${CXX} cppflags: ${CPPFLAGS} cxxflags: ${OUR_CXXFLAGS} ${CXXFLAGS} ldflags: ${LDFLAGS} doc: ${have_doc} test: ${have_test} tool: ${have_tool} vma_api: ${have_vma_api} debug: ${have_debug} ]) sockperf-3.6/contrib/000077500000000000000000000000001336630672200146465ustar00rootroot00000000000000sockperf-3.6/contrib/jenkins.groovy000077500000000000000000000006061336630672200175630ustar00rootroot00000000000000#!/usr/bin/env groovy node('master') { deleteDir() checkout scm dir('swx_ci') { checkout([$class: 'GitSCM', extensions: [[$class: 'CloneOption', shallow: true]], userRemoteConfigs: [[ url: 'https://github.com/Mellanox/swx_ci.git']] ]) } evaluate(readFile("${env.WORKSPACE}/swx_ci/sockperf/test_jenkins_pipeline.groovy")) } sockperf-3.6/contrib/jenkins_tests/000077500000000000000000000000001336630672200175315ustar00rootroot00000000000000sockperf-3.6/contrib/jenkins_tests/build.sh000077500000000000000000000017131336630672200211710ustar00rootroot00000000000000#!/bin/bash -eExl source $(dirname $0)/globals.sh do_check_filter "Checking for building with gcc ..." "off" cd $WORKSPACE rm -rf ${build_dir} mkdir -p ${build_dir} cd ${build_dir} # Set symbolic links to default build and install ln -s "${build_dir}/0/install" "${install_dir}" build_list="\ default: \ debug:--enable-debug" build_tap=${WORKSPACE}/${prefix}/build.tap echo "1..$(echo $build_list | tr " " "\n" | wc -l)" > $build_tap test_id=0 for build in $build_list; do IFS=':' read build_name build_option <<< "$build" mkdir -p ${build_dir}/${test_id} cd ${build_dir}/${test_id} test_exec='${WORKSPACE}/configure --prefix=${build_dir}/${test_id}/install $build_option $jenkins_test_custom_configure && make $make_opt install' do_check_result "$test_exec" "$test_id" "$build_name" "$build_tap" "${build_dir}/build-${test_id}" cd ${build_dir} test_id=$((test_id+1)) done echo "[${0##*/}]..................exit code = $rc" exit $rc sockperf-3.6/contrib/jenkins_tests/compiler.sh000077500000000000000000000016331336630672200217050ustar00rootroot00000000000000#!/bin/bash -eExl source $(dirname $0)/globals.sh do_check_filter "Checking for compiler ..." "on" do_module "intel/ics-15.0.1" cd $WORKSPACE rm -rf $compiler_dir mkdir -p $compiler_dir cd $compiler_dir compiler_list="icc:icpc clang:clang++" compiler_tap=${WORKSPACE}/${prefix}/compiler.tap echo "1..$(echo $compiler_list | tr " " "\n" | wc -l)" > $compiler_tap test_id=0 for compiler in $compiler_list; do IFS=':' read cc cxx <<< "$compiler" mkdir -p ${compiler_dir}/${test_id} cd ${compiler_dir}/${test_id} test_exec='${WORKSPACE}/configure --prefix=$compiler_dir-$cc CC=$cc CXX=$cxx $jenkins_test_custom_configure && make $make_opt all' do_check_result "$test_exec" "$test_id" "$compiler" "$compiler_tap" "${compiler_dir}/compiler-${test_id}" cd ${compiler_dir} test_id=$((test_id+1)) done module unload intel/ics-15.0.1 echo "[${0##*/}]..................exit code = $rc" exit $rc sockperf-3.6/contrib/jenkins_tests/cov.sh000077500000000000000000000043511336630672200206620ustar00rootroot00000000000000#!/bin/bash -xeEl source $(dirname $0)/globals.sh do_check_filter "Checking for coverity ..." "on" do_module "tools/cov-8.7" cd $WORKSPACE rm -rf $cov_dir mkdir -p $cov_dir cd $cov_dir cov_exclude_file_list="tests" cov_build_id="cov_build_${BUILD_NUMBER}" cov_build="$cov_dir/$cov_build_id" set +eE ${WORKSPACE}/configure --prefix=${cov_dir}/install $jenkins_test_custom_configure > "${cov_dir}/cov.log" 2>&1 make clean >> "${cov_dir}/cov.log" 2>&1 eval "cov-configure --config $cov_dir/coverity_config.xml --gcc" eval "cov-build --config $cov_dir/coverity_config.xml --dir $cov_build make >> "${cov_dir}/cov.log" 2>&1" rc=$(($rc+$?)) for excl in $cov_exclude_file_list; do cov-manage-emit --config $cov_dir/coverity_config.xml --dir $cov_build --tu-pattern "file('$excl')" delete sleep 1 done eval "cov-analyze --config $cov_dir/coverity_config.xml \ --all --aggressiveness-level low \ --enable-fnptr --fnptr-models --paths 20000 \ --dir $cov_build" rc=$(($rc+$?)) set -eE cov_web_path="$(echo $cov_build | sed -e s,$WORKSPACE,,g)" nerrors=$(cov-format-errors --dir $cov_build | awk '/Processing [0-9]+ errors?/ { print $2 }') rc=$(($rc+$nerrors)) index_html=$(cd $cov_build && find . -name index.html | cut -c 3-) cov_url="$WS_URL/$cov_web_path/${index_html}" cov_file="$cov_build/${index_html}" rm -f jenkins_sidelinks.txt coverity_tap=${WORKSPACE}/${prefix}/coverity.tap echo 1..1 > $coverity_tap if [ $rc -gt 0 ]; then echo "not ok 1 Coverity Detected $nerrors failures # $cov_url" >> $coverity_tap do_err "coverity" "${cov_build}/output/summary.txt" info="Coverity found $nerrors errors" status="error" else echo ok 1 Coverity found no issues >> $coverity_tap info="Coverity found no issues" status="success" fi if [ -n "$ghprbGhRepository" ]; then context="MellanoxLab/coverity" do_github_status "repo='$ghprbGhRepository' sha1='$ghprbActualCommit' target_url='$cov_url' state='$status' info='$info' context='$context'" fi echo Coverity report: $cov_url printf "%s\t%s\n" Coverity $cov_url >> jenkins_sidelinks.txt module unload tools/cov-8.7 do_archive "$( find ${cov_build}/output -type f -name "*.txt" -or -name "*.html" -or -name "*.xml" )" echo "[${0##*/}]..................exit code = $rc" exit $rc sockperf-3.6/contrib/jenkins_tests/cppcheck.sh000077500000000000000000000026521336630672200216550ustar00rootroot00000000000000#!/bin/bash -xeEl source $(dirname $0)/globals.sh do_check_filter "Checking for cppcheck ..." "on" # This unit requires cppcheck so check for existence if [ $(command -v cppcheck >/dev/null 2>&1 || echo $?) ]; then echo "[SKIP] cppcheck tool does not exist" exit 0 fi cd $WORKSPACE rm -rf $cppcheck_dir mkdir -p $cppcheck_dir cd $cppcheck_dir set +eE eval "find ${WORKSPACE}/src -name '*.h' -o -name '*.cpp' -o -name '*.c' -o -name '*.hpp' -o -name '*.inl' | \ cppcheck --std=c99 --std=c++11 --language=c++ --force --enable=information \ --inline-suppr --suppress=memleak:config_parser.y \ --template='{severity}: {id}: {file}:{line}: {message}' \ --file-list=- 2> ${cppcheck_dir}/cppcheck.err 1> ${cppcheck_dir}/cppcheck.log" rc=$(($rc+$?)) set -eE nerrors=$(cat ${cppcheck_dir}/cppcheck.err | grep error | wc -l) rc=$(($rc+$nerrors)) cppcheck_tap=${WORKSPACE}/${prefix}/cppcheck.tap echo 1..1 > $cppcheck_tap if [ $rc -gt 0 ]; then echo "not ok 1 cppcheck Detected $nerrors failures # ${cppcheck_dir}/cppcheck.err" >> $cppcheck_tap do_err "cppcheck" "${cppcheck_dir}/cppcheck.err" info="cppcheck found $nerrors errors" status="error" do_err "$1" "${5}.err" else echo ok 1 cppcheck found no issues >> $cppcheck_tap info="cppcheck found no issues" status="success" fi do_archive "${cppcheck_dir}/cppcheck.err" "${cppcheck_dir}/cppcheck.log" echo "[${0##*/}]..................exit code = $rc" exit $rc sockperf-3.6/contrib/jenkins_tests/csbuild.sh000077500000000000000000000044061336630672200215210ustar00rootroot00000000000000#!/bin/bash -xeEl source $(dirname $0)/globals.sh do_check_filter "Checking for csbuild ..." "on" # This unit requires csbuild so check for existence if [ $(command -v csbuild >/dev/null 2>&1 || echo $?) ]; then echo "[SKIP] csbuild tool does not exist" exit 0 fi # There is a bug in gcc less than 4.5 if [ $(echo `gcc -dumpversion | cut -f1-2 -d.` \< 4.5 | bc ) -eq 1 ]; then echo "[SKIP] csbuild tool can not launch on this gcc" exit 0 fi cd $WORKSPACE rm -rf $csbuild_dir mkdir -p $csbuild_dir cd $csbuild_dir set +eE ${WORKSPACE}/configure --prefix=${csbuild_dir}/install $jenkins_test_custom_configure > "${csbuild_dir}/csbuild.log" 2>&1 make clean eval "csbuild --cswrap-timeout=180 --no-clean -c \"make $make_opt \" > \"${csbuild_dir}/csbuild.log\" 2>&1" rc=$(($rc+$?)) eval "csgrep --quiet --event 'error|warning' \ --path '^${WORKSPACE}' --strip-path-prefix '${WORKSPACE}' \ --remove-duplicates '${csbuild_dir}/csbuild.log' | \ csgrep --invert-match --path '^ksh-.*[0-9]+\.c$' | \ csgrep --invert-match --checker CLANG_WARNING --event error | \ csgrep --invert-match --checker CLANG_WARNING --msg \"internal warning\" | \ csgrep --invert-match --checker COMPILER_WARNING --msg \"-Woverloaded-virtual\" | \ csgrep --invert-match --checker COMPILER_WARNING --msg \"-Wformat-nonliteral\" | \ csgrep --invert-match --checker CPPCHECK_WARNING --event 'preprocessorErrorDirective|syntaxError' | \ csgrep --mode=grep --invert-match --event 'internal warning' --prune-events=1 | \ cssort --key=path > ${csbuild_dir}/csbuild.err 2>&1 \ " eval "grep 'timed out' ${csbuild_dir}/csbuild.log >> ${csbuild_dir}/csbuild.err 2>&1" set -eE nerrors=$(cat ${csbuild_dir}/csbuild.err | grep 'Error:\|error:' | wc -l) rc=$(($rc+$nerrors)) csbuild_tap=${WORKSPACE}/${prefix}/csbuild.tap echo 1..1 > $csbuild_tap if [ $rc -gt 0 ]; then echo "not ok 1 csbuild Detected $nerrors failures # ${csbuild_dir}/csbuild.err" >> $csbuild_tap do_err "csbuild" "${csbuild_dir}/csbuild.err" info="csbuild found $nerrors errors" status="error" else echo ok 1 csbuild found no issues >> $csbuild_tap info="csbuild found no issues" status="success" fi do_archive "${csbuild_dir}/csbuild.err" "${csbuild_dir}/csbuild.log" echo "[${0##*/}]..................exit code = $rc" exit $rc sockperf-3.6/contrib/jenkins_tests/globals.sh000077500000000000000000000142361336630672200215210ustar00rootroot00000000000000#!/bin/bash WORKSPACE=${WORKSPACE:=$PWD} if [ -z "$BUILD_NUMBER" ]; then echo Running interactive BUILD_NUMBER=1 WS_URL=file://$WORKSPACE JENKINS_RUN_TESTS=yes else echo Running under jenkins WS_URL=$JOB_URL/ws fi TARGET=${TARGET:=all} i=0 if [ "$TARGET" == "all" -o "$TARGET" == "default" ]; then target_list[$i]="default: " i=$((i+1)) fi # exit code rc=0 jenkins_test_custom_configure=${jenkins_test_custom_configure:=""} jenkins_test_custom_prefix=${jenkins_test_custom_prefix:="jenkins"} prefix=${jenkins_test_custom_prefix}/${jenkins_target} build_dir=${WORKSPACE}/${prefix}/build/ install_dir=${WORKSPACE}/${prefix}/install compiler_dir=${WORKSPACE}/${prefix}/compiler test_dir=${WORKSPACE}/${prefix}/test rpm_dir=${WORKSPACE}/${prefix}/rpm cov_dir=${WORKSPACE}/${prefix}/cov cppcheck_dir=${WORKSPACE}/${prefix}/cppcheck csbuild_dir=${WORKSPACE}/${prefix}/csbuild style_dir=${WORKSPACE}/${prefix}/style nproc=$(grep processor /proc/cpuinfo|wc -l) make_opt="-j$(($nproc / 2 + 1))" if [ $(command -v timeout >/dev/null 2>&1 && echo $?) ]; then timeout_exe="timeout -s SIGKILL 20m" fi trap "on_exit" INT TERM ILL KILL FPE SEGV ALRM function on_exit() { rc=$((rc + $?)) echo "[${0##*/}]..................exit code = $rc" pkill -9 sockperf } function do_cmd() { cmd="$*" set +e eval $cmd >> /dev/null 2>&1 ret=$? set -e if [ $ret -gt 0 ]; then exit $ret fi } function do_export() { export PATH="$1/bin:${PATH}" export LD_LIBRARY_PATH="$1/lib:${LD_LIBRARY_PATH}" export MANPATH="$1/share/man:${MANPATH}" } function do_archive() { cmd="tar -rvf ${jenkins_test_artifacts}.tar $*" set +e eval $cmd >> /dev/null 2>&1 set -e } function do_github_status() { echo "Calling: github $1" eval "local $1" local token="" if [ -z "$tokenfile" ]; then tokenfile="$HOME/.mellanox-github" fi if [ -r "$tokenfile" ]; then token="$(cat $tokenfile)" else echo Error: Unable to read tokenfile: $tokenfile return fi curl \ -X POST \ -H "Content-Type: application/json" \ -d "{\"state\": \"$state\", \"context\": \"$context\",\"description\": \"$info\", \"target_url\": \"$target_url\"}" \ "https://api.github.com/repos/$repo/statuses/${sha1}?access_token=$token" } # Test if an environment module exists and load it if yes. # Otherwise, return error code. # $1 - module name # function do_module() { echo "Checking module $1" if [ $(command -v module >/dev/null 2>&1 || echo $?) ]; then echo "[SKIP] module tool does not exist" exit 0 else module load "$1" fi } # format text # function do_format() { set +x local is_format=true if [[ $is_format == true ]] ; then res="" for ((i=2; i<=$#; i++)) ; do case "${!i}" in "bold" ) res="$res\e[1m" ;; "underline" ) res="$res\e[4m" ;; "reverse" ) res="$res\e[7m" ;; "red" ) res="$res\e[91m" ;; "green" ) res="$res\e[92m" ;; "yellow" ) res="$res\e[93m" ;; esac done echo -e "$res$1\e[0m" else echo "$1" fi set -x } # print error message # function do_err() { set +x echo -e $(do_format "FAILURE: $1" "red" "bold") 2>&1 if [ -n "$2" ]; then echo ">>>" cat $2 echo ">>>" fi set -x } # Verify if current environment is suitable. # function do_check_env() { echo "Checking system configuration" if [ $(command -v pkill >/dev/null 2>&1 || echo $?) ]; then echo "pkill is not found" echo "environment [NOT OK]" exit 1 fi if [ $(sudo pwd >/dev/null 2>&1 || echo $?) ]; then echo "sudo does not work" echo "environment [NOT OK]" exit 1 fi echo "environment [OK]" } # Check if the unit should be proccesed # $1 - output message # $2 - [on|off] if on - skip this case if JENKINS_RUN_TESTS variable is OFF # function do_check_filter() { local msg=$1 local filter=$2 if [ -n "$filter" -a "$filter" == "on" ]; then if [ -z "$JENKINS_RUN_TESTS" -o "$JENKINS_RUN_TESTS" == "no" ]; then echo "$msg [SKIP]" exit 0 fi fi echo "$msg [OK]" } # Launch command and detect result of execution # $1 - test command # $2 - test id # $3 - test name # $4 - test tap file # $5 - files for stdout/stderr # function do_check_result() { set +e if [ -z "$5" ]; then eval $timeout_exe $1 ret=$? else eval $timeout_exe $1 2>> "${5}.err" 1>> "${5}.log" ret=$? do_archive "${5}.err" "${5}.log" fi set -e if [ $ret -gt 0 ]; then echo "not ok $2 $3" >> $4 if [ -z "$5" ]; then do_err "$1" else do_err "$1" "${5}.err" fi else echo "ok $2 $3" >> $4 fi rc=$((rc + $ret)) } # Detect interface ip # $1 - [ib|eth] to select link type or empty to select the first found # $2 - [empty|mlx4|mlx5] # $3 - ip address not to get # function do_get_ip() { for ip in $(ibdev2netdev | grep Up | grep "$2" | cut -f 5 -d ' '); do if [ -n "$1" -a "$1" == "ib" -a -n "$(ip link show $ip | grep 'link/inf')" ]; then found_ip=$(ip -4 address show $ip | grep 'inet' | sed 's/.*inet \([0-9\.]\+\).*/\1/') if [ -n "$(ibdev2netdev | grep $ip | grep mlx5)" ]; then local ofed_v=$(ofed_info -s | grep OFED | sed 's/.*[l|X]-\([0-9\.]\+\).*/\1/') if [ $(echo $ofed_v | grep 4.[1-9] >/dev/null 2>&1 || echo $?) ]; then echo "$ip is CX4 device that does not support IPoIB in OFED: $ofed_v" unset found_ip fi fi elif [ -n "$1" -a "$1" == "eth" -a -n "$(ip link show $ip | grep 'link/eth')" ]; then found_ip=$(ip -4 address show $ip | grep 'inet' | sed 's/.*inet \([0-9\.]\+\).*/\1/') elif [ -z "$1" ]; then found_ip=$(ip -4 address show $ip | grep 'inet' | sed 's/.*inet \([0-9\.]\+\).*/\1/') fi if [ -n "$found_ip" -a "$found_ip" != "$3" ]; then echo $found_ip break fi done } sockperf-3.6/contrib/jenkins_tests/rpm.sh000077500000000000000000000024041336630672200206660ustar00rootroot00000000000000#!/bin/bash -eExl source $(dirname $0)/globals.sh do_check_filter "Checking for rpm ..." "off" cd $WORKSPACE rm -rf $rpm_dir mkdir -p $rpm_dir cd $rpm_dir rpm_tap=${WORKSPACE}/${prefix}/rpm.tap cd ${build_dir}/0 if [ -f "/etc/debian_version" -o "$(grep -Ei 'debian|buntu|mint' /etc/*release)" ]; then echo "Build on debian" set +e ${WORKSPACE}/build/build-rpm.sh "$rpm_dir" 2> "${rpm_dir}/rpm.err" 1> "${rpm_dir}/rpm.log" rc=$((rc + $?)) ${WORKSPACE}/build/build-rpm-to-deb.sh $(find $rpm_dir/SRPMS -maxdepth 1 -type f -name "sockperf*.src.rpm") 2> "${rpm_dir}/rpm-deb.err" 1> "${rpm_dir}/rpm-deb.log" rc=$((rc + $?)) do_archive "${rpm_dir}/*.err" "${rpm_dir}/*.log" set -e echo "1..1" > $rpm_tap if [ $rc -gt 0 ]; then echo "not ok 1 Debian package" >> $rpm_tap else echo ok 1 Debian package >> $rpm_tap fi else echo "Build rpm" set +e ${WORKSPACE}/build/build-rpm.sh "$rpm_dir" 2> "${rpm_dir}/rpm.err" 1> "${rpm_dir}/rpm.log" rc=$((rc + $?)) do_archive "${rpm_dir}/*.err" "${rpm_dir}/*.log" set -e echo "1..1" > $rpm_tap if [ $rc -gt 0 ]; then echo "not ok 1 rpm package" >> $rpm_tap else echo ok 1 rpm package >> $rpm_tap fi fi echo "[${0##*/}]..................exit code = $rc" exit $rc sockperf-3.6/contrib/jenkins_tests/style.conf000066400000000000000000000025641336630672200215470ustar00rootroot00000000000000--- # BasedOnStyle: LLVM AccessModifierOffset: -4 ConstructorInitializerIndentWidth: 4 AlignEscapedNewlinesLeft: false AlignTrailingComments: true AllowAllParametersOfDeclarationOnNextLine: true AllowShortIfStatementsOnASingleLine: true AllowShortLoopsOnASingleLine: false AlwaysBreakTemplateDeclarations: false AlwaysBreakBeforeMultilineStrings: false BreakBeforeBinaryOperators: false BreakBeforeTernaryOperators: true BreakConstructorInitializersBeforeComma: false BinPackParameters: true ColumnLimit: 100 ConstructorInitializerAllOnOneLineOrOnePerLine: false DerivePointerBinding: false ExperimentalAutoDetectBinPacking: false IndentCaseLabels: false MaxEmptyLinesToKeep: 1 NamespaceIndentation: None ObjCSpaceBeforeProtocolList: true PenaltyBreakBeforeFirstCallParameter: 19 PenaltyBreakComment: 60 PenaltyBreakString: 1000 PenaltyBreakFirstLessLess: 120 PenaltyExcessCharacter: 1000000 PenaltyReturnTypeOnItsOwnLine: 60 PointerBindsToType: false SpacesBeforeTrailingComments: 1 Cpp11BracedListStyle: false Standard: Cpp03 IndentWidth: 4 TabWidth: 4 UseTab: Never BreakBeforeBraces: Attach IndentFunctionDeclarationAfterType: false SpacesInParentheses: false SpacesInAngles: false SpaceInEmptyParentheses: false SpacesInCStyleCastParentheses: false SpaceAfterControlStatementKeyword: true SpaceBeforeAssignmentOperators: true ContinuationIndentWidth: 4 ... sockperf-3.6/contrib/jenkins_tests/style.sh000077500000000000000000000023641336630672200212350ustar00rootroot00000000000000#!/bin/bash -xeEl source $(dirname $0)/globals.sh do_check_filter "Checking for codying style ..." "on" cd $WORKSPACE rm -rf $style_dir mkdir -p $style_dir cd $style_dir test_app="clang-format" if [ $(command -v $test_app >/dev/null 2>&1 || echo $?) ]; then echo can not find $test_app exit 1 fi style_tap=${WORKSPACE}/${prefix}/style_test.tap rm -rf $style_tap ln -sf $WORKSPACE/contrib/jenkins_tests/style.conf $WORKSPACE/.clang-format check_files=$(find $WORKSPACE/src/ -name '*.c' -o -name '*.cpp' -o -name '*.h') echo "1..$(echo $check_files | wc -w)" > $style_tap i=0 nerrors=0 for file in $check_files; do set +eE style_diff="${style_dir}/$(basename ${file}).diff" eval "env $test_app -style=file \ ${file} \ | diff -u ${file} - | sed -e '1s|-- |--- a/|' -e '2s|+++ -|+++ b/$file|' \ > ${style_diff} 2>&1" [ -s ${style_diff} ] ret=$((1-$?)) nerrors=$((nerrors+ret)) set -eE i=$((i+1)) file=$(basename ${file}) if [ $ret -gt 0 ]; then echo "not ok $i $file # See: ${file}.diff" >> $style_tap else echo "ok $i $file" >> $style_tap fi done do_archive "${style_dir}/*.diff" rc=$(($rc+$nerrors)) echo "[${0##*/}]..................exit code = $rc" exit $rc sockperf-3.6/contrib/jenkins_tests/test.sh000077500000000000000000000034541336630672200210550ustar00rootroot00000000000000#!/bin/bash -eExl source $(dirname $0)/globals.sh do_check_filter "Checking for test ..." "off" if [ $(command -v ibdev2netdev >/dev/null 2>&1 || echo $?) ]; then echo "[SKIP] ibdev2netdev tool does not exist" exit 0 fi cd $WORKSPACE rm -rf $test_dir mkdir -p $test_dir cd $test_dir test_app="$install_dir/bin/sockperf" if [ $(command -v $test_app >/dev/null 2>&1 || echo $?) ]; then echo can not find $test_app exit 1 fi if [ ! -z $(do_get_ip 'eth') ]; then test_ip_list="${test_ip_list} eth:$(do_get_ip 'eth')" fi test_list="tcp-pp tcp-tp tcp-ul udp-pp udp-tp udp-ul" nerrors=0 for test_link in $test_ip_list; do for test in $test_list; do IFS=':' read test_in test_ip <<< "$test_link" test_name=${test_in}-${test} test_tap=${WORKSPACE}/${prefix}/test-${test_name}.tap $timeout_exe ${WORKSPACE}/tests/verifier/verifier.pl -a ${test_app} \ -t ${test} -s ${test_ip} -l ${test_dir}/${test_name}.log \ --progress=0 # exclude multicast tests from final result # because they are not valid when server/client on the same node grep -e 'PASS' -e 'FAIL' ${test_dir}/${test_name}.dump | grep -v 'multicast' > ${test_dir}/${test_name}.tmp do_archive "${test_dir}/${test_name}.dump" "${test_dir}/${test_name}.log" echo "1..$(wc -l < ${test_dir}/${test_name}.tmp)" > $test_tap v1=1 while read line; do if [[ $(echo $line | cut -f1 -d' ') =~ 'PASS' ]]; then v0='ok' v2=$(echo $line | sed 's/PASS //') else v0='not ok' v2=$(echo $line | sed 's/FAIL //') nerrors=$((nerrors+1)) fi echo -e "$v0 ${test_in}: $v2" >> $test_tap v1=$(($v1+1)) done < ${test_dir}/${test_name}.tmp rm -f ${test_dir}/${test_name}.tmp done done rc=$(($rc+$nerrors)) echo "[${0##*/}]..................exit code = $rc" exit $rc sockperf-3.6/contrib/test_jenkins.sh000077500000000000000000000127021336630672200177070ustar00rootroot00000000000000#!/bin/bash -El # # Testing script for SOCKPERF, to run from Jenkins CI # # Copyright (C) Mellanox Technologies Ltd. 2001-2017. ALL RIGHTS RESERVED. # # See file LICENSE for terms. # # # Environment variables set by Jenkins CI: # - WORKSPACE : path to working directory # - BUILD_NUMBER : jenkins build number # - JOB_URL : jenkins job url # - JENKINS_RUN_TESTS : whether to run unit tests # - TARGET : target configuration # echo "======================================================" echo echo "# starting on host ---------> $(hostname) " echo "# arguments called with ----> ${@} " echo "# path to me ---------------> ${0} " echo "# parent path --------------> ${0%/*} " echo "# name ---------------------> ${0##*/} " echo PATH=${PATH}:/hpc/local/bin:/hpc/local/oss/vma/ MODULEPATH=${MODULEPATH}:/hpc/local/etc/modulefiles env for f in autoconf automake libtool ; do $f --version | head -1 ; done echo "======================================================" source $(dirname $0)/jenkins_tests/globals.sh set -xe # check go/not go # do_check_env rel_path=$(dirname $0) abs_path=$(readlink -f $rel_path) # Values: none, fail, always # jenkins_opt_artifacts=${jenkins_opt_artifacts:="always"} # Values: 0..N test (max 100) # jenkins_opt_exit=${jenkins_opt_exit:="6"} # Test scenario list # jenkins_test_build=${jenkins_test_build:="yes"} jenkins_test_compiler=${jenkins_test_compiler:="yes"} jenkins_test_rpm=${jenkins_test_rpm:="yes"} jenkins_test_cov=${jenkins_test_cov:="no"} jenkins_test_cppcheck=${jenkins_test_cppcheck:="yes"} jenkins_test_csbuild=${jenkins_test_csbuild:="no"} jenkins_test_run=${jenkins_test_run:="no"} jenkins_test_style=${jenkins_test_style:="no"} echo Starting on host: $(hostname) cd $WORKSPACE rm -rf ${WORKSPACE}/${prefix} rm -rf autom4te.cache ./autogen.sh -s for target_v in "${target_list[@]}"; do ret=0 IFS=':' read target_name target_option <<< "$target_v" export jenkins_test_artifacts="${WORKSPACE}/${prefix}/sockperf-${BUILD_NUMBER}-$(hostname -s)-${target_name}" export jenkins_test_custom_configure="${target_option}" export jenkins_target="${target_name}" set +x echo "======================================================" echo "Jenkins is checking for [${target_name}] target ..." echo "======================================================" set -x # check building and exit immediately in case failure # if [ "$jenkins_test_build" = "yes" ]; then $WORKSPACE/contrib/jenkins_tests/build.sh ret=$? if [ $ret -gt 0 ]; then do_err "case: [build: ret=$ret]" fi rc=$((rc + $ret)) fi # check other units w/o forcing exiting # set +e if [ 1 -lt "$jenkins_opt_exit" -o "$rc" -eq 0 ]; then if [ "$jenkins_test_compiler" = "yes" ]; then $WORKSPACE/contrib/jenkins_tests/compiler.sh ret=$? if [ $ret -gt 0 ]; then do_err "case: [compiler: ret=$ret]" fi rc=$((rc + $ret)) fi fi if [ 2 -lt "$jenkins_opt_exit" -o "$rc" -eq 0 ]; then if [ "$jenkins_test_rpm" = "yes" ]; then $WORKSPACE/contrib/jenkins_tests/rpm.sh ret=$? if [ $ret -gt 0 ]; then do_err "case: [rpm: ret=$ret]" fi rc=$((rc + $ret)) fi fi if [ 3 -lt "$jenkins_opt_exit" -o "$rc" -eq 0 ]; then if [ "$jenkins_test_cov" = "yes" ]; then $WORKSPACE/contrib/jenkins_tests/cov.sh ret=$? if [ $ret -gt 0 ]; then do_err "case: [cov: ret=$ret]" fi rc=$((rc + $ret)) fi fi if [ 4 -lt "$jenkins_opt_exit" -o "$rc" -eq 0 ]; then if [ "$jenkins_test_cppcheck" = "yes" ]; then $WORKSPACE/contrib/jenkins_tests/cppcheck.sh ret=$? if [ $ret -gt 0 ]; then do_err "case: [cppcheck: ret=$ret]" fi rc=$((rc + $ret)) fi fi if [ 5 -lt "$jenkins_opt_exit" -o "$rc" -eq 0 ]; then if [ "$jenkins_test_csbuild" = "yes" ]; then $WORKSPACE/contrib/jenkins_tests/csbuild.sh ret=$? if [ $ret -gt 0 ]; then do_err "case: [csbuild: ret=$ret]" fi rc=$((rc + $ret)) fi fi if [ 6 -lt "$jenkins_opt_exit" -o "$rc" -eq 0 ]; then if [ "$jenkins_test_run" = "yes" ]; then $WORKSPACE/contrib/jenkins_tests/test.sh ret=$? if [ $ret -gt 0 ]; then do_err "case: [test: ret=$ret]" fi rc=$((rc + $ret)) fi fi if [ 7 -lt "$jenkins_opt_exit" -o "$rc" -eq 0 ]; then if [ "$jenkins_test_style" = "yes" ]; then $WORKSPACE/contrib/jenkins_tests/style.sh ret=$? if [ $ret -gt 0 ]; then do_err "case: [style: ret=$ret]" fi rc=$((rc + $ret)) fi fi set -e # Archive all logs in single file do_archive "${WORKSPACE}/${prefix}/${target_name}/*.tap" if [ "$jenkins_opt_artifacts" == "always" ] || [ "$jenkins_opt_artifacts" == "fail" -a "$rc" -gt 0 ]; then set +x gzip "${jenkins_test_artifacts}.tar" echo "======================================================" echo "Jenkins result for [${target_name}] target: return $rc" echo "Artifacts: ${jenkins_test_artifacts}.tar.gz" echo "======================================================" set -x fi done rm -rf $WORKSPACE/config.cache echo "[${0##*/}]..................exit code = $rc" exit $rc sockperf-3.6/copying000066400000000000000000000030151336630672200146000ustar00rootroot00000000000000 /* * Copyright (c) 2011 Mellanox Technologies Ltd. * 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. * 3. Neither the name of the Mellanox Technologies Ltd nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * 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. * */ sockperf-3.6/debian/000077500000000000000000000000001336630672200144305ustar00rootroot00000000000000sockperf-3.6/debian/README.Debian000066400000000000000000000001021336630672200164620ustar00rootroot00000000000000__APP_NAME__-__VERSION__ for Debian -- __MAINTAINER__ __DATE__ sockperf-3.6/debian/changelog000066400000000000000000000001601336630672200162770ustar00rootroot00000000000000__APP_NAME__ (__VERSION__-__RELEASE__) release; urgency=low * Initial Release. -- __MAINTAINER__ __DATE__ sockperf-3.6/debian/compat000066400000000000000000000000021336630672200156260ustar00rootroot000000000000008 sockperf-3.6/debian/control000066400000000000000000000027511336630672200160400ustar00rootroot00000000000000Source: __APP_NAME__ Section: unknown Priority: extra Maintainer: Mellanox Technologies Ltd. Build-Depends: debhelper (>= 8.0.0) Standards-Version: 3.9.5 Homepage: http://www.mellanox.com Package: __APP_NAME__ Architecture: any Multi-Arch: foreign Depends: ${misc:Depends}, ${shlibs:Depends} Description: auto-generated package by debmake This Debian binary package was auto-generated by the debmake(1) command provided by the debmake package. . ===== This comes from the unmodified template file ===== . Please edit this template file (debian/control) and other package files (debian/*) to make them meet all the requirements of the Debian Policy before uploading this package to the Debian archive. . See * http://www.debian.org/doc/manuals/maint-guide/dreq.en.html#control * http://www.debian.org/doc/manuals/developers-reference/best-pkging-practices.html#bpp-debian-control . The synopsis description at the top should be about 60 characters and written as a phrase. No extra capital letters or a final period. No articles — "a", "an", or "the". . The package description for general-purpose applications should be written for a less technical user. This means that we should avoid jargon. GNOME or KDE is fine but GTK+ is probably not. . Use the canonical forms of words: * Use X Window System, X11, or X; not X Windows, X-Windows, or X Window. * Use GTK+, not GTK or gtk. * Use GNOME, not Gnome. * Use PostScript, not Postscript or postscript. sockperf-3.6/debian/copyright000066400000000000000000000043561336630672200163730ustar00rootroot00000000000000Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: __APP_NAME__ Source: ### ### Uncomment the following 2 lines to enable uscan to exclude non-DFSG components ### Files-Excluded: command/non-dfsg.exe ### docs/source/javascripts/jquery-1.7.1.min.js ### ### This is a autogenerated template for debian/copyright. ### ### Edit this accordinng to the "Machine-readable debian/copyright file" as ### http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ . ### ### Generate updated license templates with the "debmake -cc" to STDOUT ### and merge them into debian/copyright as needed. ### ### Please avoid to pick license terms that are more restrictive than the ### packaged work, as it may make Debian's contributions unacceptable upstream. Copyright: 2011 Mellanox Technologies Ltd. License: __UNKNOWN__ 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. 3. Neither the name of the Mellanox Technologies Ltd nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. . 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. . sockperf-3.6/debian/patches/000077500000000000000000000000001336630672200160575ustar00rootroot00000000000000sockperf-3.6/debian/patches/series000066400000000000000000000004421336630672200172740ustar00rootroot00000000000000### The patch files of the -p1 format included in the debian/patches directory ### are applied to the upstream source in the order listed below. ### This is manually managed by users with dquilt (quilt(1) wrapper) etc. ### Also this may be updated by dpkg-source(1) when making a package. sockperf-3.6/debian/rules000077500000000000000000000026661336630672200155220ustar00rootroot00000000000000#!/usr/bin/make -f ### See debhelper(7) (uncomment to enable) ### This is a autogenerated template for debian/rules. ### You must remove unused comment lines for the released package. ### ### Output every command that modifies files on the build system. #DH_VERBOSE = 1 ### ### Define DEB_HOST_* and DEB_BUILD_* variables using ### dpkg-architecture(1) if they are used in this file. E.g.: ###DEB_HOST_MULTIARCH = $(shell dpkg-architecture -qDEB_HOST_MULTIARCH) ###DEB_HOST_ARCH_OS = $(shell dpkg-architecture -qDEB_HOST_ARCH_OS) ### ### Copy some variable definitions from pkg-info.mk and vendor.mk ### under /usr/share/dpkg/ to here if they are useful. ### ### See FEATURE AREAS in dpkg-buildflags(1) #export DEB_BUILD_MAINT_OPTIONS = hardening=+all ### ### See ENVIRONMENT in dpkg-buildflags(1) ### Package maintainers to append CFLAGS #export DEB_CFLAGS_MAINT_APPEND = -Wall -pedantic ### Package maintainers to append LDFLAGS #export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed ### main packaging script based on dh7 syntax %: dh $@ ### Alternatively ### support for -Wl,--as-needed to ltmain.sh with autoreconf -f -i ###override_dh_autoreconf: ### dh_autoreconf --as-needed ### ### Set options for ./configure ###CONFIGURE_FLAGS = ###overrride_dh_configure: ### dh_configure -- $(CONFIGURE_FLAGS) ### ### Do not install libtool archive, python .pyc .pyo override_dh_install: dh_install --list-missing -X.la -X.pyc -X.pyo sockperf-3.6/debian/source/000077500000000000000000000000001336630672200157305ustar00rootroot00000000000000sockperf-3.6/debian/source/format000066400000000000000000000000151336630672200171370ustar00rootroot000000000000003.0 (quilt) sockperf-3.6/debian/source/local-options000066400000000000000000000001441336630672200204350ustar00rootroot00000000000000### Uncomment to active options. See dpkg-source(1) ###abort-on-upstream-changes ###unapply-patches sockperf-3.6/doc/000077500000000000000000000000001336630672200137535ustar00rootroot00000000000000sockperf-3.6/doc/Doxyfile.in000066400000000000000000001440521336630672200160740ustar00rootroot00000000000000# Doxyfile 1.4.6 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = sockperf # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = @VERSION@ # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = ./doc/man # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, # Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, # Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, # Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, # Swedish, and Ukrainian. OUTPUT_LANGUAGE = English # This tag can be used to specify the encoding used in the generated output. # The encoding is not always determined by the language that is chosen, # but also whether or not the output is meant for Windows or non-Windows users. # In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES # forces the Windows encoding (this is the default for the Windows binary), # whereas setting the tag to NO uses a Unix-style encoding (the default for # all platforms other than Windows). USE_WINDOWS_ENCODING = NO # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = YES # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = NO # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like the Qt-style comments (thus requiring an # explicit @brief command for a brief description. JAVADOC_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the DETAILS_AT_TOP tag is set to YES then Doxygen # will output the detailed description near the top, like JavaDoc. # If set to NO, the detailed description appears after the member # documentation. DETAILS_AT_TOP = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for Java. # For instance, namespaces will be presented as packages, qualified scopes # will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to # include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = YES # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = YES # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = YES # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is NO. SHOW_DIRECTORIES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from the # version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be abled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = ./doxygen.log #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = @abs_top_srcdir@/doc/main.dox # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx # *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py FILE_PATTERNS = # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = /usr/include/stdio.h \ /usr/include/sys/time.h # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix filesystem feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = .. # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES (the default) # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES (the default) # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compressed HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 1 # If the GENERATE_TREEVIEW tag is set to YES, a side panel will be # generated containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, # Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are # probably better off using the HTML help feature. GENERATE_TREEVIEW = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = YES # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = NO # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = NO # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = YES # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. This is useful # if you want to understand what is going on. On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse # the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option is superseded by the HAVE_DOT option below. This is only a # fallback. It is recommended to install and use dot, since it yields more # powerful graphs. CLASS_DIAGRAMS = YES # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = NO # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will # generate a call dependency graph for every global function or class method. # Note that enabling this option will significantly increase the time of a run. # So in most cases it will be better to enable call graphs for selected # functions only using the \callgraph command. CALL_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_WIDTH = 1024 # The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height # (in pixels) of the graphs generated by dot. If a graph becomes larger than # this value, doxygen will try to truncate the graph, so that it fits within # the specified constraint. Beware that most browsers cannot cope with very # large images. MAX_DOT_GRAPH_HEIGHT = 1024 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that a graph may be further truncated if the graph's # image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH # and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default), # the graph is not depth-constrained. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, which results in a white background. # Warning: Depending on the platform used, enabling this option may lead to # badly anti-aliased labels on the edges of a graph (i.e. they become hard to # read). DOT_TRANSPARENT = NO # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = NO # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Configuration::additions related to the search engine #--------------------------------------------------------------------------- # The SEARCHENGINE tag specifies whether or not a search engine should be # used. If set to NO the values of all tags below this one will be ignored. SEARCHENGINE = NO sockperf-3.6/doc/main.dox000066400000000000000000000672531336630672200154300ustar00rootroot00000000000000/** @page sockperf SockPerf is a tool for network performance measurement written in C++. @section _summary 1. SUMMARY SockPerf is a network testing tool oriented to measure network latency and also spikes of network latency. Tool can create UDP/TCP data streams and measure the throughput and latency of a network that is carrying them. SockPerf allows the user to define different parameters that can be used for testing a network, or alternately for optimizing or tuning a network. Tool provides a client and server functionality, and can measure the throughput and latency between the two end-points, either unidirectionally or bidirectionally. This utility can be used in Linux systems. @section _introduction 2. INTRODUCTION People are often concerned about measuring the maximum data throughput rate of a communications link or network access. A typical method of performing a measurement is to transfer a 'large' file and measure the time taken to do so. The throughput is then calculated by dividing the file size by the time to get the throughput in megabits, kilobits, or bits per second. Unfortunately, the results of such an exercise will result in the goodput which is less than the maximum throughput, leading to people believing that their communications link is not operating correctly. In fact, there are many overheads accounted for in good case in addition to transmission overheads, including latency, TCP Receive Window size and machine limitations, which means the calculated goodput does not reflect the maximum achievable throughput. Another important thing of tool capacity is latency measurement. Latency - is the time it takes packet to go from user space program on one machine to user space program on another machine. Being able to quantify latency in terms other than millisecond response time is important when determining the quality of a network. One of available tool that can help administrators do just that is Sockperf. SockPerf works as an on-demand client and server test. How this works is that one system runs the Sockperf server over a specified port and another system functions as a client running the Sockperf client. The binaries are the same, and there is an option to have the role of client or server, so the roles can easily be reversed if necessary. @section _overview 3. OVERVIEW Sockperf tests UDP/TCP network connection and maintenance following functionality: - Measure latency; - Measure TX/RX bandwidth; - Measure packet loss; - Multicast; - Multi-threaded; features: - Measure the RTT of packets in descrete way; - Provide full log of packet times; - Provide few modes to monitor multiple file descriptors as recvfrom/select/poll/epoll; - Improved CPU utilization; Initially the tool was developed to demonstrate advantages of Mellanox's Messaging Accelerator (VMA). VMA is a socket API based, dynamically linked, user space Linux library which serves to transparently enhance the performance of Multicast/UDP/TCP networking heavy applications over the InfiniBand and Ethernet network. More interested user can read detail information at http://www.mellanox.com. Actually Sockperf can be used natively, or with VMA acceleration and see the benefit of VMA. SockPerf operates by sending packets from the client to the server, which then sends the packets back to the client. This measured round trip time is the route trip time (RTT) between the two machines on a specific network path. The average RTT is calculated by dividing the total number of packets that perform this round trip by some fixed period of time. The average latency for a given one-way path between the two machines is the average RTT divided by two. SockPerf can work as server or execute under-load, ping-pong, playback and throughput tests and be a server or a client. SockPerf can be launched in single point manner that is name as the first mode and using special formatted feed file named as the second mode. Mode One: @code $sockperf server -i 224.18.7.81 -p 5001 sockperf: == version #3.5-no.git == sockperf: [SERVER] listen on: [ 0] IP = 224.18.7.81 PORT = 5001 # UDP sockperf: Warmup stage (sending a few dummy messages)... sockperf: [tid 4701] using recvfrom() to block on socket(s @endcode Mode Two: @code $sockperf server -f conf.file -F e sockperf: == version #3.5-no.git == sockperf: [SERVER] listen on: [ 0] IP = 5.2.1.3 PORT = 6671 # TCP [ 1] IP = 5.2.1.3 PORT = 6672 # TCP [ 2] IP = 5.2.1.3 PORT = 6673 # TCP [ 3] IP = 5.2.1.3 PORT = 6674 # TCP [ 4] IP = 5.2.1.3 PORT = 6675 # TCP sockperf: Warmup stage (sending a few dummy messages)... sockperf: [tid 4805] using epoll() to block on socket(s) @endcode Every line in feed file should have following format as [U|T]:address:port where - [U|T] - UDP or TCP protocol; - address - Internet Protocol (IP) address; - port - Port number; @subsection _option 3.1 Available options The following table describes Sockperf options, and their possible values: @code -h,-? --help,--usage -Show the help message and exit. --tcp -Use TCP protocol (default UDP). -i --ip -Listen on/send to ip . -p --port -Listen on/connect to port (default 11111). -f --file -Read list of connections from file (used in pair with -F option). -F --iomux-type -Type of multiple file descriptors handle [s|select|p|poll|e|epoll|r|recvfrom|x|socketxtreme](default epoll). --timeout -Set select/poll/epoll timeout to , -1 for infinite (default is 10 msec). -a --activity -Measure activity by printing a '.' for the last messages processed. -A --Activity -Measure activity by printing the duration for last messages processed. --tcp-avoid-nodelay -Stop/Start delivering TCP Messages Immediately (Enable/Disable Nagel). Default is Nagel Disabled except in Throughput where the default is Nagel enabled. --tcp-skip-blocking-send -Enables non-blocking send operation (default OFF). --tos -Allows setting tos --mc-rx-if -Set address of interface on which to receive multicast messages (can be other then route table). --mc-tx-if -Set address of interface on which to transmit multicast messages (can be other then route table). --mc-loopback-enable -Enables mc loopback (default disabled). --mc-ttl -Limit the lifetime of the message (default 2). --mc-source-filter -Set address of multicast messages source which is allowed to receive from. --uc-reuseaddr -Enables unicast reuse address (default disabled). --lls -Turn on LLS via socket option (value = usec to poll). --buffer-size -Set total socket receive/send buffer in bytes (system defined by default). --nonblocked -Open non-blocked sockets. --recv_looping_num -Set Sockperf to loop over recvfrom() until EAGAIN or good received packets, -1 for infinite, must be used with --nonblocked (default 1). --dontwarmup -Don't send warm up messages on start. --pre-warmup-wait -Time to wait before sending warm up messages (seconds). --vmazcopyread -Use VMA's zero copy reads API (See VMA's readme). --daemonize -Run as daemon. --no-rdtsc -Don't use register when taking time; instead use monotonic clock. --load-vma -Load VMA dynamically even when LD_PRELOAD was not used. --rate-limit -use rate limit (packet-pacing), with VMA must be run with VMA_RING_ALLOCATION_LOGIC_TX mode. --set-sock-accl -Set socket acceleration before run (available for some of Mellanox systems) -d --debug -Print extra debug information. @endcode @subsection _server 3.2 Server Server options are: @code --threads-num -Run threads on server side (requires '-f' option). --cpu-affinity -Set threads affinity to the given core ids in list format (see: cat /proc/cpuinfo). --vmarxfiltercb -Use VMA's receive path message filter callback API (See VMA's readme). --force-unicast-reply -Force server to reply via unicast. --dont-reply -Server won't reply to the client messages. -m --msg-size -Set maximum message size that the server can receive bytes (default 65507). -g --gap-detection -Enable gap-detection. @endcode @subsection _client 3.3 Client Sockperf supports different scenarios to run itself as a client. There are under-load, ping-pong, playback and throughput subcommands to select one of the scenarios. - under-load - run sockperf client for latency under load test; - ping-pong - run sockperf client for latency test in ping pong mode; - playback - run sockperf client for latency test using playback of predefined traffic, based on timeline and message size; - throughput - run sockperf client for one way throughput test; General client options are: @code --srv-num -Set num of servers the client works with to N. --sender-affinity -Set sender thread affinity to the given core ids in list format (see: cat /proc/cpuinfo). --receiver-affinity -Set receiver thread affinity to the given core ids in list format (see: cat /proc/cpuinfo). --full-log -Dump full log of all messages send/receive time to the given file in CSV format. --giga-size -Print sizes in GigaByte. --increase_output_precision -Increase number of digits after decimal point of the throughput output (from 3 to 9). --dummy-send -Use VMA's dummy send API instead of busy wait, must be higher than regular msg rate. optional: set dummy-send rate per second (default 10,000), usage: --dummy-send [|max] -t --time -Run for seconds (default 1, max = 36000000). --client_port -Force the client side to bind to a specific port (default = 0). --client_ip -Force the client side to bind to a specific ip address (default = 0). -b --burst -Control the client's number of a messages sent in every burst. --mps -Set number of messages-per-second (default = 10000 - for under-load mode, or max - for ping-pong and throughput modes; for maximum use --mps=max; support --pps for old compatibility). -m --msg-size -Use messages of size bytes (minimum default 14). -r --range -comes with -m , randomly change the messages size in range: +- . --data-integrity -Perform data integrity test @endcode @subsection _tool 3.4 Tools SockPerf package contains few scripts that allow to generate special formatted file to launch tool in different configurations. - filter.awk - can be used for filtering lines from the full log file based on given latency range; - gen1.awk - this awk script generates playback files (it is for stable PPS playback file); - gen2.awk - this awk script generates playback files using the input for this script is file with lines of the format: startTime; duration; startPPS; endPPS; msgSize (it is for linear increased and decreased PPS playback file); @code create playback file using gen1.awk > pfile generated file: # ==== playback file for sockperf - generated by gen1.awk ==== #baseTime=1.000000; PPS=200000; runtime=1.000000; interval=0.000005; NUM_RECORDS=200000 # file contains 200000 records 1.000005000, 12 1.000010000, 12 1.000015000, 12 1.000020000, 12 1.000025000, 12 1.000030000, 12 1.000035000, 12 1.000040000, 12 ... 1.999950000, 12 1.999955000, 12 1.999960000, 12 1.999965000, 12 1.999970000, 12 1.999975000, 12 1.999980000, 12 1.999985000, 12 1.999990000, 12 1.999995000, 12 2.000000000, 12 #200000 records were written successfully start server on ipX start client using: ./sockperf ping-pong -i -p --playback=pfile @endcode @subsection _usage 3.5 Usage @subsection _usage1 3.5.1 Running Multicast over IPoIB - Configure the routing table to map multicast addresses to the IPoIB interface on both client and server machines, as follows: @code route add -net 224.0.0.0 netmask 240.0.0.0 dev ib0 @endcode In this case, ib0 is the IPoIB interface. - Run the server as follows: @code $sockperf server -i 224.18.7.81 -p 5001 sockperf: == version #3.5-no.git == sockperf: [SERVER] listen on: [ 0] IP = 224.18.7.81 PORT = 5001 # UDP sockperf: Warmup stage (sending a few dummy messages)... sockperf: [tid 30399] using recvfrom() to block on socket(s) @endcode - Run the client as follows: @code $sockperf ping-pong -i 224.18.7.81 -p 5001 -m 16384 -t 10 --mps=max sockperf: == version #3.5-no.git == sockperf[CLIENT] send on:sockperf: using recvfrom() to block on socket(s) [ 0] IP = 224.18.7.81 PORT = 5001 # UDP sockperf: Warmup stage (sending a few dummy messages)... sockperf: Starting test... sockperf: Test end (interrupted by timer) sockperf: Test ended sockperf: [Total Run] RunTime=10.000 sec; Warm up time=400 msec; SentMessages=240464; ReceivedMessages=240463 sockperf: ========= Printing statistics for Server No: 0 sockperf: [Valid Duration] RunTime=9.550 sec; SentMessages=229630; ReceivedMessages=229630 sockperf: ====> avg-lat= 20.771 (std-dev=5.266) sockperf: # dropped messages = 0; # duplicated messages = 0; # out-of-order messages = 0 sockperf: Summary: Latency is 20.771 usec sockperf: Total 229630 observations; each percentile contains 2296.30 observations sockperf: ---> observation = 120.108 sockperf: ---> percentile 99.999 = 106.349 sockperf: ---> percentile 99.990 = 63.772 sockperf: ---> percentile 99.900 = 55.940 sockperf: ---> percentile 99.000 = 48.619 sockperf: ---> percentile 90.000 = 24.295 sockperf: ---> percentile 75.000 = 20.358 sockperf: ---> percentile 50.000 = 19.279 sockperf: ---> percentile 25.000 = 18.641 sockperf: ---> observation = 16.748 @endcode @subsection _usage2 3.5.2 Running TCP over Ethernet - Run the server as follows: @code $sockperf server -i 22.0.0.3 -p 5001 --tcp sockperf: == version #3.5-no.git == sockperf: [SERVER] listen on: [ 0] IP = 22.0.0.3 PORT = 5001 # TCP sockperf: Warmup stage (sending a few dummy messages)... sockperf: [tid 1567] using recvfrom() to block on socket(s) @endcode - Run the client as follows: @code $sockperf ping-pong -i 22.0.0.3 -p 5001 --tcp -m 64 -t 10 --mps=max sockperf: == version #3.5-no.git == sockperf[CLIENT] send on:sockperf: using recvfrom() to block on socket(s) [ 0] IP = 22.0.0.3 PORT = 5001 # TCP sockperf: Warmup stage (sending a few dummy messages)... sockperf: Starting test... sockperf: Test end (interrupted by timer) sockperf: Test ended sockperf: [Total Run] RunTime=10.000 sec; Warm up time=400 msec; SentMessages=553625; ReceivedMessages=553624 sockperf: ========= Printing statistics for Server No: 0 sockperf: [Valid Duration] RunTime=9.550 sec; SentMessages=528579; ReceivedMessages=528579 sockperf: ====> avg-lat= 9.017 (std-dev=4.171) sockperf: # dropped messages = 0; # duplicated messages = 0; # out-of-order messages = 0 sockperf: Summary: Latency is 9.017 usec sockperf: Total 528579 observations; each percentile contains 5285.79 observations sockperf: ---> observation = 98.777 sockperf: ---> percentile 99.999 = 72.628 sockperf: ---> percentile 99.990 = 17.980 sockperf: ---> percentile 99.900 = 16.824 sockperf: ---> percentile 99.000 = 16.193 sockperf: ---> percentile 90.000 = 14.731 sockperf: ---> percentile 75.000 = 14.301 sockperf: ---> percentile 50.000 = 6.222 sockperf: ---> percentile 25.000 = 5.759 sockperf: ---> observation = 4.629 @endcode @subsection _usage3 3.5.3 Running UDP over Ethernet using VMA - More interested user can read detail information about VMA at http://www.mellanox.com. - VMA_SPEC=latency is a predefined specification profile for latency. - Run the server as follows: @code $VMA_SPEC=latency LD_PRELOAD=libvma.so sockperf server -i 22.0.0.3 -p 5001 VMA INFO: --------------------------------------------------------------------------- VMA INFO: VMA_VERSION: 8.6.10-0 Development Snapshot built on Jun 27 2018 16:06:47 VMA INFO: Cmd Line: sockperf server -i 22.0.0.3 -p 5001 VMA INFO: Current Time: Tue Sep 18 08:49:23 2018 VMA INFO: Pid: 2201 VMA INFO: OFED Version: MLNX_OFED_LINUX-4.4-1.0.0.0: VMA INFO: Architecture: x86_64 VMA INFO: Node: r-aa-apollo03.mtr.labs.mlnx VMA INFO: --------------------------------------------------------------------------- VMA INFO: VMA Spec Latency [VMA_SPEC] VMA INFO: Log Level INFO [VMA_TRACELEVEL] VMA INFO: Ring On Device Memory TX 16384 [VMA_RING_DEV_MEM_TX] VMA INFO: Tx QP WRE 256 [VMA_TX_WRE] VMA INFO: Tx QP WRE Batching 4 [VMA_TX_WRE_BATCHING] VMA INFO: Rx QP WRE 256 [VMA_RX_WRE] VMA INFO: Rx QP WRE Batching 4 [VMA_RX_WRE_BATCHING] VMA INFO: Rx Poll Loops -1 [VMA_RX_POLL] VMA INFO: Rx Prefetch Bytes Before Poll 256 [VMA_RX_PREFETCH_BYTES_BEFORE_POLL] VMA INFO: GRO max streams 0 [VMA_GRO_STREAMS_MAX] VMA INFO: Select Poll (usec) -1 [VMA_SELECT_POLL] VMA INFO: Select Poll OS Force Enabled [VMA_SELECT_POLL_OS_FORCE] VMA INFO: Select Poll OS Ratio 1 [VMA_SELECT_POLL_OS_RATIO] VMA INFO: Select Skip OS 1 [VMA_SELECT_SKIP_OS] VMA INFO: CQ Drain Interval (msec) 100 [VMA_PROGRESS_ENGINE_INTERVAL] VMA INFO: CQ Interrupts Moderation Disabled [VMA_CQ_MODERATION_ENABLE] VMA INFO: CQ AIM Max Count 128 [VMA_CQ_AIM_MAX_COUNT] VMA INFO: CQ Adaptive Moderation Disabled [VMA_CQ_AIM_INTERVAL_MSEC] VMA INFO: CQ Keeps QP Full Disabled [VMA_CQ_KEEP_QP_FULL] VMA INFO: TCP nodelay 1 [VMA_TCP_NODELAY] VMA INFO: Avoid sys-calls on tcp fd Enabled [VMA_AVOID_SYS_CALLS_ON_TCP_FD] VMA INFO: Internal Thread Affinity 0 [VMA_INTERNAL_THREAD_AFFINITY] VMA INFO: Thread mode Single [VMA_THREAD_MODE] VMA INFO: Mem Allocate type 2 (Huge Pages) [VMA_MEM_ALLOC_TYPE] VMA INFO: --------------------------------------------------------------------------- sockperf: == version #3.5-no.git == sockperf: [SERVER] listen on: [ 0] IP = 22.0.0.3 PORT = 5001 # UDP sockperf: Warmup stage (sending a few dummy messages)... sockperf: [tid 2201] using recvfrom() to block on socket(s) @endcode - Run the client as follows: @code $VMA_SPEC=latency LD_PRELOAD=libvma.so sockperf ping-pong -i 22.0.0.3 -p 5001 -m 64 -t 10 --mps=max VMA INFO: --------------------------------------------------------------------------- VMA INFO: VMA_VERSION: 8.6.10-0 Development Snapshot built on Jun 27 2018 16:06:47 VMA INFO: Cmd Line: sockperf ping-pong -i 22.0.0.3 -p 5001 -m 64 -t 10 --mps=max VMA INFO: Current Time: Tue Sep 18 08:47:50 2018 VMA INFO: Pid: 20134 VMA INFO: OFED Version: MLNX_OFED_LINUX-4.4-1.0.0.0: VMA INFO: Architecture: x86_64 VMA INFO: Node: r-aa-apollo04.mtr.labs.mlnx VMA INFO: --------------------------------------------------------------------------- VMA INFO: VMA Spec Latency [VMA_SPEC] VMA INFO: Log Level INFO [VMA_TRACELEVEL] VMA INFO: Ring On Device Memory TX 16384 [VMA_RING_DEV_MEM_TX] VMA INFO: Tx QP WRE 256 [VMA_TX_WRE] VMA INFO: Tx QP WRE Batching 4 [VMA_TX_WRE_BATCHING] VMA INFO: Rx QP WRE 256 [VMA_RX_WRE] VMA INFO: Rx QP WRE Batching 4 [VMA_RX_WRE_BATCHING] VMA INFO: Rx Poll Loops -1 [VMA_RX_POLL] VMA INFO: Rx Prefetch Bytes Before Poll 256 [VMA_RX_PREFETCH_BYTES_BEFORE_POLL] VMA INFO: GRO max streams 0 [VMA_GRO_STREAMS_MAX] VMA INFO: Select Poll (usec) -1 [VMA_SELECT_POLL] VMA INFO: Select Poll OS Force Enabled [VMA_SELECT_POLL_OS_FORCE] VMA INFO: Select Poll OS Ratio 1 [VMA_SELECT_POLL_OS_RATIO] VMA INFO: Select Skip OS 1 [VMA_SELECT_SKIP_OS] VMA INFO: CQ Drain Interval (msec) 100 [VMA_PROGRESS_ENGINE_INTERVAL] VMA INFO: CQ Interrupts Moderation Disabled [VMA_CQ_MODERATION_ENABLE] VMA INFO: CQ AIM Max Count 128 [VMA_CQ_AIM_MAX_COUNT] VMA INFO: CQ Adaptive Moderation Disabled [VMA_CQ_AIM_INTERVAL_MSEC] VMA INFO: CQ Keeps QP Full Disabled [VMA_CQ_KEEP_QP_FULL] VMA INFO: TCP nodelay 1 [VMA_TCP_NODELAY] VMA INFO: Avoid sys-calls on tcp fd Enabled [VMA_AVOID_SYS_CALLS_ON_TCP_FD] VMA INFO: Internal Thread Affinity 0 [VMA_INTERNAL_THREAD_AFFINITY] VMA INFO: Thread mode Single [VMA_THREAD_MODE] VMA INFO: Mem Allocate type 2 (Huge Pages) [VMA_MEM_ALLOC_TYPE] VMA INFO: --------------------------------------------------------------------------- sockperf: == version #3.5-no.git == sockperf[CLIENT] send on:sockperf: using recvfrom() to block on socket(s) [ 0] IP = 22.0.0.3 PORT = 5001 # UDP sockperf: Warmup stage (sending a few dummy messages)... sockperf: Starting test... sockperf: Test end (interrupted by timer) sockperf: Test ended sockperf: [Total Run] RunTime=10.000 sec; Warm up time=400 msec; SentMessages=5166035; ReceivedMessages=5166034 sockperf: ========= Printing statistics for Server No: 0 sockperf: [Valid Duration] RunTime=9.550 sec; SentMessages=4951987; ReceivedMessages=4951987 sockperf: ====> avg-lat= 0.951 (std-dev=0.034) sockperf: # dropped messages = 0; # duplicated messages = 0; # out-of-order messages = 0 sockperf: Summary: Latency is 0.951 usec sockperf: Total 4951987 observations; each percentile contains 49519.87 observations sockperf: ---> observation = 4.476 sockperf: ---> percentile 99.999 = 1.318 sockperf: ---> percentile 99.990 = 1.270 sockperf: ---> percentile 99.900 = 1.179 sockperf: ---> percentile 99.000 = 1.110 sockperf: ---> percentile 90.000 = 0.967 sockperf: ---> percentile 75.000 = 0.952 sockperf: ---> percentile 50.000 = 0.943 sockperf: ---> percentile 25.000 = 0.936 sockperf: ---> observation = 0.895 @endcode @section _licensing 4. LICENSING Read "copying" file in the root place. @section _installation 5. INSTALLATION @subsection _requirements 5.1 Requirements What you will need to compile sockperf on Unix systems - perl 5.8+ (used by the automake tools) - GNU make tools: automake 1.7+, autoconf 2.57+, m4 1.4+ and libtool 1.4+ - A Compiler, among those tested are: - gcc4+ (Ubuntu) - gcc4+ (Red Hat) @subsection _options 5.2 Options to compile @subsection _install 5.3 How to install Download sockperf-\.tar.gz. Uncompress *.tar.gz file in Unix systems in the same folder with the file by runing the following command in the shell: @code tar -zxvf sockperf-.tar.gz @endcode or 2 command: @code gzip -d ./sockperf-.tar.gz tar -xf ./sockperf-.tar @endcode The sockperf package uses the GNU autotools compilation and installation framework. These are generic installation instructions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, a file `config.cache' that saves the results of its tests to speed up reconfiguring, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.in' is used to create `configure' by a program called `autoconf'. You only need `configure.in' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. If you're using `csh' on an old version of System V, you might need to type `sh ./configure' instead to prevent `csh' from trying to execute `configure' itself. Running `configure' takes awhile. While running, it prints some messages telling which features it is checking for. @code $ ./configure --prefix= @endcode There are several options to ./config (or ./Configure) to customize the build: To enable test scripts @code $ ./configure --prefix= --enable-test @endcode To enable the documentation @code $ ./configure --prefix= --enable-doc @endcode To enable the special scripts @code $ ./configure --prefix= --enable-tool @endcode To compile with debug symbols and information: @code $ ./configure --prefix= --enable-debug @endcode This will define the _DEBUG variable at compile time. Type './configure --help' for a list of all the configure options. Some of the options are generic autoconf options, while the SockPerf specific options are prefixed with "SOCKPERF:" in the help text. 2. Type `make' to compile the package. @code $ make @endcode 3. Optionally, type `make check' to run any self-tests that come with the package. 4. Type `make install' to install the programs and any data files and documentation. @code $ make install @endcode 5. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. */ sockperf-3.6/news000066400000000000000000000000001336630672200140730ustar00rootroot00000000000000sockperf-3.6/readme000066400000000000000000000031741336630672200143730ustar00rootroot00000000000000This is the distribution of sockperf * What is sockperf * Licensing * What you will need to compile aLic on Unix systems perl 5.8+ (used by the automake tools) GNU make tools: automake 1.7+, autoconf 2.57+, m4 1.4+ and libtool 1.4+ A Compiler, among those tested are: . gcc4 (Ubuntu 9) * How to install: The sockperf package uses the GNU autotools compilation and installation framework. $ ./configure $ make $ make install To enable test scripts $ ./configure --prefix= --enable-test To enable the documentation $ ./configure --prefix= --enable-doc To enable the special scripts $ ./configure --prefix= --enable-tool To compile with debug symbols and information: $ ./configure --prefix= --enable-debug This will define the _DEBUG variable at compile time. Type './configure --help' for a list of all the configure options. Some of the options are generic autoconf options, while the aLic specific options are prefixed with "SOCKPERF:" in the help text. * To build for ARM 1) Define CROSS_COMPILE in the environment to point to the cross compilation tools, e.g. set CROSS_COMPILE=/opt/gcc-linaro-arm-linux-gnueabihf-4.7-2012.11-20121123_linux/bin/arm-linux-gnueabihf- 2) Use ./autogen.sh to create the configure script. 3) Invoke ./configure with the following options: $ ./configure CXX=${CROSS_COMPILE}g++ STRIP=${CROSS_COMPILE}strip LD=${CROSS_COMPILE}ld CC=${CROSS_COMPILE}gcc --host i386 4) Invoke make * To build for FreeBSD Make sure automake tools are installed. Good luck! sockperf-3.6/src/000077500000000000000000000000001336630672200137755ustar00rootroot00000000000000sockperf-3.6/src/aopt.cpp000066400000000000000000000351571336630672200154570ustar00rootroot00000000000000/* * Copyright (c) 2011-2018 Mellanox Technologies Ltd. * 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. * 3. Neither the name of the Mellanox Technologies Ltd nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * 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. */ #include #include #include #include #include "os_abstract.h" #include "aopt.h" #define _AOPT_CONF_TRACE TRUE #if defined(_MSC_VER) #ifndef snprintf #define snprintf _snprintf #endif #endif #if defined(_AOPT_CONF_TRACE) && (_AOPT_CONF_TRACE == TRUE) #define AOPT_TRACE(fmt, ...) printf(fmt, ##__VA_ARGS__) #else #define AOPT_TRACE(fmt, ...) #endif /* _AOPT_CONF_TRACE */ /** * aopt_init * * @brief * This function parses command line and creates object with options * basing options description. It returns count of correct tokens. * * @param[in,out] argc Argument count. * @param[in] argv Argument vector. * @param[in] desc Option description. * * @retval pointer to object - on success * @retval NULL - on failure ***************************************************************************/ const AOPT_OBJECT *aopt_init(int *argc, const char **argv, const AOPT_DESC *desc) { AOPT_OBJECT *arg_obj = NULL; int status = 0; if (*argc) { const char *const *arg_p = argv + 1; size_t opt_count = 0; if (*arg_p && '-' != (*arg_p)[0]) { *argc = 0; return NULL; } for (; *arg_p; ++arg_p) { if ('-' == (*arg_p)[0] && (*arg_p)[1]) { ++opt_count; } } if (opt_count) { arg_obj = (AOPT_OBJECT *)malloc((opt_count + 1) * sizeof(AOPT_OBJECT)); memset(arg_obj, 0, (opt_count + 1) * sizeof(AOPT_OBJECT)); } } if (arg_obj) { const char **arg_p = argv + 1; AOPT_OBJECT *next_option = arg_obj; *argc = 0; for (; *arg_p; arg_p++) { if ('-' == (*arg_p)[0] && (*arg_p)[1]) { /* process valid short option (-) */ int token_type = ('-' == (*arg_p)[1] ? 2 : 1); const char *token_opt = (*arg_p) + token_type; const char *token_arg = NULL; if (!(*token_opt)) { status = __LINE__; AOPT_TRACE("Incorrect token %s\n", (*arg_p)); } else { const AOPT_DESC *opt_spec_p = desc; for (; (opt_spec_p->key && !status); opt_spec_p++) { /* * Accept -o123, -o 123, -o=123, -o */ if ((token_type == 1) && strchr(opt_spec_p->shorts, *token_opt)) { token_arg = token_opt + 1; } /* * Accept --option 123, --option=123, --option */ if (token_type == 2) { const char *desc_long = *opt_spec_p->longs; int i = 0; for (i = 0; ((i < AOPT_MAX_NUMBER) && (desc_long)); i++) { if (!strncmp(token_opt, desc_long, strlen(desc_long))) { if (!token_opt[strlen(desc_long)] || (token_opt[strlen(desc_long)] == '=')) { token_arg = token_opt + strlen(desc_long); break; } } } } if (!status && token_arg) { /* * check if option can be repeatable */ if (!(opt_spec_p->flags & AOPT_REPEAT)) { const AOPT_OBJECT *opt_p = arg_obj; for (; opt_p != next_option; ++opt_p) { if (opt_p->key == opt_spec_p->key) { status = __LINE__; AOPT_TRACE("Option %s should not be repeatable\n", (*arg_p)); } } } if (!status) { /* set option identifier */ next_option->key = opt_spec_p->key; /* set option argument */ next_option->arg = NULL; /* have valid token (option) and count it */ (*argc)++; if ((opt_spec_p->flags & AOPT_ARG) || (opt_spec_p->flags & AOPT_OPTARG)) { /* * check if argument follows the option and = in the same token * Example : [-o=1234] */ if ((token_arg[0] == '=') && token_arg[1]) { next_option->arg = token_arg + 1; } /* * check if argument follows the option in the same token * Example : [-o1234] */ else if (token_arg[0]) { next_option->arg = token_arg; } /* * check if argument follows the option next token * Example : [-o] [1234] */ else if ((*(arg_p + 1)) && ((*(arg_p + 1))[0] != '-')) { arg_p++; next_option->arg = *arg_p; /* have valid token (value) and count it */ (*argc)++; } /* * check if argument is mandatory */ else if (opt_spec_p->flags & AOPT_ARG) { status = __LINE__; AOPT_TRACE("Option %s should have an argument\n", (*arg_p)); (*argc)--; } } else { if (token_arg[0]) { status = __LINE__; AOPT_TRACE("Option %s should not have an argument\n", (*arg_p)); (*argc)--; } } } break; } } if (opt_spec_p->key) { /* move to the next frame */ next_option++; } else { #if 0 /* check unsupported options */ status = __LINE__; AOPT_TRACE("Token %s is incorrect\n", (*arg_p)); #endif } } } } } if (status) { if (arg_obj) { free(arg_obj); arg_obj = NULL; } #if 0 /* display error line */ AOPT_TRACE("Error %d\n", status); #endif } return arg_obj; } /** * aopt_exit * * @brief * The function is used as a destructor. Releases memory allocated in * the corresponding call. Object can not be used later. * * @return @a none ***************************************************************************/ void aopt_exit(AOPT_OBJECT *aopt_obj) { if (aopt_obj) { free(aopt_obj); } } /** * aopt_check * * @brief * Returns number of appearance of the option in command line. * * @param[in] aopt_obj Object. * @param[in] key Option key. * * @retval (>0) - on success * @retval ( 0) - on failure ***************************************************************************/ int aopt_check(const AOPT_OBJECT *aopt_obj, int key) { int count = 0; while (aopt_obj && aopt_obj->key) { if (aopt_obj->key == key) { count++; } aopt_obj++; } return count; } /** * aopt_value * * @brief * Returns option value by key. * * @param[in] aopt_obj Object. * @param[in] key Option key. * * @retval pointer to value - on success * @retval NULL - on failure ***************************************************************************/ const char *aopt_value(const AOPT_OBJECT *aopt_obj, int key) { const char *value = NULL; while (aopt_obj && aopt_obj->key) { if (aopt_obj->key == key) { value = aopt_obj->arg; break; } aopt_obj++; } return value; } /** * aopt_help * * @brief * This function form help informaion basing options description and * return string with one. The string should be freed using the free() * function when you are done with it. NULL is returned if the it would * produce an empty string or if the string cannot be allocated. * * @param[in] desc Option description. * * @retval pointer to string - on success * @retval NULL - on failure ***************************************************************************/ const char *aopt_help(const AOPT_DESC *desc) { char *buf = NULL; int buf_size = 256; int buf_offset = 0; if (desc) { char *buf_temp = NULL; int ret = 0; buf = (char *)malloc(buf_size); memset(buf, 0, buf_size); for (; desc && desc->key && buf; desc++) { if (NULL == desc->note) // ignore values without a description { continue; } char buf_short[10]; char buf_long[50]; const char *cur_ptr_short = NULL; const char *const *cur_ptr_long = NULL; int cur_len_short = 0; int cur_len_long = 0; memset(buf_short, 0, sizeof(buf_short)); memset(buf_long, 0, sizeof(buf_long)); /* fill short option field */ cur_ptr_short = desc->shorts; cur_len_short = 0; ret = 0; while (cur_ptr_short && (*cur_ptr_short) && (ret >= 0)) { ret = snprintf((buf_short + cur_len_short), sizeof(buf_short) - cur_len_short, (ret ? ",-%c" : "-%c"), (isprint(*cur_ptr_short) ? *cur_ptr_short : '.')); if (ret < 0) { /* size of buffer is exceeded */ free(buf); buf = NULL; break; } cur_len_short += ret; cur_ptr_short++; } /* fill long option field */ cur_ptr_long = desc->longs; cur_len_long = 0; ret = 0; while (cur_ptr_long && (*cur_ptr_long) && (ret >= 0)) { ret = snprintf((buf_long + cur_len_long), sizeof(buf_long) - cur_len_long, (ret ? ",--%s" : "--%s"), (*cur_ptr_long ? *cur_ptr_long : "")); if (ret < 0) { /* size of buffer is exceeded */ free(buf); buf = NULL; break; } cur_len_long += ret; cur_ptr_long++; } /* form help for current option */ while (buf) { char format[50]; if (strlen(buf_long) > 21) { sprintf(format, " %%-7s %%-21s\n %-7s %-21s\t-%%s\n", "", ""); } else { sprintf(format, " %%-7s %%-21s\t-%%s\n"); } ret = snprintf((buf + buf_offset), (buf_size - buf_offset), format, buf_short, buf_long, (desc->note ? desc->note : "")); /* If that worked, return */ if (ret > -1 && ret <= (buf_size - buf_offset - 1)) { buf_offset += ret; break; } /* Else try again with more space. */ if (ret > -1) /* ISO/IEC 9899:1999 */ buf_size = buf_offset + ret + 1; else /* twice the old size */ buf_size *= 2; buf_temp = buf; buf = (char *)malloc(buf_size); memset(buf, 0, buf_size); memcpy(buf, buf_temp, buf_offset); free(buf_temp); } } } return buf; } int isNumeric(const char *arg) { while (*arg) { if (!isdigit(*arg)) { return 0; } arg++; } return 1; } sockperf-3.6/src/aopt.h000066400000000000000000000141311336630672200151110ustar00rootroot00000000000000/* * Copyright (c) 2011-2018 Mellanox Technologies Ltd. * 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. * 3. Neither the name of the Mellanox Technologies Ltd nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * 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. */ /** * @file aopt.h * * @brief aOpt is tiny set of ANSI C library functions for parsing command line. * * @details This module is written in ANSI C89. Support short and long styles of * option. Automatic error messages can be turned on by _AOPT_CONF_TRACE==TRUE. * Easy initialization, simple set of operations and automatic help make * this library very friendly and flexible. * Example of option usage: * short style: -o123, -o 123, -o=123, -o * long style: --option 123, --option=123, --option * * @author Igor Ivanov * **/ #ifndef _AOPT_H_ #define _AOPT_H_ #ifdef __cplusplus extern "C" { #endif /** * @enum AOPT_TYPE * @brief Define option type. */ typedef enum { AOPT_NOARG = 0, /**< option does not have value */ AOPT_REPEAT = 1, /**< option can appear few times */ AOPT_ARG = 2, /**< option should have value */ AOPT_OPTARG = 4 /**< option can have value */ } AOPT_TYPE; /** * @def AOPT_MAX_NUMBER * @brief Maximum number of options */ #define AOPT_MAX_NUMBER 4 /** * @struct _AOPT_DESC * @brief * Description of supported options. */ typedef struct _AOPT_DESC { int key; /**< unique identifier */ AOPT_TYPE flags; /**< option type */ const char shorts[AOPT_MAX_NUMBER]; /**< short name */ const char *const longs[AOPT_MAX_NUMBER]; /**< long name */ const char *note; /**< option description */ } AOPT_DESC; /** * @struct _AOPT_OBJECT * @brief * Option container. */ typedef struct _AOPT_OBJECT { int key; /**< unique identifier */ const char *arg; /**< option value */ } AOPT_OBJECT; /** * @def aopt_set_literal * @brief * Set option as literal. */ #define aopt_set_literal(...) \ { __VA_ARGS__, 0 } /** * @def aopt_set_string * @brief * Set option as string. */ #define aopt_set_string(...) \ { __VA_ARGS__, NULL } /** * aopt_init * * @brief * This function parses command line and creates object with options * basing options description. It returns count of correct tokens. * * @param[in,out] argc Argument count. * @param[in] argv Argument vector. * @param[in] desc Option description. * * @retval pointer to object - on success * @retval NULL - on failure ***************************************************************************/ const AOPT_OBJECT *aopt_init(int *argc, const char **argv, const AOPT_DESC *desc); /** * aopt_exit * * @brief * The function is used as a destructor. Releases memory allocated in * the corresponding call. Object can not be used later. * * @return @a none ***************************************************************************/ void aopt_exit(AOPT_OBJECT *aopt_obj); /** * aopt_check * * @brief * Returns number of appearance of the option in command line. * * @param[in] aopt_obj Object. * @param[in] key Option key. * * @retval (>0) - on success * @retval ( 0) - on failure ***************************************************************************/ int aopt_check(const AOPT_OBJECT *aopt_obj, int key); /** * aopt_value * * @brief * Returns option value by key. * * @param[in] aopt_obj Object. * @param[in] key Option key. * * @retval pointer to value - on success * @retval NULL - on failure ***************************************************************************/ const char *aopt_value(const AOPT_OBJECT *aopt_obj, int key); /** * aopt_help * * @brief * This function form help information basing options description and * return string with one. The string should be freed using the free() * function when you are done with it. NULL is returned if the it would * produce an empty string or if the string cannot be allocated. * * @param[in] desc Option description. * * @retval pointer to string - on success * @retval NULL - on failure ***************************************************************************/ const char *aopt_help(const AOPT_DESC *desc); /** * isNumeric * * @brief * This function checks if the arg is from numeric type. * * @param[in] arg char* * * @retval 1 if numeric, 0 otherwise. ***************************************************************************/ int isNumeric(const char *arg); #ifdef __cplusplus } #endif #endif /* _AOPT_H_ */ sockperf-3.6/src/client.cpp000066400000000000000000001077711336630672200157740ustar00rootroot00000000000000/* * Copyright (c) 2011-2018 Mellanox Technologies Ltd. * 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. * 3. Neither the name of the Mellanox Technologies Ltd nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * 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. */ #include "defs.h" #include "playback.h" #include "client.h" #include "iohandlers.h" #include "packet.h" #include "switches.h" TicksTime s_startTime, s_endTime; //============================================================================== //============================================================================== //------------------------------------------------------------------------------ void print_average_results(double usecAvarage) { if (g_pApp->m_const_params.burst_size == 1) { log_msg("Summary: %s is %.3lf usec", g_pApp->m_const_params.full_rtt ? "Round trip" : "Latency", usecAvarage); } else { log_msg("Summary: %s of burst of %d messages is %.3lf usec", g_pApp->m_const_params.full_rtt ? "Round trip" : "Latency", g_pApp->m_const_params.burst_size, usecAvarage); } } //------------------------------------------------------------------------------ /* set the timer on client to the [-t sec] parameter given by user */ void set_client_timer(struct itimerval *timer) { // extra sec and extra msec will be excluded from results timer->it_value.tv_sec = (TEST_END_COOLDOWN_MSEC + g_pApp->m_const_params.warmup_msec) / 1000 + g_pApp->m_const_params.sec_test_duration; timer->it_value.tv_usec = (TEST_END_COOLDOWN_MSEC + g_pApp->m_const_params.warmup_msec) % 1000; timer->it_interval.tv_sec = 0; timer->it_interval.tv_usec = 0; } //------------------------------------------------------------------------------ void printPercentiles(FILE *f, TicksDuration *pLat, size_t size) { qsort(pLat, size, sizeof(TicksDuration), TicksDuration::compare); double percentile[] = { 0.99999, 0.9999, 0.999, 0.99, 0.90, 0.75, 0.50, 0.25 }; int num = sizeof(percentile) / sizeof(percentile[0]); double observationsInPercentile = (double)size / 100; log_msg_file2(f, MAGNETA "Total %lu observations" ENDCOLOR "; each percentile contains %.2lf observations", (long unsigned)size, observationsInPercentile); log_msg_file2(f, "---> observation = %8.3lf", pLat[size - 1].toDecimalUsec()); for (int i = 0; i < num; i++) { int index = (int)(0.5 + percentile[i] * size) - 1; if (index >= 0) { log_msg_file2(f, "---> percentile %6.3lf = %8.3lf", 100 * percentile[i], pLat[index].toDecimalUsec()); } } log_msg_file2(f, "---> observation = %8.3lf", pLat[0].toDecimalUsec()); } //------------------------------------------------------------------------------ typedef TicksTime RecordLog[2]; //------------------------------------------------------------------------------ void dumpFullLog(int serverNo, RecordLog *pFullLog, size_t size, TicksDuration *pLat) { FILE *f = g_pApp->m_const_params.fileFullLog; uint32_t denominator = g_pApp->m_const_params.full_rtt ? 1 : 2; if (!f || !size) return; fprintf(f, "------------------------------\n"); fprintf(f, "packet, txTime(sec), rxTime(sec), %s(usec)\n", round_trip_str[g_pApp->m_const_params.full_rtt]); for (size_t i = 0; i < size; i++) { double tx = (double)pFullLog[i][0].debugToNsec() / 1000 / 1000 / 1000; double rx = (double)pFullLog[i][1].debugToNsec() / 1000 / 1000 / 1000; double result = (rx - tx) * (USEC_PER_SEC / denominator); fprintf(f, "%zu, %.9lf, %.9lf, %.3lf\n", i, tx, rx, result); } fprintf(f, "------------------------------\n"); } //------------------------------------------------------------------------------ void client_statistics(int serverNo, Message *pMsgRequest) { const uint64_t receiveCount = g_receiveCount; const uint64_t sendCount = pMsgRequest->getSequenceCounter(); const uint64_t replyEvery = g_pApp->m_const_params.reply_every; const size_t SIZE = receiveCount; const int SERVER_NO = serverNo; FILE *f = g_pApp->m_const_params.fileFullLog; if (!receiveCount) { log_msg_file2(f, "No messages were received from the server. Is the server down?"); return; } /* Print total statistic that is independent on server count */ if (SERVER_NO == 0) { TicksDuration totalRunTime = s_endTime - s_startTime; if (g_skipCount) { log_msg_file2(f, "[Total Run] RunTime=%.3lf sec; Warm up time=%" PRIu32 " msec; SentMessages=%" PRIu64 "; ReceivedMessages=%" PRIu64 "; SkippedMessages=%" PRIu64 "", totalRunTime.toDecimalUsec() / 1000000, g_pApp->m_const_params.warmup_msec, sendCount, receiveCount, g_skipCount); } else { log_msg_file2(f, "[Total Run] RunTime=%.3lf sec; Warm up time=%" PRIu32 " msec; SentMessages=%" PRIu64 "; ReceivedMessages=%" PRIu64 "", totalRunTime.toDecimalUsec() / 1000000, g_pApp->m_const_params.warmup_msec, sendCount, receiveCount); } } /* Print server related statistic */ log_msg_file2(f, "========= Printing statistics for Server No: %d", SERVER_NO); /* * There are few reasons to ignore warmup/cooldown packets: * * 1. At the head of the test the load is not real, since only few packets were sent so far. * 2. At the tail of the test the load is not real since the sender stopped sending; hence, * the receiver accept packets without load * 3. The sender thread starts sending packets and generating load, before the receiver * thread has started, and before its code was cached to memory/cpu. * 4. There are some packets that were sent close to s_end time; the legitimate replies to * them will arrive after s_end time and may be lost. Hence, your fix may cause us to * report on those packets as dropped packets. */ TicksTime testStart = g_pPacketTimes->getTxTime(replyEvery); // first pong request packet TicksTime testEnd = g_pPacketTimes->getTxTime(sendCount); // will be "truncated" to last pong request packet if (!g_pApp->m_const_params.pPlaybackVector) { // no warmup in playback mode testStart += TicksDuration::TICKS1MSEC * TEST_START_WARMUP_MSEC; testEnd -= TicksDuration::TICKS1MSEC * TEST_END_COOLDOWN_MSEC; } log_dbg("testStart: %.9lf sec testEnd: %.9lf sec", (double)testStart.debugToNsec() / 1000 / 1000 / 1000, (double)testEnd.debugToNsec() / 1000 / 1000 / 1000); TicksDuration *pLat = new TicksDuration[SIZE]; RecordLog *pFullLog = g_pApp->m_const_params.fileFullLog ? new RecordLog[SIZE] : NULL; TicksDuration rtt; TicksDuration sumRtt(0); size_t counter = 0; size_t lcounter = 0; TicksTime prevRxTime; TicksTime startValidTime; TicksTime endValidTime; uint32_t denominator = g_pApp->m_const_params.full_rtt ? 1 : 2; uint64_t startValidSeqNo = 0; uint64_t endValidSeqNo = 0; for (size_t i = 1; (counter < SIZE) && (testStart < testEnd); i++) { uint64_t seqNo = i * replyEvery; const TicksTime &txTime = g_pPacketTimes->getTxTime(seqNo); const TicksTime &rxTime = g_pPacketTimes->getRxTimeArray(seqNo)[SERVER_NO]; if ((txTime > testEnd) || (txTime == TicksTime::TICKS0)) { break; } if (txTime < testStart) { continue; } if (startValidSeqNo == 0) { startValidSeqNo = seqNo; startValidTime = txTime; } if (rxTime == TicksTime::TICKS0) { g_pPacketTimes->incDroppedCount(SERVER_NO); if (endValidTime < txTime) { endValidSeqNo = seqNo; endValidTime = txTime; } continue; } if (rxTime < prevRxTime) { g_pPacketTimes->incOooCount(SERVER_NO); continue; } if (g_pApp->m_const_params.fileFullLog) { pFullLog[lcounter][0] = txTime; pFullLog[lcounter][1] = rxTime; } lcounter++; endValidSeqNo = seqNo; endValidTime = rxTime; rtt = rxTime - txTime; sumRtt += rtt; pLat[counter] = rtt / denominator; prevRxTime = rxTime; counter++; } if (!counter) { log_msg_file2( f, "No valid observations found. Try tune parameters: --time/--mps/--reply-every"); } else { TicksDuration validRunTime = endValidTime - startValidTime; log_msg_file2(f, "[Valid Duration] RunTime=%.3lf sec; SentMessages=%" PRIu64 "; ReceivedMessages=%" PRIu64 "", validRunTime.toDecimalUsec() / 1000000, (endValidSeqNo - startValidSeqNo + 1), (uint64_t)counter); TicksDuration avgRtt = counter ? sumRtt / (int)counter : TicksDuration::TICKS0; TicksDuration avgLatency = avgRtt / 2; double usecAvarage = g_pApp->m_const_params.full_rtt ? avgRtt.toDecimalUsec() : avgLatency.toDecimalUsec(); TicksDuration stdDev = TicksDuration::stdDev(pLat, counter); log_msg_file2(f, MAGNETA "====> avg-%s=%.3lf (std-dev=%.3lf)" ENDCOLOR, round_trip_str[g_pApp->m_const_params.full_rtt], usecAvarage, stdDev.toDecimalUsec()); /* Display ERROR statistic */ bool isColor = (g_pPacketTimes->getDroppedCount(SERVER_NO) || g_pPacketTimes->getDupCount(SERVER_NO) || g_pPacketTimes->getOooCount(SERVER_NO)); const char *colorRedStr = isColor ? RED : ""; const char *colorResetStr = isColor ? ENDCOLOR : ""; log_msg_file2(f, "%s# dropped messages = %lu; # duplicated messages = %lu; # out-of-order " "messages = %lu%s", colorRedStr, (long unsigned)g_pPacketTimes->getDroppedCount(SERVER_NO), (long unsigned)g_pPacketTimes->getDupCount(SERVER_NO), (long unsigned)g_pPacketTimes->getOooCount(SERVER_NO), colorResetStr); if (usecAvarage) print_average_results(usecAvarage); printPercentiles(f, pLat, counter); dumpFullLog(SERVER_NO, pFullLog, lcounter, pLat); } delete[] pLat; delete[] pFullLog; } //------------------------------------------------------------------------------ void stream_statistics(Message *pMsgRequest) { TicksDuration totalRunTime = s_endTime - s_startTime; if (totalRunTime <= TicksDuration::TICKS0) return; if (!g_pApp->m_const_params.b_stream) return; const uint64_t sendCount = pMsgRequest->getSequenceCounter(); // Send only mode! if (g_skipCount) { log_msg("Total of %" PRIu64 " messages sent in %.3lf sec (%" PRIu64 " messages skipped)\n", sendCount, totalRunTime.toDecimalUsec() / 1000000, g_skipCount); } else { log_msg("Total of %" PRIu64 " messages sent in %.3lf sec\n", sendCount, totalRunTime.toDecimalUsec() / 1000000); } if (g_pApp->m_const_params.mps != MPS_MAX) { if (g_pApp->m_const_params.msg_size_range) log_msg(MAGNETA "NOTE: test was performed, using average msg-size=%d (+/-%d), mps=%u. " "For getting maximum throughput use --mps=max (and consider " "--msg-size=1472 or --msg-size=4096" ENDCOLOR, g_pApp->m_const_params.msg_size, g_pApp->m_const_params.msg_size_range, g_pApp->m_const_params.mps); else log_msg(MAGNETA "NOTE: test was performed, using msg-size=%d, mps=%u. For getting " "maximum throughput use --mps=max (and consider --msg-size=1472 or " "--msg-size=4096)" ENDCOLOR, g_pApp->m_const_params.msg_size, g_pApp->m_const_params.mps); } else if (g_pApp->m_const_params.msg_size != 1472) { if (g_pApp->m_const_params.msg_size_range) log_msg(MAGNETA "NOTE: test was performed, using average msg-size=%d (+/-%d). For " "getting maximum throughput consider using --msg-size=1472" ENDCOLOR, g_pApp->m_const_params.msg_size, g_pApp->m_const_params.msg_size_range); else log_msg(MAGNETA "NOTE: test was performed, using msg-size=%d. For getting maximum " "throughput consider using --msg-size=1472" ENDCOLOR, g_pApp->m_const_params.msg_size); } int ip_frags_per_msg = (g_pApp->m_const_params.msg_size + DEFAULT_IP_PAYLOAD_SZ - 1) / DEFAULT_IP_PAYLOAD_SZ; int msgps = (int)(0.5 + ((double)sendCount) * 1000 * 1000 / totalRunTime.toDecimalUsec()); int pktps = msgps * ip_frags_per_msg; int total_line_ip_data = g_pApp->m_const_params.msg_size; double MBps = ((double)msgps * total_line_ip_data) / 1024 / 1024; /* No including IP + UDP Headers per fragment */ if (ip_frags_per_msg == 1) log_msg("Summary: Message Rate is %d [msg/sec]", msgps); else log_msg("Summary: Message Rate is %d [msg/sec], Packet Rate is about %d [pkt/sec] (%d ip " "frags / msg)", msgps, pktps, ip_frags_per_msg); if (g_pApp->m_const_params.giga_size) { log_msg("Summary: BandWidth is %.3f GBps (%.3f Gbps)", MBps / 1000, MBps * 8 / 1000); } else if (g_pApp->m_const_params.increase_output_precision) { log_msg("Summary: BandWidth is %.9f GBps (%.9f Gbps)", MBps, MBps * 8); } else { log_msg("Summary: BandWidth is %.3f MBps (%.3f Mbps)", MBps, MBps * 8); } } //------------------------------------------------------------------------------ void client_sig_handler(int signum) { if (g_b_exit) { log_msg("Test end (interrupted by signal %d)", signum); return; } s_endTime.setNowNonInline(); g_b_exit = true; // Just in case not Activity updates where logged add a '\n' if (g_pApp->m_const_params.packetrate_stats_print_ratio && !g_pApp->m_const_params.packetrate_stats_print_details) printf("\n"); switch (signum) { case SIGALRM: log_msg("Test end (interrupted by timer)"); break; case SIGINT: log_msg("Test end (interrupted by user)"); break; default: log_msg("Test end (interrupted by signal %d)", signum); break; } } //============================================================================== //============================================================================== //------------------------------------------------------------------------------ ClientBase::ClientBase() { m_pMsgReply = new Message(); m_pMsgReply->setLength(MAX_PAYLOAD_SIZE); m_pMsgRequest = new Message(); m_pMsgRequest->getHeader()->setClient(); m_pMsgRequest->setLength(g_pApp->m_const_params.msg_size); } //------------------------------------------------------------------------------ ClientBase::~ClientBase() { delete m_pMsgReply; delete m_pMsgRequest; } //------------------------------------------------------------------------------ template Client::Client(int _fd_min, int _fd_max, int _fd_num) : ClientBase(), m_ioHandler(_fd_min, _fd_max, _fd_num), m_pongModeCare(m_pMsgRequest) { os_thread_init(&m_receiverTid); } //------------------------------------------------------------------------------ template Client::~Client() {} //------------------------------------------------------------------------------ template void Client::client_receiver_thread() { while (!g_b_exit) { client_receive(); } } //------------------------------------------------------------------------------ void *client_receiver_thread(void *arg) { ClientBase *_this = (ClientBase *)arg; _this->client_receiver_thread(); return 0; } //------------------------------------------------------------------------------ template void Client::cleanupAfterLoop() { usleep(100 * 1000); // 0.1 sec - wait for rx packets for last sends (in normal flow) if (m_receiverTid.tid) { os_thread_kill(&m_receiverTid); // os_thread_join(&m_receiverTid); os_thread_detach(&m_receiverTid); // just for silenting valgrind's "possibly lost: 288 // bytes" in pthread_create os_thread_close(&m_receiverTid); } if (g_b_errorOccured) return; // cleanup started in other thread and triggerd termination of this thread log_msg("Test ended"); if (!m_pMsgRequest->getSequenceCounter()) { log_msg("No messages were sent"); } else if (g_pApp->m_const_params.b_stream) { stream_statistics(m_pMsgRequest); } else { FILE *f = g_pApp->m_const_params.fileFullLog; if (f) { fprintf(f, "------------------------------\n"); fprintf(f, "test was performed using the following parameters: " "--mps=%d --burst=%d --reply-every=%d --msg-size=%d --time=%d", (int)g_pApp->m_const_params.mps, (int)g_pApp->m_const_params.burst_size, (int)g_pApp->m_const_params.reply_every, (int)g_pApp->m_const_params.msg_size, (int)g_pApp->m_const_params.sec_test_duration); if (g_pApp->m_const_params.dummy_mps) { fprintf(f, " --dummy-send=%d", g_pApp->m_const_params.dummy_mps); } if (g_pApp->m_const_params.full_rtt) { fprintf(f, " --full-rtt"); } fprintf(f, "\n"); fprintf(f, "------------------------------\n"); } for (int i = 0; i < g_pApp->m_const_params.client_work_with_srv_num; i++) { client_statistics(i, m_pMsgRequest); } } if (g_pApp->m_const_params.fileFullLog) fclose(g_pApp->m_const_params.fileFullLog); if (g_pApp->m_const_params.cycleDuration > TicksDuration::TICKS0 && !g_cycle_wait_loop_counter) log_msg("Info: The requested message-per-second rate is too high. Try tuning --mps or " "--burst arguments"); } //------------------------------------------------------------------------------ #ifdef USING_VMA_EXTRA_API static int _connect_check_vma(int ifd) { int rc = SOCKPERF_ERR_SOCKET; int ring_fd = 0; int poll = 0; rc = g_vma_api->get_socket_rings_fds(ifd, &ring_fd, 1); if (rc == -1) { rc = SOCKPERF_ERR_SOCKET; return rc; } while (!g_b_exit && poll == 0) { struct vma_completion_t vma_comps; poll = g_vma_api->socketxtreme_poll(ring_fd, &vma_comps, 1, 0); if (poll > 0) { if (vma_comps.events & EPOLLOUT) { rc = SOCKPERF_ERR_NONE; } } } return rc; } #endif //------------------------------------------------------------------------------ static int _connect_check(int ifd) { int rc = SOCKPERF_ERR_NONE; fd_set rfds, wfds; struct timeval tv; tv.tv_sec = 0; tv.tv_usec = 500; FD_ZERO(&rfds); FD_ZERO(&wfds); int max_fd = -1; FD_SET(ifd, &wfds); FD_SET(ifd, &rfds); if (ifd > max_fd) max_fd = ifd; select(max_fd + 1, &rfds, &wfds, NULL, &tv); if (FD_ISSET(ifd, &wfds) || FD_ISSET(ifd, &rfds)) { socklen_t err_len; int error; err_len = sizeof(error); if (getsockopt(ifd, SOL_SOCKET, SO_ERROR, &error, &err_len) < 0 || error != 0) { log_err("Can`t connect socket"); rc = SOCKPERF_ERR_SOCKET; } } return rc; } //------------------------------------------------------------------------------ template int Client::initBeforeLoop() { int rc = SOCKPERF_ERR_NONE; if (g_b_exit) return rc; /* bind/connect socket */ if (rc == SOCKPERF_ERR_NONE) { // cycle through all set fds in the array (with wrap around to beginning) for (int ifd = m_ioHandler.m_fd_min; ifd <= m_ioHandler.m_fd_max; ifd++) { if (!(g_fds_array[ifd] && (g_fds_array[ifd]->active_fd_list))) continue; struct sockaddr_in *p_client_bind_addr = (struct sockaddr_in *)&g_pApp->m_const_params.client_bind_info; if (p_client_bind_addr->sin_port || p_client_bind_addr->sin_addr.s_addr) { log_dbg("[fd=%d] Binding to: %s:%d...", ifd, inet_ntoa(p_client_bind_addr->sin_addr), ntohs(p_client_bind_addr->sin_port)); if (bind(ifd, (struct sockaddr *)p_client_bind_addr, sizeof(struct sockaddr)) < 0) { log_err("[fd=%d] Can`t bind socket %s:%d", ifd, inet_ntoa(p_client_bind_addr->sin_addr), ntohs(p_client_bind_addr->sin_port)); rc = SOCKPERF_ERR_SOCKET; break; } } else { log_dbg("[fd=%d] Binding to: %s:%d...", ifd, inet_ntoa(p_client_bind_addr->sin_addr), ntohs(p_client_bind_addr->sin_port)); } if (g_fds_array[ifd]->sock_type == SOCK_STREAM) { log_dbg("[fd=%d] Connecting to: %s:%d...", ifd, inet_ntoa(g_fds_array[ifd]->server_addr.sin_addr), ntohs(g_fds_array[ifd]->server_addr.sin_port)); if (connect(ifd, (struct sockaddr *)&(g_fds_array[ifd]->server_addr), sizeof(struct sockaddr)) < 0) { if (os_err_in_progress()) { #ifdef USING_VMA_EXTRA_API if (g_pApp->m_const_params.fd_handler_type == SOCKETXTREME && g_vma_api) { rc = _connect_check_vma(ifd); } else #endif { rc = _connect_check(ifd); } if (rc == SOCKPERF_ERR_SOCKET) { break; } } else { log_err("Can`t connect socket"); rc = SOCKPERF_ERR_SOCKET; break; } } } /* * since when using VMA there is no qp until the bind, and vma cannot * check that rate-limit is supported this is done here and not * with the rest of the setsockopt */ if (s_user_params.rate_limit > 0 && sock_set_rate_limit(ifd, s_user_params.rate_limit)) { log_err("[fd=%d] failed setting rate limit on address %s\n", ifd, inet_ntoa(g_fds_array[ifd]->server_addr.sin_addr)); rc = SOCKPERF_ERR_SOCKET; break; } } } if (g_b_exit) return rc; if (rc == SOCKPERF_ERR_NONE) { printf(MODULE_NAME "[CLIENT] send on:"); if (!g_pApp->m_const_params.b_stream) { log_msg("using %s() to block on socket(s)", handler2str(g_pApp->m_const_params.fd_handler_type)); } rc = m_ioHandler.prepareNetwork(); if (rc == SOCKPERF_ERR_NONE) { sleep(g_pApp->m_const_params.pre_warmup_wait); m_ioHandler.warmup(m_pMsgRequest); sleep(2); if (g_b_exit) return rc; rc = set_affinity_list(os_getthread(), g_pApp->m_const_params.sender_affinity); if (rc == SOCKPERF_ERR_NONE) { if (!g_pApp->m_const_params.b_client_ping_pong && !g_pApp->m_const_params.b_stream) { // latency_under_load if (0 != os_thread_exec(&m_receiverTid, ::client_receiver_thread, this)) { log_err("Creating thread has failed"); rc = SOCKPERF_ERR_FATAL; } else { rc = set_affinity_list(m_receiverTid, g_pApp->m_const_params.receiver_affinity); } } if (rc == SOCKPERF_ERR_NONE) { log_msg("Starting test..."); if (!g_pApp->m_const_params.pPlaybackVector) { struct itimerval timer; set_client_timer(&timer); if (os_set_duration_timer(timer, client_sig_handler)) { log_err("Failed setting test duration timer"); rc = SOCKPERF_ERR_FATAL; } } if (rc == SOCKPERF_ERR_NONE) { s_startTime.setNowNonInline(); g_lastTicks = s_startTime; g_cycleStartTime = s_startTime - g_pApp->m_const_params.cycleDuration; } } } } } return rc; } //------------------------------------------------------------------------------ template void Client::doSendThenReceiveLoop() { // cycle through all set fds in the array (with wrap around to beginning) for (int curr_fds = m_ioHandler.m_fd_min; !g_b_exit; curr_fds = g_fds_array[curr_fds]->next_fd) client_send_then_receive(curr_fds); } //------------------------------------------------------------------------------ template void Client::doSendLoop() { // cycle through all set fds in the array (with wrap around to beginning) for (int curr_fds = m_ioHandler.m_fd_min; !g_b_exit; curr_fds = g_fds_array[curr_fds]->next_fd) client_send_burst(curr_fds); } //------------------------------------------------------------------------------ static inline void playbackCycleDurationWait(const TicksDuration &i_cycleDuration) { static TicksTime s_cycleStartTime = TicksTime().setNowNonInline(); // will only be executed once TicksTime nextCycleStartTime = s_cycleStartTime + i_cycleDuration; while (!g_b_exit) { if (TicksTime::now() >= nextCycleStartTime) { break; } } s_cycleStartTime = nextCycleStartTime; } //------------------------------------------------------------------------------ template void Client::doPlayback() { usleep(100 * 1000); // wait for receiver thread to start (since we don't use warmup) //TODO: // configure! s_startTime.setNowNonInline(); // reduce code size by calling non inline func from slow path const PlaybackVector &pv = *g_pApp->m_const_params.pPlaybackVector; size_t i = 0; const size_t size = pv.size(); // cycle through all set fds in the array (with wrap around to beginning) for (int ifd = m_ioHandler.m_fd_min; i < size && !g_b_exit; ifd = g_fds_array[ifd]->next_fd, ++i) { m_pMsgRequest->setLength(pv[i].size); // idle playbackCycleDurationWait(pv[i].duration); // send client_send_packet(ifd); m_switchActivityInfo.execute(m_pMsgRequest->getSequenceCounter()); } g_cycle_wait_loop_counter++; // for silenting waring at the end s_endTime.setNowNonInline(); // reduce code size by calling non inline func from slow path usleep(20 * 1000); // wait for reply of last packet //TODO: configure! g_b_exit = true; } //------------------------------------------------------------------------------ template void Client::doHandler() { int rc = SOCKPERF_ERR_NONE; rc = initBeforeLoop(); if (rc == SOCKPERF_ERR_NONE) { if (g_pApp->m_const_params.pPlaybackVector) doPlayback(); else if (g_pApp->m_const_params.b_client_ping_pong) doSendThenReceiveLoop(); else doSendLoop(); cleanupAfterLoop(); } } //------------------------------------------------------------------------------ template void client_handler(int _fd_min, int _fd_max, int _fd_num) { Client c(_fd_min, _fd_max, _fd_num); c.doHandler(); } //------------------------------------------------------------------------------ template void client_handler(int _fd_min, int _fd_max, int _fd_num) { if (g_pApp->m_const_params.b_stream) client_handler(_fd_min, _fd_max, _fd_num); else if (g_pApp->m_const_params.reply_every == 1) client_handler(_fd_min, _fd_max, _fd_num); else client_handler(_fd_min, _fd_max, _fd_num); } //------------------------------------------------------------------------------ template void client_handler(int _fd_min, int _fd_max, int _fd_num) { if (g_pApp->m_const_params.msg_size_range > 0) client_handler(_fd_min, _fd_max, _fd_num); else client_handler(_fd_min, _fd_max, _fd_num); } //------------------------------------------------------------------------------ template void client_handler(int _fd_min, int _fd_max, int _fd_num) { if (g_pApp->m_const_params.cycleDuration > TicksDuration::TICKS0) { if (g_pApp->m_const_params.dummy_mps) { client_handler( _fd_min, _fd_max, _fd_num); } else { client_handler( _fd_min, _fd_max, _fd_num); } } else client_handler(_fd_min, _fd_max, _fd_num); } //------------------------------------------------------------------------------ template void client_handler(int _fd_min, int _fd_max, int _fd_num) { if (g_pApp->m_const_params.packetrate_stats_print_ratio > 0) client_handler(_fd_min, _fd_max, _fd_num); else client_handler(_fd_min, _fd_max, _fd_num); } //------------------------------------------------------------------------------ template void client_handler(int _fd_min, int _fd_max, int _fd_num) { if (g_pApp->m_const_params.data_integrity) client_handler(_fd_min, _fd_max, _fd_num); else client_handler(_fd_min, _fd_max, _fd_num); } //------------------------------------------------------------------------------ void client_handler(handler_info *p_info) { if (p_info) { switch (g_pApp->m_const_params.fd_handler_type) { case SELECT: { client_handler(p_info->fd_min, p_info->fd_max, p_info->fd_num); break; } case RECVFROM: { client_handler(p_info->fd_min, p_info->fd_max, p_info->fd_num); break; } case RECVFROMMUX: { client_handler(p_info->fd_min, p_info->fd_max, p_info->fd_num); break; } #ifndef WIN32 case POLL: { client_handler(p_info->fd_min, p_info->fd_max, p_info->fd_num); break; } #ifndef __FreeBSD__ case EPOLL: { client_handler(p_info->fd_min, p_info->fd_max, p_info->fd_num); break; } #endif #ifdef USING_VMA_EXTRA_API case SOCKETXTREME: { client_handler(p_info->fd_min, p_info->fd_max, p_info->fd_num); break; } #endif #endif default: { ERROR_MSG("unknown file handler"); break; } } } } sockperf-3.6/src/client.h000066400000000000000000000362571336630672200154410ustar00rootroot00000000000000/* * Copyright (c) 2011-2018 Mellanox Technologies Ltd. * 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. * 3. Neither the name of the Mellanox Technologies Ltd nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * 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. */ #ifndef CLIENT_H_ #define CLIENT_H_ #include "common.h" #include "packet.h" //============================================================================== //============================================================================== class ClientBase { public: ClientBase(); virtual ~ClientBase(); virtual void client_receiver_thread() = 0; protected: Message *m_pMsgReply; Message *m_pMsgRequest; }; //============================================================================== //============================================================================== template class Client : public ClientBase { private: os_thread_t m_receiverTid; IoType m_ioHandler; addr_to_id m_ServerList; SwitchDataIntegrity m_switchDataIntegrity; SwitchActivityInfo m_switchActivityInfo; SwitchCycleDuration m_switchCycleDuration; SwitchMsgSize m_switchMsgSize; PongModeCare m_pongModeCare; // has msg_sendto() method and can be one of: PongModeNormal, // PongModeAlways, PongModeNever public: Client(int _fd_min, int _fd_max, int _fd_num); virtual ~Client(); void doHandler(); void client_receiver_thread(); private: int initBeforeLoop(); void doSendThenReceiveLoop(); void doSendLoop(); void doPlayback(); void cleanupAfterLoop(); //------------------------------------------------------------------------------ inline int client_get_server_id(int ifd, struct sockaddr_in *recvfrom_addr) { int serverNo = 0; assert((g_fds_array[ifd]) && "invalid fd"); if (g_pApp->m_const_params.client_work_with_srv_num == DEFAULT_CLIENT_WORK_WITH_SRV_NUM) { // if client_work_with_srv_num param is default- act as working with one server only // (even if working with multiple multicast groups) return serverNo; } if (g_fds_array[ifd] && g_fds_array[ifd]->is_multicast) { addr_to_id::iterator itr = m_ServerList.find(recvfrom_addr->sin_addr); if (itr == m_ServerList.end()) { if ((int)m_ServerList.size() >= g_pApp->m_const_params.client_work_with_srv_num) { /* To recognize case when more then expected servers are working */ serverNo = -1; } else { serverNo = (int)m_ServerList.size(); std::pair ret = m_ServerList.insert( addr_to_id::value_type(recvfrom_addr->sin_addr, m_ServerList.size())); if (!ret.second) { log_err("Failed to insert new server."); serverNo = -1; } } } else { serverNo = (int)itr->second; } } return serverNo; } //------------------------------------------------------------------------------ inline void client_send_packet(int ifd) { int ret = 0; m_pMsgRequest->incSequenceCounter(); ret = m_pongModeCare.msg_sendto(ifd); /* return on success */ if (likely(ret > 0)) { return; } /* check dead peer case */ else if (ret == RET_SOCKET_SHUTDOWN) { if (g_fds_array[ifd]->sock_type == SOCK_STREAM) { exit_with_log("A connection was forcibly closed by a peer", SOCKPERF_ERR_SOCKET, g_fds_array[ifd]); } } /* check skip send operation case */ else if (ret == RET_SOCKET_SKIPPED) { g_skipCount++; m_pMsgRequest->decSequenceCounter(); } } //------------------------------------------------------------------------------ inline unsigned int client_receive_from_selected(int ifd) { int ret = 0; struct sockaddr_in recvfrom_addr; int receiveCount = 0; int serverNo = 0; int remain_buffer = 0; fds_data *l_fds_ifd = g_fds_array[ifd]; TicksTime rxTime; #ifdef USING_VMA_EXTRA_API vma_buff_t *tmp_vma_buff = g_vma_buff; if (SOCKETXTREME == g_pApp->m_const_params.fd_handler_type && tmp_vma_buff) { ret = msg_recv_socketxtreme(l_fds_ifd, tmp_vma_buff, &recvfrom_addr); } else if (g_pApp->m_const_params.is_vmazcopyread && !(remain_buffer = free_vma_packets(ifd, l_fds_ifd->recv.cur_size))) { // Handled buffer is filled, free_vma_packets returns 0 ret = l_fds_ifd->recv.cur_size; } else #endif { ret = msg_recvfrom(ifd, l_fds_ifd->recv.cur_addr + l_fds_ifd->recv.cur_offset, l_fds_ifd->recv.cur_size, &recvfrom_addr, &l_fds_ifd->recv.cur_addr, remain_buffer); } if (unlikely(ret <= 0)) { if (ret == RET_SOCKET_SHUTDOWN) { if (l_fds_ifd->sock_type == SOCK_STREAM) { exit_with_log("A connection was forcibly closed by a peer", SOCKPERF_ERR_SOCKET, l_fds_ifd); } } if (ret < 0) return 0; } int nbytes = ret; while (nbytes) { /* 1: message header is not received yet */ if ((l_fds_ifd->recv.cur_offset + nbytes) < MsgHeader::EFFECTIVE_SIZE) { l_fds_ifd->recv.cur_size -= nbytes; l_fds_ifd->recv.cur_offset += nbytes; /* 4: set current buffer size to size of remained part of message header to * guarantee getting full message header on next iteration */ if (l_fds_ifd->recv.cur_size < MsgHeader::EFFECTIVE_SIZE) { l_fds_ifd->recv.cur_size = MsgHeader::EFFECTIVE_SIZE - l_fds_ifd->recv.cur_offset; } #ifdef USING_VMA_EXTRA_API if (tmp_vma_buff) goto next; #endif return (receiveCount); } else if (l_fds_ifd->recv.cur_offset < MsgHeader::EFFECTIVE_SIZE) { /* 2: message header is got, match message to cycle buffer */ m_pMsgReply->setBuf(l_fds_ifd->recv.cur_addr); m_pMsgReply->setHeaderToHost(); } else { /* 2: message header is got, match message to cycle buffer */ m_pMsgReply->setBuf(l_fds_ifd->recv.cur_addr); } if (unlikely(m_pMsgReply->getSequenceCounter() > m_pMsgRequest->getSequenceCounter())) { exit_with_err("Sequence Number received was higher then expected", SOCKPERF_ERR_FATAL); } if (unlikely(m_pMsgReply->getLength() > MAX_PAYLOAD_SIZE)) { exit_with_err("Message received was larger than expected.", SOCKPERF_ERR_FATAL); } /* 3: message is not complete */ if ((l_fds_ifd->recv.cur_offset + nbytes) < m_pMsgReply->getLength()) { l_fds_ifd->recv.cur_size -= nbytes; l_fds_ifd->recv.cur_offset += nbytes; /* 4: set current buffer size to size of remained part of message to * guarantee getting full message on next iteration (using extended reserved * memory) * and shift to start of cycle buffer */ if (l_fds_ifd->recv.cur_size < (int)m_pMsgReply->getMaxSize()) { l_fds_ifd->recv.cur_size = m_pMsgReply->getLength() - l_fds_ifd->recv.cur_offset; } #ifdef USING_VMA_EXTRA_API if (tmp_vma_buff) goto next; #endif return (receiveCount); } /* 5: message is complete shift to process next one */ nbytes -= m_pMsgReply->getLength() - l_fds_ifd->recv.cur_offset; l_fds_ifd->recv.cur_addr += m_pMsgReply->getLength(); l_fds_ifd->recv.cur_size -= m_pMsgReply->getLength() - l_fds_ifd->recv.cur_offset; l_fds_ifd->recv.cur_offset = 0; #if defined(LOG_TRACE_MSG_IN) && (LOG_TRACE_MSG_IN == TRUE) printf(">>> "); hexdump(m_pMsgReply->getBuf(), MsgHeader::EFFECTIVE_SIZE); #endif /* LOG_TRACE_MSG_IN */ if (g_b_exit) return 0; if (m_pMsgReply->isClient()) { assert(!(l_fds_ifd->is_multicast && g_pApp->m_const_params.mc_loop_disable)); #ifdef USING_VMA_EXTRA_API if (tmp_vma_buff) goto next; #endif continue; } // should not count the warmup messages if (unlikely(m_pMsgReply->isWarmupMessage())) { #ifdef USING_VMA_EXTRA_API if (tmp_vma_buff) goto next; #endif continue; } receiveCount++; rxTime.setNow(); #if 0 // should be part of check-data-integrity if (g_pApp->m_const_params.msg_size_range == 0) { //ABH: added 'if', otherwise, size check will not suit latency-under-load if (nbytes != g_msg_size && errno != EINTR) { exit_with_log("received message size test failed (sent:%d received:%d)", g_msg_size, nbytes,SOCKPERF_ERR_FATAL); } } #endif #ifdef DEBUG // should not occur in real test if (m_pMsgReply->getSequenceCounter() % g_pApp->m_const_params.reply_every) { log_err("skipping unexpected received message: seqNo=%" PRIu64 " mask=0x%x", m_pMsgReply->getSequenceCounter(), m_pMsgReply->getFlags()); #ifdef USING_VMA_EXTRA_API if (tmp_vma_buff) goto next; #endif continue; } #endif serverNo = client_get_server_id(ifd, &recvfrom_addr); if (unlikely(serverNo < 0)) { exit_with_log("Number of servers more than expected", SOCKPERF_ERR_FATAL); } else { g_pPacketTimes->setRxTime(m_pMsgReply->getSequenceCounter(), rxTime, serverNo); m_switchDataIntegrity.execute(m_pMsgRequest, m_pMsgReply); } #ifdef USING_VMA_EXTRA_API next: if (tmp_vma_buff) { ret = msg_process_next(l_fds_ifd, &tmp_vma_buff, &nbytes); if (ret) { return (receiveCount); } } #endif } /* 6: shift to start of cycle buffer in case receiving buffer is empty and * there is no uncompleted message */ if (!nbytes) { l_fds_ifd->recv.cur_addr = l_fds_ifd->recv.buf; l_fds_ifd->recv.cur_size = l_fds_ifd->recv.max_size; l_fds_ifd->recv.cur_offset = 0; } return (receiveCount); } //------------------------------------------------------------------------------ inline unsigned int client_receive(/*int packet_cnt_index*/) { int numReady = 0; do { // wait for arrival numReady = m_ioHandler.waitArrival(); } while (!numReady && !g_b_exit); if (g_b_exit) return 0; // check errors if (unlikely(numReady < 0)) { exit_with_log(handler2str(g_pApp->m_const_params.fd_handler_type), SOCKPERF_ERR_FATAL); } /* ready fds were found so receive from the relevant sockets*/ unsigned int recieved_packets_num = 0; int actual_fd = 0; for (int _fd = m_ioHandler.get_look_start(); _fd < m_ioHandler.get_look_end() && !g_b_exit; _fd++) { actual_fd = m_ioHandler.analyzeArrival(_fd); if (actual_fd) { int m_recived = g_pApp->m_const_params.max_looping_over_recv; while ((0 != m_recived) && (!g_b_exit)) { if (m_recived > 0) { m_recived--; } unsigned int recieved_packets = client_receive_from_selected(actual_fd /*, packet_cnt_index*/); if ((0 == recieved_packets) && (os_err_eagain())) { break; } recieved_packets_num += recieved_packets; } } } return recieved_packets_num; } //------------------------------------------------------------------------------ inline void client_send_burst(int ifd) { // init m_switchMsgSize.execute(m_pMsgRequest); // idle m_switchCycleDuration.execute(m_pMsgRequest, ifd); // send for (unsigned i = 0; i < g_pApp->m_const_params.burst_size && !g_b_exit; i++) { client_send_packet(ifd); #ifdef USING_VMA_EXTRA_API if (g_pApp->m_const_params.fd_handler_type == SOCKETXTREME && !g_pApp->m_const_params.b_client_ping_pong) { m_ioHandler.waitArrival(); } #endif } m_switchActivityInfo.execute(m_pMsgRequest->getSequenceCounter()); } //------------------------------------------------------------------------------ inline void client_receive_burst() { for (unsigned int i = 0; i < (g_pApp->m_const_params.burst_size * g_pApp->m_const_params.client_work_with_srv_num) && !g_b_exit;) { i += client_receive(); } } //------------------------------------------------------------------------------ /* ** send to and receive from selected socket */ //------------------------------------------------------------------------------ inline void client_send_then_receive(int ifd) { client_send_burst(ifd); client_receive_burst(); } }; #endif /* CLIENT_H_ */ sockperf-3.6/src/clock.h000066400000000000000000000125051336630672200152440ustar00rootroot00000000000000/* * Copyright (c) 2011-2018 Mellanox Technologies Ltd. * 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. * 3. Neither the name of the Mellanox Technologies Ltd nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * 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. */ #ifndef CLOCK_H_ #define CLOCK_H_ /* * Parameters used to convert the time values: */ #define MSEC_PER_SEC 1000L #define USEC_PER_MSEC 1000L #define NSEC_PER_USEC 1000L #define NSEC_PER_MSEC 1000000L #define USEC_PER_SEC 1000000L #define NSEC_PER_SEC 1000000000L #define FSEC_PER_SEC 1000000000000000L /* * Convenience macros for operations on timevals */ #define TIMEVAL_INITIALIZER \ { 0, 0 } #define tv_to_sec(tvp) ((tvp)->tv_sec) #define tv_to_msec(tvp) \ ((int64_t((tvp)->tv_sec) * MSEC_PER_SEC) + (int64_t((tvp)->tv_usec) / USEC_PER_MSEC)) #define tv_to_usec(tvp) ((int64_t((tvp)->tv_sec) * USEC_PER_SEC) + (int64_t((tvp)->tv_usec))) #define tv_to_nsec(tvp) \ ((int64_t((tvp)->tv_sec) * NSEC_PER_SEC) + (int64_t((tvp)->tv_usec) * NSEC_PER_USEC)) #define tv_isset(tvp) timerisset(tvp) #define tv_clear(tvp) timerclear(tvp) #define tv_cmp(a, b, CMP) timercmp(a, b, CMP) #define tv_add(a, b, result) timeradd(a, b, result) #define tv_sub(a, b, result) timersub(a, b, result) /* Convenience macros for operations on timespecs */ #define TIMESPEC_INITIALIZER \ { 0, 0 } #define ts_to_sec(tsp) ((tsp)->tv_sec) #define ts_to_msec(tsp) \ ((int64_t((tsp)->tv_sec) * MSEC_PER_SEC) + (int64_t((tsp)->tv_nsec) / NSEC_PER_MSEC)) #define ts_to_usec(tsp) \ ((int64_t((tsp)->tv_sec) * USEC_PER_SEC) + (int64_t((tsp)->tv_nsec) / NSEC_PER_USEC)) #define ts_to_nsec(tsp) ((int64_t((tsp)->tv_sec) * NSEC_PER_SEC) + (int64_t((tsp)->tv_nsec))) #define ts_isset(tvp) ((tvp)->tv_sec || (tvp)->tv_nsec) #define ts_clear(tvp) ((tvp)->tv_sec = (tvp)->tv_nsec = 0) #define ts_cmp(a, b, CMP) \ (((a)->tv_sec == (b)->tv_sec) ? ((a)->tv_nsec CMP(b)->tv_nsec) : ((a)->tv_sec CMP(b)->tv_sec)) #define ts_add(a, b, result) \ do { \ (result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \ (result)->tv_nsec = (a)->tv_nsec + (b)->tv_nsec; \ if ((result)->tv_nsec >= NSEC_PER_SEC) { \ ++(result)->tv_sec; \ (result)->tv_nsec -= NSEC_PER_SEC; \ } \ } while (0) #define ts_sub(a, b, result) \ do { \ (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ (result)->tv_nsec = (a)->tv_nsec - (b)->tv_nsec; \ if ((result)->tv_nsec < 0) { \ --(result)->tv_sec; \ (result)->tv_nsec += NSEC_PER_SEC; \ } \ } while (0) #endif /* CLOCK_H_ */ sockperf-3.6/src/common.cpp000066400000000000000000000177741336630672200160110ustar00rootroot00000000000000/* * Copyright (c) 2011-2018 Mellanox Technologies Ltd. * 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. * 3. Neither the name of the Mellanox Technologies Ltd nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * 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. */ #include "common.h" extern void cleanup(); user_params_t s_user_params; // // AvnerB: the purpose of these error functions is to take out error code from inline function // //------------------------------------------------------------------------------ void recvfromError(int fd) { if (!g_b_exit) { log_err("recvfrom() Failed receiving on fd[%d]", fd); exit_with_log(SOCKPERF_ERR_SOCKET); } } //------------------------------------------------------------------------------ void sendtoError(int fd, int nbytes, const struct sockaddr_in *sendto_addr) { if (!g_b_exit) { log_err("sendto() Failed sending on fd[%d] to %s:%d msg size of %d bytes", fd, inet_ntoa(sendto_addr->sin_addr), ntohs(sendto_addr->sin_port), nbytes); exit_with_log(SOCKPERF_ERR_SOCKET); } } //------------------------------------------------------------------------------ void exit_with_log(int status) { exit_with_log("program exits because of an error.", status); } //------------------------------------------------------------------------------ void exit_with_log(const char *error, int status) { log_err("%s", error); g_b_errorOccured = true; g_b_exit = true; cleanup(); #ifdef DEBUG os_printf_backtrace(); #endif exit(status); } //------------------------------------------------------------------------------ void exit_with_log(const char *error, int status, fds_data *fds) { printf("IP = %-15s PORT = %5d # %s ", inet_ntoa(fds->server_addr.sin_addr), ntohs(fds->server_addr.sin_port), PRINT_PROTOCOL(fds->sock_type)); exit_with_log(error, status); } //------------------------------------------------------------------------------ void exit_with_err(const char *error, int status) { log_err("%s", error); #ifdef DEBUG os_printf_backtrace(); #endif exit(status); } //------------------------------------------------------------------------------ void print_log_dbg(struct in_addr sin_addr, in_port_t sin_port, int ifd) { log_dbg("peer address to close: %s:%d [%d]", inet_ntoa(sin_addr), ntohs(sin_port), ifd); } //------------------------------------------------------------------------------ int set_affinity_list(os_thread_t thread, const char *cpu_list) { int rc = SOCKPERF_ERR_NONE; if (cpu_list && cpu_list[0]) { long cpu_from = -1; long cpu_cur = 0; char *buf = strdup(cpu_list); char *cur_buf = buf; char *cur_ptr = buf; char *end_ptr = NULL; os_cpuset_t mycpuset; os_init_cpuset(&mycpuset); /* Parse cpu list */ while (cur_buf) { errno = 0; if (*cur_ptr == '\0') { cpu_cur = strtol(cur_buf, &end_ptr, 0); if ((errno != 0) || (cur_buf == end_ptr)) { log_err("Invalid argument: %s", cpu_list); rc = SOCKPERF_ERR_BAD_ARGUMENT; break; } cur_buf = NULL; } else if (*cur_ptr == ',') { *cur_ptr = '\0'; cpu_cur = strtol(cur_buf, &end_ptr, 0); if ((errno != 0) || (cur_buf == end_ptr)) { log_err("Invalid argument: %s", cpu_list); rc = SOCKPERF_ERR_BAD_ARGUMENT; break; } cur_buf = cur_ptr + 1; cur_ptr++; } else if (*cur_ptr == '-') { *cur_ptr = '\0'; cpu_from = strtol(cur_buf, &end_ptr, 0); if ((errno != 0) || (cur_buf == end_ptr)) { log_err("Invalid argument: %s", cpu_list); rc = SOCKPERF_ERR_BAD_ARGUMENT; break; } cur_buf = cur_ptr + 1; cur_ptr++; continue; } else { cur_ptr++; continue; } if ((cpu_from <= cpu_cur) && (cpu_cur < CPU_SETSIZE)) { if (cpu_from == -1) cpu_from = cpu_cur; os_cpu_set(&mycpuset, cpu_from, cpu_cur); cpu_from = -1; } else { log_err("Invalid argument: %s", cpu_list); rc = SOCKPERF_ERR_BAD_ARGUMENT; break; } } if ((rc == SOCKPERF_ERR_NONE) && os_set_affinity(thread, mycpuset)) { log_err("Set thread affinity failed to set tid(%lu) to cpu(%s)", (unsigned long)thread.tid, cpu_list); rc = SOCKPERF_ERR_FATAL; } if (buf) { free(buf); } } return rc; } //------------------------------------------------------------------------------ void hexdump(void *ptr, int buflen) { unsigned char *buf = (unsigned char *)ptr; int i, j; for (i = 0; i < buflen; i += 16) { printf("%06x: ", i); for (j = 0; j < 16; j++) if (i + j < buflen) printf("%02x ", buf[i + j]); else printf(" "); printf(" "); for (j = 0; j < 16; j++) if (i + j < buflen) printf("%c", isprint(buf[i + j]) ? buf[i + j] : '.'); printf("\n"); } } //------------------------------------------------------------------------------ const char *handler2str(fd_block_handler_t type) { // must be coordinated with fd_block_handler_t in defs.h static const char *s_fds_handle_desc[FD_HANDLE_MAX] = { "recvfrom", "recvfrom", "select" #ifndef WIN32 , "poll", "epoll", #ifdef USING_VMA_EXTRA_API "socketxtreme" #endif #endif }; return s_fds_handle_desc[type]; } // Receives as input a path to a system file and returns the value stored in the file int read_int_from_sys_file(const char *path) { int retVal; FILE *file = fopen(path, "r"); if (!file) return -1; if (1 != fscanf(file, "%d", &retVal)) retVal = 0; fclose(file); return retVal; } int sock_set_rate_limit(int fd, uint32_t rate_limit) { int rc = SOCKPERF_ERR_NONE; if (setsockopt(fd, SOL_SOCKET, SO_MAX_PACING_RATE, &rate_limit, sizeof(rate_limit)) < 0) { log_err("setsockopt(SO_MAX_PACING_RATE), set rate-limit failed. " "It could be that this option is not supported in your system"); rc = SOCKPERF_ERR_SOCKET; } else { log_msg("succeed to set sock-SO_MAX_PACING_RATE"); } return rc; } sockperf-3.6/src/common.h000066400000000000000000000313411336630672200154400ustar00rootroot00000000000000/* * Copyright (c) 2011-2018 Mellanox Technologies Ltd. * 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. * 3. Neither the name of the Mellanox Technologies Ltd nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * 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. */ #ifndef COMMON_H_ #define COMMON_H_ #include "defs.h" //#include "switches.h" #include "message.h" extern user_params_t s_user_params; //------------------------------------------------------------------------------ void recvfromError(int fd); // take out error code from inline function void sendtoError(int fd, int nbytes, const struct sockaddr_in *sendto_addr); // take out error code from inline function void exit_with_log(int status); void exit_with_log(const char *error, int status); void exit_with_log(const char *error, int status, fds_data *fds); void exit_with_err(const char *error, int status); void print_log_dbg(struct in_addr sin_addr, in_port_t sin_port, int ifd); int set_affinity_list(os_thread_t thread, const char *cpu_list); void hexdump(void *ptr, int buflen); const char *handler2str(fd_block_handler_t type); int read_int_from_sys_file(const char *path); // inline functions #ifdef USING_VMA_EXTRA_API //------------------------------------------------------------------------------ static inline int msg_recv_socketxtreme(fds_data *l_fds_ifd, vma_buff_t *tmp_vma_buff, struct sockaddr_in *recvfrom_addr) { *recvfrom_addr = g_vma_comps->src; if (l_fds_ifd->recv.cur_offset) { l_fds_ifd->recv.cur_addr = l_fds_ifd->recv.buf; l_fds_ifd->recv.cur_size = l_fds_ifd->recv.max_size - l_fds_ifd->recv.cur_offset; memmove(l_fds_ifd->recv.cur_addr + l_fds_ifd->recv.cur_offset, (uint8_t *)tmp_vma_buff->payload, tmp_vma_buff->len); } else { l_fds_ifd->recv.cur_addr = (uint8_t *)tmp_vma_buff->payload; l_fds_ifd->recv.cur_size = l_fds_ifd->recv.max_size; l_fds_ifd->recv.cur_offset = 0; } return tmp_vma_buff->len; } //------------------------------------------------------------------------------ static inline int msg_process_next(fds_data *l_fds_ifd, vma_buff_t **tmp_vma_buff, int *nbytes) { if (l_fds_ifd->recv.cur_offset) { memmove(l_fds_ifd->recv.buf, l_fds_ifd->recv.cur_addr, l_fds_ifd->recv.cur_offset); l_fds_ifd->recv.cur_addr = l_fds_ifd->recv.buf; l_fds_ifd->recv.cur_size = l_fds_ifd->recv.max_size - l_fds_ifd->recv.cur_offset; if ((*tmp_vma_buff)->next) { *tmp_vma_buff = (*tmp_vma_buff)->next; memmove(l_fds_ifd->recv.cur_addr + l_fds_ifd->recv.cur_offset, (uint8_t *)(*tmp_vma_buff)->payload, (*tmp_vma_buff)->len); *nbytes = (*tmp_vma_buff)->len; } else { return 1; } } else if (0 == *nbytes && (*tmp_vma_buff)->next) { *tmp_vma_buff = (*tmp_vma_buff)->next; l_fds_ifd->recv.cur_addr = (uint8_t *)(*tmp_vma_buff)->payload; l_fds_ifd->recv.cur_size = l_fds_ifd->recv.max_size; l_fds_ifd->recv.cur_offset = 0; *nbytes = (*tmp_vma_buff)->len; } return 0; } //------------------------------------------------------------------------------ static inline int free_vma_packets(int fd, int nbytes) { int data_to_copy; int remain_buffer = 0; struct vma_packet_t *pkt; ZeroCopyData *z_ptr = g_zeroCopyData[fd]; if (z_ptr) { remain_buffer = nbytes; // Receive held data, and free VMA's previously received zero copied packets if (z_ptr->m_pkts && z_ptr->m_pkts->n_packet_num > 0) { pkt = &z_ptr->m_pkts->pkts[0]; while (z_ptr->m_pkt_index < pkt->sz_iov) { data_to_copy = _min(remain_buffer, (int)(pkt->iov[z_ptr->m_pkt_index].iov_len - z_ptr->m_pkt_offset)); remain_buffer -= data_to_copy; z_ptr->m_pkt_offset += data_to_copy; // Handled buffer is filled if (z_ptr->m_pkt_offset < pkt->iov[z_ptr->m_pkt_index].iov_len) return 0; z_ptr->m_pkt_offset = 0; z_ptr->m_pkt_index++; } g_vma_api->free_packets(fd, z_ptr->m_pkts->pkts, z_ptr->m_pkts->n_packet_num); z_ptr->m_pkts = NULL; z_ptr->m_pkt_index = 0; z_ptr->m_pkt_offset = 0; // Handled buffer is filled if (remain_buffer == 0) return 0; } return remain_buffer; } return nbytes; } #endif //------------------------------------------------------------------------------ static inline int msg_recvfrom(int fd, uint8_t *buf, int nbytes, struct sockaddr_in *recvfrom_addr, uint8_t **zcopy_pkt_addr, int remain_buffer) { int ret = 0; socklen_t size = sizeof(struct sockaddr_in); int flags = 0; #ifdef USING_VMA_EXTRA_API if (g_pApp->m_const_params.is_vmazcopyread) { int data_to_copy; struct vma_packet_t *pkt; ZeroCopyData *z_ptr = g_zeroCopyData[fd]; if (z_ptr) { // Receive the next packet with zero copy API ret = g_vma_api->recvfrom_zcopy(fd, z_ptr->m_pkt_buf, Message::getMaxSize(), &flags, (struct sockaddr *)recvfrom_addr, &size); if (ret > 0) { // Zcopy receive is performed if (flags & MSG_VMA_ZCOPY) { z_ptr->m_pkts = (struct vma_packets_t *)z_ptr->m_pkt_buf; if (z_ptr->m_pkts->n_packet_num > 0) { pkt = &z_ptr->m_pkts->pkts[0]; // Make receive address point to the beginning of returned recvfrom_zcopy // buffer *zcopy_pkt_addr = (uint8_t *)pkt->iov[z_ptr->m_pkt_index].iov_base; while (z_ptr->m_pkt_index < pkt->sz_iov) { data_to_copy = _min(remain_buffer, (int)pkt->iov[z_ptr->m_pkt_index].iov_len); remain_buffer -= data_to_copy; z_ptr->m_pkt_offset += data_to_copy; // Handled buffer is filled if (z_ptr->m_pkt_offset < pkt->iov[z_ptr->m_pkt_index].iov_len) return nbytes; z_ptr->m_pkt_offset = 0; z_ptr->m_pkt_index++; } ret = nbytes - remain_buffer; } else { ret = (remain_buffer == nbytes) ? -1 : (nbytes - remain_buffer); } } else { data_to_copy = _min(remain_buffer, ret); memcpy(buf + (nbytes - remain_buffer), &z_ptr->m_pkt_buf[fd], data_to_copy); ret = nbytes - (remain_buffer - data_to_copy); } } // Non_blocked with held packet. else if (ret < 0 && os_err_eagain() && (remain_buffer < nbytes)) { return nbytes - remain_buffer; } } } else #endif { /* When writing onto a connection-oriented socket that has been shut down (by the local or the remote end) SIGPIPE is sent to the writing process and EPIPE is returned. The signal is not sent when the write call specified the MSG_NOSIGNAL flag. Note: another way is call signal (SIGPIPE,SIG_IGN); */ #ifndef WIN32 flags = MSG_NOSIGNAL; #endif ret = recvfrom(fd, buf, nbytes, flags, (struct sockaddr *)recvfrom_addr, &size); #if defined(LOG_TRACE_MSG_IN) && (LOG_TRACE_MSG_IN == TRUE) printf("> "); hexdump(buf, MsgHeader::EFFECTIVE_SIZE); #endif /* LOG_TRACE_MSG_IN */ #if defined(LOG_TRACE_RECV) && (LOG_TRACE_RECV == TRUE) LOG_TRACE("raw", "%s IP: %s:%d [fd=%d ret=%d] %s", __FUNCTION__, inet_ntoa(recvfrom_addr->sin_addr), ntohs(recvfrom_addr->sin_port), fd, ret, strerror(errno)); #endif /* LOG_TRACE_RECV */ } if (ret == 0 || errno == EPIPE || os_err_conn_reset()) { /* If no messages are available to be received and the peer has performed an orderly * shutdown, * recv()/recvfrom() shall return 0 * */ ret = RET_SOCKET_SHUTDOWN; errno = 0; } /* ret < MsgHeader::EFFECTIVE_SIZE * ret value less than MsgHeader::EFFECTIVE_SIZE * is bad case for UDP so error could be actual but it is possible value for TCP */ else if (ret < 0 && !os_err_eagain() && errno != EINTR) { recvfromError(fd); } return ret; } //------------------------------------------------------------------------------ static inline int msg_sendto(int fd, uint8_t *buf, int nbytes, const struct sockaddr_in *sendto_addr) { int ret = 0; int flags = 0; #if defined(LOG_TRACE_MSG_OUT) && (LOG_TRACE_MSG_OUT == TRUE) printf("<<< "); hexdump(buf, MsgHeader::EFFECTIVE_SIZE); #endif /* LOG_TRACE_SEND */ /* * MSG_NOSIGNAL: * When writing onto a connection-oriented socket that has been shut down * (by the local or the remote end) SIGPIPE is sent to the writing process * and EPIPE is returned. The signal is not sent when the write call specified * the MSG_NOSIGNAL flag. * Note: another way is call signal (SIGPIPE,SIG_IGN); */ #ifndef WIN32 flags = MSG_NOSIGNAL; /* * MSG_DONTWAIT: * Enables non-blocking operation; if the operation would block, * EAGAIN is returned (this can also be enabled using the O_NONBLOCK with * the F_SETFL fcntl()). */ if (g_pApp->m_const_params.is_nonblocked_send) { flags |= MSG_DONTWAIT; } #endif int size = nbytes; while (nbytes) { ret = sendto(fd, buf, nbytes, flags, (struct sockaddr *)sendto_addr, sizeof(struct sockaddr)); #if defined(LOG_TRACE_SEND) && (LOG_TRACE_SEND == TRUE) LOG_TRACE("raw", "%s IP: %s:%d [fd=%d ret=%d] %s", __FUNCTION__, inet_ntoa(sendto_addr->sin_addr), ntohs(sendto_addr->sin_port), fd, ret, strerror(errno)); #endif /* LOG_TRACE_SEND */ if (likely(ret > 0)) { nbytes -= ret; buf += ret; ret = size; } else if (ret == 0 || errno == EPIPE || os_err_conn_reset()) { /* If no messages are available to be received and the peer has performed an orderly * shutdown, * send()/sendto() shall return (RET_SOCKET_SHUTDOWN) */ errno = 0; ret = RET_SOCKET_SHUTDOWN; break; } else if (ret < 0 && (os_err_eagain() || errno == EWOULDBLOCK)) { /* If space is not available at the sending socket to hold the message to be transmitted * and * the socket file descriptor does have O_NONBLOCK set and * no bytes related message sent before * send()/sendto() shall return (RET_SOCKET_SKIPPED) */ errno = 0; if (nbytes < size) continue; ret = RET_SOCKET_SKIPPED; break; } else if (ret < 0 && (errno == EINTR)) { /* A signal occurred. */ errno = 0; break; } else { /* Unprocessed error */ sendtoError(fd, nbytes, sendto_addr); errno = 0; break; } } return ret; } int sock_set_rate_limit(int fd, uint32_t rate_limit); #endif /* COMMON_H_ */ sockperf-3.6/src/defs.cpp000066400000000000000000000052721336630672200154300ustar00rootroot00000000000000/* * Copyright (c) 2011-2018 Mellanox Technologies Ltd. * 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. * 3. Neither the name of the Mellanox Technologies Ltd nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * 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. */ #include "defs.h" #include "message.h" #include "packet.h" /* Global variables */ bool g_b_exit = false; bool g_b_errorOccured = false; uint64_t g_receiveCount = 0; // TODO: should be one per server uint64_t g_skipCount = 0; // TODO: should be one per server unsigned long long g_cycle_wait_loop_counter = 0; TicksTime g_cycleStartTime; debug_level_t g_debug_level = LOG_LVL_INFO; #ifdef USING_VMA_EXTRA_API struct vma_buff_t *g_vma_buff = NULL; struct vma_completion_t *g_vma_comps; ZeroCopyData::ZeroCopyData() : m_pkt_buf(NULL), m_pkts(NULL), m_pkt_index(0), m_pkt_offset(0) {}; void ZeroCopyData::allocate() { m_pkt_buf = (unsigned char *)MALLOC(Message::getMaxSize()); } ZeroCopyData::~ZeroCopyData() { if (m_pkt_buf) FREE(m_pkt_buf); } zeroCopyMap g_zeroCopyData; #endif uint32_t MPS_MAX = MPS_MAX_UL; // will be overwrite at runtime in case of ping-pong test PacketTimes *g_pPacketTimes = NULL; TicksTime g_lastTicks; const int MAX_FDS_NUM = os_get_max_active_fds_num(); fds_data **g_fds_array = NULL; int MAX_PAYLOAD_SIZE = 65507; int IGMP_MAX_MEMBERSHIPS = IP_MAX_MEMBERSHIPS; #ifdef USING_VMA_EXTRA_API struct vma_api_t *g_vma_api; #endif const App *g_pApp = NULL; sockperf-3.6/src/defs.h000066400000000000000000000617751336630672200151070ustar00rootroot00000000000000/* * Copyright (c) 2011-2018 Mellanox Technologies Ltd. * 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. * 3. Neither the name of the Mellanox Technologies Ltd nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * 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. */ #ifndef DEFS_H_ #define DEFS_H_ #define __STDC_FORMAT_MACROS #ifdef WIN32 #include #include #include #include #include typedef uint16_t in_port_t; #else #ifdef __linux__ #include #endif /* every file that use fd_set must include this section first for using big fd set size */ #if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) #include #undef __FD_SETSIZE #define __FD_SETSIZE 32768 #include #endif #ifdef __linux__ #include #endif #include #include #include #include /* getopt() and sleep()*/ #include /* printf PRItn */ #include #include #include #include /* timers*/ #include /* sockets*/ #include /* select() According to POSIX 1003.1-2001 */ #include #include /* internet address manipulation */ #include /* internet address manipulation */ #include /* gethostbyname() */ #include /* tcp specific */ #include #endif #include /* random()*/ #include #include #include #include #include #include /* clock_gettime()*/ #include /* isprint()*/ #include #include #include /* sockets*/ #include #include #include "ticks.h" #include "message.h" #include "playback.h" #if !defined(WIN32) && !defined(__FreeBSD__) #include "vma-redirect.h" #ifdef USING_VMA_EXTRA_API #include #endif #endif #define MIN_PAYLOAD_SIZE (MsgHeader::EFFECTIVE_SIZE) extern int MAX_PAYLOAD_SIZE; #define MAX_STREAM_SIZE (50 * 1024 * 1024) #define MAX_TCP_SIZE ((1 << 20) - 1) const uint32_t MPS_MAX_UL = 10 * 1000 * 1000; // 10 M MPS is 4 times the maximum possible under VMA today const uint32_t MPS_MAX_PP = 600 * 1000; // 600 K MPS for ping-pong will be break only when we reach RTT of 1.667 usec extern uint32_t MPS_MAX; const uint32_t MPS_DEFAULT = 10 * 1000; const uint32_t REPLY_EVERY_DEFAULT = 100; const uint32_t TEST_START_WARMUP_MSEC = 400; const uint32_t TEST_END_COOLDOWN_MSEC = 50; const uint32_t TEST_FIRST_CONNECTION_FIRST_PACKET_TTL_THRESHOLD_MSEC = 50; #define TEST_ANY_CONNECTION_FIRST_PACKET_TTL_THRESHOLD_MSEC (0.1) #define DEFAULT_CLIENT_WORK_WITH_SRV_NUM 1 #define DEFAULT_TEST_DURATION 1 /* [sec] */ #define DEFAULT_MC_ADDR "0.0.0.0" #define DEFAULT_PORT 11111 #define DEFAULT_IP_MTU 1500 #define DEFAULT_IP_PAYLOAD_SZ (DEFAULT_IP_MTU - 28) #define DUMMY_PORT 57341 #define MAX_ACTIVE_FD_NUM \ 1024 /* maximum number of active connection to the single TCP addr:port \ */ #ifdef USING_VMA_EXTRA_API #define MAX_VMA_COMPS 1024 /* maximum size for the VMA completions array for VMA Poll */ #endif #ifndef MAX_PATH_LENGTH #define MAX_PATH_LENGTH 1024 #endif #define MAX_MCFILE_LINE_LENGTH 41 /* sizeof("U:255.255.255.255:11111:255.255.255.255\0") */ #define IP_PORT_FORMAT_REG_EXP \ "^([UuTt]:)*([a-zA-Z0-9\\.\\-]+):(6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|6[0-4][0-9]{3}|[0-" \ "5]?[0-9]{1,4})(:[a-zA-Z0-9\\.\\-]+)?[\r\n]" /* #define IP_PORT_FORMAT_REG_EXP "^([UuTt]:)*((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}"\ "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?):"\ "(6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|6[0-4][0-9]{3}|[0-5]?[0-9]{1,4})\n" */ #define PRINT_PROTOCOL(type) \ ((type) == SOCK_DGRAM ? "UDP" : ((type) == SOCK_STREAM ? "TCP" : "")) #define MAX_ARGV_SIZE 256 #define MAX_DURATION 36000000 extern const int MAX_FDS_NUM; #define SOCK_BUFF_DEFAULT_SIZE 0 #define DEFAULT_SELECT_TIMEOUT_MSEC 10 #define DEFAULT_DEBUG_LEVEL 0 #ifndef SO_MAX_PACING_RATE #define SO_MAX_PACING_RATE 47 #endif /* Used by offload libraries to do egress path warm-up of caches. It is not in use by kernel. WARNING: it will actually end this packet on the wire. DUMMY_SEND_FLAG value should be compatible with the value of VMA_SND_FLAGS_DUMMY (More info at vma_extra.h). */ #define DUMMY_SEND_FLAG 0x400 // equals to MSG_SYN #define DUMMY_SEND_MPS_DEFAULT 10000 enum { OPT_RX_MC_IF = 1, OPT_TX_MC_IF, // 2 OPT_SELECT_TIMEOUT, // 3 OPT_THREADS_NUM, // 4 OPT_CLIENT_CYCLE_DURATION, // 5 OPT_BUFFER_SIZE, // 6 OPT_DATA_INTEGRITY, // 7 OPT_DAEMONIZE, // 8 OPT_NONBLOCKED, // 9 OPT_DONTWARMUP, // 10 OPT_PREWARMUPWAIT, // 11 OPT_VMARXFILTERCB, // 12 OPT_VMAZCOPYREAD, // 13 OPT_SOCKETXTREME, // 14 OPT_MC_LOOPBACK_ENABLE, // 15 OPT_CLIENT_WORK_WITH_SRV_NUM, // 16 OPT_FORCE_UC_REPLY, // 17 OPT_MPS, // 18 OPT_REPLY_EVERY, // 19 OPT_NO_RDTSC, // 20 OPT_SENDER_AFFINITY, // 21 OPT_RECEIVER_AFFINITY, // 22 OPT_LOAD_VMA, // 23 OPT_FULL_LOG, // 24 OPT_GIGA_SIZE, // 25 OPT_PLAYBACK_DATA, // 26 OPT_TCP, // 27 OPT_TCP_NODELAY_OFF, // 28 OPT_NONBLOCKED_SEND, // 29 OPT_IP_MULTICAST_TTL, // 30 OPT_SOCK_ACCL, // 31 OPT_THREADS_AFFINITY, // 32 OPT_DONT_REPLY, // 33 OPT_RECV_LOOPING, // 34 OPT_OUTPUT_PRECISION, // 35 OPT_CLIENTPORT, // 36 OPT_CLIENTIP, // 37 OPT_TOS, // 38 OPT_LLS, // 39 OPT_MC_SOURCE_IP, // 40 OPT_DUMMY_SEND, // 41 OPT_RATE_LIMIT, // 42 OPT_UC_REUSEADDR, // 43 OPT_FULL_RTT // 44 }; static const char *const round_trip_str[] = { "latency", "rtt" }; #define MODULE_NAME "sockperf" #define MODULE_COPYRIGHT \ "Copyright (C) 2011 Mellanox Technologies Ltd." \ "\nSockPerf is open source software, see http://github.com/mellanox/sockperf" #define log_msg(log_fmt, ...) printf(MODULE_NAME ": " log_fmt "\n", ##__VA_ARGS__) #define log_msg_file(file, log_fmt, ...) fprintf(file, MODULE_NAME ": " log_fmt "\n", ##__VA_ARGS__) #define log_msg_file2(file, log_fmt, ...) \ if (1) { \ log_msg(log_fmt, ##__VA_ARGS__); \ if (file) log_msg_file(file, log_fmt, ##__VA_ARGS__); \ } else #define log_err(log_fmt, ...) \ printf("sockperf: ERROR: " log_fmt " (errno=%d %s)\n", ##__VA_ARGS__, errno, strerror(errno)) #ifdef DEBUG #undef log_err #define log_err(log_fmt, ...) \ printf(MODULE_NAME ": " \ "%s:%d:ERROR: " log_fmt " (errno=%d %s)\n", \ __FILE__, __LINE__, ##__VA_ARGS__, errno, strerror(errno)) #endif #define log_dbg(log_fmt, ...) \ if (g_debug_level >= LOG_LVL_DEBUG) { \ printf(MODULE_NAME ": " log_fmt "\n", ##__VA_ARGS__); \ } else #define TRACE(msg) log_msg("TRACE <%s>: %s() %s:%d\n", msg, __func__, __FILE__, __LINE__) #define ERROR_MSG(msg) \ if (1) { \ TRACE(msg); \ exit_with_log(-1); \ } else typedef enum { LOG_LVL_INFO = 0, LOG_LVL_DEBUG } debug_level_t; #ifndef TRUE #define TRUE (1 == 1) #endif /* TRUE */ #ifndef FALSE #define FALSE (1 == 0) #endif /* FALSE */ /* This macros should be used in printf to display uintptr_t */ #ifndef PRIXPTR #define PRIXPTR "lX" #endif #ifndef UNREFERENCED_PARAMETER #define UNREFERENCED_PARAMETER(P) ((void)P) #endif #ifndef likely #if defined(__GNUC__) || defined(__INTEL_COMPILER) #define likely(x) __builtin_expect(!!(x), 1) #define unlikely(x) __builtin_expect(!!(x), 0) #else #define likely(x) (x) #define unlikely(x) (x) #endif #endif #define RET_SOCKET_SKIPPED (-2) /**< socket operation is skipped */ #define RET_SOCKET_SHUTDOWN 0 /**< socket is shutdown */ /** * @enum SOCKPERF_ERROR * @brief List of supported error codes. */ typedef enum { SOCKPERF_ERR_NONE = 0x0, /**< the function completed */ SOCKPERF_ERR_BAD_ARGUMENT, /**< incorrect parameter */ SOCKPERF_ERR_INCORRECT, /**< incorrect format of object */ SOCKPERF_ERR_UNSUPPORTED, /**< this function is not supported */ SOCKPERF_ERR_NOT_EXIST, /**< requested object does not exist */ SOCKPERF_ERR_NO_MEMORY, /**< dynamic memory error */ SOCKPERF_ERR_FATAL, /**< system fatal error */ SOCKPERF_ERR_SOCKET, /**< socket operation error */ SOCKPERF_ERR_TIMEOUT, /**< the time limit expires */ SOCKPERF_ERR_UNKNOWN /**< general error */ } SOCKPERF_ERROR; /* * Debug configuration settings */ #ifdef DEBUG #define LOG_TRACE_SEND FALSE #define LOG_TRACE_RECV FALSE #define LOG_TRACE_MSG_IN FALSE #define LOG_TRACE_MSG_OUT FALSE #define LOG_MEMORY_CHECK FALSE #define LOG_LOCK_CHECK FALSE #define LOG_TRACE(category, format, ...) \ log_send(category, 1, __FILE__, __LINE__, __FUNCTION__, format, ##__VA_ARGS__) inline void log_send(const char *name, int priority, const char *file_name, const int line_no, const char *func_name, const char *format, ...) { if (priority) { char buf[250]; va_list va; int n = 0; va_start(va, format); n = vsnprintf(buf, sizeof(buf) - 1, format, va); va_end(va); printf("[%s] %s: %s <%s: %s #%d> size %d\n", "debug", (name ? name : ""), buf, file_name, func_name, line_no, n); } } #if defined(LOG_MEMORY_CHECK) && (LOG_MEMORY_CHECK == TRUE) #define MALLOC(size) __malloc(size, __FUNCTION__, __LINE__) #define FREE(ptr) \ do { \ __free(ptr, __FUNCTION__, __LINE__); \ ptr = NULL; \ } while (0) #else #define MALLOC(size) malloc(size) #define FREE(ptr) \ do { \ free(ptr); \ ptr = NULL; \ } while (0) #endif /* LOG_MEMORY_CHECK */ inline void *__malloc(int size, const char *func, int line) { void *ptr = malloc(size); printf("malloc: %p (%d) <%s:%d>\n", ptr, size, func, line); return ptr; } inline void __free(void *ptr, const char *func, int line) { free(ptr); printf("free : %p <%s:%d>\n", ptr, func, line); return; } #else #define LOG_TRACE(category, format, ...) #define MALLOC(size) malloc(size) #define FREE(ptr) \ do { \ free(ptr); \ ptr = NULL; \ } while (0) // FREE is not expected to be called from fast path #endif /* DEBUG */ /** * @name Synchronization * @brief Multi-threading Synchronization operations. */ /** @{ */ #define CRITICAL_SECTION os_mutex_t #if defined(_GNU_SOURCE) #define INIT_CRITICAL(x) \ { \ pthread_mutexattr_t attr; \ pthread_mutexattr_init(&attr); \ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_DEFAULT); \ pthread_mutex_init(x.mutex, &attr); \ pthread_mutexattr_destroy(&attr); \ } #else #define INIT_CRITICAL(x) os_mutex_init(x) #endif #define DELETE_CRITICAL(x) os_mutex_close(x) #define DBG_ENTER_CRITICAL(x) os_mutex_lock(x) #define DBG_LEAVE_CRITICAL(x) os_mutex_unlock(x) /* Debugging Multi-threading operations. */ #if defined(LOG_LOCK_CHECK) && (LOG_LOCK_CHECK == TRUE) #define ENTER_CRITICAL(x) \ { \ printf("lock = 0x%" PRIXPTR " <%s: %s #%d>\n", (uintptr_t)x, __FILE__, __FUNCTION__, \ __LINE__); \ DBG_ENTER_CRITICAL(x); \ } #define LEAVE_CRITICAL(x) \ { \ printf("unlock = 0x%" PRIXPTR " <%s: %s #%d>\n", (uintptr_t)x, __FILE__, __FUNCTION__, \ __LINE__); \ DBG_LEAVE_CRITICAL(x); \ } #else #define ENTER_CRITICAL(x) DBG_ENTER_CRITICAL(x) #define LEAVE_CRITICAL(x) DBG_LEAVE_CRITICAL(x) #endif /* LOG_LOCK_CHECK */ /** @} */ /* Global variables */ extern bool g_b_exit; extern bool g_b_errorOccured; extern uint64_t g_receiveCount; extern uint64_t g_skipCount; extern unsigned long long g_cycle_wait_loop_counter; extern TicksTime g_cycleStartTime; extern debug_level_t g_debug_level; #ifdef USING_VMA_EXTRA_API extern struct vma_buff_t *g_vma_buff; extern struct vma_completion_t *g_vma_comps; class ZeroCopyData { public: ZeroCopyData(); void allocate(); ~ZeroCopyData(); unsigned char *m_pkt_buf; struct vma_packets_t *m_pkts; unsigned int m_pkt_index; unsigned int m_pkt_offset; }; // map from fd to zeroCopyData typedef std::map zeroCopyMap; extern zeroCopyMap g_zeroCopyData; #endif class Message; class PacketTimes; extern PacketTimes *g_pPacketTimes; extern TicksTime g_lastTicks; typedef struct spike { // double usec; TicksDuration ticks; unsigned long long packet_counter_at_spike; int next; } spike; typedef struct port_and_type { int sock_type; /**< SOCK_STREAM (tcp), SOCK_DGRAM (udp), SOCK_RAW (ip) */ in_port_t port; } port_type; /** * @struct fds_data * @brief Socket related info */ typedef struct fds_data { struct sockaddr_in server_addr; /**< server address information */ int is_multicast; /**< if this socket is multicast */ int sock_type; /**< SOCK_STREAM (tcp), SOCK_DGRAM (udp), SOCK_RAW (ip) */ int next_fd; int active_fd_count; /**< number of active connections (by default 1-for UDP; 0-for TCP) */ int * active_fd_list; /**< list of fd related active connections (UDP has the same fd by default) */ struct sockaddr_in *memberships_addr; /**< more servers on the same socket information */ struct in_addr mc_source_ip_addr; /**< message source ip for multicast packet filtering */ int memberships_size; struct { uint8_t *buf; int max_size; uint8_t *cur_addr; int cur_offset; int cur_size; } recv; #ifdef USING_VMA_EXTRA_API Message *p_msg; #endif } fds_data; /** * @struct handler_info * @brief Handler configuration data */ typedef struct handler_info { int id; /**< handler ID */ int fd_min; /**< minimum descriptor (fd) */ int fd_max; /**< maximum socket descriptor (fd) */ int fd_num; /**< number of socket descriptors */ } handler_info; typedef struct clt_session_info { uint64_t seq_num; uint64_t total_drops; sockaddr_in addr; bool started; } clt_session_info_t; // The only types that TR1 has built-in hash/equal_to functions for, are scalar types, // std:: string, and std::wstring. For any other type, we need to write a // hash/equal_to functions, by ourself. namespace std { #if !defined(WIN32) && !defined(__FreeBSD__) namespace tr1 { #endif template <> struct hash : public std::unary_function { int operator()(struct sockaddr_in const &key) const { // XOR "a.b" part of "a.b.c.d" address with 16bit port; leave "c.d" part untouched for // maximum hashing return key.sin_addr.s_addr ^ key.sin_port; } }; template <> struct hash : public std::unary_function { int operator()(struct port_and_type const &key) const { // XOR "a.b" part of "a.b.c.d" address with 16bit port; leave "c.d" part untouched for // maximum hashing return key.sock_type ^ key.port; } }; template <> struct hash : public std::unary_function { int operator()(struct in_addr const &key) const { return key.s_addr & 0xFF; } }; #if !defined(WIN32) && !defined(__FreeBSD__) } // closes namespace tr1 #endif template <> struct equal_to : public std::binary_function { bool operator()(struct sockaddr_in const &key1, struct sockaddr_in const &key2) const { return key1.sin_port == key2.sin_port && key1.sin_addr.s_addr == key2.sin_addr.s_addr; } }; template <> struct equal_to : public std::binary_function { bool operator()(struct port_and_type const &key1, struct port_and_type const &key2) const { return key1.sock_type == key2.sock_type && key1.port == key2.port; } }; template <> struct equal_to : public std::binary_function { bool operator()(struct in_addr const &key1, struct in_addr const &key2) const { return key1.s_addr == key2.s_addr; } }; } #ifdef USING_VMA_EXTRA_API struct vma_ring_comps { vma_completion_t vma_comp_list[MAX_VMA_COMPS]; int vma_comp_list_size; bool is_freed; }; #endif #ifndef __FreeBSD__ typedef std::tr1::unordered_map seq_num_map; typedef std::tr1::unordered_map addr_to_id; #ifdef USING_VMA_EXTRA_API typedef std::tr1::unordered_map rings_vma_comps_map; #endif #else typedef std::unordered_map seq_num_map; typedef std::unordered_map addr_to_id; #ifdef USING_VMA_EXTRA_API typedef std::unordered_map rings_vma_comps_map; #endif #endif extern fds_data **g_fds_array; extern int IGMP_MAX_MEMBERSHIPS; #ifdef USING_VMA_EXTRA_API typedef std::queue vma_comps_queue; extern struct vma_api_t *g_vma_api; #endif typedef enum { MODE_CLIENT = 0, MODE_SERVER, MODE_BRIDGE } work_mode_t; typedef enum { // must be coordinated with s_fds_handle_desc in common.cpp RECVFROM = 0, RECVFROMMUX, SELECT, #ifndef WIN32 POLL, EPOLL, SOCKETXTREME, #endif FD_HANDLE_MAX } fd_block_handler_t; struct user_params_t { work_mode_t mode; // either client or server struct in_addr rx_mc_if_addr; struct in_addr tx_mc_if_addr; struct in_addr mc_source_ip_addr; int msg_size; int msg_size_range; int sec_test_duration; bool data_integrity; fd_block_handler_t fd_handler_type; unsigned int packetrate_stats_print_ratio; unsigned int burst_size; bool packetrate_stats_print_details; // bool stream_mode; - use b_stream instead int mthread_server; struct timeval *select_timeout; int sock_buff_size; int threads_num; char threads_affinity[MAX_ARGV_SIZE]; bool is_blocked; bool do_warmup; unsigned int pre_warmup_wait; uint32_t warmup_msec; bool is_vmarxfiltercb; bool is_vmazcopyread; TicksDuration cycleDuration; bool mc_loop_disable; bool uc_reuseaddr; int client_work_with_srv_num; bool b_server_reply_via_uc; bool b_server_dont_reply; bool b_server_detect_gaps; uint32_t mps; // client side only struct sockaddr_in client_bind_info; uint32_t reply_every; // client side only bool b_client_ping_pong; // client side only bool b_no_rdtsc; char sender_affinity[MAX_ARGV_SIZE]; char receiver_affinity[MAX_ARGV_SIZE]; FILE *fileFullLog; // client side only bool full_rtt; // client side only bool giga_size; // client side only bool increase_output_precision; // client side only bool b_stream; // client side only PlaybackVector *pPlaybackVector; // client side only struct sockaddr_in addr; int sock_type; bool tcp_nodelay; bool is_nonblocked_send; int mc_ttl; int daemonize; char feedfile_name[MAX_PATH_LENGTH]; bool withsock_accl; int max_looping_over_recv; int tos; unsigned int lls_usecs; bool lls_is_set; uint32_t dummy_mps; // client side only TicksDuration dummySendCycleDuration; // client side only uint32_t rate_limit; }; struct mutable_params_t {}; //============================================================================== class App { public: App(const struct user_params_t &_user_params, const struct mutable_params_t &_mutable_params) : m_const_params(_user_params), m_mutable_params(_mutable_params) { TicksBase::init(m_const_params.b_no_rdtsc ? TicksBase::CLOCK : TicksBase::RDTSC); } ~App() {} const struct user_params_t m_const_params; struct mutable_params_t m_mutable_params; }; extern const App *g_pApp; //------------------------------------------------------------------------------ #endif /* DEFS_H_ */ sockperf-3.6/src/iohandlers.cpp000066400000000000000000000343731336630672200166430ustar00rootroot00000000000000/* * Copyright (c) 2011-2018 Mellanox Technologies Ltd. * 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. * 3. Neither the name of the Mellanox Technologies Ltd nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * 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. */ #include "iohandlers.h" //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ IoHandler::IoHandler(int _fd_min, int _fd_max, int _fd_num, int _look_start, int _look_end) : m_fd_min(_fd_min), m_fd_max(_fd_max), m_fd_num(_fd_num), m_look_start(_look_start), m_look_end(_look_end) {} //------------------------------------------------------------------------------ IoHandler::~IoHandler() {} //------------------------------------------------------------------------------ void IoHandler::warmup(Message *pMsgRequest) const { if (!g_pApp->m_const_params.do_warmup) return; pMsgRequest->setWarmupMessage(); log_msg("Warmup stage (sending a few dummy messages)..."); for (int ifd = m_fd_min; ifd <= m_fd_max; ifd++) { if (g_fds_array[ifd] && g_fds_array[ifd]->is_multicast) { for (int count = 0; count < 2; count++) { int length = pMsgRequest->getLength(); pMsgRequest->setHeaderToNetwork(); msg_sendto(ifd, pMsgRequest->getBuf(), length, &(g_fds_array[ifd]->server_addr)); pMsgRequest->setHeaderToHost(); } } } pMsgRequest->resetWarmupMessage(); } //============================================================================== //------------------------------------------------------------------------------ IoRecvfrom::IoRecvfrom(int _fd_min, int _fd_max, int _fd_num) : IoHandler(_fd_min, _fd_max, _fd_num, _fd_min, _fd_min + 1) {} //------------------------------------------------------------------------------ IoRecvfrom::~IoRecvfrom() {} //------------------------------------------------------------------------------ int IoRecvfrom::prepareNetwork() { int rc = SOCKPERF_ERR_NONE; int list_count = 0; printf("\n"); for (int ifd = m_fd_min; ifd <= m_fd_max; ifd++) { if (g_fds_array[ifd]) { printf("[%2d] IP = %-15s PORT = %5d # %s\n", list_count++, inet_ntoa(g_fds_array[ifd]->server_addr.sin_addr), ntohs(g_fds_array[ifd]->server_addr.sin_port), PRINT_PROTOCOL(g_fds_array[ifd]->sock_type)); for (int i = 0; i < g_fds_array[ifd]->memberships_size; i++) { printf("[%2d] IP = %-15s PORT = %5d # %s\n", list_count++, inet_ntoa(g_fds_array[ifd]->memberships_addr[i].sin_addr), ntohs(g_fds_array[ifd]->server_addr.sin_port), PRINT_PROTOCOL(g_fds_array[ifd]->sock_type)); } } } return rc; } //============================================================================== //------------------------------------------------------------------------------ IoRecvfromMUX::IoRecvfromMUX(int _fd_min, int _fd_max, int _fd_num) : IoHandler(_fd_min, _fd_max, _fd_num, _fd_num == 1 ? _fd_min : _fd_min - 1, _fd_num == 1 ? _fd_num + 1 : _fd_min), m_fd_min_all(_fd_min), m_fd_max_all(_fd_max) {} //------------------------------------------------------------------------------ IoRecvfromMUX::~IoRecvfromMUX() {} //------------------------------------------------------------------------------ int IoRecvfromMUX::prepareNetwork() { int rc = SOCKPERF_ERR_NONE; int list_count = 0; printf("\n"); for (int ifd = m_fd_min; ifd <= m_fd_max; ifd++) { if (g_fds_array[ifd]) { printf("[%2d] IP = %-15s PORT = %5d # %s\n", list_count++, inet_ntoa(g_fds_array[ifd]->server_addr.sin_addr), ntohs(g_fds_array[ifd]->server_addr.sin_port), PRINT_PROTOCOL(g_fds_array[ifd]->sock_type)); for (int i = 0; i < g_fds_array[ifd]->memberships_size; i++) { printf("[%2d] IP = %-15s PORT = %5d # %s\n", list_count++, inet_ntoa(g_fds_array[ifd]->memberships_addr[i].sin_addr), ntohs(g_fds_array[ifd]->server_addr.sin_port), PRINT_PROTOCOL(g_fds_array[ifd]->sock_type)); } } } return rc; } //============================================================================== //------------------------------------------------------------------------------ IoSelect::IoSelect(int _fd_min, int _fd_max, int _fd_num) : IoHandler(_fd_min, _fd_max, _fd_num, _fd_min, _fd_max + 1), mp_timeout_timeval(g_pApp->m_const_params.select_timeout ? &m_timeout_timeval : NULL) {} //------------------------------------------------------------------------------ IoSelect::~IoSelect() {} //------------------------------------------------------------------------------ int IoSelect::prepareNetwork() { int rc = SOCKPERF_ERR_NONE; int list_count = 0; FD_ZERO(&m_save_fds); printf("\n"); for (int ifd = m_fd_min; ifd <= m_fd_max; ifd++) { if (g_fds_array[ifd]) { printf("[%2d] IP = %-15s PORT = %5d # %s\n", list_count++, inet_ntoa(g_fds_array[ifd]->server_addr.sin_addr), ntohs(g_fds_array[ifd]->server_addr.sin_port), PRINT_PROTOCOL(g_fds_array[ifd]->sock_type)); FD_SET(ifd, &m_save_fds); for (int i = 0; i < g_fds_array[ifd]->memberships_size; i++) { printf("[%2d] IP = %-15s PORT = %5d # %s\n", list_count++, inet_ntoa(g_fds_array[ifd]->memberships_addr[i].sin_addr), ntohs(g_fds_array[ifd]->server_addr.sin_port), PRINT_PROTOCOL(g_fds_array[ifd]->sock_type)); } } } return rc; } #ifndef WIN32 //============================================================================== //------------------------------------------------------------------------------ IoPoll::IoPoll(int _fd_min, int _fd_max, int _fd_num) : IoHandler(_fd_min, _fd_max, _fd_num, 0, _fd_num), m_timeout_msec(g_pApp->m_const_params.select_timeout ? g_pApp->m_const_params.select_timeout->tv_sec * 1000 + g_pApp->m_const_params.select_timeout->tv_usec / 1000 : -1) { mp_poll_fd_arr = NULL; } //------------------------------------------------------------------------------ IoPoll::~IoPoll() { if (mp_poll_fd_arr) { FREE(mp_poll_fd_arr); } } //------------------------------------------------------------------------------ int IoPoll::prepareNetwork() { int rc = SOCKPERF_ERR_NONE; mp_poll_fd_arr = (struct pollfd *)MALLOC(MAX_FDS_NUM * sizeof(struct pollfd)); if (!mp_poll_fd_arr) { log_err("Failed to allocate memory for poll fd array"); rc = SOCKPERF_ERR_NO_MEMORY; } else { printf("\n"); int fd_count = 0; int list_count = 0; for (int ifd = m_fd_min; ifd <= m_fd_max; ifd++) { if (g_fds_array[ifd]) { printf("[%2d] IP = %-15s PORT = %5d # %s\n", list_count++, inet_ntoa(g_fds_array[ifd]->server_addr.sin_addr), ntohs(g_fds_array[ifd]->server_addr.sin_port), PRINT_PROTOCOL(g_fds_array[ifd]->sock_type)); for (int i = 0; i < g_fds_array[ifd]->memberships_size; i++) { printf("[%2d] IP = %-15s PORT = %5d # %s\n", list_count++, inet_ntoa(g_fds_array[ifd]->memberships_addr[i].sin_addr), ntohs(g_fds_array[ifd]->server_addr.sin_port), PRINT_PROTOCOL(g_fds_array[ifd]->sock_type)); } mp_poll_fd_arr[fd_count].fd = ifd; mp_poll_fd_arr[fd_count].events = POLLIN | POLLPRI; fd_count++; } } } return rc; } #ifndef __FreeBSD__ //============================================================================== //------------------------------------------------------------------------------ IoEpoll::IoEpoll(int _fd_min, int _fd_max, int _fd_num) : IoHandler(_fd_min, _fd_max, _fd_num, 0, 0), m_timeout_msec(g_pApp->m_const_params.select_timeout ? g_pApp->m_const_params.select_timeout->tv_sec * 1000 + g_pApp->m_const_params.select_timeout->tv_usec / 1000 : -1) { mp_epoll_events = NULL; m_max_events = 0; } //------------------------------------------------------------------------------ IoEpoll::~IoEpoll() { if (mp_epoll_events) { close(m_epfd); FREE(mp_epoll_events); } } //------------------------------------------------------------------------------ int IoEpoll::prepareNetwork() { int rc = SOCKPERF_ERR_NONE; struct epoll_event ev = { 0, { 0 } }; int list_count = 0; mp_epoll_events = (struct epoll_event *)MALLOC(MAX_FDS_NUM * sizeof(struct epoll_event)); if (!mp_epoll_events) { log_err("Failed to allocate memory for epoll event array"); rc = SOCKPERF_ERR_NO_MEMORY; } else { printf("\n"); m_max_events = 0; m_epfd = epoll_create(MAX_FDS_NUM); for (int ifd = m_fd_min; ifd <= m_fd_max; ifd++) { if (g_fds_array[ifd]) { printf("[%2d] IP = %-15s PORT = %5d # %s\n", list_count++, inet_ntoa(g_fds_array[ifd]->server_addr.sin_addr), ntohs(g_fds_array[ifd]->server_addr.sin_port), PRINT_PROTOCOL(g_fds_array[ifd]->sock_type)); for (int i = 0; i < g_fds_array[ifd]->memberships_size; i++) { printf("[%2d] IP = %-15s PORT = %5d # %s\n", list_count++, inet_ntoa(g_fds_array[ifd]->memberships_addr[i].sin_addr), ntohs(g_fds_array[ifd]->server_addr.sin_port), PRINT_PROTOCOL(g_fds_array[ifd]->sock_type)); } ev.events = EPOLLIN | EPOLLPRI; ev.data.fd = ifd; epoll_ctl(m_epfd, EPOLL_CTL_ADD, ev.data.fd, &ev); m_max_events++; } } } return rc; } #endif #ifdef USING_VMA_EXTRA_API //============================================================================== //------------------------------------------------------------------------------ IoSocketxtreme::IoSocketxtreme(int _fd_min, int _fd_max, int _fd_num) : IoHandler(_fd_min, _fd_max, _fd_num, 0, 0) { m_current_vma_ring_comp = NULL; } //------------------------------------------------------------------------------ IoSocketxtreme::~IoSocketxtreme() { for (m_rings_vma_comps_map_itr = m_rings_vma_comps_map.begin(); m_rings_vma_comps_map_itr != m_rings_vma_comps_map.end(); ++m_rings_vma_comps_map_itr) { FREE(m_rings_vma_comps_map_itr->second); } } //------------------------------------------------------------------------------ int IoSocketxtreme::prepareNetwork() { int rc = SOCKPERF_ERR_NONE; int list_count = 0; int ring_fd = 0; printf("\n"); for (int ifd = m_fd_min; ifd <= m_fd_max; ifd++) { if (g_fds_array[ifd]) { ring_fd = 0; int rings = g_vma_api->get_socket_rings_fds(ifd, &ring_fd, 1); if (rings == -1) { rc = SOCKPERF_ERR_SOCKET; return rc; } rings_vma_comps_map::iterator itr = m_rings_vma_comps_map.find(ring_fd); if (itr == m_rings_vma_comps_map.end()) { vma_ring_comps *temp = NULL; temp = (struct vma_ring_comps *)MALLOC(sizeof(vma_ring_comps)); if (!temp) { log_err("Failed to allocate memory"); rc = SOCKPERF_ERR_NO_MEMORY; } memset(temp, 0, sizeof(vma_ring_comps)); temp->is_freed = true; temp->vma_comp_list_size = 0; std::pair ret = m_rings_vma_comps_map.insert(std::make_pair(ring_fd, temp)); if (!ret.second) { log_err("Failed to insert new ring."); rc = SOCKPERF_ERR_NO_MEMORY; } } printf("[%2d] IP = %-15s PORT = %5d # %s\n", list_count++, inet_ntoa(g_fds_array[ifd]->server_addr.sin_addr), ntohs(g_fds_array[ifd]->server_addr.sin_port), PRINT_PROTOCOL(g_fds_array[ifd]->sock_type)); for (int i = 0; i < g_fds_array[ifd]->memberships_size; i++) { printf("[%2d] IP = %-15s PORT = %5d # %s\n", list_count++, inet_ntoa(g_fds_array[ifd]->memberships_addr[i].sin_addr), ntohs(g_fds_array[ifd]->server_addr.sin_port), PRINT_PROTOCOL(g_fds_array[ifd]->sock_type)); } } } return rc; } #endif #endif sockperf-3.6/src/iohandlers.h000066400000000000000000000456411336630672200163100ustar00rootroot00000000000000/* * Copyright (c) 2011-2018 Mellanox Technologies Ltd. * 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. * 3. Neither the name of the Mellanox Technologies Ltd nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * 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. */ #ifndef IOHANDLERS_H_ #define IOHANDLERS_H_ #include "common.h" //============================================================================== class IoHandler { public: IoHandler(int _fd_min, int _fd_max, int _fd_num, int _look_start, int _look_end); virtual ~IoHandler(); inline int get_look_start() const { return m_look_start; } inline int get_look_end() const { return m_look_end; } virtual int prepareNetwork() = 0; void warmup(Message *pMsgRequest) const; const int m_fd_min, m_fd_max, m_fd_num; protected: int m_look_start; int m_look_end; // non const because of epoll }; //============================================================================== class IoRecvfrom : public IoHandler { public: IoRecvfrom(int _fd_min, int _fd_max, int _fd_num); virtual ~IoRecvfrom(); inline void update() {} inline int waitArrival() { return (m_fd_num); } inline int analyzeArrival(int ifd) const { assert(g_fds_array[ifd] && "invalid fd"); int active_fd_count = g_fds_array[ifd]->active_fd_count; int *active_fd_list = g_fds_array[ifd]->active_fd_list; assert(active_fd_list && "corrupted fds_data object"); return (active_fd_count ? active_fd_list[0] : ifd); } virtual int prepareNetwork(); }; //============================================================================== /* * limitations (due to no real iomux): * 1. client must open sockets and send packets in the same order as the server try to receive them *(client and server feed files must have the same order). * 2. no support for multiple clients (parallel/serial) for the same server (except for TCP serial *clients). * 3. no support for TCP listen socket to accept more than one connection (e.g. identical two lines *in feed file). * * In order to overcome this limitations we must know the state of each socket at every iteration *(like real iomux). * It can be done by loop of non-blocking recvfrom with MSG_PEEK over all sockets at each iteration *(similar to select internal implementation). * * NOTE: currently, IoRecvfromMUX can replace IoRecvfrom, but it is less efficient. */ class IoRecvfromMUX : public IoHandler { public: IoRecvfromMUX(int _fd_min, int _fd_max, int _fd_num); virtual ~IoRecvfromMUX(); inline void update() { m_fd_min_all = m_fd_min; m_fd_max_all = m_fd_max; for (int ifd = m_fd_min; ifd <= m_fd_max; ifd++) { if (g_fds_array[ifd]) { int i = 0; int active_fd_count = g_fds_array[ifd]->active_fd_count; int *active_fd_list = g_fds_array[ifd]->active_fd_list; assert(active_fd_list && "corrupted fds_data object"); while (active_fd_count) { /* process active sockets in case TCP (listen sockets are set in * prepareNetwork()) and * skip active socket in case UDP (it is the same with set in prepareNetwork()) */ if (active_fd_list[i] != (int)INVALID_SOCKET) { if (active_fd_list[i] != ifd) { m_fd_min_all = _min(m_fd_min_all, active_fd_list[i]); m_fd_max_all = _max(m_fd_max_all, active_fd_list[i]); /* it is possible to set the same socket */ errno = 0; } active_fd_count--; } i++; assert((i < MAX_ACTIVE_FD_NUM) && "maximum number of active connection to the single TCP addr:port"); } } } if (m_look_start > m_fd_max || m_look_start < m_fd_min) m_look_start = m_fd_max; else if (m_look_start == m_fd_max) m_look_start = m_fd_min_all - 1; } inline int waitArrival() { do { m_look_start++; if (m_look_start > m_fd_max_all) m_look_start = m_fd_min_all; } while (!g_fds_array[m_look_start] || g_fds_array[m_look_start]->active_fd_count); m_look_end = m_look_start + 1; return 1; } inline int analyzeArrival(int ifd) const { assert(g_fds_array[ifd] && "invalid fd"); int active_fd_count = g_fds_array[ifd]->active_fd_count; int *active_fd_list = g_fds_array[ifd]->active_fd_list; assert(active_fd_list && "corrupted fds_data object"); return (active_fd_count ? active_fd_list[0] : ifd); } virtual int prepareNetwork(); int m_fd_min_all, m_fd_max_all; }; //============================================================================== class IoSelect : public IoHandler { public: IoSelect(int _fd_min, int _fd_max, int _fd_num); virtual ~IoSelect(); //------------------------------------------------------------------------------ inline void update() { int ifd = 0; FD_ZERO(&m_save_fds); m_look_start = m_fd_min; m_look_end = m_fd_max; for (ifd = m_fd_min; ifd <= m_fd_max; ifd++) { if (g_fds_array[ifd]) { int i = 0; int active_fd_count = g_fds_array[ifd]->active_fd_count; int *active_fd_list = g_fds_array[ifd]->active_fd_list; FD_SET(ifd, &m_save_fds); assert(active_fd_list && "corrupted fds_data object"); while (active_fd_count) { /* process active sockets in case TCP (listen sockets are set in * prepareNetwork()) and * skip active socket in case UDP (it is the same with set in prepareNetwork()) */ if (active_fd_list[i] != (int)INVALID_SOCKET) { if (active_fd_list[i] != ifd) { FD_SET(active_fd_list[i], &m_save_fds); m_look_start = _min(m_look_start, active_fd_list[i]); m_look_end = _max(m_look_end, active_fd_list[i]); /* it is possible to set the same socket */ errno = 0; } active_fd_count--; } i++; assert((i < MAX_ACTIVE_FD_NUM) && "maximum number of active connection to the single TCP addr:port"); } } } m_look_end++; } //------------------------------------------------------------------------------ inline int waitArrival() { if (mp_timeout_timeval) { memcpy(mp_timeout_timeval, g_pApp->m_const_params.select_timeout, sizeof(struct timeval)); } memcpy(&m_readfds, &m_save_fds, sizeof(fd_set)); return select(m_look_end, &m_readfds, NULL, NULL, mp_timeout_timeval); } //------------------------------------------------------------------------------ inline int analyzeArrival(int ifd) const { return FD_ISSET(ifd, &m_readfds) ? ifd : 0; } virtual int prepareNetwork(); private: struct timeval m_timeout_timeval; struct timeval *const mp_timeout_timeval; fd_set m_readfds, m_save_fds; }; #ifndef WIN32 //============================================================================== class IoPoll : public IoHandler { public: IoPoll(int _fd_min, int _fd_max, int _fd_num); IoPoll(const IoPoll &); virtual ~IoPoll(); //------------------------------------------------------------------------------ inline void update() { int ifd = 0; m_look_start = 0; m_look_end = m_fd_num; for (ifd = m_fd_min; ifd <= m_fd_max; ifd++) { if (g_fds_array[ifd]) { int i = 0; int active_fd_count = g_fds_array[ifd]->active_fd_count; int *active_fd_list = g_fds_array[ifd]->active_fd_list; assert(active_fd_list && "corrupted fds_data object"); while (active_fd_count) { /* process active sockets in case TCP (listen sockets are set in * prepareNetwork()) and * skip active socket in case UDP (it is the same with set in prepareNetwork()) */ if (active_fd_list[i] != (int)INVALID_SOCKET) { if (active_fd_list[i] != ifd) { mp_poll_fd_arr[m_look_end].fd = active_fd_list[i]; mp_poll_fd_arr[m_look_end].events = POLLIN | POLLPRI; /* it is possible to set the same socket * EEXIST error appears in this case but it harmless condition */ errno = 0; m_look_end++; } active_fd_count--; } i++; assert((i < MAX_ACTIVE_FD_NUM) && "maximum number of active connection to the single TCP addr:port"); } } } } //------------------------------------------------------------------------------ inline int waitArrival() { return poll(mp_poll_fd_arr, m_look_end, m_timeout_msec); } //------------------------------------------------------------------------------ inline int analyzeArrival(int ifd) const { assert((ifd < MAX_FDS_NUM) && "exceeded tool limitation (MAX_FDS_NUM)"); if (mp_poll_fd_arr[ifd].revents & POLLIN || mp_poll_fd_arr[ifd].revents & POLLPRI || mp_poll_fd_arr[ifd].revents & POLLERR || mp_poll_fd_arr[ifd].revents & POLLHUP) { return mp_poll_fd_arr[ifd].fd; } else { return 0; } } virtual int prepareNetwork(); private: const int m_timeout_msec; struct pollfd *mp_poll_fd_arr; }; #ifndef __FreeBSD__ //============================================================================== class IoEpoll : public IoHandler { public: IoEpoll(int _fd_min, int _fd_max, int _fd_num); virtual ~IoEpoll(); //------------------------------------------------------------------------------ inline void update() { int ifd = 0; struct epoll_event ev = { 0, { 0 } }; m_look_start = 0; m_look_end = m_fd_num; m_max_events = m_fd_num; for (ifd = m_fd_min; ifd <= m_fd_max; ifd++) { if (g_fds_array[ifd]) { int i = 0; int active_fd_count = g_fds_array[ifd]->active_fd_count; int *active_fd_list = g_fds_array[ifd]->active_fd_list; assert(active_fd_list && "corrupted fds_data object"); while (active_fd_count) { /* process active sockets in case TCP (listen sockets are set in * prepareNetwork()) and * skip active socket in case UDP (it is the same with set in prepareNetwork()) */ if (active_fd_list[i] != (int)INVALID_SOCKET) { if (active_fd_list[i] != ifd) { ev.data.fd = active_fd_list[i]; ev.events = EPOLLIN | EPOLLPRI; epoll_ctl(m_epfd, EPOLL_CTL_ADD, ev.data.fd, &ev); /* it is possible to set the same socket * EEXIST error appears in this case but it harmless condition */ errno = 0; m_max_events++; } active_fd_count--; } i++; assert((i < MAX_ACTIVE_FD_NUM) && "maximum number of active connection to the single TCP addr:port"); assert(m_max_events < MAX_FDS_NUM); } } } /* It can be omitted */ m_look_end = m_max_events; } //------------------------------------------------------------------------------ inline int waitArrival() { m_look_end = epoll_wait(m_epfd, mp_epoll_events, m_max_events, m_timeout_msec); return m_look_end; } //------------------------------------------------------------------------------ inline int analyzeArrival(int ifd) const { assert((ifd < MAX_FDS_NUM) && "exceeded tool limitation (MAX_FDS_NUM)"); return mp_epoll_events[ifd].data.fd; } virtual int prepareNetwork(); private: const int m_timeout_msec; struct epoll_event *mp_epoll_events; int m_epfd; int m_max_events; }; #endif #ifdef USING_VMA_EXTRA_API //============================================================================== class IoSocketxtreme : public IoHandler { public: IoSocketxtreme(int _fd_min, int _fd_max, int _fd_num); virtual ~IoSocketxtreme(); //------------------------------------------------------------------------------ inline void update() { int ifd = 0; m_look_start = 0; m_look_end = m_fd_num; for (ifd = m_fd_min; ifd <= m_fd_max; ifd++) { if (g_fds_array[ifd]) { int i = 0; int active_fd_count = g_fds_array[ifd]->active_fd_count; int *active_fd_list = g_fds_array[ifd]->active_fd_list; assert(active_fd_list && "corrupted fds_data object"); while (active_fd_count) { /* process active sockets in case TCP (listen sockets are set in * prepareNetwork()) and * skip active socket in case UDP (it is the same with set in prepareNetwork()) */ if (active_fd_list[i] != (int)INVALID_SOCKET) { active_fd_count--; } i++; assert((i < MAX_ACTIVE_FD_NUM) && "maximum number of active connection to the single TCP addr:port"); } } } } //------------------------------------------------------------------------------ inline int waitArrival() { m_look_end = 0; for (m_rings_vma_comps_map_itr = m_rings_vma_comps_map.begin(); m_rings_vma_comps_map_itr != m_rings_vma_comps_map.end(); ++m_rings_vma_comps_map_itr) { int ring_fd = m_rings_vma_comps_map_itr->first; if (!m_rings_vma_comps_map_itr->second->is_freed) { for (int i = 0; i < m_rings_vma_comps_map_itr->second->vma_comp_list_size; i++) { if (m_rings_vma_comps_map_itr->second->vma_comp_list[i].events & VMA_SOCKETXTREME_PACKET) { g_vma_api->socketxtreme_free_vma_packets( &m_rings_vma_comps_map_itr->second->vma_comp_list[i].packet, 1); } } memset(m_rings_vma_comps_map_itr->second->vma_comp_list, 0, m_rings_vma_comps_map_itr->second->vma_comp_list_size * sizeof(vma_completion_t)); m_rings_vma_comps_map_itr->second->is_freed = true; m_rings_vma_comps_map_itr->second->vma_comp_list_size = 0; } m_rings_vma_comps_map_itr->second->vma_comp_list_size = g_vma_api->socketxtreme_poll( ring_fd, (vma_completion_t *)(&m_rings_vma_comps_map_itr->second->vma_comp_list), MAX_VMA_COMPS, 0); if (m_rings_vma_comps_map_itr->second->vma_comp_list_size > 0) { m_vma_comps_queue.push(ring_fd); m_rings_vma_comps_map_itr->second->is_freed = false; m_look_end += m_rings_vma_comps_map_itr->second->vma_comp_list_size; } } return m_look_end; } //------------------------------------------------------------------------------ inline int analyzeArrival(int ifd) { assert((ifd < MAX_FDS_NUM) && "exceeded tool limitation (MAX_FDS_NUM)"); int ring_fd = 0; g_vma_buff = NULL; if (!m_current_vma_ring_comp) { ring_fd = m_vma_comps_queue.front(); m_vma_comps_queue.pop(); m_rings_vma_comps_map_itr = m_rings_vma_comps_map.find(ring_fd); if (m_rings_vma_comps_map_itr != m_rings_vma_comps_map.end()) { m_current_vma_ring_comp = m_rings_vma_comps_map_itr->second; m_vma_comp_index = 0; } } g_vma_comps = (vma_completion_t *)&m_current_vma_ring_comp->vma_comp_list[m_vma_comp_index]; if (g_vma_comps->events & VMA_SOCKETXTREME_NEW_CONNECTION_ACCEPTED) { ifd = g_vma_comps->listen_fd; } else if (g_vma_comps->events & VMA_SOCKETXTREME_PACKET) { g_vma_buff = g_vma_comps->packet.buff_lst; ifd = g_vma_comps->user_data; } else { ifd = 0; } m_vma_comp_index++; if (m_vma_comp_index == m_current_vma_ring_comp->vma_comp_list_size) { m_vma_comp_index = 0; m_current_vma_ring_comp = NULL; } return ifd; } virtual int prepareNetwork(); private: int m_vma_comp_index; vma_ring_comps *m_current_vma_ring_comp; vma_comps_queue m_vma_comps_queue; rings_vma_comps_map m_rings_vma_comps_map; rings_vma_comps_map::iterator m_rings_vma_comps_map_itr; }; #endif #endif #endif /* IOHANDLERS_H_ */ sockperf-3.6/src/message.cpp000066400000000000000000000077721336630672200161420ustar00rootroot00000000000000/* * Copyright (c) 2011-2018 Mellanox Technologies Ltd. * 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. * 3. Neither the name of the Mellanox Technologies Ltd nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * 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. */ #include "message.h" #ifndef __FreeBSD__ #include #endif #include #include "common.h" // static memebers initialization /*static*/ uint64_t Message::ms_maxSequenceNo; /*static*/ int Message::ms_maxSize; //------------------------------------------------------------------------------ class MemException : public std::exception { public: MemException(const char *file, int line, const char *handler, size_t size) throw(); virtual ~MemException() throw() {} virtual const char *what() const throw() { return m_what.c_str(); } private: std::string m_what; }; //------------------ MemException::MemException(const char *file, int line, const char *handler, size_t size) throw() { const size_t LEN = 256; char buf[LEN + 1]; snprintf(buf, LEN, "%s:%d: %s failed allocating %d bytes", file, line, handler, (int)size); buf[LEN] = '\0'; m_what = buf; } //------------------------------------------------------------------------------ /*static*/ void Message::initMaxSize(int size) { if (size < 0) throw std::out_of_range("size < 0"); else if (ms_maxSize) throw std::logic_error("MaxSize is already initialized"); else ms_maxSize = size; } //------------------------------------------------------------------------------ /*static*/ void Message::initMaxSeqNo(uint64_t seqno) { if (ms_maxSequenceNo) throw std::logic_error("MaxSeqNo is already initialized"); else ms_maxSequenceNo = seqno; } //------------------------------------------------------------------------------ Message::Message() { if (!ms_maxSize) throw std::logic_error("MaxSize was NOT initialized"); if (ms_maxSize < MsgHeader::EFFECTIVE_SIZE) throw std::out_of_range("maxSize < MsgHeader::EFFECTIVE_SIZE"); m_buf = MALLOC(ms_maxSize + 7); // extra +7 for enabling 8 alignment of m_sequence_number if (!m_buf) { throw MemException(__FILE__, __LINE__, "malloc", ms_maxSize); } setBuf(); for (int len = 0; len < ms_maxSize; len++) m_addr[len] = (uint8_t)rand(); memset(m_header, 0, MsgHeader::EFFECTIVE_SIZE); /* log_msg("ms_maxSize=%d, m_buf=%p, alignment=%d, m_data=%p, m_header=%p", ms_maxSize, m_buf, alignment, m_data, m_header); log_msg("header adresses: m_sequence_number=%p", &m_header->m_sequence_number); //*/ } //------------------------------------------------------------------------------ Message::~Message() { if (m_buf) { FREE(m_buf); } } sockperf-3.6/src/message.h000066400000000000000000000160161336630672200155760ustar00rootroot00000000000000/* * Copyright (c) 2011-2018 Mellanox Technologies Ltd. * 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. * 3. Neither the name of the Mellanox Technologies Ltd nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * 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. */ #ifndef MESSAGE_H_ #define MESSAGE_H_ #include #include #include #include // for uint64_t #include "os_abstract.h" // Using pack() pragma set needed alignment #pragma pack(push, 2) class MsgHeader { friend class Message; public: MsgHeader(uint64_t _sequence_number = 0) : m_sequence_number(_sequence_number) {} ~MsgHeader() {} // uint32_t isClient() const {return m_isClient;} // void setClient() {m_isClient = 1;} // void setServer() {m_isClient = 0;} // uint32_t isPongRequest() const {return m_isPongRequest;} // void setPongRequest(bool on = true) {m_isPongRequest = on ? 1 : 0;} bool isClient() const { return (!!(m_flags_and_length.m_flags & MASK_CLIENT)); } void setClient() { m_flags_and_length.m_flags |= MASK_CLIENT; } void setServer() { m_flags_and_length.m_flags &= ~MASK_CLIENT; } bool isPongRequest() const { return (!!(m_flags_and_length.m_flags & MASK_PONG)); } void setPongRequest() { m_flags_and_length.m_flags |= MASK_PONG; } void resetPongRequest() { m_flags_and_length.m_flags &= ~MASK_PONG; } bool isWarmupMessage() const { return (!!(m_flags_and_length.m_flags & MASK_WARMUP_MSG)); } void setWarmupMessage() { m_flags_and_length.m_flags |= MASK_WARMUP_MSG; } void resetWarmupMessage() { m_flags_and_length.m_flags &= ~MASK_WARMUP_MSG; } void hton() { m_sequence_number = htonll(m_sequence_number); m_flags_and_length.m_flags = htons(m_flags_and_length.m_flags); m_flags_and_length.length = htonl(m_flags_and_length.length); } void ntoh() { m_sequence_number = ntohll(m_sequence_number); m_flags_and_length.m_flags = ntohs(m_flags_and_length.m_flags); m_flags_and_length.length = ntohl(m_flags_and_length.length); } // this is different than sizeof(MsgHeader) and safe only for the current implementation of the // class static const int EFFECTIVE_SIZE = (int)(sizeof(uint64_t) + sizeof(uint16_t) + sizeof(uint32_t)); // static const int EFFECTIVE_SIZE = 16; private: typedef struct { uint16_t m_flags; uint32_t length; } s_flags_and_length; // NOTE: m_sequence_number must be the 1st field, because we want EFFECTIVE_SIZE of header to be // 14 bytes // hence we need the padding (to 16 bytes) to be after last field and not between fields // pack() pragma can be added to set needed alignment uint64_t m_sequence_number; s_flags_and_length m_flags_and_length; static const uint32_t MASK_CLIENT = 1; static const uint32_t MASK_PONG = 2; static const uint32_t MASK_WARMUP_MSG = 4; /* uint32_t m_isClient:1; uint32_t m_isPongRequest:1; uint32_t m_reservedFlags:6; uint32_t m_reserved:24; */ }; #pragma pack(pop) class Message { public: Message(); ~Message(); static void initMaxSize(int size); static void initMaxSeqNo(uint64_t seqno); static size_t getMaxSize() { return ms_maxSize; } uint8_t *getBuf() const { return m_addr; } uint8_t *setBuf(uint8_t *addr = NULL) { /* set buffer as intrenal in case NULL is passed */ if (!addr) { int alignment = (8 - (long int)m_buf) % 8; addr = (uint8_t *)m_buf + alignment; // this will force m_sequence_number to be 8 // aligned even on 32 bit arch } m_addr = addr; m_header = (MsgHeader *)m_addr; m_data = (uint8_t *)m_header + MsgHeader::EFFECTIVE_SIZE; if ((void *)m_addr != (void *)m_header) throw std::logic_error("address error"); return m_addr; } const MsgHeader *getHeader() const { return m_header; } MsgHeader *getHeader() { return m_header; } uint8_t *getData() const { return m_data; } uint16_t isClient() const { return m_header->isClient(); } void setClient() { m_header->setClient(); } void setServer() { m_header->setServer(); } uint16_t isPongRequest() const { return m_header->isPongRequest(); } uint64_t getSequenceCounter() const { assert((m_header->m_sequence_number <= ms_maxSequenceNo) && "exceeded message number limitation"); return m_header->m_sequence_number; } void setSequenceCounter(uint64_t _sequence) { assert((_sequence <= ms_maxSequenceNo) && "exceeded message number limitation"); m_header->m_sequence_number = _sequence; } void incSequenceCounter() { m_header->m_sequence_number++; } void decSequenceCounter() { m_header->m_sequence_number--; } uint16_t isWarmupMessage() const { return m_header->isWarmupMessage(); } void setWarmupMessage() { m_header->setWarmupMessage(); } void resetWarmupMessage() { m_header->resetWarmupMessage(); } void setHeaderToHost() { m_header->ntoh(); } void setHeaderToNetwork() { m_header->hton(); } uint16_t getFlags() const { return (m_header->m_flags_and_length.m_flags); } int getLength() const { // extract msg length from m_length and m_flags. return m_header->m_flags_and_length.length; } void setLength(uint32_t _length) { m_header->m_flags_and_length.length = _length; } private: void *m_buf; uint8_t *m_addr; // points to 1st 8 aligned adrs inside m_buf MsgHeader *m_header; // points to header uint8_t *m_data; // points to data static uint64_t ms_maxSequenceNo; // maximum expected sequence number static int ms_maxSize; // use int (instead of size_t to save casting to 'int' in recvfrom) }; #endif /* MESSAGE_H_ */ sockperf-3.6/src/os_abstract.cpp000066400000000000000000000233621336630672200170130ustar00rootroot00000000000000/* * Copyright (c) 2011-2018 Mellanox Technologies Ltd. * 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. * 3. Neither the name of the Mellanox Technologies Ltd nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * 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. */ #include "os_abstract.h" #include #include void os_printf_backtrace(void) { #ifdef WIN32 unsigned int i; void *stack[100]; unsigned short frames; SYMBOL_INFO *symbol; HANDLE process; process = GetCurrentProcess(); SymInitialize(process, NULL, TRUE); frames = CaptureStackBackTrace(0, 100, stack, NULL); symbol = (SYMBOL_INFO *)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1); symbol->MaxNameLen = 255; symbol->SizeOfStruct = sizeof(SYMBOL_INFO); for (i = 0; i < frames; i++) { SymFromAddr(process, (DWORD64)(stack[i]), 0, symbol); printf("%i: %s - 0x%0X\n", frames - i - 1, symbol->Name, symbol->Address); } free(symbol); #else char **strings; void *m_backtrace[25]; int m_backtrace_size = backtrace(m_backtrace, 25); printf("sockperf: [tid: %lu] ------\n", (unsigned long)os_getthread().tid); strings = backtrace_symbols(m_backtrace, m_backtrace_size); for (int i = 0; i < m_backtrace_size; i++) printf("sockperf: [%i] %p: %s\n", i, m_backtrace[i], strings[i]); free(strings); #endif } // Thread functions void os_thread_init(os_thread_t *thr) { #ifdef WIN32 thr->hThread = NULL; thr->tid = 0; #else thr->tid = 0; #endif } void os_thread_close(os_thread_t *thr) { #ifdef WIN32 if (thr->hThread) CloseHandle(thr->hThread); #endif } void os_thread_detach(os_thread_t *thr) { #ifndef WIN32 pthread_detach(thr->tid); #endif } int os_thread_exec(os_thread_t *thr, void *(*start)(void *), void *arg) { #ifdef WIN32 if (thr->hThread) CloseHandle(thr->hThread); thr->hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)start, arg, 0, &thr->tid); if (thr->hThread == INVALID_HANDLE_VALUE) { return -1; } return 0; #else pthread_attr_t atts; pthread_attr_init(&atts); #ifdef HAVE_PTHREAD_ATTR_SETSCOPE pthread_attr_setscope(&atts, PTHREAD_SCOPE_SYSTEM); #endif #ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE pthread_attr_setstacksize(&atts, 256 * 1024); #endif return pthread_create(&thr->tid, &atts, start, arg); #endif } void os_thread_kill(os_thread_t *thr) { #ifdef WIN32 DWORD exit_code; if (GetExitCodeThread(thr, &exit_code)) TerminateThread(thr, exit_code); // kill thread #else pthread_kill(thr->tid, SIGINT); #endif } void os_thread_join(os_thread_t *thr) { #ifdef WIN32 WaitForSingleObject(thr, INFINITE); #else pthread_join(thr->tid, 0); #endif } os_thread_t os_getthread(void) { os_thread_t mythread; #ifdef WIN32 mythread.tid = GetCurrentThreadId(); mythread.hThread = GetCurrentThread(); #elif __FreeBSD__ mythread.tid = pthread_self(); #else mythread.tid = syscall(__NR_gettid); #endif return mythread; } // Mutex functions void os_mutex_init(os_mutex_t *lock) { #ifdef WIN32 lock->mutex = CreateMutex(NULL, FALSE, NULL); #else pthread_mutex_init(&lock->mutex, NULL); #endif } void os_mutex_close(os_mutex_t *lock) { #ifdef WIN32 CloseHandle(lock->mutex); #else pthread_mutex_destroy(&lock->mutex); #endif } void os_mutex_lock(os_mutex_t *lock) { #ifdef WIN32 WaitForSingleObject(lock->mutex, INFINITE); #else pthread_mutex_lock(&lock->mutex); #endif } void os_mutex_unlock(os_mutex_t *lock) { #ifdef WIN32 ReleaseMutex(lock->mutex); #else pthread_mutex_unlock(&lock->mutex); #endif } int os_set_nonblocking_socket(int fd) { #ifdef WIN32 int iResult; u_long iMode = 1; // = Non-blocking iResult = ioctlsocket(fd, FIONBIO, &iMode); if (iResult != NO_ERROR) { printf("ERROR: ioctlsocket failed with error: %ld\n", iResult); return -1; } return 0; #else int flags, ret; flags = fcntl(fd, F_GETFL); if (flags < 0) { printf("ERROR: fcntl(F_GETFL)\n"); return -1; } flags |= O_NONBLOCK; ret = fcntl(fd, F_SETFL, flags); if (ret < 0) { printf("ERROR: fcntl(F_SETFL)\n"); return -1; } return 0; #endif } void os_set_signal_action(int signum, sig_handler handler) { #ifdef WIN32 // Meny: No SIGALRM on Windows, A different thread handles test duration timer. signal(signum, handler); #else static struct sigaction sigact; // Avner: is 'static' needed? sigact.sa_handler = handler; sigemptyset(&sigact.sa_mask); sigact.sa_flags = 0; sigaction(signum, &sigact, NULL); #endif } int os_daemonize() { #ifdef WIN32 printf("ERROR: daemonize is not supported!\n"); return -1; #else if (daemon(1, 1)) { return -1; } else { return 0; } #endif } #ifdef WIN32 struct TimeHandler { itimerval myTimer; sig_handler *handler; TimeHandler(itimerval _Timer, sig_handler _handler) { this->myTimer = _Timer; this->handler = _handler; } }; #endif int os_set_duration_timer(const itimerval &timer, sig_handler handler) { int ret; #ifdef WIN32 // Creating a new thread to handle timer logic os_thread_t timer_thread; os_thread_init(&timer_thread); TimeHandler *pTimeHandler = new TimeHandler(timer, handler); ret = os_thread_exec(&timer_thread, win_set_timer, (void *)pTimeHandler); if (ret) { printf("ERROR: win_set_timer() failed\n"); return -1; } #else os_set_signal_action(SIGALRM, handler); ret = setitimer(ITIMER_REAL, &timer, NULL); if (ret) { printf("ERROR: setitimer() failed\n"); return -1; } #endif return 0; } #ifdef WIN32 // Meny: This function contains test duration timer logic void *win_set_timer(void *_pTimeHandler) { TimeHandler *pTimeHandler = (TimeHandler *)_pTimeHandler; itimerval timer = pTimeHandler->myTimer; HANDLE hTimer = CreateWaitableTimer(NULL, FALSE, NULL); if (!hTimer) printf("ERROR: Create timer failed\n"); LARGE_INTEGER liDueTime; // Create an integer that will be used to signal the timer __int64 qwDueTime = -(((timer.it_value.tv_sec) * _SECOND) + (timer.it_value.tv_usec) * 10); // Copy the relative time into a LARGE_INTEGER. liDueTime.LowPart = (DWORD)(qwDueTime & 0xFFFFFFFF); liDueTime.HighPart = (LONG)(qwDueTime >> 32); int bSuccess = SetWaitableTimer(hTimer, // Handle to the timer object &liDueTime, // When timer will become signaled 0, // Periodic timer 0, // Completion routine NULL, // Argument to the completion routine FALSE); // Do not restore a suspended system if (WaitForSingleObject(hTimer, INFINITE) != WAIT_OBJECT_0) printf("WaitForSingleObject failed (%d)\n", GetLastError()); pTimeHandler->handler(SIGALRM); CloseHandle(hTimer); return 0; } #endif bool os_sock_startup() { #ifdef WIN32 WSADATA wsaData; if (WSAStartup(0x202, &wsaData) != 0) { return false; } return true; #else return true; #endif } bool os_sock_cleanup() { #ifdef WIN32 if (WSACleanup() != 0) { return false; } return true; #else return true; #endif } void os_init_cpuset(os_cpuset_t *_mycpuset) { #ifdef WIN32 _mycpuset->cpuset = 0; #else CPU_ZERO(&_mycpuset->cpuset); #endif } void os_cpu_set(os_cpuset_t *_mycpuset, long _cpu_from, long _cpu_cur) { while ((_cpu_from <= _cpu_cur)) { #ifdef WIN32 _mycpuset->cpuset = (int)(1 << _cpu_from); #else CPU_SET(_cpu_from, &(_mycpuset->cpuset)); #endif _cpu_from++; } } int os_set_affinity(const os_thread_t &thread, const os_cpuset_t &_mycpuset) { #ifdef WIN32 if (0 == SetThreadAffinityMask(thread.hThread, _mycpuset.cpuset)) return -1; #else // Can't use thread.tid since it's syscall and not pthread_t if (0 != pthread_setaffinity_np(pthread_self(), sizeof(os_cpuset_t), &(_mycpuset.cpuset))) return -1; #endif return 0; } int os_get_max_active_fds_num() { #ifdef WIN32 return MAX_OPEN_FILES; #else static int max_active_fd_num = 0; if (!max_active_fd_num) { struct rlimit curr_limits; if (getrlimit(RLIMIT_NOFILE, &curr_limits) == -1) { perror("getrlimit"); return 1024; // try the common default } max_active_fd_num = (int)curr_limits.rlim_max; } return max_active_fd_num; #endif } sockperf-3.6/src/os_abstract.h000066400000000000000000000204761336630672200164630ustar00rootroot00000000000000/* * Copyright (c) 2011-2018 Mellanox Technologies Ltd. * 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. * 3. Neither the name of the Mellanox Technologies Ltd nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * 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. */ /** * @file os_abstract.h * * @details: OS abstract file compatible for both Linux and Windows. * * @author Meny Yossefi * reviewed by Avner Ben Hanoch * **/ #ifndef _OS_ABSTRACT_H_ #define _OS_ABSTRACT_H_ #include /* clock_gettime()*/ #include /* sockets*/ #include "ticks_os.h" /*********************************************************************************** * WIN32 ***********************************************************************************/ #ifdef WIN32 #include // backtrace #include #include #ifdef _M_IX86 #define PRIu64 "llu" #define PRId64 "lld" #elif defined _M_X64 #define PRIu64 "lu" #define PRId64 "ld" #endif #define sleep(x) Sleep(x * 1000) #define close(x) CloseHandle(&x) #define IP_MAX_MEMBERSHIPS 20 // ported from Linux #define MAX_OPEN_FILES 65535 #define _SECOND 10000000 // timer (SetWaitableTimer) #define SIGALRM 999 #define __CPU_SETSIZE 1024 // ported from Linux #define __NCPUBITS (8 * sizeof(__cpu_mask)) // ported from Linux #define CPU_SETSIZE __CPU_SETSIZE #define __func__ __FUNCTION__ // Socket api #define inet_aton(x, y) inet_pton(AF_INET, x, y) #define getsockopt(a, b, c, d, e) getsockopt(a, b, c, (char *)d, e) #define setsockopt(a, b, c, d, e) setsockopt(a, b, c, (char *)d, e) #define recvfrom(a, b, c, d, e, f) recvfrom(a, (char *)b, c, d, e, f) #define sendto(a, b, c, d, e, f) sendto(a, (char *)b, c, d, e, f) /* Type of the second argument to `getitimer' and the second and third arguments `setitimer'. */ struct itimerval { /* Value to put into `it_value' when the timer expires. */ struct timeval it_interval; /* Time to the next timer expiration. */ struct timeval it_value; }; void *win_set_timer(void *p_timer); #else /*********************************************************************************** * UNIX ***********************************************************************************/ #include // for backtraces #include #include #include #include #include #include #include #include #define INVALID_SOCKET (-1) /*********************************************************************************** * FreeBSD ***********************************************************************************/ #ifdef __FreeBSD__ #include #include #include #define htonll htonl #define ntohll ntohl /*********************************************************************************** * Linux ***********************************************************************************/ #else #include #include #include #ifndef htobe64 #ifdef __USE_BSD /* Conversion interfaces. */ #include #if __BYTE_ORDER == __LITTLE_ENDIAN #define htobe64(x) __bswap_64(x) #define be64toh(x) __bswap_64(x) #else #define htobe64(x) (x) #define be64toh(x) (x) #endif #endif #endif #ifndef htonll #define htonll htobe64 #endif #ifndef ntohll #define ntohll be64toh #endif #endif #endif /*********************************************************************************** * Common ***********************************************************************************/ typedef struct os_thread_t { #ifdef WIN32 HANDLE hThread; DWORD tid; #else pthread_t tid; #endif } os_thread_t; typedef struct os_mutex_t { #ifndef WIN32 pthread_mutex_t mutex; #else HANDLE mutex; #endif } os_mutex_t; typedef struct os_cpuset_t { #ifdef WIN32 DWORD_PTR cpuset; #elif __FreeBSD__ cpuset_t cpuset; #else cpu_set_t cpuset; #endif } os_cpuset_t; typedef void sig_handler(int signum); void os_set_signal_action(int signum, sig_handler handler); void os_printf_backtrace(void); int os_set_nonblocking_socket(int fd); int os_daemonize(); int os_set_duration_timer(const itimerval &timer, sig_handler handler); int os_get_max_active_fds_num(); bool os_sock_startup(); bool os_sock_cleanup(); // Colors #ifdef WIN32 #define MAGNETA "" #define RED "" #define ENDCOLOR "" #else #define MAGNETA "\e[2;35m" #define RED "\e[0;31m" #define ENDCOLOR "\e[0m" #endif // Thread functions void os_thread_init(os_thread_t *thr); void os_thread_close(os_thread_t *thr); void os_thread_detach(os_thread_t *thr); int os_thread_exec(os_thread_t *thr, void *(*start)(void *), void *arg); void os_thread_kill(os_thread_t *thr); void os_thread_join(os_thread_t *thr); os_thread_t os_getthread(void); // Mutex functions void os_mutex_init(os_mutex_t *lock); void os_mutex_close(os_mutex_t *lock); void os_mutex_lock(os_mutex_t *lock); void os_mutex_unlock(os_mutex_t *lock); // CPUset functions void os_init_cpuset(os_cpuset_t *_mycpuset); void os_cpu_set(os_cpuset_t *_mycpuset, long _cpu_from, long _cpu_cur); int os_set_affinity(const os_thread_t &thread, const os_cpuset_t &_mycpuset); // ERRORS inline bool os_err_in_progress() { #ifdef WIN32 // In Windows it's WSAEINPROGRESS for blocking sockets and WSAEWOULDBLOCK for non-vlocking // sockets return (WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAEINPROGRESS); #else return (errno == EINPROGRESS); #endif } inline bool os_err_eagain() { #ifdef WIN32 return (WSAGetLastError() == WSAEWOULDBLOCK); #else return (errno == EAGAIN); #endif } inline bool os_err_conn_reset() { #ifdef WIN32 return (WSAGetLastError() == WSAECONNRESET); #else return (errno == ECONNRESET); #endif } #ifdef WIN32 #define _max(x, y) max(x, y) #define _min(x, y) min(x, y) #else #define _max(x, y) \ ({ \ typeof(x) _x = (x); \ typeof(y) _y = (y); \ (void)(&_x == &_y); \ _x > _y ? _x : _y; \ }) #define _min(x, y) \ ({ \ typeof(x) _x = (x); \ typeof(y) _y = (y); \ (void)(&_x == &_y); \ _x < _y ? _x : _y; \ }) #endif #endif /*_OS_ABSTRACT_H_*/ sockperf-3.6/src/packet.cpp000066400000000000000000000052251336630672200157540ustar00rootroot00000000000000/* * Copyright (c) 2011-2018 Mellanox Technologies Ltd. * 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. * 3. Neither the name of the Mellanox Technologies Ltd nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * 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. */ #include #include "defs.h" #include "packet.h" #include "common.h" PacketTimes::PacketTimes(uint64_t _maxSequenceNo, uint64_t _replyEvery, uint64_t _numServers) : m_maxSequenceNo(_maxSequenceNo), m_replyEvery(_replyEvery), m_blockSize(1 + _numServers) // 1 sent + N replies , m_pTimes(new TicksTime[(_maxSequenceNo / _replyEvery + 1) * m_blockSize]) //_maxSequenceNo/_replyEvery+1 is _numBlocks rounded up , m_pInternalUse(&m_pTimes[1]), m_pErrors(new ArrivalErrors[_numServers]) { /* log_msg("m_maxSequenceNo=%lu, m_replyEvery=%lu, m_blockSize=%lu, m_pTimes=%p[%lu], m_pInternalUse=%p, m_pErrors=%p[%lu]" , m_maxSequenceNo, m_replyEvery, m_blockSize, m_pTimes , (_maxSequenceNo / _replyEvery + 1) * m_blockSize , m_pInternalUse , m_pErrors, _numServers ); //*/ } PacketTimes::~PacketTimes() { delete[] m_pTimes; delete[] m_pErrors; } bool PacketTimes::verifyError(uint64_t _seqNo) { exit_with_err("_seqN > m_maxSequenceNo", SOCKPERF_ERR_FATAL); return false; } sockperf-3.6/src/packet.h000066400000000000000000000116421336630672200154210ustar00rootroot00000000000000/* * Copyright (c) 2011-2018 Mellanox Technologies Ltd. * 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. * 3. Neither the name of the Mellanox Technologies Ltd nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * 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. */ #ifndef PACKETTIMES_H_ #define PACKETTIMES_H_ #include // for uint64_t #include "ticks.h" #include #include "common.h" class PacketTimes { public: PacketTimes(uint64_t _maxSequenceNo, uint64_t _replyEvery, uint64_t _numServers); ~PacketTimes(); bool verifyError(uint64_t _seqNo); uint64_t seq2index(uint64_t _seqNo) { return ((_seqNo <= m_maxSequenceNo) ? _seqNo / m_replyEvery * m_blockSize : verifyError(_seqNo)); } // index 0 is not used for real packets const TicksTime &getTxTime(uint64_t _seqNo) { return m_pTimes[seq2index(_seqNo)]; } const TicksTime *getRxTimeArray(uint64_t _seqNo) { return &m_pInternalUse[seq2index(_seqNo)]; } void clearTxTime(uint64_t _seqNo) { m_pTimes[seq2index(_seqNo)] = TicksTime::TICKS0; } void setTxTime(uint64_t _seqNo) { m_pTimes[seq2index(_seqNo)].setNow(); // log_msg(">>> %lu: tx=%.3lf", _seqNo, // (double)m_pTimes[seq2index(_seqNo)].debugToNsec()/1000/1000 );//TODO: remove } void setRxTime(uint64_t _seqNo, uint64_t _serverNo = 0) { setRxTime(_seqNo, TicksTime().setNow(), _serverNo); } void setRxTime(uint64_t _seqNo, const TicksTime &_time, uint64_t _serverNo = 0) { TicksTime *rxTimes = &m_pInternalUse[seq2index(_seqNo)]; if (rxTimes[_serverNo] == TicksTime::TICKS0) { rxTimes[_serverNo] = _time; ++g_receiveCount; // log_msg("<<< %lu: rx=%.3lf", _seqNo, (double)_time.debugToNsec()/1000/1000 );//TODO: // remove } else if (!g_b_exit) { incDupCount(_serverNo); /*log_err("dup-packket at _seqNo=%lu", _seqNo);*/ } } void incDupCount(uint64_t serverNo) { m_pErrors[serverNo].duplicates++; } void incOooCount(uint64_t serverNo) { m_pErrors[serverNo].ooo++; } void incDroppedCount(uint64_t serverNo) { m_pErrors[serverNo].dropped++; } size_t getDupCount(uint64_t serverNo) { return m_pErrors[serverNo].duplicates; } size_t getOooCount(uint64_t serverNo) { return m_pErrors[serverNo].ooo; } size_t getDroppedCount(uint64_t serverNo) { return m_pErrors[serverNo].dropped; } const uint64_t m_maxSequenceNo; const uint64_t m_replyEvery; const uint64_t m_blockSize; private: TicksTime *const m_pTimes; TicksTime *const m_pInternalUse; // prevent creation by compiler PacketTimes(const PacketTimes &); PacketTimes &operator=(const PacketTimes &); struct ArrivalErrors { size_t duplicates; size_t ooo; // out-of-order size_t dropped; ArrivalErrors() : duplicates(0), ooo(0), dropped(0) {} }; ArrivalErrors *const m_pErrors; // array with one line per server /* //------------------------------------------------------------------------------ void dumpFullLog(FILE * f) { if (!f) return; fprintf(f, "------------------------------\n"); const uint64_t NUM_SERVERS = m_blockSize -1; fprintf(f, "txTime"); for (uint64_t i = 0; i < NUM_SERVERS; i++) fprintf(f, ", rxTime%d", i); fprintf(f, "\n"); // for (uint64_t i = 0; i < m_maxSequenceNo; i++) { printf("%.9lf", debugToNsec()) double tx = (double)pFullLog[i][0].debugToNsec()/1000/1000/1000; double rx = (double)pFullLog[i][1].debugToNsec()/1000/1000/1000; fprintf(f, "%.9lf, %.9lf\n", tx, rx); } fprintf(f, "------------------------------\n"); } */ }; #endif /* PACKETTIMES_H_ */ sockperf-3.6/src/playback.cpp000066400000000000000000000101121336630672200162620ustar00rootroot00000000000000/* * Copyright (c) 2011-2018 Mellanox Technologies Ltd. * 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. * 3. Neither the name of the Mellanox Technologies Ltd nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * 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. */ #include #include #include #include #include "defs.h" #include "playback.h" #include "ticks.h" // How to build unit test: g++ Playback.cpp Ticks.cpp -lrt -Wall -Dplayback_test=main -o playback using std::cout; typedef std::vector StringVector; void readFile(StringVector &sv, const char *filename) { std::string line; std::ifstream infile(filename, std::ios_base::in); if (infile.fail()) { log_msg("Can't open file: %s\n", filename); exit(SOCKPERF_ERR_NOT_EXIST); } int i = 0; while (infile.good() && getline(infile, line)) { sv.push_back(line); i++; } if (!infile.eof()) { log_msg("file: %s, error in line: #%d\n", filename, i + 1); exit(SOCKPERF_ERR_INCORRECT); } } void parsePlaybackData(PlaybackVector &pv, StringVector &sv) { PlaybackItem pi; double curr_time, prev_time = 0; TicksDuration duration; for (size_t i = 0; i < sv.size(); i++) { std::string s = sv[i]; if (!s.empty() && s[0] != '#') { // printf("[%lu]: %s\n", i+1, s.c_str()); if (2 == sscanf(s.c_str(), "%lf, %d", &curr_time, &pi.size)) { if (prev_time > curr_time) { printf("out-of-order timestamp at line #%lu\n", (long unsigned)i + 1); exit(SOCKPERF_ERR_INCORRECT); } pi.duration.setFromSeconds(curr_time - prev_time); if (!pi.isValid()) { printf("illegal time or size at line #%lu\n", (long unsigned)i + 1); exit(SOCKPERF_ERR_INCORRECT); } pv.push_back(pi); prev_time = curr_time; } else { cout << "can't read time & size, at line #" << i + 1 << '\n'; exit(1); } } } // printf("pv.size()=%d\n", (int)pv.size()); } void loadPlaybackData(PlaybackVector &pv, const char *filename) { StringVector sv; readFile(sv, filename); parsePlaybackData(pv, sv); sv.clear(); } void doPlayback(PlaybackVector &pv) { size_t size = pv.size(); for (size_t i = 0; i < size; i++) printf("item #%lu: duration=%" PRId64 ", size=%d\n", (long unsigned)i, pv[i].duration.toNsec(), pv[i].size); } // unit test int playback_test(int argc, char *argv[]) { if (argc < 2) { cout << argv[0] << ": Need a filename for a parameter.\n"; exit(1); } PlaybackVector pv; loadPlaybackData(pv, argv[1]); doPlayback(pv); return 0; } sockperf-3.6/src/playback.h000066400000000000000000000036601336630672200157410ustar00rootroot00000000000000/* * Copyright (c) 2011-2018 Mellanox Technologies Ltd. * 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. * 3. Neither the name of the Mellanox Technologies Ltd nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * 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. */ #ifndef PLAYBACK_H_ #define PLAYBACK_H_ #include #include "ticks.h" struct PlaybackItem { TicksDuration duration; int size; bool isValid() { return duration > TicksDuration::TICKS0 && size >= 14 && size <= 64000; } }; typedef std::vector PlaybackVector; // main interface to the module void loadPlaybackData(PlaybackVector &pv, const char *filename); #endif /* PLAYBACK_H__ */ sockperf-3.6/src/server.cpp000066400000000000000000000660351336630672200160210ustar00rootroot00000000000000/* * Copyright (c) 2011-2018 Mellanox Technologies Ltd. * 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. * 3. Neither the name of the Mellanox Technologies Ltd nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * 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. */ #include "server.h" #include "iohandlers.h" #include "switches.h" // static members initialization /*static*/ seq_num_map SwitchOnCalcGaps::ms_seq_num_map; static CRITICAL_SECTION thread_exit_lock; static os_thread_t *thread_pid_array = NULL; //============================================================================== //------------------------------------------------------------------------------ ServerBase::ServerBase(IoHandler &_ioHandler) : m_ioHandlerRef(_ioHandler) { m_pMsgReply = new Message(); m_pMsgReply->setLength(MAX_PAYLOAD_SIZE); m_pMsgRequest = new Message(); m_pMsgRequest->getHeader()->setServer(); m_pMsgRequest->setLength(g_pApp->m_const_params.msg_size); } //------------------------------------------------------------------------------ ServerBase::~ServerBase() { delete m_pMsgReply; delete m_pMsgRequest; } //------------------------------------------------------------------------------ int ServerBase::initBeforeLoop() { int rc = SOCKPERF_ERR_NONE; rc = set_affinity_list(os_getthread(), g_pApp->m_const_params.threads_affinity); if (g_b_exit) return rc; /* bind socket */ if (rc == SOCKPERF_ERR_NONE) { log_dbg("thread %lu: fd_min: %d, fd_max : %d, fd_num: %d", (unsigned long)os_getthread().tid, m_ioHandlerRef.m_fd_min, m_ioHandlerRef.m_fd_max, m_ioHandlerRef.m_fd_num); // cycle through all set fds in the array (with wrap around to beginning) for (int ifd = m_ioHandlerRef.m_fd_min; ifd <= m_ioHandlerRef.m_fd_max; ifd++) { if (!(g_fds_array[ifd] && (g_fds_array[ifd]->active_fd_list))) continue; #ifdef USING_VMA_EXTRA_API g_fds_array[ifd]->p_msg = m_pMsgReply; #endif struct sockaddr_in *p_bind_addr = &g_fds_array[ifd]->server_addr; struct sockaddr_in bind_addr; // Meny: Can't bind to a multicast addr in Windows if (g_fds_array[ifd]->memberships_size || IN_MULTICAST(ntohl(p_bind_addr->sin_addr.s_addr))) { // if more then one address on socket (for multiple MC join case oon same port) memcpy(&bind_addr, p_bind_addr, sizeof(struct sockaddr_in)); bind_addr.sin_addr.s_addr = INADDR_ANY; p_bind_addr = &bind_addr; } log_dbg("[fd=%d] Binding to: %s:%d...", ifd, inet_ntoa(p_bind_addr->sin_addr), ntohs(p_bind_addr->sin_port)); if (bind(ifd, (struct sockaddr *)p_bind_addr, sizeof(struct sockaddr)) < 0) { log_err("[fd=%d] Can`t bind socket, IP to bind: %s:%d\n", ifd, inet_ntoa(p_bind_addr->sin_addr), ntohs(p_bind_addr->sin_port)); rc = SOCKPERF_ERR_SOCKET; break; } /* * since when using VMA there is no qp until the bind, and vma cannot * check that rate-limit is supported this is done here and not * with the rest of the setsockopt */ if (s_user_params.rate_limit > 0 && sock_set_rate_limit(ifd, s_user_params.rate_limit)) { log_err("[fd=%d] failed setting rate limit, %s\n", ifd, inet_ntoa(p_bind_addr->sin_addr)); rc = SOCKPERF_ERR_SOCKET; break; } if ((g_fds_array[ifd]->sock_type == SOCK_STREAM) && (listen(ifd, 10) < 0)) { log_err("Failed listen() for connection\n"); rc = SOCKPERF_ERR_SOCKET; break; } } } if (g_b_exit) return rc; if (rc == SOCKPERF_ERR_NONE) { if (g_pApp->m_const_params.mode == MODE_BRIDGE) { char to_array[20]; sprintf(to_array, "%s", inet_ntoa(g_pApp->m_const_params.tx_mc_if_addr)); printf(MODULE_NAME ": [BRIDGE] transferring messages from %s to %s on:", inet_ntoa(g_pApp->m_const_params.rx_mc_if_addr), to_array); } else { printf(MODULE_NAME ": [SERVER] listen on:"); } rc = m_ioHandlerRef.prepareNetwork(); if (rc == SOCKPERF_ERR_NONE) { sleep(g_pApp->m_const_params.pre_warmup_wait); m_ioHandlerRef.warmup(m_pMsgRequest); log_msg("[tid %lu] using %s() to block on socket(s)", (unsigned long)os_getthread().tid, handler2str(g_pApp->m_const_params.fd_handler_type)); } } return rc; } //------------------------------------------------------------------------------ void ServerBase::cleanupAfterLoop() { // cleanup log_dbg("thread %lu released allocations", (unsigned long)os_getthread().tid); if (!g_pApp->m_const_params.mthread_server) { log_msg("%s() exit", __func__); } } //============================================================================== //============================================================================== //------------------------------------------------------------------------------ template Server::Server(int _fd_min, int _fd_max, int _fd_num) : ServerBase(m_ioHandler), m_ioHandler(_fd_min, _fd_max, _fd_num) {} //------------------------------------------------------------------------------ template Server::~Server() {} //------------------------------------------------------------------------------ template void Server::doLoop() { int numReady = 0; int actual_fd = 0; while (!g_b_exit) { // wait for arrival numReady = m_ioHandler.waitArrival(); // check errors if (g_b_exit) continue; if (numReady < 0) { log_err("%s()", handler2str(g_pApp->m_const_params.fd_handler_type)); exit_with_log(SOCKPERF_ERR_FATAL); } if (numReady == 0) { if (!g_pApp->m_const_params.select_timeout) log_msg("Error: %s() returned without fd ready", handler2str(g_pApp->m_const_params.fd_handler_type)); continue; } // handle arrival and response int accept_fd = (int)INVALID_SOCKET; // TODO: use SOCKET all over the way and avoid this cast bool do_update = false; for (int ifd = m_ioHandler.get_look_start(); (numReady) && (ifd < m_ioHandler.get_look_end()); ifd++) { actual_fd = m_ioHandler.analyzeArrival(ifd); if (actual_fd) { assert(g_fds_array[actual_fd] && "invalid fd"); if (!g_fds_array[actual_fd]) { print_log("fd received was larger than expected, ignored.", actual_fd); /* do nothing invalid fd*/ } else { accept_fd = server_accept(actual_fd); if (accept_fd == actual_fd) { int m_recived = g_pApp->m_const_params.max_looping_over_recv; while ((0 != m_recived) && (!g_b_exit)) { if (m_recived > 0) { m_recived--; } if (server_receive_then_send(actual_fd)) { do_update = true; } else if (os_err_eagain()) { break; } } } else if (accept_fd != (int)INVALID_SOCKET) { // TODO: use SOCKET all over the // way and avoid this cast do_update = true; } else { /* do nothing */ } } numReady--; } } /* do update of active fd in case accept/close was occured */ if (do_update) { m_ioHandler.update(); } assert(!numReady && "all waiting descriptors should have been processed"); } } //------------------------------------------------------------------------------ template int Server::server_accept(int ifd) { bool do_accept = false; int active_ifd = ifd; if (!g_fds_array[ifd]) { return (int)INVALID_SOCKET; // TODO: use SOCKET all over the way and avoid this cast } if (g_fds_array[ifd]->sock_type == SOCK_STREAM && g_fds_array[ifd]->active_fd_list) { struct sockaddr_in addr; socklen_t addr_size = sizeof(addr); fds_data *tmp; tmp = (struct fds_data *)MALLOC(sizeof(struct fds_data)); if (!tmp) { log_err("Failed to allocate memory with malloc()"); return (int)INVALID_SOCKET; // TODO: use SOCKET all over the way and avoid this cast } memcpy(tmp, g_fds_array[ifd], sizeof(struct fds_data)); tmp->recv.buf = (uint8_t *)malloc(sizeof(uint8_t) * 2 * MAX_PAYLOAD_SIZE); if (!tmp->recv.buf) { log_err("Failed to allocate memory with malloc()"); FREE(tmp); return SOCKPERF_ERR_NO_MEMORY; } tmp->next_fd = ifd; tmp->active_fd_list = NULL; tmp->active_fd_count = 0; tmp->recv.cur_addr = tmp->recv.buf; tmp->recv.max_size = MAX_PAYLOAD_SIZE; tmp->recv.cur_offset = 0; tmp->recv.cur_size = tmp->recv.max_size; #ifdef USING_VMA_EXTRA_API if (g_vma_api && g_pApp->m_const_params.fd_handler_type == SOCKETXTREME) { active_ifd = g_vma_comps->user_data; } else #endif { active_ifd = (int)accept( ifd, (struct sockaddr *)&addr, (socklen_t *)&addr_size); // TODO: use SOCKET all over the way and avoid this cast } if (active_ifd < 0) { active_ifd = (int)INVALID_SOCKET; // TODO: use SOCKET all over the way and avoid this cast if (tmp->recv.buf) { FREE(tmp->recv.buf); } if (tmp->active_fd_list) { FREE(tmp->active_fd_list); } FREE(tmp); log_dbg("Can`t accept connection\n"); } else { /* Check if it is exceeded internal limitations * MAX_FDS_NUM and MAX_ACTIVE_FD_NUM */ if ((active_ifd < MAX_FDS_NUM) && (g_fds_array[ifd]->active_fd_count < (MAX_ACTIVE_FD_NUM - 1))) { if (prepare_socket(active_ifd, tmp) != (int)INVALID_SOCKET) { // TODO: use SOCKET all over the way and avoid this cast int *active_fd_list = g_fds_array[ifd]->active_fd_list; int i = 0; for (i = 0; i < MAX_ACTIVE_FD_NUM; i++) { if (active_fd_list[i] == (int)INVALID_SOCKET) { // TODO: use SOCKET all over // the way and avoid this // cast active_fd_list[i] = active_ifd; g_fds_array[ifd]->active_fd_count++; g_fds_array[active_ifd] = tmp; #ifdef USING_VMA_EXTRA_API if (g_vma_api && g_pApp->m_const_params.fd_handler_type == SOCKETXTREME) { log_dbg("peer address to accept: %s:%d [%d]", inet_ntoa(g_vma_comps->src.sin_addr), ntohs(g_vma_comps->src.sin_port), active_ifd); } else #endif { log_dbg("peer address to accept: %s:%d [%d]", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port), active_ifd); } do_accept = true; break; } } } } if (!do_accept) { log_msg("WARNING: closing a socket because we can not accept " "active_fd_count=%d MAX_ACTIVE_FD_NUM=%d", g_fds_array[ifd]->active_fd_count, MAX_ACTIVE_FD_NUM); close(active_ifd); active_ifd = (int)INVALID_SOCKET; // TODO: use SOCKET all over the way and avoid this cast if (tmp->recv.buf) { FREE(tmp->recv.buf); } if (tmp->active_fd_list) { FREE(tmp->active_fd_list); } FREE(tmp); #ifdef USING_VMA_EXTRA_API if (g_vma_api && g_pApp->m_const_params.fd_handler_type == SOCKETXTREME) { log_dbg("peer address to refuse: %s:%d [%d]", inet_ntoa(g_vma_comps->src.sin_addr), ntohs(g_vma_comps->src.sin_port), active_ifd); } else #endif { log_dbg("peer address to refuse: %s:%d [%d]", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port), active_ifd); } } } } return active_ifd; } //------------------------------------------------------------------------------ template void server_handler(int _fd_min, int _fd_max, int _fd_num) { Server s(_fd_min, _fd_max, _fd_num); s.doHandler(); } //------------------------------------------------------------------------------ template void server_handler(int _fd_min, int _fd_max, int _fd_num) { if (g_pApp->m_const_params.b_server_detect_gaps) server_handler(_fd_min, _fd_max, _fd_num); else server_handler(_fd_min, _fd_max, _fd_num); } //------------------------------------------------------------------------------ template void server_handler(int _fd_min, int _fd_max, int _fd_num) { if (g_pApp->m_const_params.packetrate_stats_print_ratio > 0) server_handler(_fd_min, _fd_max, _fd_num); else server_handler(_fd_min, _fd_max, _fd_num); } //------------------------------------------------------------------------------ void server_handler(handler_info *p_info) { if (p_info) { switch (g_pApp->m_const_params.fd_handler_type) { case RECVFROM: { server_handler(p_info->fd_min, p_info->fd_max, p_info->fd_num); break; } case RECVFROMMUX: { server_handler(p_info->fd_min, p_info->fd_max, p_info->fd_num); break; } case SELECT: { server_handler(p_info->fd_min, p_info->fd_max, p_info->fd_num); break; } #ifndef WIN32 case POLL: { server_handler(p_info->fd_min, p_info->fd_max, p_info->fd_num); break; } #ifndef __FreeBSD__ case EPOLL: { server_handler(p_info->fd_min, p_info->fd_max, p_info->fd_num); break; } #endif #ifdef USING_VMA_EXTRA_API case SOCKETXTREME: { server_handler(p_info->fd_min, p_info->fd_max, p_info->fd_num); break; } #endif #endif default: ERROR_MSG("unknown file handler"); } } } //------------------------------------------------------------------------------ void *server_handler_for_multi_threaded(void *arg) { handler_info *p_info = (handler_info *)arg; if (p_info) { server_handler(p_info); /* Mark this thread as complete (the first index is reserved for main thread) */ { int i = p_info->id + 1; if (p_info->id < g_pApp->m_const_params.threads_num) { if (thread_pid_array && thread_pid_array[i].tid && (thread_pid_array[i].tid == os_getthread().tid)) { ENTER_CRITICAL(&thread_exit_lock); thread_pid_array[i].tid = 0; LEAVE_CRITICAL(&thread_exit_lock); } } } } return 0; } //------------------------------------------------------------------------------ void find_min_max_fds(int start_look_from, int len, int *p_fd_min, int *p_fd_max) { int num_of_detected_fds; int i; for (num_of_detected_fds = 0, i = start_look_from; num_of_detected_fds < len; i++) { if (g_fds_array[i]) { if (!num_of_detected_fds) { *p_fd_min = i; } num_of_detected_fds++; } } *p_fd_max = i - 1; } //------------------------------------------------------------------------------ void server_sig_handler(int signum) { if (g_b_exit) { log_msg("Test end (interrupted by signal %d)", signum); log_dbg("thread %lu - exiting", (unsigned long)os_getthread().tid); return; } // Just in case not Activity updates where logged add a '\n' if (g_pApp->m_const_params.packetrate_stats_print_ratio && !g_pApp->m_const_params.packetrate_stats_print_details && (g_pApp->m_const_params.packetrate_stats_print_ratio < g_receiveCount)) printf("\n"); if (g_pApp->m_const_params.mthread_server) { if (os_getthread().tid == thread_pid_array[0].tid) { // main thread if (g_debug_level >= LOG_LVL_DEBUG) { log_dbg("Main thread %lu got signal %d - exiting", (unsigned long)os_getthread().tid, signum); } else { log_msg("Got signal %d - exiting", signum); } } else { log_dbg("Secondary thread %lu got signal %d - exiting", (unsigned long)os_getthread().tid, signum); } } else { switch (signum) { case SIGINT: log_msg("Test end (interrupted by user)"); break; default: log_msg("Test end (interrupted by signal %d)", signum); break; } } if (!g_receiveCount) { log_msg("No messages were received on the server."); } else { log_msg("Total %" PRIu64 " messages received and handled", g_receiveCount); // TODO: print also send count } SwitchOnCalcGaps::print_summary(); g_b_exit = true; } //------------------------------------------------------------------------------ void server_select_per_thread(int _fd_num) { int rc = SOCKPERF_ERR_NONE; int i; os_thread_t thread; int fd_num; int num_of_remainded_fds; int last_fds = 0; handler_info *handler_info_array = NULL; handler_info_array = (handler_info *)MALLOC(sizeof(handler_info) * g_pApp->m_const_params.threads_num); memset(handler_info_array, 0, sizeof(handler_info) * g_pApp->m_const_params.threads_num); if (!handler_info_array) { log_err("Failed to allocate memory for handler_info_arr"); rc = SOCKPERF_ERR_NO_MEMORY; } if (rc == SOCKPERF_ERR_NONE) { thread_pid_array = (os_thread_t *)MALLOC(sizeof(os_thread_t) * (g_pApp->m_const_params.threads_num + 1)); if (!thread_pid_array) { log_err("Failed to allocate memory for pid array"); rc = SOCKPERF_ERR_NO_MEMORY; } else { memset(thread_pid_array, 0, sizeof(os_thread_t) * (g_pApp->m_const_params.threads_num + 1)); log_msg("Running %d threads to manage %d sockets", g_pApp->m_const_params.threads_num, _fd_num); } } if (rc == SOCKPERF_ERR_NONE) { INIT_CRITICAL(&thread_exit_lock); thread_pid_array[0].tid = os_getthread().tid; /* Divide fds_arr between threads */ num_of_remainded_fds = _fd_num % g_pApp->m_const_params.threads_num; fd_num = _fd_num / g_pApp->m_const_params.threads_num; for (i = 0; i < g_pApp->m_const_params.threads_num; i++) { handler_info *cur_handler_info = (handler_info_array + i); /* Set ID of handler (thread) */ cur_handler_info->id = i; /* Set number of processed sockets */ cur_handler_info->fd_num = fd_num; if (num_of_remainded_fds) { cur_handler_info->fd_num++; num_of_remainded_fds--; } /* Set min/max possible socket to be processed */ find_min_max_fds(last_fds, cur_handler_info->fd_num, &(cur_handler_info->fd_min), &(cur_handler_info->fd_max)); /* Launch handler */ errno = 0; int ret = os_thread_exec(&thread, server_handler_for_multi_threaded, (void *)cur_handler_info); /* * There is undocumented behaviour for early versions of libc (for example libc 2.5, * 2.6, 2.7) * as pthread_create() call returns error code 12 ENOMEM and return value 0 * Note: libc-2.9 demonstrates expected behaivour */ if ((ret != 0) || (errno == ENOMEM)) { log_err("create thread has failed"); rc = SOCKPERF_ERR_FATAL; break; } thread_pid_array[i + 1].tid = thread.tid; last_fds = cur_handler_info->fd_max + 1; } /* Wait for ^C */ while ((rc == SOCKPERF_ERR_NONE) && !g_b_exit) { sleep(1); } /* Stop all launched threads (the first index is reserved for main thread) */ for (i = 1; i <= g_pApp->m_const_params.threads_num; i++) { os_thread_t cur_thread_pid; cur_thread_pid.tid = 0; ENTER_CRITICAL(&thread_exit_lock); cur_thread_pid.tid = thread_pid_array[i].tid; if (cur_thread_pid.tid) { os_thread_kill(&cur_thread_pid); } LEAVE_CRITICAL(&thread_exit_lock); if (cur_thread_pid.tid) { os_thread_join(&cur_thread_pid); } } DELETE_CRITICAL(&thread_exit_lock); } /* Free thread info allocated data */ if (handler_info_array) { FREE(handler_info_array); } /* Free thread TID array */ if (thread_pid_array) { FREE(thread_pid_array); } log_msg("%s() exit", __func__); } // Temp location because of compilation issue (inline-unit-growth=200) with the way this method was // inlined void SwitchOnCalcGaps::execute(struct sockaddr_in *clt_addr, uint64_t seq_num, bool is_warmup) { seq_num_map::iterator itr = ms_seq_num_map.find(*clt_addr); bool starting_new_session = false; bool print_summary = false; if (itr == ms_seq_num_map.end()) { clt_session_info_t new_session; memcpy(&new_session.addr, clt_addr, sizeof(struct sockaddr_in)); new_session.seq_num = seq_num; new_session.total_drops = 0; new_session.started = false; std::pair ret_val = ms_seq_num_map.insert(seq_num_map::value_type(*clt_addr, new_session)); if (ret_val.second) itr = ret_val.first; else { log_err("Failed to insert new session info, so the gap detection is not supported."); return; } starting_new_session = true; } else if (is_warmup && itr->second.started) { // first warmup packet and old session was found in DB => // needed to print old session summary. itr->second.started = false; starting_new_session = true; print_summary = true; } // print summary of the previous session + reset the counters if (print_summary) { print_session_summary(&(itr->second)); itr->second.seq_num = seq_num; itr->second.total_drops = 0; } // received first packet of the new session if (starting_new_session) print_new_session_info(&itr->second); if (!is_warmup) { if (!itr->second.started) itr->second.started = true; check_gaps(seq_num, itr); } } // Temp location because of compilation issue (inline-unit-growth=200) with the way this method was // inlined void SwitchOnActivityInfo::execute(uint64_t counter) { static TicksTime s_currTicks; static int s_print_header = 0; if (counter % g_pApp->m_const_params.packetrate_stats_print_ratio == 0) { if (g_pApp->m_const_params.packetrate_stats_print_details) { TicksDuration interval = s_currTicks.setNow() - g_lastTicks; if (interval < TicksDuration::TICKS1HOUR) { if (s_print_header++ % 20 == 0) { printf( " -- Interval -- -- Message Rate -- -- Total Message Count --\n"); } int64_t interval_packet_rate = g_pApp->m_const_params.packetrate_stats_print_ratio * NSEC_IN_SEC / interval.toNsec(); printf(" %10" PRId64 " [usec] %10" PRId64 " [msg/s] %13" PRIu64 " [msg]\n", interval.toUsec(), interval_packet_rate, counter); } g_lastTicks = s_currTicks; } else { printf("."); } fflush(stdout); } } sockperf-3.6/src/server.h000066400000000000000000000324471336630672200154660ustar00rootroot00000000000000/* * Copyright (c) 2011-2018 Mellanox Technologies Ltd. * 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. * 3. Neither the name of the Mellanox Technologies Ltd nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * 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. */ #ifndef SERVER_H_ #define SERVER_H_ #include "common.h" #ifdef ST_TEST extern int prepare_socket(int fd, struct fds_data *p_data, bool stTest = false); #else extern int prepare_socket(int fd, struct fds_data *p_data); #endif class IoHandler; class ServerBase { private: // protected: public: //------------------------------------------------------------------------------ ServerBase(IoHandler &_ioHandler); virtual ~ServerBase(); void doHandler() { int rc = SOCKPERF_ERR_NONE; rc = initBeforeLoop(); if (rc == SOCKPERF_ERR_NONE) { doLoop(); } cleanupAfterLoop(); } int initBeforeLoop(); void cleanupAfterLoop(); virtual void doLoop() = 0; // don't implement doLoop here because we want the compiler to // provide distinct // implementation with inlined functions of derived classes in each derived class protected: // Note: for static binding at compilation time, we use the // reference to IoHandler base class ONLY for accessing non-virtual functions IoHandler &m_ioHandlerRef; Message *m_pMsgReply; Message *m_pMsgRequest; }; //============================================================================== //============================================================================== template class Server : public ServerBase { private: IoType m_ioHandler; // protected: public: //------------------------------------------------------------------------------ Server(int _fd_min, int _fd_max, int _fd_num); virtual ~Server(); virtual void doLoop(); //------------------------------------------------------------------------------ /* ** receive from and send to selected socket */ /*inline*/ bool server_receive_then_send(int ifd); //------------------------------------------------------------------------------ int server_accept(int ifd); private: SwitchActivityInfo m_switchActivityInfo; SwitchCalcGaps m_switchCalcGaps; }; void print_log(const char *error, fds_data *fds) { printf("IP = %-15s PORT = %5d # %s ", inet_ntoa(fds->server_addr.sin_addr), ntohs(fds->server_addr.sin_port), PRINT_PROTOCOL(fds->sock_type)); log_err("%s", error); } void print_log(const char *error, int fds) { printf("actual_fd = %d ", fds); log_err("%s", error); } //------------------------------------------------------------------------------ /* ** when ret == RET_SOCKET_SHUTDOWN ** close ifd */ void close_ifd(int fd, int ifd, fds_data *l_fds_ifd) { fds_data *l_next_fd = g_fds_array[fd]; #ifdef USING_VMA_EXTRA_API if (g_vma_api) { ZeroCopyData *z_ptr = g_zeroCopyData[fd]; if (z_ptr && z_ptr->m_pkts) { g_vma_api->free_packets(fd, z_ptr->m_pkts->pkts, z_ptr->m_pkts->n_packet_num); z_ptr->m_pkts = NULL; z_ptr->m_pkt_index = 0; z_ptr->m_pkt_offset = 0; } g_vma_api->register_recv_callback(fd, NULL, NULL); } #endif for (int i = 0; i < MAX_ACTIVE_FD_NUM; i++) { if (l_next_fd->active_fd_list[i] == ifd) { print_log_dbg(l_fds_ifd->server_addr.sin_addr, l_fds_ifd->server_addr.sin_port, ifd); close(ifd); l_next_fd->active_fd_count--; l_next_fd->active_fd_list[i] = (int)INVALID_SOCKET; // TODO: use SOCKET all over the way and avoid this cast if (g_fds_array[ifd]->active_fd_list) { FREE(g_fds_array[ifd]->active_fd_list); } if (g_fds_array[ifd]->recv.buf) { FREE(g_fds_array[ifd]->recv.buf); } free(g_fds_array[ifd]); g_fds_array[ifd] = NULL; break; } } } //------------------------------------------------------------------------------ /* ** receive from and send to selected socket */ template inline bool Server::server_receive_then_send(int ifd) { struct sockaddr_in recvfrom_addr; struct sockaddr_in sendto_addr; bool do_update = true; int ret = 0; int remain_buffer = 0; fds_data *l_fds_ifd = g_fds_array[ifd]; if (unlikely(!l_fds_ifd)) { return (do_update); } #ifdef USING_VMA_EXTRA_API vma_buff_t *tmp_vma_buff = g_vma_buff; if (SOCKETXTREME == g_pApp->m_const_params.fd_handler_type && tmp_vma_buff) { ret = msg_recv_socketxtreme(l_fds_ifd, tmp_vma_buff, &recvfrom_addr); } else if (g_pApp->m_const_params.is_vmazcopyread && !(remain_buffer = free_vma_packets(ifd, l_fds_ifd->recv.cur_size))) { // Handled buffer is filled, free_vma_packets returns 0 ret = l_fds_ifd->recv.cur_size; } else #endif { ret = msg_recvfrom(ifd, l_fds_ifd->recv.cur_addr + l_fds_ifd->recv.cur_offset, l_fds_ifd->recv.cur_size, &recvfrom_addr, &l_fds_ifd->recv.cur_addr, remain_buffer); } if (unlikely(ret <= 0)) { if (ret == RET_SOCKET_SHUTDOWN) { if (l_fds_ifd->sock_type == SOCK_STREAM) { close_ifd(l_fds_ifd->next_fd, ifd, l_fds_ifd); } return (do_update); } if (ret < 0) return (!do_update); } int nbytes = ret; while (nbytes) { /* 1: message header is not received yet */ if ((l_fds_ifd->recv.cur_offset + nbytes) < MsgHeader::EFFECTIVE_SIZE) { l_fds_ifd->recv.cur_size -= nbytes; l_fds_ifd->recv.cur_offset += nbytes; /* 4: set current buffer size to size of remained part of message header to * guarantee getting full message header on next iteration */ if (l_fds_ifd->recv.cur_size < MsgHeader::EFFECTIVE_SIZE) { l_fds_ifd->recv.cur_size = MsgHeader::EFFECTIVE_SIZE - l_fds_ifd->recv.cur_offset; } #ifdef USING_VMA_EXTRA_API if (tmp_vma_buff) goto next; #endif return (!do_update); } else if (l_fds_ifd->recv.cur_offset < MsgHeader::EFFECTIVE_SIZE) { /* 2: message header is got, match message to cycle buffer */ m_pMsgReply->setBuf(l_fds_ifd->recv.cur_addr); m_pMsgReply->setHeaderToHost(); } else { /* 2: message header is got, match message to cycle buffer */ m_pMsgReply->setBuf(l_fds_ifd->recv.cur_addr); } if ((unsigned)m_pMsgReply->getLength() > (unsigned)MAX_PAYLOAD_SIZE) { // Message received was larger than expected, message ignored. - only on stream mode. print_log("Message received was larger than expected, message ignored.", l_fds_ifd); close_ifd(l_fds_ifd->next_fd, ifd, l_fds_ifd); return (do_update); } /* 3: message is not complete */ if ((l_fds_ifd->recv.cur_offset + nbytes) < m_pMsgReply->getLength()) { l_fds_ifd->recv.cur_size -= nbytes; l_fds_ifd->recv.cur_offset += nbytes; /* 4: set current buffer size to size of remained part of message to * guarantee getting full message on next iteration (using extended reserved memory) * and shift to start of cycle buffer */ if (l_fds_ifd->recv.cur_size < (int)m_pMsgReply->getMaxSize()) { l_fds_ifd->recv.cur_size = m_pMsgReply->getLength() - l_fds_ifd->recv.cur_offset; } #ifdef USING_VMA_EXTRA_API if (tmp_vma_buff) goto next; #endif return (!do_update); } /* 5: message is complete shift to process next one */ nbytes -= m_pMsgReply->getLength() - l_fds_ifd->recv.cur_offset; l_fds_ifd->recv.cur_addr += m_pMsgReply->getLength(); l_fds_ifd->recv.cur_size -= m_pMsgReply->getLength() - l_fds_ifd->recv.cur_offset; l_fds_ifd->recv.cur_offset = 0; #if defined(LOG_TRACE_MSG_IN) && (LOG_TRACE_MSG_IN == TRUE) printf(">>> "); hexdump(m_pMsgReply->getBuf(), MsgHeader::EFFECTIVE_SIZE); #endif /* LOG_TRACE_MSG_IN */ if (g_b_exit) return (!do_update); if (!m_pMsgReply->isClient()) { /* 6: shift to start of cycle buffer in case receiving buffer is empty and * there is no uncompleted message */ if (!nbytes) { l_fds_ifd->recv.cur_addr = l_fds_ifd->recv.buf; l_fds_ifd->recv.cur_size = l_fds_ifd->recv.max_size; l_fds_ifd->recv.cur_offset = 0; } #ifdef USING_VMA_EXTRA_API if (tmp_vma_buff) goto next; #endif return (!do_update); } if (unlikely(m_pMsgReply->isWarmupMessage())) { m_switchCalcGaps.execute(&recvfrom_addr, 0, true); /* 6: shift to start of cycle buffer in case receiving buffer is empty and * there is no uncompleted message */ if (!nbytes) { l_fds_ifd->recv.cur_addr = l_fds_ifd->recv.buf; l_fds_ifd->recv.cur_size = l_fds_ifd->recv.max_size; l_fds_ifd->recv.cur_offset = 0; } #ifdef USING_VMA_EXTRA_API if (tmp_vma_buff) goto next; #endif return (!do_update); } g_receiveCount++; //// should move to setRxTime (once we use it in server side) if (m_pMsgReply->getHeader()->isPongRequest()) { /* if server in a no reply mode - shift to start of cycle buffer*/ if (g_pApp->m_const_params.b_server_dont_reply) { #ifdef USING_VMA_EXTRA_API if (tmp_vma_buff) goto next; #endif l_fds_ifd->recv.cur_addr = l_fds_ifd->recv.buf; l_fds_ifd->recv.cur_size = l_fds_ifd->recv.max_size; l_fds_ifd->recv.cur_offset = 0; return (do_update); } /* prepare message header */ if (g_pApp->m_const_params.mode != MODE_BRIDGE) { m_pMsgReply->setServer(); } /* get source addr to reply. memcpy is not used to improve performance */ sendto_addr = l_fds_ifd->server_addr; if (l_fds_ifd->memberships_size || !l_fds_ifd->is_multicast || g_pApp->m_const_params.b_server_reply_via_uc) { // In unicast case reply to sender /* get source addr to reply. memcpy is not used to improve performance */ sendto_addr = recvfrom_addr; } else if (l_fds_ifd->is_multicast) { /* always send to the same port recved from */ sendto_addr.sin_port = recvfrom_addr.sin_port; } int length = m_pMsgReply->getLength(); m_pMsgReply->setHeaderToNetwork(); ret = msg_sendto(ifd, m_pMsgReply->getBuf(), length, &sendto_addr); if (unlikely(ret == RET_SOCKET_SHUTDOWN)) { if (l_fds_ifd->sock_type == SOCK_STREAM) { close_ifd(l_fds_ifd->next_fd, ifd, l_fds_ifd); } return (do_update); } m_pMsgReply->setHeaderToHost(); } m_switchCalcGaps.execute(&recvfrom_addr, m_pMsgReply->getSequenceCounter(), false); m_switchActivityInfo.execute(g_receiveCount); #ifdef USING_VMA_EXTRA_API next: if (tmp_vma_buff) { ret = msg_process_next(l_fds_ifd, &tmp_vma_buff, &nbytes); if (ret) { return (!do_update); } } #endif } /* 6: shift to start of cycle buffer in case receiving buffer is empty and * there is no uncompleted message */ // nbytes == 0 l_fds_ifd->recv.cur_addr = l_fds_ifd->recv.buf; l_fds_ifd->recv.cur_size = l_fds_ifd->recv.max_size; l_fds_ifd->recv.cur_offset = 0; return (!do_update); } #endif /* SERVER_H_ */ sockperf-3.6/src/sockperf.cpp000066400000000000000000004200231336630672200163160ustar00rootroot00000000000000/* * Copyright (c) 2011-2018 Mellanox Technologies Ltd. * 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. * 3. Neither the name of the Mellanox Technologies Ltd nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * 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. */ /* * How to Build: 'g++ *.cpp -O3 --param inline-unit-growth=200 -lrt -lpthread -ldl -o sockperf' */ /* * Still to do: * * V 2. stream mode should support respect --mps * * playback file * * * finalize playback (possible conflicts with other cmd-args, including disclaimer, print info *before looping) * * * support factor 2x, 4x, etc in playback * * * playback should use the defined WARMUP and not hard-coded 100*1000usec (before & after)! * * * verify/support of playback behavior in case user presses CTRL-C during test * * * edit printout to full-log file for playback (duration & num records) * * * save 50% of temp memory in parsePlaybackData * 3. param for printing highest N spikes * 4. support multiple servers (infra structure exists in PacketTimes and in client_statistics) * 5. gap analysis in server * 6. packaging, probably like iperf, include tar/rpm, readme, make clean all install * V 7. dup-packets are not considered in receive-count. Is this correct? * 8. Server should print send-count (in addition to receive-count) * 11 sockperf should work in exclusive modes (like svn): relevant modes are: latency-under-load, *stream, ping-pong, playback, subscriber (aka server) * * * 7. support OOO check for select/poll/epoll (currently check will fail unless recvfrom is used) * 8. configure and better handling of warmup/cooldown (flag on warmup packets) * 9. merge with perf envelope * 10. improve format of statistics at the end (tx/rx statistics line excluding warmup) * V 11. don't consider dropped packets at the end * X 12. consider: automatically set --mps=max in case of --ping-pong * 13. consider: loop till desirable seqNo instead of using timer (will distinguish between test and *cool down) * 14. remove error printouts about dup packets, or illegal seqno (and recheck illegal seqno with *mps=100 when server listen on same MC with 120 sockets) * 15. in case server is registered twice to same MC group+port, we consider the 2 replies as dup *packet. is this correct? * 16. handshake between C/S at the beginning of run will allow the client to configure N servers *(like perf envelope) and more * 17. support sockperf version with -v * 18. consider preventing --range when --stream is used (for best statistcs) * 19. warmup also for uc (mainly server side) * 20. less permuatation in templates, for example receiver thread can be different entity than *sender thread * 21. use ptpd for latency test using synced clocks across machines (without RTT) * 22. use --mps=max as the default for ping-pong and throughput modes * */ #define __STDC_LIMIT_MACROS // for UINT32_MAX in C++ #include #include #include "common.h" #include "message.h" #include "packet.h" #include "switches.h" #include "aopt.h" #include #include #ifndef WIN32 #include #endif // forward declarations from Client.cpp & Server.cpp extern void client_sig_handler(int signum); extern void client_handler(handler_info *); extern void server_sig_handler(int signum); extern void server_handler(handler_info *); extern void server_select_per_thread(int fd_num); static bool sock_lib_started = 0; // static int s_fd_max = 0; static int s_fd_min = 0; /* used as THE fd when single mc group is given (RECVFROM blocked mode) */ static int s_fd_num = 0; static struct mutable_params_t s_mutable_params; static void set_select_timeout(int time_out_msec); static int set_sockets_from_feedfile(const char *feedfile_name); #ifdef ST_TEST int prepare_socket(int fd, struct fds_data *p_data, bool stTest = false); #else int prepare_socket(int fd, struct fds_data *p_data); #endif void cleanup(); #ifndef VERSION #define VERSION "unknown" #endif static int proc_mode_help(int, int, const char **); static int proc_mode_version(int, int, const char **); static int proc_mode_under_load(int, int, const char **); static int proc_mode_ping_pong(int, int, const char **); static int proc_mode_throughput(int, int, const char **); static int proc_mode_playback(int, int, const char **); static int proc_mode_server(int, int, const char **); static const struct app_modes { int (*func)(int, int, const char **); /* proc function */ const char *name; /* mode name to use from command line as an argument */ const char *const shorts[4]; /* short name */ const char *note; /* mode description */ } sockperf_modes[] = { { proc_mode_help, "help", aopt_set_string("h", "?"), "Display list of supported commands." }, { proc_mode_version, "--version", aopt_set_string(NULL), "Tool version information." }, { proc_mode_under_load, "under-load", aopt_set_string("ul"), "Run " MODULE_NAME " client for latency under load test." }, { proc_mode_ping_pong, "ping-pong", aopt_set_string("pp"), "Run " MODULE_NAME " client for latency test in ping pong mode." }, { proc_mode_playback, "playback", aopt_set_string("pb"), "Run " MODULE_NAME " client for latency test using playback of predefined traffic, based " "on timeline and message size." }, { proc_mode_throughput, "throughput", aopt_set_string("tp"), "Run " MODULE_NAME " client for one way throughput test." }, { proc_mode_server, "server", aopt_set_string("sr"), "Run " MODULE_NAME " as a server." }, { NULL, NULL, aopt_set_string(NULL), NULL } }; os_mutex_t _mutex; static int parse_common_opt(const AOPT_OBJECT *); static int parse_client_opt(const AOPT_OBJECT *); static char *display_opt(int, char *, size_t); /* * List of supported general options. */ static const AOPT_DESC common_opt_desc[] = { { 'h', AOPT_NOARG, aopt_set_literal('h', '?'), aopt_set_string("help", "usage"), "Show the help message and exit." }, { OPT_TCP, AOPT_NOARG, aopt_set_literal(0), aopt_set_string("tcp"), "Use TCP protocol (default UDP)." }, { 'i', AOPT_ARG, aopt_set_literal('i'), aopt_set_string("ip"), "Listen on/send to ip ." }, { 'p', AOPT_ARG, aopt_set_literal('p'), aopt_set_string("port"), "Listen on/connect to port (default 11111)." }, { 'f', AOPT_ARG, aopt_set_literal('f'), aopt_set_string("file"), "Read list of connections from file (used in pair with -F option)." }, { 'F', AOPT_ARG, aopt_set_literal('F'), aopt_set_string("iomux-type"), #ifdef WIN32 "Type of multiple file descriptors handle [s|select|r|recvfrom](default select)." #elif __FreeBSD__ "Type of multiple file descriptors handle [s|select|p|poll|r|recvfrom](default select)." #else "Type of multiple file descriptors handle " "[s|select|p|poll|e|epoll|r|recvfrom|x|socketxtreme](default epoll)." #endif }, { OPT_SELECT_TIMEOUT, AOPT_ARG, aopt_set_literal(0), aopt_set_string("timeout"), #ifdef WIN32 "Set select timeout to , -1 for infinite (default is 10 msec)." #elif __FreeBSD__ "Set select/poll timeout to , -1 for infinite (default is 10 msec)." #else "Set select/poll/epoll timeout to , -1 for infinite (default is 10 msec)." #endif }, { 'a', AOPT_ARG, aopt_set_literal('a'), aopt_set_string("activity"), "Measure activity by printing a '.' for the last messages processed." }, { 'A', AOPT_ARG, aopt_set_literal('A'), aopt_set_string("Activity"), "Measure activity by printing the duration for last messages processed." }, { OPT_TCP_NODELAY_OFF, AOPT_NOARG, aopt_set_literal(0), aopt_set_string("tcp-avoid-nodelay"), "Stop/Start delivering TCP Messages Immediately (Enable/Disable Nagel). Default is Nagel " "Disabled except in Throughput where the default is Nagel enabled." }, { OPT_NONBLOCKED_SEND, AOPT_NOARG, aopt_set_literal(0), aopt_set_string("tcp-skip-blocking-send"), "Enables non-blocking send operation (default OFF)." }, { OPT_TOS, AOPT_ARG, aopt_set_literal(0), aopt_set_string("tos"), "Allows setting tos" }, { OPT_RX_MC_IF, AOPT_ARG, aopt_set_literal(0), aopt_set_string("mc-rx-if"), "Set address of interface on which to receive mulitcast messages (can be other then " "route table)." }, { OPT_TX_MC_IF, AOPT_ARG, aopt_set_literal(0), aopt_set_string("mc-tx-if"), "Set address of interface on which to transmit mulitcast messages (can be other then " "route table)." }, { OPT_MC_LOOPBACK_ENABLE, AOPT_NOARG, aopt_set_literal(0), aopt_set_string("mc-loopback-enable"), "Enables mc loopback (default disabled)." }, { OPT_IP_MULTICAST_TTL, AOPT_ARG, aopt_set_literal(0), aopt_set_string("mc-ttl"), "Limit the lifetime of the message (default 2)." }, { OPT_MC_SOURCE_IP, AOPT_ARG, aopt_set_literal(0), aopt_set_string("mc-source-filter"), "Set address of mulitcast messages source which is allowed to receive from." }, { OPT_UC_REUSEADDR, AOPT_NOARG, aopt_set_literal(0), aopt_set_string("uc-reuseaddr"), "Enables unicast reuse address (default disabled)." }, { OPT_LLS, AOPT_ARG, aopt_set_literal(0), aopt_set_string("lls"), "Turn on LLS via socket option (value = usec to poll)." }, { OPT_BUFFER_SIZE, AOPT_ARG, aopt_set_literal(0), aopt_set_string("buffer-size"), "Set total socket receive/send buffer in bytes (system defined by default)." }, { OPT_NONBLOCKED, AOPT_NOARG, aopt_set_literal(0), aopt_set_string("nonblocked"), "Open non-blocked sockets." }, { OPT_RECV_LOOPING, AOPT_ARG, aopt_set_literal(0), aopt_set_string("recv_looping_num"), "Set sockperf to loop over recvfrom() until EAGAIN or good received packets, -1 for " "infinite, must be used with --nonblocked (default 1). " }, { OPT_DONTWARMUP, AOPT_NOARG, aopt_set_literal(0), aopt_set_string("dontwarmup"), "Don't send warm up messages on start." }, { OPT_PREWARMUPWAIT, AOPT_ARG, aopt_set_literal(0), aopt_set_string("pre-warmup-wait"), "Time to wait before sending warm up messages (seconds)." }, #ifndef WIN32 { OPT_VMAZCOPYREAD, AOPT_NOARG, aopt_set_literal(0), aopt_set_string("vmazcopyread"), "Use VMA's zero copy reads API (See VMA's readme)." }, { OPT_DAEMONIZE, AOPT_NOARG, aopt_set_literal(0), aopt_set_string("daemonize"), "Run as " "daemon." }, { OPT_NO_RDTSC, AOPT_NOARG, aopt_set_literal(0), aopt_set_string("no-rdtsc"), "Don't use register when taking time; instead use monotonic clock." }, { OPT_LOAD_VMA, AOPT_OPTARG, aopt_set_literal(0), aopt_set_string("load-vma"), "Load VMA dynamically even when LD_PRELOAD was not used." }, { OPT_RATE_LIMIT, AOPT_ARG, aopt_set_literal(0), aopt_set_string("rate-limit"), "use rate limit (packet-pacing), with VMA must be run with VMA_RING_ALLOCATION_LOGIC_TX " "mode." }, #endif { OPT_SOCK_ACCL, AOPT_NOARG, aopt_set_literal(0), aopt_set_string("set-sock-accl"), "Set socket accleration before run (available for some of Mellanox systems)" }, { 'd', AOPT_NOARG, aopt_set_literal('d'), aopt_set_string("debug"), "Print extra debug information." }, { 0, AOPT_NOARG, aopt_set_literal(0), aopt_set_string(NULL), NULL } }; /* * List of supported client options. */ static const AOPT_DESC client_opt_desc[] = { { OPT_CLIENT_WORK_WITH_SRV_NUM, AOPT_ARG, aopt_set_literal(0), aopt_set_string("srv-num"), "Set num of servers the client works with to N." }, { OPT_SENDER_AFFINITY, AOPT_ARG, aopt_set_literal(0), aopt_set_string("sender-affinity"), "Set sender thread affinity to the given core ids in list format (see: cat /proc/cpuinfo)." }, { OPT_RECEIVER_AFFINITY, AOPT_ARG, aopt_set_literal(0), aopt_set_string("receiver-affinity"), "Set receiver thread affinity to the given core ids in list format (see: cat " "/proc/cpuinfo)." }, { OPT_FULL_LOG, AOPT_ARG, aopt_set_literal(0), aopt_set_string("full-log"), "Dump full log of all messages send/receive time to the given file in CSV format." }, { OPT_FULL_RTT, AOPT_NOARG, aopt_set_literal(0), aopt_set_string("full-rtt"), "Show results in round-trip-time instead of latency." }, { OPT_GIGA_SIZE, AOPT_NOARG, aopt_set_literal(0), aopt_set_string("giga-size"), "Print sizes in GigaByte." }, { OPT_OUTPUT_PRECISION, AOPT_NOARG, aopt_set_literal(0), aopt_set_string("increase_output_precision"), "Increase number of digits after decimal point of the throughput output (from 3 to 9). " }, { OPT_DUMMY_SEND, AOPT_OPTARG, aopt_set_literal(0), aopt_set_string("dummy-send"), "Use VMA's dummy send API instead of busy wait, must be higher than regular msg rate. " "\n\t\t\t\t optional: set dummy-send rate per second (default 10,000), usage: --dummy-send " "[|max]" }, { 0, AOPT_NOARG, aopt_set_literal(0), aopt_set_string(NULL), NULL } }; //------------------------------------------------------------------------------ static int proc_mode_help(int id, int argc, const char **argv) { int i = 0; printf(MODULE_NAME " is a tool for testing network latency and throughput.\n"); printf("version %s\n", VERSION); printf("\n"); printf("Usage: " MODULE_NAME " [options] [args]\n"); printf("Type: \'" MODULE_NAME " --help\' for help on a specific subcommand.\n"); printf("Type: \'" MODULE_NAME " --version\' to see the program version number.\n"); printf("\n"); printf("Available subcommands:\n"); for (i = 0; sockperf_modes[i].name != NULL; i++) { char tmp_buf[21]; /* skip commands with prefix '--', they are special */ if (sockperf_modes[i].name[0] != '-') { printf(" %-20.20s\t%-s\n", display_opt(i, tmp_buf, sizeof(tmp_buf)), sockperf_modes[i].note); } } printf("\n"); printf("For additional information visit our website http://github.com/mellanox/sockperf , see " "README file, or Type \'sockperf --help\'.\n\n"); return -1; /* this return code signals to do exit */ } //------------------------------------------------------------------------------ static int proc_mode_version(int id, int argc, const char **argv) { printf(MODULE_NAME ", version %s\n", VERSION); printf(" compiled %s, %s\n", __DATE__, __TIME__); printf("\n%s\n", MODULE_COPYRIGHT); return -1; /* this return code signals to do exit */ } //------------------------------------------------------------------------------ static int proc_mode_under_load(int id, int argc, const char **argv) { int rc = SOCKPERF_ERR_NONE; const AOPT_OBJECT *common_obj = NULL; const AOPT_OBJECT *client_obj = NULL; const AOPT_OBJECT *self_obj = NULL; /* * List of supported under-load options. */ const AOPT_DESC self_opt_desc[] = { { 't', AOPT_ARG, aopt_set_literal('t'), aopt_set_string("time"), "Run for seconds (default 1, max = 36000000)." }, { OPT_CLIENTPORT, AOPT_ARG, aopt_set_literal(0), aopt_set_string("client_port"), "Force the client side to bind to a specific port (default = 0). " }, { OPT_CLIENTIP, AOPT_ARG, aopt_set_literal(0), aopt_set_string("client_ip"), "Force the client side to bind to a specific ip address (default = 0). " }, { 'b', AOPT_ARG, aopt_set_literal('b'), aopt_set_string("burst"), "Control the client's number of a messages sent in every burst." }, { OPT_REPLY_EVERY, AOPT_ARG, aopt_set_literal(0), aopt_set_string("reply-every"), "Set number of send messages between reply messages (default = 100)." }, { OPT_MPS, AOPT_ARG, aopt_set_literal(0), aopt_set_string("mps"), "Set number of messages-per-second (default = 10000 - for under-load mode, or max - for " "ping-pong and throughput modes; for maximum use --mps=max; \n\t\t\t\t support --pps for " "old compatibility)." }, { OPT_MPS, AOPT_ARG, aopt_set_literal(0), aopt_set_string("pps"), NULL }, { 'm', AOPT_ARG, aopt_set_literal('m'), aopt_set_string("msg-size"), "Use messages of size bytes (minimum default 14)." }, { 'r', AOPT_ARG, aopt_set_literal('r'), aopt_set_string("range"), "comes with -m , randomly change the messages size in range: +- ." }, { 0, AOPT_NOARG, aopt_set_literal(0), aopt_set_string(NULL), NULL } }; /* Load supported option and create option objects */ { int valid_argc = 0; int temp_argc = 0; temp_argc = argc; common_obj = aopt_init(&temp_argc, (const char **)argv, common_opt_desc); valid_argc += temp_argc; temp_argc = argc; client_obj = aopt_init(&temp_argc, (const char **)argv, client_opt_desc); valid_argc += temp_argc; temp_argc = argc; self_obj = aopt_init(&temp_argc, (const char **)argv, self_opt_desc); valid_argc += temp_argc; if (valid_argc < (argc - 1)) { rc = SOCKPERF_ERR_BAD_ARGUMENT; } } if (rc || aopt_check(common_obj, 'h')) { rc = -1; } /* Set default values */ s_user_params.mode = MODE_CLIENT; s_user_params.mps = MPS_DEFAULT; s_user_params.reply_every = REPLY_EVERY_DEFAULT; /* Set command line common options */ if (!rc && common_obj) { rc = parse_common_opt(common_obj); } /* Set command line client values */ if (!rc && client_obj) { rc = parse_client_opt(client_obj); } /* Set command line specific values */ if (!rc && self_obj) { if (!rc && aopt_check(self_obj, 't')) { const char *optarg = aopt_value(self_obj, 't'); if (optarg) { errno = 0; int value = strtol(optarg, NULL, 0); if (errno != 0 || value <= 0 || value > MAX_DURATION) { log_msg("'-%c' Invalid duration: %s", 't', optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else { s_user_params.sec_test_duration = value; } } else { log_msg("'-%c' Invalid value", 't'); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } if (!rc && aopt_check(self_obj, 'b')) { const char *optarg = aopt_value(self_obj, 'b'); if (optarg) { errno = 0; int value = strtol(optarg, NULL, 0); if (errno != 0 || value < 1) { log_msg("'-%c' Invalid burst size: %s", 'b', optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else { s_user_params.burst_size = value; } } else { log_msg("'-%c' Invalid value", 'b'); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } if (!rc && aopt_check(self_obj, OPT_REPLY_EVERY)) { const char *optarg = aopt_value(self_obj, OPT_REPLY_EVERY); if (optarg) { errno = 0; long long value = strtol(optarg, NULL, 0); if (errno != 0 || value <= 0 || value > 1 << 30) { log_msg("Invalid %d val: %s", OPT_REPLY_EVERY, optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else { s_user_params.reply_every = (uint32_t)value; } } else { log_msg("'-%d' Invalid value", OPT_REPLY_EVERY); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } if (!rc && aopt_check(self_obj, OPT_MPS)) { const char *optarg = aopt_value(self_obj, OPT_MPS); if (optarg) { if (0 == strcmp("MAX", optarg) || 0 == strcmp("max", optarg)) { s_user_params.mps = UINT32_MAX; } else { errno = 0; long long value = strtol(optarg, NULL, 0); if (errno != 0 || value <= 0 || value > 1 << 30) { log_msg("Invalid %d val: %s", OPT_MPS, optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else { s_user_params.mps = (uint32_t)value; } } } else { log_msg("'-%d' Invalid value", OPT_MPS); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } if (!rc && aopt_check(self_obj, OPT_CLIENTPORT)) { if (aopt_check(common_obj, 'f')) { log_msg("--client_port conflicts with -f option"); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else { const char *optarg = aopt_value(self_obj, OPT_CLIENTPORT); if (optarg) { errno = 0; long value = strtol(optarg, NULL, 0); /* strtol() returns 0 if there were no digits at all */ if (errno != 0) { log_msg("'-%c' Invalid port: %s", OPT_CLIENTPORT, optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else { s_user_params.client_bind_info.sin_port = htons((uint16_t)value); } } else { log_msg("'-%c' Invalid value", OPT_CLIENTPORT); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } } if (!rc && aopt_check(self_obj, OPT_CLIENTIP)) { int len; const char *optarg = aopt_value(self_obj, OPT_CLIENTIP); if (!optarg) { /* already in network byte order*/ log_msg("'-%c' Invalid address: %s", OPT_CLIENTIP, optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else if (4 != sscanf(optarg, "%d.%d.%d.%d", &len, &len, &len, &len)) { log_msg("'-%c' Invalid address: %s", OPT_CLIENTIP, optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else if (!inet_aton(optarg, &s_user_params.client_bind_info.sin_addr)) { log_msg("'-%c' Invalid address: %s", OPT_CLIENTIP, optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } if (!rc && aopt_check(self_obj, 'm')) { const char *optarg = aopt_value(self_obj, 'm'); if (optarg) { errno = 0; int value = strtol(optarg, NULL, 0); if (errno != 0 || value < MIN_PAYLOAD_SIZE) { log_msg("'-%c' Invalid message size: %s (min: %d)", 'm', optarg, MIN_PAYLOAD_SIZE); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else if (!aopt_check(common_obj, OPT_TCP) && value > MAX_PAYLOAD_SIZE) { log_msg("'-%c' Invalid message size: %s (max: %d)", 'm', optarg, MAX_PAYLOAD_SIZE); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else if (aopt_check(common_obj, OPT_TCP) && value > MAX_TCP_SIZE) { log_msg("'-%c' Invalid message size: %s (max: %d)", 'm', optarg, MAX_TCP_SIZE); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else { MAX_PAYLOAD_SIZE = value; s_user_params.msg_size = value; } } else { log_msg("'-%c' Invalid value", 'm'); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } if (!rc && aopt_check(self_obj, 'r')) { const char *optarg = aopt_value(self_obj, 'r'); if (optarg && (isNumeric(optarg))) { errno = 0; int value = strtol(optarg, NULL, 0); if (errno != 0 || value < 0) { log_msg("'-%c' Invalid message range: %s", 'r', optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else { s_user_params.msg_size_range = value; } } else { log_msg("'-%c' Invalid value", 'r'); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } } if (rc) { const char *help_str = NULL; char temp_buf[30]; printf("%s: %s\n", display_opt(id, temp_buf, sizeof(temp_buf)), sockperf_modes[id].note); printf("\n"); printf("Usage: " MODULE_NAME " %s [options] [args]...\n", sockperf_modes[id].name); printf(" " MODULE_NAME " %s -i ip [-p port] [-m message_size] [-t time] [--data_integrity]\n", sockperf_modes[id].name); printf(" " MODULE_NAME " %s -f file [-F s/p/e] [-m message_size] [-r msg_size_range] [-t time]\n", sockperf_modes[id].name); printf("\n"); printf("Options:\n"); help_str = aopt_help(common_opt_desc); if (help_str) { printf("%s\n", help_str); free((void *)help_str); } printf("Valid arguments:\n"); help_str = aopt_help(client_opt_desc); if (help_str) { printf("%s", help_str); free((void *)help_str); help_str = aopt_help(self_opt_desc); if (help_str) { printf("%s", help_str); free((void *)help_str); } printf("\n"); } } /* Destroy option objects */ aopt_exit((AOPT_OBJECT *)common_obj); aopt_exit((AOPT_OBJECT *)client_obj); aopt_exit((AOPT_OBJECT *)self_obj); return rc; } //------------------------------------------------------------------------------ static int proc_mode_ping_pong(int id, int argc, const char **argv) { int rc = SOCKPERF_ERR_NONE; const AOPT_OBJECT *common_obj = NULL; const AOPT_OBJECT *client_obj = NULL; const AOPT_OBJECT *self_obj = NULL; /* * List of supported ping-pong options. */ const AOPT_DESC self_opt_desc[] = { { 't', AOPT_ARG, aopt_set_literal('t'), aopt_set_string("time"), "Run for seconds (default 1, max = 36000000)." }, { OPT_CLIENTPORT, AOPT_ARG, aopt_set_literal(0), aopt_set_string("client_port"), "Force the client side to bind to a specific port (default = 0). " }, { OPT_CLIENTIP, AOPT_ARG, aopt_set_literal(0), aopt_set_string("client_ip"), "Force the client side to bind to a specific ip address (default = 0). " }, { 'b', AOPT_ARG, aopt_set_literal('b'), aopt_set_string("burst"), "Control the client's number of a messages sent in every burst." }, { OPT_MPS, AOPT_ARG, aopt_set_literal(0), aopt_set_string("mps"), "Set number of messages-per-second (default = 10000 - for under-load mode, or max - for " "ping-pong and throughput modes; for maximum use --mps=max; \n\t\t\t\t support --pps for " "old compatibility)." }, { OPT_MPS, AOPT_ARG, aopt_set_literal(0), aopt_set_string("pps"), NULL }, { 'm', AOPT_ARG, aopt_set_literal('m'), aopt_set_string("msg-size"), "Use messages of size bytes (minimum default 14)." }, { 'r', AOPT_ARG, aopt_set_literal('r'), aopt_set_string("range"), "comes with -m , randomly change the messages size in range: +- ." }, { OPT_DATA_INTEGRITY, AOPT_NOARG, aopt_set_literal(0), aopt_set_string("data-integrity"), "Perform data integrity test." }, { 0, AOPT_NOARG, aopt_set_literal(0), aopt_set_string(NULL), NULL } }; /* Load supported option and create option objects */ { int valid_argc = 0; int temp_argc = 0; temp_argc = argc; common_obj = aopt_init(&temp_argc, (const char **)argv, common_opt_desc); valid_argc += temp_argc; temp_argc = argc; client_obj = aopt_init(&temp_argc, (const char **)argv, client_opt_desc); valid_argc += temp_argc; temp_argc = argc; self_obj = aopt_init(&temp_argc, (const char **)argv, self_opt_desc); valid_argc += temp_argc; if (valid_argc < (argc - 1)) { rc = SOCKPERF_ERR_BAD_ARGUMENT; } } if (rc || aopt_check(common_obj, 'h')) { rc = -1; } /* Set default values */ s_user_params.mode = MODE_CLIENT; s_user_params.b_client_ping_pong = true; s_user_params.mps = UINT32_MAX; s_user_params.reply_every = 1; /* Set command line common options */ if (!rc && common_obj) { rc = parse_common_opt(common_obj); } /* Set command line client values */ if (!rc && client_obj) { rc = parse_client_opt(client_obj); } /* Set command line specific values */ if (!rc && self_obj) { if (!rc && aopt_check(self_obj, 't')) { const char *optarg = aopt_value(self_obj, 't'); if (optarg) { errno = 0; int value = strtol(optarg, NULL, 0); if (errno != 0 || value <= 0 || value > MAX_DURATION) { log_msg("'-%c' Invalid duration: %s", 't', optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else { s_user_params.sec_test_duration = value; } } else { log_msg("'-%c' Invalid value", 't'); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } if (!rc && aopt_check(self_obj, 'b')) { const char *optarg = aopt_value(self_obj, 'b'); if (optarg) { errno = 0; int value = strtol(optarg, NULL, 0); if (errno != 0 || value < 1) { log_msg("'-%c' Invalid burst size: %s", 'b', optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else { s_user_params.burst_size = value; } } else { log_msg("'-%c' Invalid value", 'b'); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } if (!rc && aopt_check(self_obj, OPT_MPS)) { const char *optarg = aopt_value(self_obj, OPT_MPS); if (optarg) { if (0 == strcmp("MAX", optarg) || 0 == strcmp("max", optarg)) { s_user_params.mps = UINT32_MAX; } else { errno = 0; long long value = strtol(optarg, NULL, 0); if (errno != 0 || value <= 0 || value > 1 << 30) { log_msg("Invalid %d val: %s", OPT_MPS, optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else { s_user_params.mps = (uint32_t)value; } } } else { log_msg("'-%d' Invalid value", OPT_MPS); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } if (!rc && aopt_check(self_obj, OPT_CLIENTPORT)) { if (aopt_check(common_obj, 'f')) { log_msg("--client_port conflicts with -f option"); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else { const char *optarg = aopt_value(self_obj, OPT_CLIENTPORT); if (optarg) { errno = 0; long value = strtol(optarg, NULL, 0); /* strtol() returns 0 if there were no digits at all */ if (errno != 0) { log_msg("'-%c' Invalid port: %s", OPT_CLIENTPORT, optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else { s_user_params.client_bind_info.sin_port = htons((uint16_t)value); } } else { log_msg("'-%c' Invalid value", OPT_CLIENTPORT); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } } if (!rc && aopt_check(self_obj, OPT_CLIENTIP)) { int len; const char *optarg = aopt_value(self_obj, OPT_CLIENTIP); if (!optarg) { /* already in network byte order*/ log_msg("'-%c' Invalid address: %s", OPT_CLIENTIP, optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else if (4 != sscanf(optarg, "%d.%d.%d.%d", &len, &len, &len, &len)) { log_msg("'-%c' Invalid address: %s", OPT_CLIENTIP, optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else if (!inet_aton(optarg, &s_user_params.client_bind_info.sin_addr)) { log_msg("'-%c' Invalid address: %s", OPT_CLIENTIP, optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } if (!rc && aopt_check(self_obj, 'm')) { const char *optarg = aopt_value(self_obj, 'm'); if (optarg) { errno = 0; int value = strtol(optarg, NULL, 0); if (errno != 0 || value < MIN_PAYLOAD_SIZE) { log_msg("'-%c' Invalid message size: %s (min: %d)", 'm', optarg, MIN_PAYLOAD_SIZE); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else if (!aopt_check(common_obj, OPT_TCP) && value > MAX_PAYLOAD_SIZE) { log_msg("'-%c' Invalid message size: %s (max: %d)", 'm', optarg, MAX_PAYLOAD_SIZE); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else if (aopt_check(common_obj, OPT_TCP) && value > MAX_TCP_SIZE) { log_msg("'-%c' Invalid message size: %s (max: %d)", 'm', optarg, MAX_TCP_SIZE); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else { MAX_PAYLOAD_SIZE = value; s_user_params.msg_size = value; } } else { log_msg("'-%c' Invalid value", 'm'); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } if (!rc && aopt_check(self_obj, 'r')) { const char *optarg = aopt_value(self_obj, 'r'); if (optarg && (isNumeric(optarg))) { errno = 0; int value = strtol(optarg, NULL, 0); if (errno != 0 || value < 0) { log_msg("'-%c' Invalid message range: %s", 'r', optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else { s_user_params.msg_size_range = value; } } else { log_msg("'-%c' Invalid value", 'r'); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } if (!rc && aopt_check(self_obj, OPT_DATA_INTEGRITY)) { if (!aopt_check(self_obj, 'b')) { s_user_params.data_integrity = true; } else { log_msg("--data-integrity conflicts with -b option"); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } } if (rc) { const char *help_str = NULL; char temp_buf[30]; printf("%s: %s\n", display_opt(id, temp_buf, sizeof(temp_buf)), sockperf_modes[id].note); printf("\n"); printf("Usage: " MODULE_NAME " %s [options] [args]...\n", sockperf_modes[id].name); printf(" " MODULE_NAME " %s -i ip [-p port] [-m message_size] [-t time]\n", sockperf_modes[id].name); printf(" " MODULE_NAME " %s -f file [-F s/p/e] [-m message_size] [-r msg_size_range] [-t time]\n", sockperf_modes[id].name); printf("\n"); printf("Options:\n"); help_str = aopt_help(common_opt_desc); if (help_str) { printf("%s\n", help_str); free((void *)help_str); } printf("Valid arguments:\n"); help_str = aopt_help(client_opt_desc); if (help_str) { printf("%s", help_str); free((void *)help_str); help_str = aopt_help(self_opt_desc); if (help_str) { printf("%s", help_str); free((void *)help_str); } printf("\n"); } } /* Destroy option objects */ aopt_exit((AOPT_OBJECT *)common_obj); aopt_exit((AOPT_OBJECT *)client_obj); aopt_exit((AOPT_OBJECT *)self_obj); /* It is set to reduce memory needed for PacketTime buffer */ if (s_user_params.mps == UINT32_MAX) { // MAX MPS mode MPS_MAX = MPS_MAX_PP * s_user_params.burst_size; if (MPS_MAX > MPS_MAX_UL) MPS_MAX = MPS_MAX_UL; } return rc; } //------------------------------------------------------------------------------ static int proc_mode_throughput(int id, int argc, const char **argv) { int rc = SOCKPERF_ERR_NONE; const AOPT_OBJECT *common_obj = NULL; const AOPT_OBJECT *client_obj = NULL; const AOPT_OBJECT *self_obj = NULL; /* * List of supported throughput options. */ const AOPT_DESC self_opt_desc[] = { { 't', AOPT_ARG, aopt_set_literal('t'), aopt_set_string("time"), "Run for seconds (default 1, max = 36000000)." }, { OPT_CLIENTPORT, AOPT_ARG, aopt_set_literal(0), aopt_set_string("client_port"), "Force the client side to bind to a specific port (default = 0). " }, { OPT_CLIENTIP, AOPT_ARG, aopt_set_literal(0), aopt_set_string("client_ip"), "Force the client side to bind to a specific ip address (default = 0). " }, { 'b', AOPT_ARG, aopt_set_literal('b'), aopt_set_string("burst"), "Control the client's number of a messages sent in every burst." }, { OPT_MPS, AOPT_ARG, aopt_set_literal(0), aopt_set_string("mps"), "Set number of messages-per-second (default = 10000 - for under-load mode, or max - for " "ping-pong and throughput modes; for maximum use --mps=max; \n\t\t\t\t support --pps for " "old compatibility)." }, { OPT_MPS, AOPT_ARG, aopt_set_literal(0), aopt_set_string("pps"), NULL }, { 'm', AOPT_ARG, aopt_set_literal('m'), aopt_set_string("msg-size"), "Use messages of size bytes (minimum default 14)." }, { 'r', AOPT_ARG, aopt_set_literal('r'), aopt_set_string("range"), "comes with -m , randomly change the messages size in range: +- ." }, { 0, AOPT_NOARG, aopt_set_literal(0), aopt_set_string(NULL), NULL } }; /* Load supported option and create option objects */ { int valid_argc = 0; int temp_argc = 0; temp_argc = argc; common_obj = aopt_init(&temp_argc, (const char **)argv, common_opt_desc); valid_argc += temp_argc; temp_argc = argc; client_obj = aopt_init(&temp_argc, (const char **)argv, client_opt_desc); valid_argc += temp_argc; temp_argc = argc; self_obj = aopt_init(&temp_argc, (const char **)argv, self_opt_desc); valid_argc += temp_argc; if (valid_argc < (argc - 1)) { rc = SOCKPERF_ERR_BAD_ARGUMENT; } } if (rc || aopt_check(common_obj, 'h')) { rc = -1; } /* Set default values */ s_user_params.mode = MODE_CLIENT; s_user_params.b_stream = true; s_user_params.mps = UINT32_MAX; s_user_params.reply_every = 1 << (8 * sizeof(s_user_params.reply_every) - 2); /* Set command line common options */ if (!rc && common_obj) { rc = parse_common_opt(common_obj); } /* Set command line client values */ if (!rc && client_obj) { rc = parse_client_opt(client_obj); } /* Set command line specific values */ if (!rc && self_obj) { if (!rc && aopt_check(self_obj, 't')) { const char *optarg = aopt_value(self_obj, 't'); if (optarg) { errno = 0; int value = strtol(optarg, NULL, 0); if (errno != 0 || value <= 0 || value > MAX_DURATION) { log_msg("'-%c' Invalid duration: %s", 't', optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else { s_user_params.sec_test_duration = value; } } else { log_msg("'-%c' Invalid value", 't'); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } if (!rc && aopt_check(self_obj, 'b')) { const char *optarg = aopt_value(self_obj, 'b'); if (optarg) { errno = 0; int value = strtol(optarg, NULL, 0); if (errno != 0 || value < 1) { log_msg("'-%c' Invalid burst size: %s", 'b', optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else { s_user_params.burst_size = value; } } else { log_msg("'-%c' Invalid value", 'b'); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } if (!rc && aopt_check(self_obj, OPT_MPS)) { const char *optarg = aopt_value(self_obj, OPT_MPS); if (optarg) { if (0 == strcmp("MAX", optarg) || 0 == strcmp("max", optarg)) { s_user_params.mps = UINT32_MAX; } else { errno = 0; long long value = strtol(optarg, NULL, 0); if (errno != 0 || value <= 0 || value > 1 << 30) { log_msg("Invalid %d val: %s", OPT_MPS, optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else { s_user_params.mps = (uint32_t)value; } } } else { log_msg("'-%d' Invalid value", OPT_MPS); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } if (!rc && aopt_check(self_obj, OPT_CLIENTPORT)) { if (aopt_check(common_obj, 'f')) { log_msg("--client_port conflicts with -f option"); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else { const char *optarg = aopt_value(self_obj, OPT_CLIENTPORT); if (optarg) { errno = 0; long value = strtol(optarg, NULL, 0); /* strtol() returns 0 if there were no digits at all */ if (errno != 0) { log_msg("'-%c' Invalid port: %s", OPT_CLIENTPORT, optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else { s_user_params.client_bind_info.sin_port = htons((uint16_t)value); } } else { log_msg("'-%c' Invalid value", OPT_CLIENTPORT); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } } if (!rc && aopt_check(self_obj, OPT_CLIENTIP)) { int len; const char *optarg = aopt_value(self_obj, OPT_CLIENTIP); if (!optarg) { /* already in network byte order*/ log_msg("'-%c' Invalid address: %s", OPT_CLIENTIP, optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else if (4 != sscanf(optarg, "%d.%d.%d.%d", &len, &len, &len, &len)) { log_msg("'-%c' Invalid address: %s", OPT_CLIENTIP, optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else if (!inet_aton(optarg, &s_user_params.client_bind_info.sin_addr)) { log_msg("'-%c' Invalid address: %s", OPT_CLIENTIP, optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } if (!rc && aopt_check(self_obj, 'm')) { const char *optarg = aopt_value(self_obj, 'm'); if (optarg) { errno = 0; int value = strtol(optarg, NULL, 0); if (errno != 0 || value < MIN_PAYLOAD_SIZE) { log_msg("'-%c' Invalid message size: %s (min: %d)", 'm', optarg, MIN_PAYLOAD_SIZE); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else if (!aopt_check(common_obj, OPT_TCP) && value > MAX_PAYLOAD_SIZE) { log_msg("'-%c' Invalid message size: %s (max: %d)", 'm', optarg, MAX_PAYLOAD_SIZE); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else if (aopt_check(common_obj, OPT_TCP) && value > MAX_TCP_SIZE) { log_msg("'-%c' Invalid message size: %s (max: %d)", 'm', optarg, MAX_TCP_SIZE); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else { MAX_PAYLOAD_SIZE = value; s_user_params.msg_size = value; } } else { log_msg("'-%c' Invalid value", 'm'); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } if (!rc && aopt_check(self_obj, 'r')) { const char *optarg = aopt_value(self_obj, 'r'); if (optarg && (isNumeric(optarg))) { errno = 0; int value = strtol(optarg, NULL, 0); if (errno != 0 || value < 0) { log_msg("'-%c' Invalid message range: %s", 'r', optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else { s_user_params.msg_size_range = value; } } else { log_msg("'-%c' Invalid value", 'r'); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } } if (rc) { const char *help_str = NULL; char temp_buf[30]; printf("%s: %s\n", display_opt(id, temp_buf, sizeof(temp_buf)), sockperf_modes[id].note); printf("\n"); printf("Usage: " MODULE_NAME " %s [options] [args]...\n", sockperf_modes[id].name); printf(" " MODULE_NAME " %s -i ip [-p port] [-m message_size] [-t time]\n", sockperf_modes[id].name); printf(" " MODULE_NAME " %s -f file [-F s/p/e] [-m message_size] [-r msg_size_range] [-t time]\n", sockperf_modes[id].name); printf("\n"); printf("Options:\n"); help_str = aopt_help(common_opt_desc); if (help_str) { printf("%s\n", help_str); free((void *)help_str); } printf("Valid arguments:\n"); help_str = aopt_help(client_opt_desc); if (help_str) { printf("%s", help_str); free((void *)help_str); help_str = aopt_help(self_opt_desc); if (help_str) { printf("%s", help_str); free((void *)help_str); } printf("\n"); } } /* Destroy option objects */ aopt_exit((AOPT_OBJECT *)common_obj); aopt_exit((AOPT_OBJECT *)client_obj); aopt_exit((AOPT_OBJECT *)self_obj); // In Throughput the default is nagel enabled while the rest mode uses nagel disabled. s_user_params.tcp_nodelay = !s_user_params.tcp_nodelay; return rc; } //------------------------------------------------------------------------------ static int proc_mode_playback(int id, int argc, const char **argv) { int rc = SOCKPERF_ERR_NONE; const AOPT_OBJECT *common_obj = NULL; const AOPT_OBJECT *client_obj = NULL; const AOPT_OBJECT *self_obj = NULL; /* * List of supported under-load options. */ const AOPT_DESC self_opt_desc[] = { { OPT_REPLY_EVERY, AOPT_ARG, aopt_set_literal(0), aopt_set_string("reply-every"), "Set number of send messages between reply messages (default = 100)." }, { OPT_PLAYBACK_DATA, AOPT_ARG, aopt_set_literal(0), aopt_set_string("data-file"), "Pre-prepared CSV file with timestamps and message sizes." }, { 0, AOPT_NOARG, aopt_set_literal(0), aopt_set_string(NULL), NULL } }; /* Load supported option and create option objects */ { int valid_argc = 0; int temp_argc = 0; temp_argc = argc; common_obj = aopt_init(&temp_argc, (const char **)argv, common_opt_desc); valid_argc += temp_argc; temp_argc = argc; client_obj = aopt_init(&temp_argc, (const char **)argv, client_opt_desc); valid_argc += temp_argc; temp_argc = argc; self_obj = aopt_init(&temp_argc, (const char **)argv, self_opt_desc); valid_argc += temp_argc; if (valid_argc < (argc - 1)) { rc = SOCKPERF_ERR_BAD_ARGUMENT; } } if (rc || aopt_check(common_obj, 'h')) { rc = -1; } /* Set default values */ s_user_params.mode = MODE_CLIENT; s_user_params.mps = MPS_DEFAULT; s_user_params.reply_every = REPLY_EVERY_DEFAULT; /* Set command line common options */ if (!rc && common_obj) { rc = parse_common_opt(common_obj); } /* Set command line client values */ if (!rc && client_obj) { rc = parse_client_opt(client_obj); } /* Set command line specific values */ if (!rc && self_obj) { if (!rc && aopt_check(self_obj, OPT_PLAYBACK_DATA)) { const char *optarg = aopt_value(self_obj, OPT_PLAYBACK_DATA); if (optarg) { static PlaybackVector pv; loadPlaybackData(pv, optarg); s_user_params.pPlaybackVector = &pv; } else { log_msg("'-%d' Invalid value", OPT_PLAYBACK_DATA); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } if (!rc && aopt_check(self_obj, OPT_REPLY_EVERY)) { const char *optarg = aopt_value(self_obj, OPT_REPLY_EVERY); if (optarg) { errno = 0; long long value = strtol(optarg, NULL, 0); if (errno != 0 || value <= 0 || value > 1 << 30) { log_msg("Invalid %d val: %s", OPT_REPLY_EVERY, optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else { s_user_params.reply_every = (uint32_t)value; } } else { log_msg("'-%d' Invalid value", OPT_REPLY_EVERY); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } } /* force --data-file */ if (!rc && (!self_obj || (self_obj && !aopt_check(self_obj, OPT_PLAYBACK_DATA)))) { log_msg("--data-file must be used with playback mode"); rc = SOCKPERF_ERR_BAD_ARGUMENT; } if (rc) { const char *help_str = NULL; char temp_buf[30]; printf("%s: %s\n", display_opt(id, temp_buf, sizeof(temp_buf)), sockperf_modes[id].note); printf("\n"); printf("Usage: " MODULE_NAME " %s [options] [args]...\n", sockperf_modes[id].name); printf(" " MODULE_NAME " %s -i ip [-p port] --data-file playback.csv\n", sockperf_modes[id].name); printf("\n"); printf("Options:\n"); help_str = aopt_help(common_opt_desc); if (help_str) { printf("%s\n", help_str); free((void *)help_str); } printf("Valid arguments:\n"); help_str = aopt_help(client_opt_desc); if (help_str) { printf("%s", help_str); free((void *)help_str); help_str = aopt_help(self_opt_desc); if (help_str) { printf("%s", help_str); free((void *)help_str); } printf("\n"); } } /* Destroy option objects */ aopt_exit((AOPT_OBJECT *)common_obj); aopt_exit((AOPT_OBJECT *)client_obj); aopt_exit((AOPT_OBJECT *)self_obj); return rc; } //------------------------------------------------------------------------------ static int proc_mode_server(int id, int argc, const char **argv) { int rc = SOCKPERF_ERR_NONE; const AOPT_OBJECT *common_obj = NULL; const AOPT_OBJECT *server_obj = NULL; /* * List of supported server options. */ static const AOPT_DESC server_opt_desc[] = { /* { 'B', AOPT_NOARG, aopt_set_literal( 'B' ), aopt_set_string( "Bridge" ), "Run in Bridge mode." }, */ { OPT_THREADS_NUM, AOPT_ARG, aopt_set_literal(0), aopt_set_string("threads-num"), "Run threads on server side (requires '-f' option)." }, { OPT_THREADS_AFFINITY, AOPT_ARG, aopt_set_literal(0), aopt_set_string("cpu-affinity"), "Set threads affinity to the given core ids in list format (see: cat /proc/cpuinfo)." }, #ifndef WIN32 { OPT_VMARXFILTERCB, AOPT_NOARG, aopt_set_literal(0), aopt_set_string("vmarxfiltercb"), "Use VMA's receive path message filter callback API (See VMA's readme)." }, #endif { OPT_FORCE_UC_REPLY, AOPT_NOARG, aopt_set_literal(0), aopt_set_string("force-unicast-reply"), "Force server to reply via unicast." }, { OPT_DONT_REPLY, AOPT_NOARG, aopt_set_literal(0), aopt_set_string("dont-reply"), "Server won't reply to the client messages." }, { 'm', AOPT_ARG, aopt_set_literal('m'), aopt_set_string("msg-size"), "Set maximum message size that the server can receive bytes (default 65507)." }, { 'g', AOPT_NOARG, aopt_set_literal('g'), aopt_set_string("gap-detection"), "Enable gap-detection." }, { 0, AOPT_NOARG, aopt_set_literal(0), aopt_set_string(NULL), NULL } }; /* Load supported option and create option objects */ { int valid_argc = 0; int temp_argc = 0; temp_argc = argc; common_obj = aopt_init(&temp_argc, (const char **)argv, common_opt_desc); valid_argc += temp_argc; temp_argc = argc; server_obj = aopt_init(&temp_argc, (const char **)argv, server_opt_desc); valid_argc += temp_argc; if (valid_argc < (argc - 1)) { rc = SOCKPERF_ERR_BAD_ARGUMENT; } } if (rc || aopt_check(common_obj, 'h')) { rc = -1; } /* Set default values */ s_user_params.mode = MODE_SERVER; s_user_params.mps = MPS_DEFAULT; s_user_params.msg_size = MAX_PAYLOAD_SIZE; /* Set command line common options */ if (!rc && common_obj) { rc = parse_common_opt(common_obj); } /* Set command line specific values */ if (!rc && server_obj) { struct sockaddr_in *p_addr = &s_user_params.addr; if (!rc && aopt_check(server_obj, 'B')) { log_msg("update to bridge mode"); s_user_params.mode = MODE_BRIDGE; p_addr->sin_port = htons(5001); /*iperf's default port*/ } if (!rc && aopt_check(server_obj, OPT_THREADS_NUM)) { if (aopt_check(common_obj, 'f')) { const char *optarg = aopt_value(server_obj, OPT_THREADS_NUM); if (optarg) { s_user_params.mthread_server = 1; errno = 0; int threads_num = strtol(optarg, NULL, 0); if (errno != 0 || threads_num <= 0) { log_msg("'-%d' Invalid threads number: %s", OPT_THREADS_NUM, optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else { s_user_params.threads_num = threads_num; } } else { log_msg("'-%d' Invalid value", OPT_THREADS_NUM); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } else { log_msg("--threads-num must be used with feed file (option '-f')"); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } if (!rc && aopt_check(server_obj, OPT_THREADS_AFFINITY)) { const char *optarg = aopt_value(server_obj, OPT_THREADS_AFFINITY); if (optarg) { strcpy(s_user_params.threads_affinity, optarg); } else { log_msg("'-%d' Invalid threads affinity", OPT_THREADS_AFFINITY); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } #ifndef WIN32 if (!rc && aopt_check(server_obj, OPT_VMARXFILTERCB)) { s_user_params.is_vmarxfiltercb = true; } #endif if (!rc && aopt_check(server_obj, OPT_FORCE_UC_REPLY)) { s_user_params.b_server_reply_via_uc = true; } if (!rc && aopt_check(server_obj, OPT_DONT_REPLY)) { if (aopt_check(common_obj, OPT_TCP)) { log_msg("--tcp conflicts with --dont-reply option"); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else { s_user_params.b_server_dont_reply = true; } } if (!rc && aopt_check(server_obj, 'm')) { const char *optarg = aopt_value(server_obj, 'm'); if (optarg) { int value = strtol(optarg, NULL, 0); if ((value > MAX_TCP_SIZE) || !(isNumeric(optarg))) { log_msg("'-%c' Invalid message size: %s (max: %d)", 'm', optarg, MAX_TCP_SIZE); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else { MAX_PAYLOAD_SIZE = _max(MAX_PAYLOAD_SIZE, value); } } } if (!rc && aopt_check(server_obj, 'g')) { s_user_params.b_server_detect_gaps = true; } } if (rc) { const char *help_str = NULL; char temp_buf[30]; printf("%s: %s\n", display_opt(id, temp_buf, sizeof(temp_buf)), sockperf_modes[id].note); printf("\n"); printf("Usage: " MODULE_NAME " %s [options] [args]...\n", sockperf_modes[id].name); printf(" " MODULE_NAME " %s\n", sockperf_modes[id].name); printf(" " MODULE_NAME " %s [-i ip] [-p port] [--mc-rx-if ip] [--mc-tx-if ip] [--mc-source-filter ip]\n", sockperf_modes[id].name); #ifndef WIN32 printf(" " MODULE_NAME " %s -f file [-F s/p/e] [--mc-rx-if ip] [--mc-tx-if ip] [--mc-source-filter ip]\n", sockperf_modes[id].name); #else printf(" " MODULE_NAME " %s -f file [-F s] [--mc-rx-if ip] [--mc-tx-if ip] [--mc-source-filter ip]\n", sockperf_modes[id].name); #endif printf("\n"); printf("Options:\n"); help_str = aopt_help(common_opt_desc); if (help_str) { printf("%s\n", help_str); free((void *)help_str); } printf("Valid arguments:\n"); help_str = aopt_help(server_opt_desc); if (help_str) { printf("%s\n", help_str); free((void *)help_str); } } /* Destroy option objects */ aopt_exit((AOPT_OBJECT *)common_obj); aopt_exit((AOPT_OBJECT *)server_obj); return rc; } //------------------------------------------------------------------------------ static int parse_common_opt(const AOPT_OBJECT *common_obj) { int rc = SOCKPERF_ERR_NONE; if (common_obj) { struct sockaddr_in *p_addr = &s_user_params.addr; int *p_daemonize = &s_user_params.daemonize; char *feedfile_name = s_user_params.feedfile_name; if (!rc && aopt_check(common_obj, 'd')) { g_debug_level = LOG_LVL_DEBUG; } if (!rc && aopt_check(common_obj, 'i')) { const char *optarg = aopt_value(common_obj, 'i'); int len; if (!optarg) { /* already in network byte order*/ log_msg("'-%c' Invalid address: %s", 'i', optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else if (4 != sscanf(optarg, "%d.%d.%d.%d", &len, &len, &len, &len)) { log_msg("'-%c' Invalid address: %s", 'i', optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else if (!inet_aton(optarg, &p_addr->sin_addr)) { struct hostent *hostip = gethostbyname(optarg); if (hostip) { memcpy(&p_addr->sin_addr, hostip->h_addr_list[0], hostip->h_length); s_user_params.fd_handler_type = RECVFROM; } else { log_msg("'-%c' Invalid address: %s", 'i', optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } else { s_user_params.fd_handler_type = RECVFROM; } } if (!rc && aopt_check(common_obj, 'p')) { const char *optarg = aopt_value(common_obj, 'p'); if (optarg && (isNumeric(optarg))) { errno = 0; long value = strtol(optarg, NULL, 0); /* strtol() returns 0 if there were no digits at all */ if (errno != 0) { log_msg("'-%c' Invalid port: %s", 'p', optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else { p_addr->sin_port = htons((uint16_t)value); s_user_params.fd_handler_type = RECVFROM; } } else { log_msg("'-%c' Invalid value", 'p'); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } if (!rc && aopt_check(common_obj, 'f')) { if (!aopt_check(common_obj, 'i') && !aopt_check(common_obj, 'p')) { const char *optarg = aopt_value(common_obj, 'f'); if (optarg) { strncpy(feedfile_name, optarg, MAX_ARGV_SIZE); feedfile_name[MAX_PATH_LENGTH - 1] = '\0'; #if defined(WIN32) && defined(__FreeBSD__) s_user_params.fd_handler_type = SELECT; #else s_user_params.fd_handler_type = EPOLL; #endif } else { log_msg("'-%c' Invalid value", 'f'); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } else { log_msg("-f conflicts with -i,-p options"); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } if (!rc && aopt_check(common_obj, 'F')) { if (aopt_check(common_obj, 'f')) { const char *optarg = aopt_value(common_obj, 'F'); if (optarg) { char fd_handle_type[MAX_ARGV_SIZE]; strncpy(fd_handle_type, optarg, MAX_ARGV_SIZE); fd_handle_type[MAX_ARGV_SIZE - 1] = '\0'; #ifndef WIN32 #ifndef __FreeBSD__ if (!strcmp(fd_handle_type, "epoll") || !strcmp(fd_handle_type, "e")) { s_user_params.fd_handler_type = EPOLL; } else #endif if (!strcmp(fd_handle_type, "poll") || !strcmp(fd_handle_type, "p")) { s_user_params.fd_handler_type = POLL; } else #endif if (!strcmp(fd_handle_type, "select") || !strcmp(fd_handle_type, "s")) { s_user_params.fd_handler_type = SELECT; } else if (!strcmp(fd_handle_type, "recvfrom") || !strcmp(fd_handle_type, "r")) { s_user_params.fd_handler_type = RECVFROMMUX; } else if (!strcmp(fd_handle_type, "socketxtreme") || !strcmp(fd_handle_type, "x")) { s_user_params.fd_handler_type = SOCKETXTREME; s_user_params.is_blocked = false; } else { log_msg("'-%c' Invalid muliply io hanlde type: %s", 'F', optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } else { log_msg("'-%c' Invalid value", 'F'); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } else { log_msg("-F must be used with feed file (option '-f')"); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } if (!rc && aopt_check(common_obj, 'a')) { const char *optarg = aopt_value(common_obj, 'a'); if (optarg) { errno = 0; s_user_params.packetrate_stats_print_ratio = strtol(optarg, NULL, 0); s_user_params.packetrate_stats_print_details = false; if (errno != 0) { log_msg("'-%c' Invalid message rate stats print value: %d", 'a', s_user_params.packetrate_stats_print_ratio); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } else { log_msg("'-%c' Invalid value", 'a'); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } if (!rc && aopt_check(common_obj, 'A')) { const char *optarg = aopt_value(common_obj, 'A'); if (optarg) { errno = 0; s_user_params.packetrate_stats_print_ratio = strtol(optarg, NULL, 0); s_user_params.packetrate_stats_print_details = true; if (errno != 0) { log_msg("'-%c' Invalid message rate stats print value: %d", 'A', s_user_params.packetrate_stats_print_ratio); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } else { log_msg("'-%c' Invalid value", 'A'); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } if (!rc && aopt_check(common_obj, OPT_RX_MC_IF)) { const char *optarg = aopt_value(common_obj, OPT_RX_MC_IF); if (!optarg || ((s_user_params.rx_mc_if_addr.s_addr = inet_addr(optarg)) == INADDR_NONE)) { /* already in network byte order*/ log_msg("'-%d' Invalid address: %s", OPT_RX_MC_IF, optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } if (!rc && aopt_check(common_obj, OPT_TX_MC_IF)) { const char *optarg = aopt_value(common_obj, OPT_TX_MC_IF); if (!optarg || ((s_user_params.tx_mc_if_addr.s_addr = inet_addr(optarg)) == INADDR_NONE)) { /* already in network byte order*/ log_msg("'-%d' Invalid address: %s", OPT_TX_MC_IF, optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } if (!rc && aopt_check(common_obj, OPT_MC_SOURCE_IP)) { const char *optarg = aopt_value(common_obj, OPT_MC_SOURCE_IP); if (optarg) { if (!inet_aton(optarg, &(s_user_params.mc_source_ip_addr))) { struct hostent *hostip = gethostbyname(optarg); if (hostip) { memcpy(&(s_user_params.mc_source_ip_addr), hostip->h_addr_list[0], hostip->h_length); } else { log_msg("Invalid multicast source address: '%s'", optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } } else { log_msg("'-%d' Invalid address: %s", OPT_MC_SOURCE_IP, optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } if (!rc && aopt_check(common_obj, OPT_SELECT_TIMEOUT)) { const char *optarg = aopt_value(common_obj, OPT_SELECT_TIMEOUT); if (optarg) { errno = 0; int value = strtol(optarg, NULL, 0); if (errno != 0 || value < -1) { #ifdef WIN32 log_msg("'-%d' Invalid select timeout val: %s", OPT_SELECT_TIMEOUT, optarg); #elif __FreeBSD__ log_msg("'-%d' Invalid select/poll timeout val: %s", OPT_SELECT_TIMEOUT, optarg); #else log_msg("'-%d' Invalid select/poll/epoll timeout val: %s", OPT_SELECT_TIMEOUT, optarg); #endif rc = SOCKPERF_ERR_BAD_ARGUMENT; } else { set_select_timeout(value); } } else { log_msg("'-%d' Invalid value", OPT_SELECT_TIMEOUT); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } if (!rc && aopt_check(common_obj, OPT_MC_LOOPBACK_ENABLE)) { s_user_params.mc_loop_disable = false; } if (!rc && aopt_check(common_obj, OPT_UC_REUSEADDR)) { s_user_params.uc_reuseaddr = true; } if (!rc && aopt_check(common_obj, OPT_BUFFER_SIZE)) { const char *optarg = aopt_value(common_obj, OPT_BUFFER_SIZE); if (optarg) { errno = 0; int value = strtol(optarg, NULL, 0); if (errno != 0 || value <= 0) { log_msg("'-%d' Invalid socket buffer size: %s", OPT_BUFFER_SIZE, optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else { s_user_params.sock_buff_size = value; } } else { log_msg("'-%d' Invalid value", OPT_BUFFER_SIZE); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } if (!rc && aopt_check(common_obj, OPT_NONBLOCKED)) { s_user_params.is_blocked = false; } if (!rc && aopt_check(common_obj, OPT_TOS)) { const char *optarg = aopt_value(common_obj, OPT_TOS); if (optarg) { #if defined(WIN32) || defined(_WIN32) log_msg("TOS option not supported for Windows"); rc = SOCKPERF_ERR_UNSUPPORTED; #else int value = strtol(optarg, NULL, 0); s_user_params.tos = value; #endif } } if (!rc && aopt_check(common_obj, OPT_LLS)) { const char *optarg = aopt_value(common_obj, OPT_LLS); if (optarg) { #if defined(WIN32) || defined(_WIN32) log_msg("LLS option not supported for Windows"); rc = SOCKPERF_ERR_UNSUPPORTED; #else errno = 0; int value = strtoul(optarg, NULL, 0); if (errno != 0 || value < 0) { log_msg("'-%d' Invalid LLS value: %s", OPT_LLS, optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else { s_user_params.lls_usecs = value; s_user_params.lls_is_set = true; } } else { log_msg("'-%d' Invalid value", OPT_LLS); rc = SOCKPERF_ERR_BAD_ARGUMENT; #endif } } if (!rc && aopt_check(common_obj, OPT_NONBLOCKED_SEND)) { s_user_params.is_nonblocked_send = true; } if (!rc && aopt_check(common_obj, OPT_RECV_LOOPING)) { const char *optarg = aopt_value(common_obj, OPT_RECV_LOOPING); if (optarg) { errno = 0; int value = strtol(optarg, NULL, 0); if (errno != 0) { log_msg("Invalid number of loops - %d: %s", OPT_RECV_LOOPING, optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else { if (1 != value) { if (!aopt_check(common_obj, OPT_NONBLOCKED)) { log_msg("recv_looping_num larger then one must be used in a " "none-blocked mode only. add --nonblocked."); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } else if (0 == value) { log_msg("recv_looping_num cannot be equal to 0."); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else { s_user_params.max_looping_over_recv = value; } } } else { log_msg("'-%d' Invalid value", OPT_RECV_LOOPING); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } if (!rc && aopt_check(common_obj, OPT_DONTWARMUP)) { s_user_params.do_warmup = false; } if (!rc && aopt_check(common_obj, OPT_PREWARMUPWAIT)) { const char *optarg = aopt_value(common_obj, OPT_PREWARMUPWAIT); if (optarg) { errno = 0; int value = strtol(optarg, NULL, 0); if (errno != 0 || value <= 0) { log_msg("'-%d' Invalid pre warmup wait: %s", OPT_PREWARMUPWAIT, optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else { s_user_params.pre_warmup_wait = value; } } else { log_msg("'-%d' Invalid value", OPT_PREWARMUPWAIT); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } if (!rc && aopt_check(common_obj, OPT_SOCK_ACCL)) { s_user_params.withsock_accl = true; } #ifndef WIN32 if (!rc && aopt_check(common_obj, OPT_VMAZCOPYREAD)) { s_user_params.is_vmazcopyread = true; } if (!rc && aopt_check(common_obj, OPT_DAEMONIZE)) { *p_daemonize = true; } if (!rc && aopt_check(common_obj, OPT_NO_RDTSC)) { s_user_params.b_no_rdtsc = true; } if (!rc && aopt_check(common_obj, OPT_RATE_LIMIT)) { const char *optarg = aopt_value(common_obj, OPT_RATE_LIMIT); if (optarg) { errno = 0; uint32_t value = strtol(optarg, NULL, 0); if (errno != 0 || value <= 0) { log_msg("'-%d' Invalid rate limit : %s", OPT_RATE_LIMIT, optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else { s_user_params.rate_limit = value; } } else { log_msg("'-%d' Invalid value", OPT_RATE_LIMIT); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } #if defined(__arm__) || defined(__aarch64__) if (s_user_params.b_no_rdtsc == false) { log_msg("ARM target build does not support rdtsc, use --no-rdtsc"); rc = SOCKPERF_ERR_BAD_ARGUMENT; } #endif #ifndef __FreeBSD__ if (!rc && aopt_check(common_obj, OPT_LOAD_VMA)) { const char *optarg = aopt_value(common_obj, OPT_LOAD_VMA); // s_user_params.b_load_vma = true; if (!optarg || !*optarg) optarg = (char *)"libvma.so"; // default value bool success = vma_set_func_pointers(optarg); if (!success) { log_msg("Invalid --load-vma value: %s: failed to set function pointers using the " "given libvma.so path:", optarg); log_msg("dlerror() says: %s:", dlerror()); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } #endif #endif if (!rc && aopt_check(common_obj, OPT_TCP)) { if (!aopt_check(common_obj, 'f')) { s_user_params.sock_type = SOCK_STREAM; } else { log_msg("--tcp conflicts with -f option"); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } if (!rc && aopt_check(common_obj, OPT_TCP_NODELAY_OFF)) { s_user_params.tcp_nodelay = false; } if (!rc && aopt_check(common_obj, OPT_IP_MULTICAST_TTL)) { const char *optarg = aopt_value(common_obj, OPT_IP_MULTICAST_TTL); if (optarg) { errno = 0; int value = strtol(optarg, NULL, 0); if (errno != 0 || value < 0 || value > 255) { log_msg("'-%d' Invalid value: %s", OPT_IP_MULTICAST_TTL, optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else { s_user_params.mc_ttl = value; } } else { log_msg("'-%d' Invalid value", OPT_IP_MULTICAST_TTL); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } } return rc; } //------------------------------------------------------------------------------ static int parse_client_opt(const AOPT_OBJECT *client_obj) { int rc = SOCKPERF_ERR_NONE; s_user_params.mode = MODE_CLIENT; if (client_obj) { if (!rc && aopt_check(client_obj, OPT_CLIENT_WORK_WITH_SRV_NUM)) { const char *optarg = aopt_value(client_obj, OPT_CLIENT_WORK_WITH_SRV_NUM); if (optarg) { errno = 0; int value = strtol(optarg, NULL, 0); if (errno != 0 || value < 1) { log_msg("'-%d' Invalid server num val: %s", OPT_CLIENT_WORK_WITH_SRV_NUM, optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else { s_user_params.client_work_with_srv_num = value; } } else { log_msg("'-%d' Invalid value", OPT_CLIENT_WORK_WITH_SRV_NUM); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } if (!rc && aopt_check(client_obj, OPT_SENDER_AFFINITY)) { const char *optarg = aopt_value(client_obj, OPT_SENDER_AFFINITY); if (optarg) { strcpy(s_user_params.sender_affinity, optarg); } else { log_msg("'-%d' Invalid sender affinity", OPT_SENDER_AFFINITY); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } if (!rc && aopt_check(client_obj, OPT_RECEIVER_AFFINITY)) { const char *optarg = aopt_value(client_obj, OPT_RECEIVER_AFFINITY); if (optarg) { strcpy(s_user_params.receiver_affinity, optarg); } else { log_msg("'-%d' Invalid receiver affinity", OPT_RECEIVER_AFFINITY); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } if (!rc && aopt_check(client_obj, OPT_FULL_LOG)) { const char *optarg = aopt_value(client_obj, OPT_FULL_LOG); if (optarg) { errno = 0; s_user_params.fileFullLog = fopen(optarg, "w"); if (errno || !s_user_params.fileFullLog) { log_msg("Invalid %d val. Can't open file %s for writing: %m", OPT_FULL_LOG, optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } else { log_msg("'-%d' Invalid value", OPT_FULL_LOG); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } if (!rc && aopt_check(client_obj, OPT_FULL_RTT)) { s_user_params.full_rtt = true; } if (!rc && aopt_check(client_obj, OPT_GIGA_SIZE)) { s_user_params.giga_size = true; } if (!rc && aopt_check(client_obj, OPT_OUTPUT_PRECISION)) { s_user_params.increase_output_precision = true; } if (!rc && aopt_check(client_obj, OPT_DUMMY_SEND)) { s_user_params.dummy_mps = DUMMY_SEND_MPS_DEFAULT; const char *optarg = aopt_value(client_obj, OPT_DUMMY_SEND); if (optarg) { if (0 == strcmp("MAX", optarg) || 0 == strcmp("max", optarg)) { s_user_params.dummy_mps = UINT32_MAX; } else { errno = 0; int value = strtol(optarg, NULL, 0); if (errno != 0 || value <= 0 || value > 1 << 30) { log_msg("'-%d' Invalid value of dummy send rate : %s", OPT_DUMMY_SEND, optarg); rc = SOCKPERF_ERR_BAD_ARGUMENT; } else { s_user_params.dummy_mps = (uint32_t)value; } } } } } return rc; } //------------------------------------------------------------------------------ static char *display_opt(int id, char *buf, size_t buf_size) { char *cur_ptr = buf; if (buf && buf_size) { int cur_len = 0; int ret = 0; int j = 0; ret = snprintf((cur_ptr + cur_len), (buf_size - cur_len), "%s", sockperf_modes[id].name); cur_len += (ret < 0 ? 0 : ret); for (j = 0; (ret >= 0) && (sockperf_modes[id].shorts[j] != NULL); j++) { if (j == 0) { ret = snprintf((cur_ptr + cur_len), (buf_size - cur_len), " (%s", sockperf_modes[id].shorts[j]); } else { ret = snprintf((cur_ptr + cur_len), (buf_size - cur_len), " ,%s", sockperf_modes[id].shorts[j]); } cur_len += (ret < 0 ? 0 : ret); } if ((j > 0) && (ret >= 0)) { ret = snprintf((cur_ptr + cur_len), (buf_size - cur_len), ")"); cur_len += (ret < 0 ? 0 : ret); } } return (cur_ptr ? cur_ptr : (char *)""); } //#define ST_TEST // use it with command such as: VMA ./sockperf -s -f conf/conf.inp --vmarxfiltercb #ifdef ST_TEST static int st1, st2; #endif //------------------------------------------------------------------------------ void cleanup() { os_mutex_lock(&_mutex); int ifd; if (g_fds_array) { for (ifd = 0; ifd <= s_fd_max; ifd++) { if (g_fds_array[ifd]) { close(ifd); if (g_fds_array[ifd]->active_fd_list) { FREE(g_fds_array[ifd]->active_fd_list); } if (g_fds_array[ifd]->recv.buf) { FREE(g_fds_array[ifd]->recv.buf); } if (g_fds_array[ifd]->is_multicast) { FREE(g_fds_array[ifd]->memberships_addr); } FREE(g_fds_array[ifd]); } } } if (s_user_params.select_timeout) { FREE(s_user_params.select_timeout); } #ifdef USING_VMA_EXTRA_API if (g_vma_api && s_user_params.is_vmazcopyread) { zeroCopyMap::iterator it; while ((it = g_zeroCopyData.begin()) != g_zeroCopyData.end()) { delete it->second; g_zeroCopyData.erase(it); } } #endif if (g_fds_array) { FREE(g_fds_array); } if (NULL != g_pPacketTimes) { delete g_pPacketTimes; g_pPacketTimes = NULL; } os_mutex_unlock(&_mutex); if (sock_lib_started && !os_sock_cleanup()) { log_err("Failed to cleanup WSA"); // Only relevant for Windows } } //------------------------------------------------------------------------------ /* set the timeout of select*/ static void set_select_timeout(int time_out_msec) { if (!s_user_params.select_timeout) { s_user_params.select_timeout = (struct timeval *)MALLOC(sizeof(struct timeval)); if (!s_user_params.select_timeout) { log_err("Failed to allocate memory for pointer select timeout structure"); exit_with_log(SOCKPERF_ERR_NO_MEMORY); } } if (time_out_msec >= 0) { // Update timeout s_user_params.select_timeout->tv_sec = time_out_msec / 1000; s_user_params.select_timeout->tv_usec = 1000 * (time_out_msec - s_user_params.select_timeout->tv_sec * 1000); } else { // Clear timeout FREE(s_user_params.select_timeout); } } //------------------------------------------------------------------------------ void set_defaults() { #if !defined(WIN32) && !defined(__FreeBSD__) bool success = vma_set_func_pointers(false); if (!success) { log_dbg("Failed to set function pointers for system functions."); log_dbg("Check vma-redirect.cpp for functions which your OS implementation is missing. " "Re-compile sockperf without them."); } #endif g_fds_array = (fds_data **)MALLOC(MAX_FDS_NUM * sizeof(fds_data *)); if (!g_fds_array) { log_err("Failed to allocate memory for global pointer fds_array"); exit_with_log(SOCKPERF_ERR_NO_MEMORY); } int igmp_max_memberships = read_int_from_sys_file("/proc/sys/net/ipv4/igmp_max_memberships"); if (igmp_max_memberships != -1) IGMP_MAX_MEMBERSHIPS = igmp_max_memberships; memset(&s_user_params, 0, sizeof(struct user_params_t)); memset(g_fds_array, 0, sizeof(fds_data *) * MAX_FDS_NUM); s_user_params.rx_mc_if_addr.s_addr = htonl(INADDR_ANY); s_user_params.tx_mc_if_addr.s_addr = htonl(INADDR_ANY); s_user_params.mc_source_ip_addr.s_addr = htonl(INADDR_ANY); s_user_params.sec_test_duration = DEFAULT_TEST_DURATION; s_user_params.client_bind_info.sin_family = AF_INET; s_user_params.client_bind_info.sin_addr.s_addr = INADDR_ANY; s_user_params.client_bind_info.sin_port = 0; s_user_params.mode = MODE_SERVER; s_user_params.packetrate_stats_print_ratio = 0; s_user_params.packetrate_stats_print_details = false; s_user_params.burst_size = 1; s_user_params.data_integrity = false; s_user_params.fd_handler_type = RECVFROM; s_user_params.mthread_server = 0; s_user_params.msg_size = MIN_PAYLOAD_SIZE; s_user_params.msg_size_range = 0; s_user_params.sock_buff_size = SOCK_BUFF_DEFAULT_SIZE; set_select_timeout(DEFAULT_SELECT_TIMEOUT_MSEC); s_user_params.threads_num = 1; memset(s_user_params.threads_affinity, 0, sizeof(s_user_params.threads_affinity)); s_user_params.is_blocked = true; s_user_params.is_nonblocked_send = false; s_user_params.max_looping_over_recv = 1; s_user_params.do_warmup = true; s_user_params.pre_warmup_wait = 0; s_user_params.is_vmarxfiltercb = false; s_user_params.is_vmazcopyread = false; g_debug_level = LOG_LVL_INFO; s_user_params.mc_loop_disable = true; s_user_params.uc_reuseaddr = false; s_user_params.client_work_with_srv_num = DEFAULT_CLIENT_WORK_WITH_SRV_NUM; s_user_params.b_server_reply_via_uc = false; s_user_params.b_server_dont_reply = false; s_user_params.b_server_detect_gaps = false; s_user_params.mps = MPS_DEFAULT; s_user_params.reply_every = REPLY_EVERY_DEFAULT; s_user_params.b_client_ping_pong = false; #if defined(__arm__) || defined(__aarch64__) s_user_params.b_no_rdtsc = true; #else s_user_params.b_no_rdtsc = false; #endif memset(s_user_params.sender_affinity, 0, sizeof(s_user_params.sender_affinity)); memset(s_user_params.receiver_affinity, 0, sizeof(s_user_params.receiver_affinity)); // s_user_params.b_load_vma = false; s_user_params.fileFullLog = NULL; s_user_params.b_stream = false; s_user_params.full_rtt = false; s_user_params.giga_size = false; s_user_params.increase_output_precision = false; s_user_params.pPlaybackVector = NULL; s_user_params.addr.sin_family = AF_INET; s_user_params.addr.sin_port = htons(DEFAULT_PORT); inet_aton(DEFAULT_MC_ADDR, &s_user_params.addr.sin_addr); s_user_params.sock_type = SOCK_DGRAM; s_user_params.tcp_nodelay = true; s_user_params.mc_ttl = 2; s_user_params.daemonize = false; s_user_params.withsock_accl = false; s_user_params.dummy_mps = 0; memset(s_user_params.feedfile_name, 0, sizeof(s_user_params.feedfile_name)); s_user_params.tos = 0x00; } //------------------------------------------------------------------------------ #ifdef USING_VMA_EXTRA_API vma_recv_callback_retval_t myapp_vma_recv_pkt_filter_callback(int fd, size_t iov_sz, struct iovec iov[], struct vma_info_t *vma_info, void *context) { #ifdef ST_TEST if (st1) { log_msg("DEBUG: ST_TEST - myapp_vma_recv_pkt_filter_callback fd=%d", fd); close(st1); close(st2); st1 = st2 = 0; } #endif if (iov_sz) { }; if (context) { }; // Check info structure version if (vma_info->struct_sz < sizeof(struct vma_info_t)) { log_msg("VMA's info struct is not something we can handle so un-register the application's " "callback function"); g_vma_api->register_recv_callback(fd, NULL, NULL); return VMA_PACKET_RECV; } // If there is data in local buffer, then push new packet in TCP queue.Otherwise handle received // packet inside callback. if (g_zeroCopyData[fd] && g_zeroCopyData[fd]->m_pkts && g_zeroCopyData[fd]->m_pkts->n_packet_num > 0) { return VMA_PACKET_RECV; } size_t index; int nbytes; struct fds_data *l_fds_ifd; Message *msgReply; uint8_t *start_addrs; struct sockaddr_in sendto_addr; l_fds_ifd = g_fds_array[fd]; if (!l_fds_ifd) { return VMA_PACKET_RECV; } msgReply = l_fds_ifd->p_msg; // Copy and concatenate received data in local reserved buffer nbytes = 0; for (index = 0; index < iov_sz; index++) { nbytes += iov[index].iov_len; } if (nbytes > l_fds_ifd->recv.cur_size) { memmove(l_fds_ifd->recv.buf, l_fds_ifd->recv.cur_addr, l_fds_ifd->recv.cur_offset); l_fds_ifd->recv.cur_addr = l_fds_ifd->recv.buf; l_fds_ifd->recv.cur_size = l_fds_ifd->recv.max_size - l_fds_ifd->recv.cur_offset; if (nbytes > l_fds_ifd->recv.cur_size) { log_msg("Can't handle data in callback : Received data bigger than available buffer"); /* * TODO going to recvfrom will not work if this callback call is coming from recvfrom * context. * this is because the callback is working on the same buffer that was given to * recvfrom, so * recvfrom will return and override the data that the callback wrote. * if working with recvfrom, and not with iomux, need to give recvfrom and callback * different buffers. * This should be fixed in sockperf, so we also won't need to call the above memmove. */ return VMA_PACKET_RECV; } } nbytes = 0; for (index = 0; index < iov_sz; index++) { start_addrs = l_fds_ifd->recv.cur_addr + l_fds_ifd->recv.cur_offset + nbytes; memcpy(start_addrs, iov[index].iov_base, iov[index].iov_len); nbytes += iov[index].iov_len; } while (nbytes) { /* 1: message header is not received yet */ if ((l_fds_ifd->recv.cur_offset + nbytes) < MsgHeader::EFFECTIVE_SIZE) { l_fds_ifd->recv.cur_size -= nbytes; l_fds_ifd->recv.cur_offset += nbytes; /* 4: set current buffer size to size of remained part of message header to * guarantee getting full message header on next iteration */ if (l_fds_ifd->recv.cur_size < MsgHeader::EFFECTIVE_SIZE) { l_fds_ifd->recv.cur_size = MsgHeader::EFFECTIVE_SIZE - l_fds_ifd->recv.cur_offset; } return VMA_PACKET_DROP; } else if (l_fds_ifd->recv.cur_offset < MsgHeader::EFFECTIVE_SIZE) { /* 2: message header is got, match message to cycle buffer */ msgReply->setBuf(l_fds_ifd->recv.cur_addr); msgReply->setHeaderToHost(); } else { /* 2: message header is got, match message to cycle buffer */ msgReply->setBuf(l_fds_ifd->recv.cur_addr); } if ((unsigned)msgReply->getLength() > (unsigned)MAX_PAYLOAD_SIZE) { log_msg("Message received was larger than expected, handle from recv_from"); return VMA_PACKET_RECV; } /* 3: message is not complete */ if ((l_fds_ifd->recv.cur_offset + nbytes) < msgReply->getLength()) { l_fds_ifd->recv.cur_size -= nbytes; l_fds_ifd->recv.cur_offset += nbytes; /* 4: set current buffer size to size of remained part of message to * guarantee getting full message on next iteration (using extended reserved memory) * and shift to start of cycle buffer */ if (l_fds_ifd->recv.cur_size < (int)msgReply->getMaxSize()) { l_fds_ifd->recv.cur_size = msgReply->getLength() - l_fds_ifd->recv.cur_offset; } return VMA_PACKET_DROP; } /* 5: message is complete shift to process next one */ nbytes -= msgReply->getLength() - l_fds_ifd->recv.cur_offset; l_fds_ifd->recv.cur_addr += msgReply->getLength(); l_fds_ifd->recv.cur_size -= msgReply->getLength() - l_fds_ifd->recv.cur_offset; l_fds_ifd->recv.cur_offset = 0; if (g_b_exit) return VMA_PACKET_DROP; if (!msgReply->isClient()) { /* 6: shift to start of cycle buffer in case receiving buffer is empty and * there is no uncompleted message */ if (!nbytes) { l_fds_ifd->recv.cur_addr = l_fds_ifd->recv.buf; l_fds_ifd->recv.cur_size = l_fds_ifd->recv.max_size; l_fds_ifd->recv.cur_offset = 0; } return VMA_PACKET_DROP; } if (msgReply->isWarmupMessage()) { // m_switchCalcGaps.execute(vma_info->src, 0, true); /* 6: shift to start of cycle buffer in case receiving buffer is empty and * there is no uncompleted message */ if (!nbytes) { l_fds_ifd->recv.cur_addr = l_fds_ifd->recv.buf; l_fds_ifd->recv.cur_size = l_fds_ifd->recv.max_size; l_fds_ifd->recv.cur_offset = 0; } return VMA_PACKET_DROP; } g_receiveCount++; if (msgReply->getHeader()->isPongRequest()) { /* if server in a no reply mode - shift to start of cycle buffer*/ if (g_pApp->m_const_params.b_server_dont_reply) { l_fds_ifd->recv.cur_addr = l_fds_ifd->recv.buf; l_fds_ifd->recv.cur_size = l_fds_ifd->recv.max_size; l_fds_ifd->recv.cur_offset = 0; return VMA_PACKET_DROP; } /* prepare message header */ if (g_pApp->m_const_params.mode != MODE_BRIDGE) { msgReply->setServer(); } /* get source addr to reply. memcpy is not used to improve performance */ sendto_addr = l_fds_ifd->server_addr; if (l_fds_ifd->memberships_size || !l_fds_ifd->is_multicast || g_pApp->m_const_params.b_server_reply_via_uc) { // In unicast case reply to sender /* get source addr to reply. memcpy is not used to improve performance */ sendto_addr = *vma_info->src; } else if (l_fds_ifd->is_multicast) { /* always send to the same port recved from */ sendto_addr.sin_port = vma_info->src->sin_port; } int length = msgReply->getLength(); msgReply->setHeaderToNetwork(); msg_sendto(fd, msgReply->getBuf(), length, &sendto_addr); /*if (ret == RET_SOCKET_SHUTDOWN) { if (l_fds_ifd->sock_type == SOCK_STREAM) { close_ifd( l_fds_ifd->next_fd,ifd,l_fds_ifd); } return VMA_PACKET_DROP; }*/ msgReply->setHeaderToHost(); } /* * TODO * To support other server functionality when using zero callback, * pass the server as user_context or as we pass the replyMsg, and call the server functions */ // m_switchCalcGaps.execute(vma_info->src, msgReply->getSequenceCounter(), false); // m_switchActivityInfo.execute(g_receiveCount); } /* 6: shift to start of cycle buffer in case receiving buffer is empty and * there is no uncompleted message */ l_fds_ifd->recv.cur_addr = l_fds_ifd->recv.buf; l_fds_ifd->recv.cur_size = l_fds_ifd->recv.max_size; l_fds_ifd->recv.cur_offset = 0; return VMA_PACKET_DROP; } #endif int sock_set_accl(int fd) { int rc = SOCKPERF_ERR_NONE; if (setsockopt(fd, SOL_SOCKET, 100, NULL, 0) < 0) { log_err("setsockopt(100), set sock-accl failed. It could be that this option is not " "supported in your system"); rc = SOCKPERF_ERR_SOCKET; } log_msg("succeed to set sock-accl"); return rc; } int sock_set_reuseaddr(int fd) { int rc = SOCKPERF_ERR_NONE; u_int reuseaddr_true = 1; if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr_true, sizeof(reuseaddr_true)) < 0) { log_err("setsockopt(SO_REUSEADDR) failed"); rc = SOCKPERF_ERR_SOCKET; } return rc; } #ifndef SO_LL #define SO_LL 46 #endif int sock_set_lls(int fd) { int rc = SOCKPERF_ERR_NONE; if (setsockopt(fd, SOL_SOCKET, SO_LL, &(s_user_params.lls_usecs), sizeof(s_user_params.lls_usecs)) < 0) { log_err("setsockopt(SO_LL) failed"); rc = SOCKPERF_ERR_SOCKET; } return rc; } int sock_set_snd_rcv_bufs(int fd) { /* * Sets or gets the maximum socket receive buffer in bytes. The kernel * doubles this value (to allow space for bookkeeping overhead) when it * is set using setsockopt(), and this doubled value is returned by * getsockopt(). */ int rc = SOCKPERF_ERR_NONE; int size = sizeof(int); int rcv_buff_size = 0; int snd_buff_size = 0; if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &(s_user_params.sock_buff_size), sizeof(s_user_params.sock_buff_size)) < 0) { log_err("setsockopt(SO_RCVBUF) failed"); rc = SOCKPERF_ERR_SOCKET; } if (!rc && (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcv_buff_size, (socklen_t *)&size) < 0)) { log_err("getsockopt(SO_RCVBUF) failed"); rc = SOCKPERF_ERR_SOCKET; } /* * Sets or gets the maximum socket send buffer in bytes. The kernel * doubles this value (to allow space for bookkeeping overhead) when it * is set using setsockopt(), and this doubled value is returned by * getsockopt(). */ if (!rc && (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &(s_user_params.sock_buff_size), sizeof(s_user_params.sock_buff_size)) < 0)) { log_err("setsockopt(SO_SNDBUF) failed"); rc = SOCKPERF_ERR_SOCKET; } if (!rc && (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &snd_buff_size, (socklen_t *)&size) < 0)) { log_err("getsockopt(SO_SNDBUF) failed"); rc = SOCKPERF_ERR_SOCKET; } if (!rc) { log_msg("Socket buffers sizes of fd %d: RX: %d Byte, TX: %d Byte", fd, rcv_buff_size, snd_buff_size); if (rcv_buff_size < s_user_params.sock_buff_size * 2 || snd_buff_size < s_user_params.sock_buff_size * 2) { log_msg("WARNING: Failed setting receive or send socket buffer size to %d bytes (check " "'sysctl net.core.rmem_max' value)", s_user_params.sock_buff_size); } } return rc; } int sock_set_tcp_nodelay(int fd) { int rc = SOCKPERF_ERR_NONE; if (s_user_params.tcp_nodelay) { /* set Delivering Messages Immediately */ int tcp_nodelay = 1; if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&tcp_nodelay, sizeof(tcp_nodelay)) < 0) { log_err("setsockopt(TCP_NODELAY)"); rc = SOCKPERF_ERR_SOCKET; } } return rc; } int sock_set_tos(int fd) { int rc = SOCKPERF_ERR_NONE; if (s_user_params.tos) { socklen_t len = sizeof(s_user_params.tos); if (setsockopt(fd, IPPROTO_IP, IP_TOS, (char *)&s_user_params.tos, len) < 0) { log_err("setsockopt(TOS), set failed. It could be that this option is not supported " "in your system"); rc = SOCKPERF_ERR_SOCKET; } } return rc; } int sock_set_multicast(int fd, struct fds_data *p_data) { int rc = SOCKPERF_ERR_NONE; struct sockaddr_in *p_addr = NULL; p_addr = &(p_data->server_addr); /* use setsockopt() to request that the kernel join a multicast group */ /* and specify a specific interface address on which to receive the packets of this socket */ /* and may specify message source IP address on which to receive from */ /* NOTE: we don't do this if case of client (sender) in stream mode */ if (!s_user_params.b_stream || s_user_params.mode != MODE_CLIENT) { if (p_data->mc_source_ip_addr.s_addr != INADDR_ANY) { struct ip_mreq_source mreq_src; memset(&mreq_src, 0, sizeof(struct ip_mreq_source)); mreq_src.imr_multiaddr = p_addr->sin_addr; mreq_src.imr_interface.s_addr = s_user_params.rx_mc_if_addr.s_addr; mreq_src.imr_sourceaddr.s_addr = p_data->mc_source_ip_addr.s_addr; if (setsockopt(fd, IPPROTO_IP, IP_ADD_SOURCE_MEMBERSHIP, &mreq_src, sizeof(mreq_src)) < 0) { if (errno == ENOBUFS) { log_err("setsockopt(IP_ADD_SOURCE_MEMBERSHIP) - Maximum multicast source " "addresses that can be filtered is limited by " "/proc/sys/net/ipv4/igmp_max_msf"); } else { log_err("setsockopt(IP_ADD_SOURCE_MEMBERSHIP)"); } rc = SOCKPERF_ERR_SOCKET; } } else { struct ip_mreq mreq; memset(&mreq, 0, sizeof(struct ip_mreq)); mreq.imr_multiaddr = p_addr->sin_addr; mreq.imr_interface.s_addr = s_user_params.rx_mc_if_addr.s_addr; if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) { if (errno == ENOBUFS) { log_err("setsockopt(IP_ADD_MEMBERSHIP) - Maximum multicast addresses that can " "join same group is limited by " "/proc/sys/net/ipv4/igmp_max_memberships"); } else { log_err("setsockopt(IP_ADD_MEMBERSHIP)"); } rc = SOCKPERF_ERR_SOCKET; } } } /* specify a specific interface address on which to transmitted the multicast packets of this * socket */ if (!rc && (s_user_params.tx_mc_if_addr.s_addr != INADDR_ANY)) { if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, &s_user_params.tx_mc_if_addr, sizeof(s_user_params.tx_mc_if_addr)) < 0) { log_err("setsockopt(IP_MULTICAST_IF)"); rc = SOCKPERF_ERR_SOCKET; } } if (!rc && (s_user_params.mc_loop_disable)) { /* disable multicast loop of all transmitted packets */ u_char loop_disabled = 0; if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop_disabled, sizeof(loop_disabled)) < 0) { log_err("setsockopt(IP_MULTICAST_LOOP)"); rc = SOCKPERF_ERR_SOCKET; } } if (!rc) { /* the IP_MULTICAST_TTL socket option allows the application to primarily * limit the lifetime of the packet in the Internet and prevent it from * circulating */ int value = s_user_params.mc_ttl; if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&value, sizeof(value)) < 0) { log_err("setsockopt(IP_MULTICAST_TTL)"); rc = SOCKPERF_ERR_SOCKET; } } return rc; } //------------------------------------------------------------------------------ /* returns the new socket fd or exit with error code */ #ifdef ST_TEST int prepare_socket(int fd, struct fds_data *p_data, bool stTest = false) #else int prepare_socket(int fd, struct fds_data *p_data) #endif { int rc = SOCKPERF_ERR_NONE; if (!p_data) { return (int)INVALID_SOCKET; // TODO: use SOCKET all over the way and avoid this cast } if (!rc && !s_user_params.is_blocked) { /*Uncomment to test FIONBIO command of ioctl * int opt = 1; * ioctl(fd, FIONBIO, &opt); */ /* change socket to non-blocking */ if (os_set_nonblocking_socket(fd)) { log_err("failed setting socket as nonblocking\n"); rc = SOCKPERF_ERR_SOCKET; } } if (!rc && (s_user_params.withsock_accl == true)) { rc = sock_set_accl(fd); } if (!rc && ((p_data->is_multicast) || (s_user_params.uc_reuseaddr)) && ((s_user_params.mode == MODE_SERVER && p_data->server_addr.sin_port) || (s_user_params.mode == MODE_CLIENT && s_user_params.client_bind_info.sin_port))) { /* allow multiple sockets to use the same PORT (SO_REUSEADDR) number * only if it is a well know L4 port only for MC or if uc_reuseaddr parameter was set. */ rc = sock_set_reuseaddr(fd); } if (!rc && (s_user_params.lls_is_set == true)) { rc = sock_set_lls(fd); } if (!rc && (s_user_params.sock_buff_size > 0)) { rc = sock_set_snd_rcv_bufs(fd); } if (!rc && (p_data->is_multicast)) { rc = sock_set_multicast(fd, p_data); } if (!rc && (p_data->sock_type == SOCK_STREAM)) { rc = sock_set_tcp_nodelay(fd); } if (!rc && (s_user_params.tos)) { rc = sock_set_tos(fd); } #ifdef USING_VMA_EXTRA_API #ifdef ST_TEST if (!stTest) #endif if (!rc && (s_user_params.is_vmarxfiltercb && g_vma_api)) { // Try to register application with VMA's special receive notification callback logic if (g_vma_api->register_recv_callback(fd, myapp_vma_recv_pkt_filter_callback, NULL) < 0) { log_err("vma_api->register_recv_callback failed. Try running without option " "'vmarxfiltercb'"); } else { log_dbg("vma_api->register_recv_callback successful registered"); } } else if (!rc && (s_user_params.is_vmazcopyread && g_vma_api)) { g_zeroCopyData[fd] = new ZeroCopyData(); g_zeroCopyData[fd]->allocate(); } #endif return (!rc ? fd : (int)INVALID_SOCKET); // TODO: use SOCKET all over the way and avoid this cast } //------------------------------------------------------------------------------ /* get IP:port pairs from the file and initialize the list */ static int set_sockets_from_feedfile(const char *feedfile_name) { int rc = SOCKPERF_ERR_NONE; FILE *file_fd = NULL; char line[MAX_MCFILE_LINE_LENGTH]; char *res; int sock_type = SOCK_DGRAM; char *ip = NULL; char *port = NULL; char *mc_src_ip = NULL; fds_data *tmp; int curr_fd = 0, last_fd = 0; #ifndef WIN32 int regexpres; regex_t regexpr; #endif struct stat st_buf; const int status = stat(feedfile_name, &st_buf); // Get the status of the file system object. if (status != 0) { log_msg("Can't open file: %s\n", feedfile_name); return SOCKPERF_ERR_NOT_EXIST; } #ifndef WIN32 if (!S_ISREG(st_buf.st_mode)) { log_msg("Can't open file: %s -not a regular file.\n", feedfile_name); return SOCKPERF_ERR_NOT_EXIST; } #endif if ((file_fd = fopen(feedfile_name, "r")) == NULL) { log_msg("Can't open file: %s\n", feedfile_name); return SOCKPERF_ERR_NOT_EXIST; } /* a map to keep records on the address we received */ #ifndef __FreeBSD__ std::tr1::unordered_map fd_socket_map; // #else std::unordered_map fd_socket_map; // #endif while (!rc && (res = fgets(line, MAX_MCFILE_LINE_LENGTH, file_fd))) { if (!res) { if (ferror(file_fd)) { log_err("fread()"); fclose(file_fd); return -1; } else { fclose(file_fd); return 0; /* encountered EOF */ } } /* skip empty lines and comments */ if (line[0] == ' ' || line[0] == '\r' || line[0] == '\n' || line[0] == '#') { continue; } #ifndef WIN32 regexpres = regcomp(®expr, IP_PORT_FORMAT_REG_EXP, REG_EXTENDED | REG_NOSUB); if (regexpres) { log_msg("Failed to compile regexp"); rc = SOCKPERF_ERR_FATAL; break; } else { regexpres = regexec(®expr, line, (size_t)0, NULL, 0); regfree(®expr); if (regexpres) { log_msg("Invalid input in line %s: " "each line must have the following format: ip:port or type:ip:port or " "type:ip:port:mc_src_ip", line); rc = SOCKPERF_ERR_INCORRECT; break; } } #endif /* this code support backward compatibility with old format of file */ if (line[0] == 'U' || line[0] == 'u' || line[0] == 'T' || line[0] == 't') { sock_type = (line[0] == 'T' || line[0] == 't' ? SOCK_STREAM : SOCK_DGRAM); strtok(line, ":"); ip = strtok(NULL, ":"); } else { sock_type = SOCK_DGRAM; ip = strtok(line, ":"); } if (sock_type == SOCK_DGRAM && s_user_params.mode == MODE_CLIENT) { if (s_user_params.fd_handler_type == SOCKETXTREME && s_user_params.client_bind_info.sin_addr.s_addr == INADDR_ANY) { log_msg("socketxtreme requires forcing the client side to bind to a specific ip " "address (use --client_ip) option"); rc = SOCKPERF_ERR_INCORRECT; break; } } port = strtok(NULL, ":\n"); mc_src_ip = strtok(NULL, ":\n"); if (!ip || !port) { log_msg("Invalid input in line %s: " "each line must have the following format: ip:port or type:ip:port or " "type:ip:port:mc_src_ip", line); rc = SOCKPERF_ERR_INCORRECT; break; } tmp = (struct fds_data *)MALLOC(sizeof(struct fds_data)); if (!tmp) { log_err("Failed to allocate memory with malloc()"); rc = SOCKPERF_ERR_NO_MEMORY; } else { memset(tmp, 0, sizeof(struct fds_data)); tmp->server_addr.sin_family = AF_INET; tmp->server_addr.sin_port = htons(atoi(port)); tmp->mc_source_ip_addr.s_addr = s_user_params.mc_source_ip_addr.s_addr; if (!inet_aton(ip, &tmp->server_addr.sin_addr)) { struct hostent *hostip = gethostbyname(ip); if (hostip) { memcpy(&(tmp->server_addr.sin_addr), hostip->h_addr_list[0], hostip->h_length); } else { log_msg("Invalid address in line %s: '%s:%s'", line, ip, port); FREE(tmp); rc = SOCKPERF_ERR_INCORRECT; break; } } if ((mc_src_ip) && (!inet_aton(mc_src_ip, &(tmp->mc_source_ip_addr)))) { struct hostent *hostip = gethostbyname(mc_src_ip); if (hostip) { memcpy(&(tmp->mc_source_ip_addr), hostip->h_addr_list[0], hostip->h_length); } else { log_msg("Invalid multicast source address in line %s: '%s'", line, mc_src_ip); FREE(tmp); rc = SOCKPERF_ERR_INCORRECT; break; } } tmp->is_multicast = IN_MULTICAST(ntohl(tmp->server_addr.sin_addr.s_addr)); tmp->sock_type = sock_type; /* Check if the same value exists */ bool is_exist = false; port_and_type port_type_tmp = { tmp->sock_type, tmp->server_addr.sin_port }; for (int i = s_fd_min; i <= s_fd_max; i++) { /* duplicated values are accepted in case client connection using TCP */ /* or in case source address is set for multicast socket */ if (((s_user_params.mode == MODE_CLIENT) && (tmp->sock_type == SOCK_STREAM)) || ((tmp->is_multicast) && (tmp->mc_source_ip_addr.s_addr != INADDR_ANY))) { continue; } if (g_fds_array[i] && !memcmp(&(g_fds_array[i]->server_addr), &(tmp->server_addr), sizeof(tmp->server_addr)) && fd_socket_map[port_type_tmp]) { is_exist = true; break; } } if (is_exist) { if (tmp->recv.buf) { FREE(tmp->recv.buf); } FREE(tmp); continue; } tmp->active_fd_count = 0; tmp->active_fd_list = (int *)MALLOC(MAX_ACTIVE_FD_NUM * sizeof(int)); bool new_socket_flag = true; if (!tmp->active_fd_list) { log_err("Failed to allocate memory with malloc()"); rc = SOCKPERF_ERR_NO_MEMORY; } else { /* if this port already been received before, join socket - multicast only */ if ((0 != fd_socket_map[port_type_tmp]) && (tmp->is_multicast)) { /* join socket */ curr_fd = fd_socket_map[port_type_tmp]; new_socket_flag = false; if (g_fds_array[curr_fd]->memberships_addr == NULL) { g_fds_array[curr_fd]->memberships_addr = (struct sockaddr_in *)MALLOC( IGMP_MAX_MEMBERSHIPS * sizeof(struct sockaddr_in)); } g_fds_array[curr_fd]->memberships_addr[g_fds_array[curr_fd]->memberships_size] = tmp->server_addr; g_fds_array[curr_fd]->memberships_size++; } else { /* create a socket */ if ((curr_fd = (int)socket(AF_INET, tmp->sock_type, 0)) < 0) { // TODO: use SOCKET all over the way and avoid this cast log_err("socket(AF_INET, SOCK_x)"); rc = SOCKPERF_ERR_SOCKET; } fd_socket_map[port_type_tmp] = curr_fd; if (tmp->is_multicast) { tmp->memberships_addr = (struct sockaddr_in *)MALLOC( IGMP_MAX_MEMBERSHIPS * sizeof(struct sockaddr_in)); } else { tmp->memberships_addr = NULL; } tmp->memberships_size = 0; s_fd_num++; } if (curr_fd >= 0) { if ((curr_fd >= MAX_FDS_NUM) || (prepare_socket(curr_fd, tmp) == (int) INVALID_SOCKET)) { // TODO: use SOCKET all over the way and avoid this cast log_err("Invalid socket"); close(curr_fd); rc = SOCKPERF_ERR_SOCKET; } else { int i = 0; for (i = 0; i < MAX_ACTIVE_FD_NUM; i++) { tmp->active_fd_list[i] = (int)INVALID_SOCKET; // TODO: use SOCKET all // over the way and avoid // this cast } // TODO: In the following malloc we have a one time memory allocation of // 128KB that are not reclaimed // This O(1) leak was introduced in revision 133 tmp->recv.buf = (uint8_t *)malloc(sizeof(uint8_t) * 2 * MAX_PAYLOAD_SIZE); if (!tmp->recv.buf) { log_err("Failed to allocate memory with malloc()"); FREE(tmp); rc = SOCKPERF_ERR_NO_MEMORY; } tmp->recv.cur_addr = tmp->recv.buf; tmp->recv.max_size = MAX_PAYLOAD_SIZE; tmp->recv.cur_offset = 0; tmp->recv.cur_size = tmp->recv.max_size; if (new_socket_flag) { if (s_fd_num == 1) { /*it is the first fd*/ s_fd_min = curr_fd; s_fd_max = curr_fd; } else { g_fds_array[last_fd]->next_fd = curr_fd; s_fd_min = _min(s_fd_min, curr_fd); s_fd_max = _max(s_fd_max, curr_fd); } last_fd = curr_fd; g_fds_array[curr_fd] = tmp; } } } } /* Failure check */ if (rc) { if (tmp->active_fd_list) { FREE(tmp->active_fd_list); } if (tmp->recv.buf) { FREE(tmp->recv.buf); } FREE(tmp); } } } fclose(file_fd); if (!rc) { g_fds_array[s_fd_max]->next_fd = s_fd_min; /* close loop for fast wrap around in client */ #ifdef ST_TEST { char *ip = "224.3.2.1"; char *port = "11111"; static fds_data data1, data2; tmp = &data1; memset(tmp, 0, sizeof(struct fds_data)); tmp->server_addr.sin_family = AF_INET; tmp->server_addr.sin_port = htons(atoi(port)); if (!inet_aton(ip, &tmp->server_addr.sin_addr)) { log_msg("Invalid input: '%s:%s'", ip, port); exit_with_log(SOCKPERF_ERR_INCORRECT); } tmp->sock_type = sock_type; tmp->is_multicast = IN_MULTICAST(ntohl(tmp->server_addr.sin_addr.s_addr)); st1 = prepare_socket(tmp, true); tmp = &data2; memset(tmp, 0, sizeof(struct fds_data)); tmp->server_addr.sin_family = AF_INET; tmp->server_addr.sin_port = htons(atoi(port)); if (!inet_aton(ip, &tmp->server_addr.sin_addr)) { log_msg("Invalid input: '%s:%s'", ip, port); exit_with_log(SOCKPERF_ERR_INCORRECT); } tmp->sock_type = sock_type; tmp->is_multicast = IN_MULTICAST(ntohl(tmp->server_addr.sin_addr.s_addr)); st2 = prepare_socket(tmp, true); } #endif } return rc; } //------------------------------------------------------------------------------ int bringup(const int *p_daemonize) { int rc = SOCKPERF_ERR_NONE; os_mutex_init(&_mutex); if (os_sock_startup() == false) { // Only relevant for Windows log_err("Failed to initialize WSA"); rc = SOCKPERF_ERR_FATAL; } else { sock_lib_started = 1; } if (*p_daemonize) { if (os_daemonize()) { log_err("Failed to daemonize"); rc = SOCKPERF_ERR_FATAL; } else { log_msg("Running as daemon"); } } /* Setup VMA */ int _vma_pkts_desc_size = 0; #ifdef USING_VMA_EXTRA_API if (!rc && (s_user_params.is_vmarxfiltercb || s_user_params.is_vmazcopyread || s_user_params.fd_handler_type == SOCKETXTREME)) { // Get VMA extended API g_vma_api = vma_get_api(); if (g_vma_api == NULL) { errno = EPERM; exit_with_err("VMA Extra API is not available", SOCKPERF_ERR_FATAL); } else { log_msg("VMA Extra API is in use"); } _vma_pkts_desc_size = sizeof(struct vma_packets_t) + sizeof(struct vma_packet_t) + sizeof(struct iovec) * 16; } #else if (!rc && (s_user_params.is_vmarxfiltercb || s_user_params.is_vmazcopyread || s_user_params.fd_handler_type == SOCKETXTREME)) { errno = EPERM; exit_with_err("Please compile with VMA Extra API to use these options", SOCKPERF_ERR_FATAL); } #endif /* Create and initialize sockets */ if (!rc) { setbuf(stdout, NULL); int _max_buff_size = _max(s_user_params.msg_size + 1, _vma_pkts_desc_size); _max_buff_size = _max(_max_buff_size, MAX_PAYLOAD_SIZE); Message::initMaxSize(_max_buff_size); /* initialize g_fds_array array */ if (strlen(s_user_params.feedfile_name)) { rc = set_sockets_from_feedfile(s_user_params.feedfile_name); } else { int curr_fd = (int)INVALID_SOCKET; // TODO: use SOCKET all over the way and avoid this cast fds_data *tmp = (struct fds_data *)MALLOC(sizeof(struct fds_data)); if (!tmp) { log_err("Failed to allocate memory with malloc()"); rc = SOCKPERF_ERR_NO_MEMORY; } else { memset(tmp, 0, sizeof(struct fds_data)); memcpy(&tmp->server_addr, &(s_user_params.addr), sizeof(struct sockaddr_in)); tmp->mc_source_ip_addr.s_addr = s_user_params.mc_source_ip_addr.s_addr; tmp->is_multicast = IN_MULTICAST(ntohl(tmp->server_addr.sin_addr.s_addr)); tmp->sock_type = s_user_params.sock_type; tmp->active_fd_count = 0; tmp->active_fd_list = (int *)MALLOC(MAX_ACTIVE_FD_NUM * sizeof(int)); if (!tmp->active_fd_list) { log_err("Failed to allocate memory with malloc()"); rc = SOCKPERF_ERR_NO_MEMORY; } else { /* create a socket */ if ((curr_fd = (int)socket(AF_INET, tmp->sock_type, 0)) < 0) { // TODO: use SOCKET all over the way and avoid this cast log_err("socket(AF_INET, SOCK_x)"); rc = SOCKPERF_ERR_SOCKET; } else { if ((curr_fd >= MAX_FDS_NUM) || (prepare_socket(curr_fd, tmp) == (int)INVALID_SOCKET)) { // TODO: use SOCKET all over the way and avoid // this cast log_err("Invalid socket"); close(curr_fd); rc = SOCKPERF_ERR_SOCKET; } else { int i = 0; s_fd_num = 1; for (i = 0; i < MAX_ACTIVE_FD_NUM; i++) { tmp->active_fd_list[i] = (int)INVALID_SOCKET; } tmp->recv.buf = (uint8_t *)malloc(sizeof(uint8_t) * 2 * MAX_PAYLOAD_SIZE); if (!tmp->recv.buf) { log_err("Failed to allocate memory with malloc()"); FREE(tmp); rc = SOCKPERF_ERR_NO_MEMORY; } tmp->recv.cur_addr = tmp->recv.buf; tmp->recv.max_size = MAX_PAYLOAD_SIZE; tmp->recv.cur_offset = 0; tmp->recv.cur_size = tmp->recv.max_size; s_fd_min = s_fd_max = curr_fd; g_fds_array[s_fd_min] = tmp; g_fds_array[s_fd_min]->next_fd = s_fd_min; } } } /* Failure check */ if (rc) { if (tmp->active_fd_list) { FREE(tmp->active_fd_list); } if (tmp->recv.buf) { FREE(tmp->recv.buf); } FREE(tmp); } } } if (!rc && (s_user_params.threads_num > s_fd_num || s_user_params.threads_num == 0)) { log_msg("Number of threads should be less than sockets count"); rc = SOCKPERF_ERR_BAD_ARGUMENT; } if (!rc && s_user_params.dummy_mps && s_user_params.mps >= s_user_params.dummy_mps) { log_err( "Dummy send is allowed only if dummy-send rate is higher than regular msg rate"); rc = SOCKPERF_ERR_BAD_ARGUMENT; } } /* Setup internal data */ if (!rc) { int64_t cycleDurationNsec = NSEC_IN_SEC * s_user_params.burst_size / s_user_params.mps; if (s_user_params.mps == UINT32_MAX) { // MAX MPS mode s_user_params.mps = MPS_MAX; cycleDurationNsec = 0; } s_user_params.cycleDuration = TicksDuration(cycleDurationNsec); if (s_user_params.dummy_mps) { // Calculate dummy send rate int64_t dummySendCycleDurationNsec = (s_user_params.dummy_mps == UINT32_MAX) ? 0 : NSEC_IN_SEC / s_user_params.dummy_mps; s_user_params.dummySendCycleDuration = TicksDuration(dummySendCycleDurationNsec); } s_user_params.warmup_msec = TEST_FIRST_CONNECTION_FIRST_PACKET_TTL_THRESHOLD_MSEC + s_fd_num * TEST_ANY_CONNECTION_FIRST_PACKET_TTL_THRESHOLD_MSEC; if (s_user_params.warmup_msec < TEST_START_WARMUP_MSEC) { s_user_params.warmup_msec = TEST_START_WARMUP_MSEC; } else { log_dbg( "Warm-up set in relation to number of active connections. Warm up time: %" PRIu32 " usec; first connection's first packet TTL: %d usec; following connections' first " "packet TTL: %d usec\n", g_pApp->m_const_params.warmup_msec, TEST_FIRST_CONNECTION_FIRST_PACKET_TTL_THRESHOLD_MSEC * 1000, (int)(TEST_ANY_CONNECTION_FIRST_PACKET_TTL_THRESHOLD_MSEC * 1000)); } uint64_t _maxTestDuration = 1 + s_user_params.sec_test_duration + s_user_params.warmup_msec / 1000; // + 1sec for timer inaccuracy safety uint64_t _maxSequenceNo = _maxTestDuration * s_user_params.mps + 10 * s_user_params.reply_every; // + 10 replies for safety _maxSequenceNo += s_user_params.burst_size; // needed for the case burst_size > mps if (s_user_params.pPlaybackVector) { _maxSequenceNo = s_user_params.pPlaybackVector->size(); } /* SERVER does not have info about max number of expected packets */ if (s_user_params.mode == MODE_SERVER) { _maxSequenceNo = UINT64_MAX; } Message::initMaxSeqNo(_maxSequenceNo); if (!s_user_params.b_stream && (!s_user_params.mode) == MODE_SERVER) { g_pPacketTimes = new PacketTimes(_maxSequenceNo, s_user_params.reply_every, s_user_params.client_work_with_srv_num); } os_set_signal_action(SIGINT, s_user_params.mode ? server_sig_handler : client_sig_handler); } return rc; } //------------------------------------------------------------------------------ void do_test() { handler_info info; info.id = 0; info.fd_min = s_fd_min; info.fd_max = s_fd_max; info.fd_num = s_fd_num; switch (s_user_params.mode) { case MODE_CLIENT: client_handler(&info); break; case MODE_SERVER: if (s_user_params.mthread_server) { server_select_per_thread(s_fd_num); } else { server_handler(&info); } break; case MODE_BRIDGE: server_handler(&info); break; } cleanup(); } //------------------------------------------------------------------------------ int main(int argc, char *argv[]) { try { int rc = SOCKPERF_ERR_NONE; // step #1: set default values for command line args set_defaults(); // step #2: parse command line args if (argc > 1) { int i = 0; int j = 0; int found = 0; for (i = 0; sockperf_modes[i].name != NULL; i++) { if (strcmp(sockperf_modes[i].name, argv[1]) == 0) { found = 1; } else { for (j = 0; sockperf_modes[i].shorts[j] != NULL; j++) { if (strcmp(sockperf_modes[i].shorts[j], argv[1]) == 0) { found = 1; break; } } } if (found) { rc = sockperf_modes[i].func(i, argc - 1, (const char **)(argv + 1)); break; } } /* check if the first option is invalid or rc > 0 */ if ((sockperf_modes[i].name == NULL) || (rc > 0)) { rc = proc_mode_help(0, 0, NULL); } } else { rc = proc_mode_help(0, 0, NULL); } if (rc) { cleanup(); exit(0); } // Prepare application to start rc = bringup(&s_user_params.daemonize); if (rc) { exit_with_log(rc); // will also perform cleanup } log_dbg( "+INFO:\n\t\ mode = %d \n\t\ with_sock_accl = %d \n\t\ msg_size = %d \n\t\ msg_size_range = %d \n\t\ sec_test_duration = %d \n\t\ data_integrity = %d \n\t\ packetrate_stats_print_ratio = %d \n\t\ burst_size = %d \n\t\ packetrate_stats_print_details = %d \n\t\ fd_handler_type = %d \n\t\ mthread_server = %d \n\t\ sock_buff_size = %d \n\t\ threads_num = %d \n\t\ threads_affinity = %s \n\t\ is_blocked = %d \n\t\ is_nonblocked_send = %d \n\t\ do_warmup = %d \n\t\ pre_warmup_wait = %d \n\t\ is_vmarxfiltercb = %d \n\t\ is_vmazcopyread = %d \n\t\ mc_loop_disable = %d \n\t\ mc_ttl = %d \n\t\ uc_reuseaddr = %d \n\t\ tcp_nodelay = %d \n\t\ client_work_with_srv_num = %d \n\t\ b_server_reply_via_uc = %d \n\t\ b_server_dont_reply = %d \n\t\ b_server_detect_gaps = %d\n\t\ mps = %d \n\t\ client_bind_info = %s:%d \n\t\ reply_every = %d \n\t\ b_client_ping_pong = %d \n\t\ b_no_rdtsc = %d \n\t\ sender_affinity = %s \n\t\ receiver_affinity = %s \n\t\ b_stream = %d \n\t\ daemonize = %d \n\t\ feedfile_name = %s \n\t\ tos = %d \n\t\ packet pace limit = %d", s_user_params.mode, s_user_params.withsock_accl, s_user_params.msg_size, s_user_params.msg_size_range, s_user_params.sec_test_duration, s_user_params.data_integrity, s_user_params.packetrate_stats_print_ratio, s_user_params.burst_size, s_user_params.packetrate_stats_print_details, s_user_params.fd_handler_type, s_user_params.mthread_server, s_user_params.sock_buff_size, s_user_params.threads_num, s_user_params.threads_affinity, s_user_params.is_blocked, s_user_params.is_nonblocked_send, s_user_params.do_warmup, s_user_params.pre_warmup_wait, s_user_params.is_vmarxfiltercb, s_user_params.is_vmazcopyread, s_user_params.mc_loop_disable, s_user_params.mc_ttl, s_user_params.uc_reuseaddr, s_user_params.tcp_nodelay, s_user_params.client_work_with_srv_num, s_user_params.b_server_reply_via_uc, s_user_params.b_server_dont_reply, s_user_params.b_server_detect_gaps, s_user_params.mps, inet_ntoa(s_user_params.client_bind_info.sin_addr), ntohs(s_user_params.client_bind_info.sin_port), s_user_params.reply_every, s_user_params.b_client_ping_pong, s_user_params.b_no_rdtsc, (strlen(s_user_params.sender_affinity) ? s_user_params.sender_affinity : ""), (strlen(s_user_params.receiver_affinity) ? s_user_params.receiver_affinity : ""), s_user_params.b_stream, s_user_params.daemonize, (strlen(s_user_params.feedfile_name) ? s_user_params.feedfile_name : ""), s_user_params.tos, s_user_params.rate_limit); // Display application version log_msg(MAGNETA "== version #%s == " ENDCOLOR, VERSION); // Display VMA version #ifdef VMA_LIBRARY_MAJOR log_msg("Linked with VMA version: %d.%d.%d.%d", VMA_LIBRARY_MAJOR, VMA_LIBRARY_MINOR, VMA_LIBRARY_REVISION, VMA_LIBRARY_RELEASE); #endif #ifdef VMA_DATE_TIME log_msg("VMA Build Date: %s", VMA_DATE_TIME); #endif // step #4: get prepared for test - store application context in global variables (will use // const member) App app(s_user_params, s_mutable_params); g_pApp = &app; // temp test for measuring time of taking time const int SIZE = 1000; TicksTime start, end; start.setNow(); for (int i = 0; i < SIZE; i++) end.setNow(); log_dbg("+INFO: taking time, using the given settings, consumes %.3lf nsec", (double)(end - start).toNsec() / SIZE); #if !defined(__arm__) && !defined(__aarch64__) ticks_t tstart = 0, tend = 0; tstart = os_gettimeoftsc(); for (int i = 0; i < SIZE; i++) tend = os_gettimeoftsc(); double tdelta = (double)tend - (double)tstart; double ticks_per_second = (double)get_tsc_rate_per_second(); log_dbg("+INFO: taking rdtsc directly consumes %.3lf nsec", tdelta / SIZE * 1000 * 1000 * 1000 / ticks_per_second); #endif // step #5: check is user defined a specific SEED value to be used in all rand() calls // if no seed value is provided, the rand() function is automatically seeded with a value of // 1. char *env_ptr = NULL; if ((env_ptr = getenv("SEED")) != NULL) { int seed = (unsigned)atoi(env_ptr); srand(seed); } // step #6: do run the test /* ** TEST START */ do_test(); /* ** TEST END */ } catch (const std::exception &e) { printf(MODULE_NAME ": test failed because of an exception with the following information:\n\t%s\n", e.what()); exit_with_log(SOCKPERF_ERR_FATAL); } catch (...) { printf(MODULE_NAME ": test failed because of an unknown exception \n"); exit_with_log(SOCKPERF_ERR_FATAL); } exit(0); } sockperf-3.6/src/switches.h000066400000000000000000000300041336630672200157740ustar00rootroot00000000000000/* * Copyright (c) 2011-2018 Mellanox Technologies Ltd. * 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. * 3. Neither the name of the Mellanox Technologies Ltd nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * 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. */ #ifndef SWITCHES_H_ #define SWITCHES_H_ #include "defs.h" #include "common.h" #include "message.h" #include "ticks.h" #include "packet.h" //============================================================================== class SwitchOff { public: inline void execute() {} inline void execute(int) {} // inline void execute(unsigned long long) {} inline void execute(uint64_t) {} inline void execute(int, uint64_t) {} inline void execute(TicksTime &) {} inline void execute(struct sockaddr_in *, uint64_t, bool) {} inline void execute(Message *, Message *) {} inline void execute(Message *) {} inline void execute(Message *, int) {} /* inline void execute2() {} inline void execute(struct timespec &) {} */ }; //------------------------------------------------------------------------------ class SwitchOnMsgSize { public: SwitchOnMsgSize() { assert(g_pApp); m_min_msg_size = _max(MIN_PAYLOAD_SIZE, g_pApp->m_const_params.msg_size - g_pApp->m_const_params.msg_size_range); m_range_msg_size = _min(MAX_PAYLOAD_SIZE, g_pApp->m_const_params.msg_size + g_pApp->m_const_params.msg_size_range) - m_min_msg_size + 1; } inline void execute(Message *pMsgRequest) { client_update_msg_size(pMsgRequest); } private: inline void client_update_msg_size(Message *pMsgRequest) { int m_msg_size = _min(MAX_PAYLOAD_SIZE, (m_min_msg_size + (int)(rand() % m_range_msg_size))); pMsgRequest->setLength(m_msg_size); } int m_min_msg_size; int m_range_msg_size; }; //============================================================================== class SwitchOnCycleDuration { public: // busy wait between two cycles starting point and take starting point of next cycle inline void execute(Message *, int) { TicksTime nextCycleStartTime = g_cycleStartTime + g_pApp->m_const_params.cycleDuration; while (!g_b_exit) { if (TicksTime::now() >= nextCycleStartTime) { break; } g_cycle_wait_loop_counter++; // count delta between time takings vs. num of cycles } g_cycleStartTime = nextCycleStartTime; } }; //============================================================================= class SwitchOnDummySend { public: // dummy send between two cycles starting point and take starting point of next cycle inline void execute(Message *pMsgRequest, int ifd) { TicksTime now; TicksTime nextCycleStartTime = g_cycleStartTime + g_pApp->m_const_params.cycleDuration; TicksTime nextDummySendTime = g_cycleStartTime + g_pApp->m_const_params.dummySendCycleDuration; while (!g_b_exit) { now = TicksTime::now(); if (now >= nextCycleStartTime) { break; } if (now >= nextDummySendTime) { // We don't use Sockperf's msg_sendto() for dummy messages because we want to ignore // the error handling. sendto(ifd, pMsgRequest->getBuf(), pMsgRequest->getLength(), DUMMY_SEND_FLAG, (struct sockaddr *)&(g_fds_array[ifd]->server_addr), sizeof(struct sockaddr)); nextDummySendTime += g_pApp->m_const_params.dummySendCycleDuration; } g_cycle_wait_loop_counter++; // count delta between time takings vs. num of cycles } g_cycleStartTime = nextCycleStartTime; } }; //* //============================================================================== class PongModeNormal { // indicate that pong-request bit is set for part of the packets public: PongModeNormal() { assert(0); /* do not call this constructor */ } PongModeNormal(Message *pMsgRequest) { m_pMsgRequest = pMsgRequest; m_pMsgRequest->getHeader()->resetPongRequest(); } inline int msg_sendto(int ifd) { int length = m_pMsgRequest->getLength(); if (m_pMsgRequest->getSequenceCounter() % g_pApp->m_const_params.reply_every == 0) { m_pMsgRequest->getHeader()->setPongRequest(); g_pPacketTimes->setTxTime(m_pMsgRequest->getSequenceCounter()); m_pMsgRequest->setHeaderToNetwork(); int ret = ::msg_sendto(ifd, m_pMsgRequest->getBuf(), length, &(g_fds_array[ifd]->server_addr)); m_pMsgRequest->setHeaderToHost(); /* check skip send operation case */ if (ret == RET_SOCKET_SKIPPED) { g_pPacketTimes->clearTxTime(m_pMsgRequest->getSequenceCounter()); } m_pMsgRequest->getHeader()->resetPongRequest(); return ret; } else { m_pMsgRequest->setHeaderToNetwork(); int ret = ::msg_sendto(ifd, m_pMsgRequest->getBuf(), length, &(g_fds_array[ifd]->server_addr)); m_pMsgRequest->setHeaderToHost(); return ret; } } private: Message *m_pMsgRequest; }; //============================================================================== class PongModeAlways { // indicate that pong-request bit is always on public: PongModeAlways() { assert(0); /* do not call this constructor */ } PongModeAlways(Message *pMsgRequest) { m_pMsgRequest = pMsgRequest; m_pMsgRequest->getHeader()->setPongRequest(); } inline int msg_sendto(int ifd) { int length = m_pMsgRequest->getLength(); g_pPacketTimes->setTxTime(m_pMsgRequest->getSequenceCounter()); m_pMsgRequest->setHeaderToNetwork(); int ret = ::msg_sendto(ifd, m_pMsgRequest->getBuf(), length, &(g_fds_array[ifd]->server_addr)); m_pMsgRequest->setHeaderToHost(); /* check skip send operation case */ if (ret == RET_SOCKET_SKIPPED) { g_pPacketTimes->clearTxTime(m_pMsgRequest->getSequenceCounter()); } return ret; } private: Message *m_pMsgRequest; }; //============================================================================== class PongModeNever { // indicate that pong-request bit is never on (no need to take tXtime) public: PongModeNever() { assert(0); /* do not call this constructor */ } PongModeNever(Message *pMsgRequest) { m_pMsgRequest = pMsgRequest; m_pMsgRequest->getHeader()->resetPongRequest(); } inline int msg_sendto(int ifd) { int length = m_pMsgRequest->getLength(); m_pMsgRequest->setHeaderToNetwork(); int ret = ::msg_sendto(ifd, m_pMsgRequest->getBuf(), length, &(g_fds_array[ifd]->server_addr)); m_pMsgRequest->setHeaderToHost(); return ret; } private: Message *m_pMsgRequest; }; //*/ //============================================================================== class SwitchOnActivityInfo { public: /*inline*/ void execute(uint64_t counter); }; //============================================================================== class SwitchOnDataIntegrity { public: //---------------------- inline void execute(Message *pMsgSend, Message *pMsgReply) { if (!check_data_integrity(pMsgSend, pMsgReply)) { exit_with_log("data integrity test failed", SOCKPERF_ERR_INCORRECT); } } private: //---------------------- /* returns 1 if buffers are identical */ inline int check_data_integrity(Message *pMsgSend, Message *pMsgReply) { uint8_t *message_buf = pMsgSend->getBuf(); size_t buf_size = pMsgSend->getLength(); /*static int to_print = 1; if (to_print == 1) { printf("%s\n", rcvd_buf); to_print = 0; }*/ pMsgReply->setClient(); return !memcmp(pMsgReply->getBuf(), message_buf, buf_size); } }; class SwitchOnCalcGaps { public: /*inline*/ void execute(struct sockaddr_in *clt_addr, uint64_t seq_num, bool is_warmup); static void print_summary() { seq_num_map::iterator itr; seq_num_map *p_seq_num_map = &ms_seq_num_map; if (!p_seq_num_map) return; for (itr = p_seq_num_map->begin(); itr != p_seq_num_map->end(); itr++) { print_session_summary(&(itr->second)); } } static void print_session_summary(clt_session_info *p_clt_session) { char ip_port_str[30]; if (p_clt_session) { sprintf(ip_port_str, "[%s:%d]", inet_ntoa(p_clt_session->addr.sin_addr), ntohs(p_clt_session->addr.sin_port)); log_msg("%-23s Summary: Total Dropped/OOO: %" PRIu64, ip_port_str, p_clt_session->total_drops); } } private: inline void check_gaps(uint64_t received_seq_num, seq_num_map::iterator &seq_num_map_itr) { if (received_seq_num != ++seq_num_map_itr->second.seq_num) { uint64_t drops_num; drops_num = calc_gaps_num(seq_num_map_itr->second.seq_num, received_seq_num); seq_num_map_itr->second.total_drops += drops_num; // Unordered packet if (!drops_num) seq_num_map_itr->second.seq_num--; else { char drops_num_str[10]; char seq_num_info_str[50]; char ip_port_str[30]; sprintf(ip_port_str, "[%s:%d]", inet_ntoa(seq_num_map_itr->second.addr.sin_addr), ntohs(seq_num_map_itr->second.addr.sin_port)); sprintf(drops_num_str, "(%" PRIu64 ")", drops_num); sprintf(seq_num_info_str, "[%" PRIu64 " - %" PRIu64 "]", seq_num_map_itr->second.seq_num, received_seq_num - 1); log_msg("%-23s Total Dropped/OOO: %-12" PRIu64 "GAP:%-7s %s", ip_port_str, seq_num_map_itr->second.total_drops, drops_num_str, seq_num_info_str); seq_num_map_itr->second.seq_num = received_seq_num; } } } inline uint64_t calc_gaps_num(uint64_t expected_seq, uint64_t received_seq) { return (received_seq > expected_seq) ? (received_seq - expected_seq) : 0; } inline void print_new_session_info(clt_session_info *p_clt_session) { if (p_clt_session) { char ip_port_str[30]; sprintf(ip_port_str, "[%s:%d]", inet_ntoa(p_clt_session->addr.sin_addr), ntohs(p_clt_session->addr.sin_port)); log_msg("Starting new session: %-23s", ip_port_str); } } static seq_num_map ms_seq_num_map; }; #endif /* SWITCHES_H_ */ sockperf-3.6/src/ticks.cpp000066400000000000000000000142311336630672200156170ustar00rootroot00000000000000/* * Copyright (c) 2011-2018 Mellanox Technologies Ltd. * 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. * 3. Neither the name of the Mellanox Technologies Ltd nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * 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. */ #define __STDC_LIMIT_MACROS // for INT64_MAX in __cplusplus #include "ticks.h" #include #include #include #include // strerror() #include // INT64_MAX #include #include "clock.h" #ifndef WIN32 #include // for usleep #endif /** * RDTSC extensions */ #define TSCVAL_INITIALIZER (0) /** * Read RDTSC register */ /** * Calibrate RDTSC with CPU speed * @return number of tsc ticks per second */ ticks_t get_tsc_rate_per_second() { static ticks_t tsc_per_second = TSCVAL_INITIALIZER; if (!tsc_per_second) { uint64_t delta_usec; timespec ts_before, ts_after, ts_delta; ticks_t tsc_before, tsc_after, tsc_delta; // Measure the time actually slept because usleep() is very inaccurate. os_ts_gettimeofclock(&ts_before); tsc_before = os_gettimeoftsc(); usleep(100000); // 0.1 sec os_ts_gettimeofclock(&ts_after); tsc_after = os_gettimeoftsc(); // Calc delta's tsc_delta = tsc_after - tsc_before; ts_sub(&ts_after, &ts_before, &ts_delta); delta_usec = ts_to_usec(&ts_delta); // Calc rate tsc_per_second = tsc_delta * USEC_PER_SEC / delta_usec; } return tsc_per_second; } // static variables initialization const int64_t TicksImplRdtsc::TICKS_PER_SEC = get_tsc_rate_per_second(); const int64_t TicksImplRdtsc::TICKS_PER_MSEC = (TicksImplRdtsc::TICKS_PER_SEC + 500) / 1000; const int64_t TicksImplRdtsc::MAX_MSEC_CONVERT = TICKS_PER_MSEC > NSEC_IN_MSEC ? INT64_MAX / TICKS_PER_MSEC : INT64_MAX / NSEC_IN_MSEC; const ticks_t TicksImplRdtsc::BASE_TICKS = os_gettimeoftsc(); const TicksDuration TicksDuration::TICKS0(0, 0); // call the non inline CTOR from slow path const TicksDuration TicksDuration::TICKS1USEC(1000, 0); // call the non inline CTOR from slow path const TicksDuration TicksDuration::TICKS1MSEC(1000 * 1000, 0); // call the non inline CTOR from slow path const TicksDuration TicksDuration::TICKS1SEC(1000 * 1000 * 1000, 0); // call the non inline CTOR from slow path const TicksDuration TicksDuration::TICKS1MIN(TICKS1SEC * 60); const TicksDuration TicksDuration::TICKS1HOUR(TICKS1MIN * 60); const TicksDuration TicksDuration::TICKS1DAY(TICKS1HOUR * 24); const TicksDuration TicksDuration::TICKS1WEEK(TICKS1DAY * 7); const TicksTime TicksTime::TICKS0; TicksBase::Mode TicksBase::ms_mode = TicksBase::RDTSC; //------------------------------------------------------------------------------ // provide non inline functions/CTORs for reducing code size outside fast path and for quieting the // compiler TicksBase::TicksBase(ticks_t _ticks, int) : m_ticks(_ticks) {} ticks_t TicksBase::nsec2ticksNonInline(int64_t _val) { return ms_mode == RDTSC ? TicksImplRdtsc::nsec2ticks(_val) : TicksImplClock::nsec2ticks(_val); } TicksDuration::TicksDuration(int64_t _nsec, int) : TicksBase(nsec2ticks(_nsec), 0) {} TicksTime &TicksTime::setNowNonInline() { m_ticks = getCurrentTicks(); return *this; } //------------------------------------------------------------------------------ /*static*/ bool TicksBase::init(Mode _mode) { /* inited to rdtsc mode or clock mode */ static bool isInited = false; if (isInited) return false; ms_mode = _mode; return true; } //============================================================================== class TicksException : public std::exception { public: TicksException(const char *_what) : m_what(_what) {} virtual ~TicksException() throw() {} virtual const char *what() const throw() { return m_what.c_str(); } const std::string m_what; }; //------------------------------------------------------------------------------ /*static*/ void TicksImplClock::doThrow(const char *_func, const char *_file, int _line) { const size_t LEN = 256; char buf[LEN + 1]; snprintf(buf, LEN, "%s:%d: %s() has failed: (errno=%d %s)\n", _file, _line, _func, errno, strerror(errno)); buf[LEN] = '\0'; throw TicksException(buf); } //------------------------------------------------------------------------------ /*static*/ TicksDuration TicksDuration::stdDev(TicksDuration *pArr, size_t size) { if (size <= 1) return TICKS0; double sum = 0; double sum_sqr = 0; double ticks = 0; for (size_t i = 0; i < size; i++) { ticks = (double)pArr[i].m_ticks; sum += ticks; sum_sqr += ticks * ticks; } double avg = sum / size; double variance = (sum_sqr - size * avg * avg) / (size - 1); double stdDev = sqrt(variance); return TicksDuration(ticks_t(stdDev + 0.5), true); } sockperf-3.6/src/ticks.h000066400000000000000000000423401336630672200152660ustar00rootroot00000000000000/* * Copyright (c) 2011-2018 Mellanox Technologies Ltd. * 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. * 3. Neither the name of the Mellanox Technologies Ltd nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * 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. */ #ifndef TICKS_H_ #define TICKS_H_ /* * TicksTime represents a point in time measured by ticks (related to some * abstract base point and not necessarily to real clock) * TicksDuration represents an interval of time measured by ticks (usually * delta between 2 TicksTime objects) that can be converted to nsec * The classes hide their internal implementation and therefore free to optimize/change it. * The current known internal implementations are based on clock_gettime or on RDTSC register. * Both classes are intended to be as efficient as primitive integral data types. * The advantage in these classes is because: * 1. you can easily switch your application to be based on clock_gettime or * on RDTSC register (or on any other future implementation) * 2. the classes contain many utility and conversion functions to/from many 'time' types * 3. the classes contain operators for all valid comparison & arithmetic * operations that are *legal* for them * 4. any operation that is illegal will be recognized as compilation * error (for example division by TicksTime object) * 5, using these classes will make your code cleaner and safer and faster * 6. and more... * ------------ NOTE #1: For efficiency purposes, the classes leave all runtime checks to their users. Hence, there are no overflow/underflow/divizion-by-zero checks. Also there is no semantic for illegal values (for example: zero/negative time is considered legal from the class's point of view) (still, there are many compile time error checks, based on types and based on valid operations) NOTE #2: any method that is related to getting current time * from CLOCK (not from RDTSC register) * may throw Exception (in case of fatal error related to clock) ------------ ------------ Inspired by Boost.Date_Time documentation, this section describes some of basic arithmetic rules that can be performed with TicksTime and TicksDuration objects: TicksTime + TicksDuration --> TicksTime TicksTime - TicksDuration --> TicksTime TicksTime - TicksTime --> TicksDuration Unlike regular numeric types, the following operations are undefined and therefore prevented by the class'es interface: TicksTime + TicksTime --> Undefined TicksDuration + TicksTime --> Undefined TicksDuration - TicksTime --> Undefined --- TicksDuration represent a length of time and can have positive and negative values. It is frequently useful to be able to perform calculations with other TicksDuration objects and with simple integral values. The following describes these calculations: TicksDuration + TicksDuration --> TicksDuration TicksDuration - TicksDuration --> TicksDuration TicksDuration * Integer --> TicksDuration Integer * TicksDuration --> TicksDuration TicksDuration / Integer --> TicksDuration (Integer Division rules) */ #include /* clock_gettime()*/ #include #include // for int64_t #include // for qsort #ifdef __FreeBSD__ #include #endif #include "ticks_os.h" // usefull constants static const int64_t USEC_IN_SEC = 1000 * 1000; static const int64_t NSEC_IN_MSEC = 1000 * 1000; //------------------------------------------------------------------------------ // utility functions inline static int64_t timeval2nsec(const struct timeval &_val) { return NSEC_IN_SEC * _val.tv_sec + 1000 * _val.tv_usec; } ticks_t get_tsc_rate_per_second(); //------------------------------------------------------------------------------ // forward declaration of classes in this file class TicksImpl; class TicksImplRdtsc; class TicksImplClock; // class TicksBase; class TicksTime; class TicksDuration; //------------------------------------------------------------------------------ class TicksImpl { friend class TicksBase; protected: TicksImpl() {} virtual ~TicksImpl() {} /* commented out because we avoid inheritance for saving time of dynamically invoking virtual function virtual ticks_t nsec2ticks(int64_t _val) = 0; virtual int64_t ticks2nsec(ticks_t _val) = 0; virtual ticks_t getCurrentTicks( ) = 0; */ }; //------------------------------------------------------------------------------ class TicksImplRdtsc : public TicksImpl { friend class TicksBase; friend class TicksTime; protected: TicksImplRdtsc() {} virtual ~TicksImplRdtsc() {} static ticks_t nsec2ticks(int64_t _val) { if (_val < MAX_MSEC_CONVERT) return nsec2ticks_smallNamubers(_val); else return (ticks_t)_val / NSEC_IN_MSEC * TICKS_PER_MSEC + nsec2ticks_smallNamubers(_val % NSEC_IN_MSEC); } static int64_t ticks2nsec(ticks_t _val) { if (_val < MAX_MSEC_CONVERT) return ticks2nsec_smallNamubers(_val); else return (int64_t)_val / TICKS_PER_MSEC * NSEC_IN_MSEC + ticks2nsec_smallNamubers(_val % TICKS_PER_MSEC); } static ticks_t getCurrentTicks() { return os_gettimeoftsc() - BASE_TICKS; } // these methods may overflow in conversions for values greater than 1 million seconds ( > 10 // days) inline static ticks_t nsec2ticks_smallNamubers(int64_t _val) { return (ticks_t)_val * TICKS_PER_MSEC / NSEC_IN_MSEC; } inline static int64_t ticks2nsec_smallNamubers(ticks_t _val) { return (int64_t)_val * NSEC_IN_MSEC / TICKS_PER_MSEC; } static const int64_t TICKS_PER_SEC; static const int64_t TICKS_PER_MSEC; static const int64_t MAX_MSEC_CONVERT; static const ticks_t BASE_TICKS; }; //------------------------------------------------------------------------------ class TicksImplClock : public TicksImpl { friend class TicksBase; protected: TicksImplClock() {} virtual ~TicksImplClock() {} static ticks_t nsec2ticks(int64_t _val) { return (ticks_t)_val; } static int64_t ticks2nsec(ticks_t _val) { return (int64_t)_val; } static ticks_t getCurrentTicks() { return os_gettimeofclock(); } //------------------------------------------------------------------------------ // utility function for throwing exception related to this class (no need to inline it) static void doThrow(const char *_func, const char *_file, int _line); }; //============================================================================== //============================================================================== //============================================================================== class TicksBase { public: enum Mode { RDTSC, CLOCK }; // initialize our system to rdtsc mode or clock mode // getting time from RDTSC takes ~34nsec, getting time from CLOCK takes ~620nsec // (in addition clock accuracy is 1usec) static bool init(Mode _mode = RDTSC); //------------------------------------------------------------------------------ protected: static Mode ms_mode; ticks_t m_ticks; //------------------------------------------------------------------------------ // these 3 methods are the sole thing that depends on mode (RDTSC/CLOCK/...) inline static ticks_t nsec2ticks(int64_t _val) { return ms_mode == RDTSC ? TicksImplRdtsc::nsec2ticks(_val) : TicksImplClock::nsec2ticks(_val); } static ticks_t nsec2ticksNonInline(int64_t _val); inline static int64_t ticks2nsec(ticks_t _val) { return ms_mode == RDTSC ? TicksImplRdtsc::ticks2nsec(_val) : TicksImplClock::ticks2nsec(_val); } inline static ticks_t getCurrentTicks() { return ms_mode == RDTSC ? TicksImplRdtsc::getCurrentTicks() : TicksImplClock::getCurrentTicks(); } //------------------------------------------------------------------------------ // CTORs inline TicksBase(ticks_t _ticks) : m_ticks(_ticks) {} TicksBase(ticks_t _ticks, int); // provide non inline CTOR just to quite compiler inline TicksBase(const TicksBase &other) : m_ticks(other.m_ticks) {} }; //============================================================================== class TicksDuration : public TicksBase { friend class TicksTime; public: // CTORs & DTOR inline TicksDuration() : TicksBase(0) {} inline explicit TicksDuration(int64_t _nsec) : TicksBase(nsec2ticks(_nsec)) {} inline explicit TicksDuration(const struct timeval &_val) : TicksBase(nsec2ticks(timeval2nsec(_val))) {} inline explicit TicksDuration(const struct timespec &_val) : TicksBase(nsec2ticks(timespec2nsec(_val))) {} inline ~TicksDuration() {} // Useful constants static const TicksDuration TICKS0; // = TicksDuration(0); static const TicksDuration TICKS1USEC; static const TicksDuration TICKS1MSEC; static const TicksDuration TICKS1SEC; static const TicksDuration TICKS1MIN; // = TicksDuration(TICKS1SEC*60); static const TicksDuration TICKS1HOUR; // = TicksDuration(TICKS1MIN*60); static const TicksDuration TICKS1DAY; // = TicksDuration(TICKS1HOUR*24); static const TicksDuration TICKS1WEEK; // = TicksDuration(TICKS1DAY*7); // operators inline bool operator<(const TicksDuration &rhs) const { return this->m_ticks < rhs.m_ticks; } inline bool operator>(const TicksDuration &rhs) const { return this->m_ticks > rhs.m_ticks; } inline bool operator==(const TicksDuration &rhs) const { return this->m_ticks == rhs.m_ticks; } inline bool operator!=(const TicksDuration &rhs) const { return this->m_ticks != rhs.m_ticks; } inline bool operator<=(const TicksDuration &rhs) const { return this->m_ticks <= rhs.m_ticks; } inline bool operator>=(const TicksDuration &rhs) const { return this->m_ticks >= rhs.m_ticks; } inline TicksDuration operator+(const TicksDuration &rhs) const { return TicksDuration(this->m_ticks + rhs.m_ticks, true); } inline TicksDuration operator-(const TicksDuration &rhs) const { return TicksDuration(this->m_ticks - rhs.m_ticks, true); } inline TicksDuration &operator+=(const TicksDuration &rhs) { this->m_ticks += rhs.m_ticks; return *this; } inline TicksDuration &operator-=(const TicksDuration &rhs) { this->m_ticks -= rhs.m_ticks; return *this; } inline TicksDuration operator*(int rhs) const { return TicksDuration(this->m_ticks * rhs, true); } inline TicksDuration operator/(int rhs) const { return TicksDuration(this->m_ticks / rhs, true); } inline TicksDuration &operator*=(int rhs) { this->m_ticks *= rhs; return *this; } inline TicksDuration &operator/=(int rhs) { this->m_ticks /= rhs; return *this; } // 'getCurrentTicks' related method - may throw exception if using clock_gettime and call // fatally failed /*inline*/ void setDurationSince(const TicksTime &start); inline void setFromSeconds(double seconds) { int64_t nsec = (int64_t)(seconds * NSEC_IN_SEC); m_ticks = nsec2ticks(nsec); } // utility functions //------------------------------------------------------------------------------ inline int64_t toNsec() const { return ticks2nsec(m_ticks); } inline int64_t toUsec() const { return (toNsec() + 500) / 1000; } inline double toDecimalUsec() const { return (double)toNsec() / 1000; } //------------------------------------------------------------------------------ inline void toTimespec(struct timespec &_val) const { int64_t nsec = toNsec(); _val.tv_sec = (long)(nsec / NSEC_IN_SEC); _val.tv_nsec = (long)(nsec % NSEC_IN_SEC); } //------------------------------------------------------------------------------ inline void toTimeval(struct timeval &_val) const { int64_t usec = toUsec(); _val.tv_sec = (long)(usec / (USEC_IN_SEC)); _val.tv_usec = (long)(usec % (USEC_IN_SEC)); } //------------------------------------------------------------------------------ static int compare(const void *arg1, const void *arg2) { const TicksDuration &t1 = *(TicksDuration *)arg1; const TicksDuration &t2 = *(TicksDuration *)arg2; return t1 > t2 ? 1 : t1 < t2 ? -1 : 0; // Note: returning t1-t2 will not be safe because of // cast to int } //------------------------------------------------------------------------------ static void sort(TicksDuration *pArr, size_t size) { qsort(pArr, size, sizeof(TicksDuration), compare); } //------------------------------------------------------------------------------ static TicksDuration stdDev(TicksDuration *pArr, size_t size); private: inline explicit TicksDuration(ticks_t _ticks, bool) : TicksBase(_ticks) {} explicit TicksDuration(int64_t _nsec, int); // provide non inline function for reducing code // size outside fast path }; //============================================================================== class TicksTime : public TicksBase { friend class TicksDuration; public: // CTORs & DTOR inline TicksTime() : TicksBase(0) {} // init to 0 // inline TicksTime (bool) : TicksBase(getCurrentTicks()){} //init to now inline ~TicksTime() {} static const TicksTime TICKS0; // = TicksTime(0); // 'getCurrentTicks' related method - may throw exception if using clock_gettime and call // fatally failed inline static TicksTime now() { return TicksTime(getCurrentTicks()); } inline TicksTime &setNow() { m_ticks = getCurrentTicks(); return *this; } TicksTime &setNowNonInline(); // provide non inline function for reducing code size outside fast // path inline TicksDuration durationTillNow() { return TicksDuration(getCurrentTicks() - m_ticks, true); } // operators inline bool operator<(const TicksTime &rhs) const { return this->m_ticks < rhs.m_ticks; } inline bool operator>(const TicksTime &rhs) const { return this->m_ticks > rhs.m_ticks; } inline bool operator==(const TicksTime &rhs) const { return this->m_ticks == rhs.m_ticks; } inline bool operator!=(const TicksTime &rhs) const { return this->m_ticks != rhs.m_ticks; } inline bool operator<=(const TicksTime &rhs) const { return this->m_ticks <= rhs.m_ticks; } inline bool operator>=(const TicksTime &rhs) const { return this->m_ticks >= rhs.m_ticks; } inline TicksTime operator+(const TicksDuration &rhs) const { return TicksTime(this->m_ticks + rhs.m_ticks); } inline TicksTime operator-(const TicksDuration &rhs) const { return TicksTime(this->m_ticks - rhs.m_ticks); } inline TicksDuration operator-(const TicksTime &rhs) const { return TicksDuration(this->m_ticks - rhs.m_ticks, true); } inline TicksTime &operator+=(const TicksDuration &rhs) { this->m_ticks += rhs.m_ticks; return *this; } inline TicksTime &operator-=(const TicksDuration &rhs) { this->m_ticks -= rhs.m_ticks; return *this; } // this method is for debug purposes only since it breaks the concept of TicksTime as a point in // time // and consider it as duration since some base point!! inline int64_t debugToNsec() const { return ticks2nsec(m_ticks); } //------------------------------------------------------------------------------ private: inline TicksTime(ticks_t _ticks) : TicksBase(_ticks) {} }; //------------------------------------------------------------------------------ // 'getCurrentTicks' related method - may throw exception if using clock_gettime and call fatally // failed inline void TicksDuration::setDurationSince(const TicksTime &start) { m_ticks = getCurrentTicks(); m_ticks -= start.m_ticks; } #endif /* TICKS_H_ */ sockperf-3.6/src/ticks_os.h000066400000000000000000000104751336630672200157730ustar00rootroot00000000000000/* * Copyright (c) 2011-2018 Mellanox Technologies Ltd. * 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. * 3. Neither the name of the Mellanox Technologies Ltd nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * 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. */ /** * @file ticks_os.h * * * @details: Base functions taken from ticks.h in favor of Windows compatibility, * using QueryPerformanceFrequency() and QueryPerformanceCounter() for max accuracy. * * * @author Meny Yossefi * **/ #ifndef _TICKS_OS_H_ #define _TICKS_OS_H_ #include /* clock_gettime()*/ #include #include // for int64_t #include // for qsort #include "clock.h" typedef int64_t ticks_t; #ifdef WIN32 #include #include #pragma warning(disable : 4290) // exception specification ignored except to indicate a function is // not __declspec(nothrow) #pragma warning(disable \ : 4996) // The compiler encountered a function that was marked with deprecated. #define usleep(x) Sleep(x / 1000) #define snprintf _snprintf struct timespec { time_t tv_sec; // Seconds. long int tv_nsec; // Nanoseconds. }; #endif /** * RDTSC extensions */ #define TSCVAL_INITIALIZER (0) static const int64_t NSEC_IN_SEC = 1000 * 1000 * 1000; // Utility function inline ticks_t timespec2nsec(const struct timespec &_val) { return NSEC_IN_SEC * _val.tv_sec + _val.tv_nsec; } inline ticks_t os_gettimeoftsc() { #ifdef WIN32 LARGE_INTEGER lp; double PCFreq = 0.0; QueryPerformanceFrequency(&lp); PCFreq = (double(lp.QuadPart)) / (double)NSEC_IN_SEC; // NanoSec QueryPerformanceCounter(&lp); lp.QuadPart = (LONGLONG)((lp.QuadPart) / (PCFreq)); return (ticks_t)(lp.QuadPart); #else register uint32_t upper_32, lower_32; #if defined(__powerpc64__) unsigned long long ret; asm volatile("mftb %0" : "=r"(ret) :); return (ticks_t)ret; #elif defined(__s390__) unsigned long long ret; asm volatile("stck %0" : "=Q"(ret) : : "cc"); return (ticks_t)ret; #elif defined(__arm__) || defined(__aarch64__) // so the compiler will not complain. for // arm compile, this inline is not used // since no rdtsc supported on most arm processors upper_32 = lower_32 = 0; /*throw("rdtsc not supported in arm");*/ #else // ReaD Time Stamp Counter (RDTCS) __asm__ __volatile__("rdtsc" : "=a"(lower_32), "=d"(upper_32)); #endif // Return to user return (((ticks_t)upper_32) << 32) | lower_32; #endif } inline void os_ts_gettimeofclock(struct timespec *pts) { #ifdef WIN32 ticks_t val = os_gettimeoftsc(); // probably just NSEC_IN_SEC pts->tv_sec = val / NSEC_IN_SEC; pts->tv_nsec = val % NSEC_IN_SEC; #else if (clock_gettime(CLOCK_MONOTONIC, pts)) { throw("clock_gettime failed"); } #endif } inline ticks_t os_gettimeofclock() { struct timespec ts; os_ts_gettimeofclock(&ts); return timespec2nsec(ts); } #endif /*_TICKS_OS_H_*/ sockperf-3.6/src/vma-redirect.cpp000066400000000000000000000174361336630672200170760ustar00rootroot00000000000000/* * Copyright (c) 2011-2018 Mellanox Technologies Ltd. * 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. * 3. Neither the name of the Mellanox Technologies Ltd nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * 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. */ #include "vma-redirect.h" #include socket_fptr_t fn_socket = NULL; close_fptr_t fn_close = NULL; shutdown_fptr_t fn_shutdown = NULL; accept_fptr_t fn_accept = NULL; bind_fptr_t fn_bind = NULL; connect_fptr_t fn_connect = NULL; listen_fptr_t fn_listen = NULL; setsockopt_fptr_t fn_setsockopt = NULL; getsockopt_fptr_t fn_getsockopt = NULL; fcntl_fptr_t fn_fcntl = NULL; ioctl_fptr_t fn_ioctl = NULL; getsockname_fptr_t fn_getsockname = NULL; getpeername_fptr_t fn_getpeername = NULL; read_fptr_t fn_read = NULL; readv_fptr_t fn_readv = NULL; recv_fptr_t fn_recv = NULL; recvmsg_fptr_t fn_recvmsg = NULL; recvmmsg_fptr_t fn_recvmmsg = NULL; recvfrom_fptr_t fn_recvfrom = NULL; write_fptr_t fn_write = NULL; writev_fptr_t fn_writev = NULL; send_fptr_t fn_send = NULL; sendmsg_fptr_t fn_sendmsg = NULL; sendmmsg_fptr_t fn_sendmmsg = NULL; sendto_fptr_t fn_sendto = NULL; select_fptr_t fn_select = NULL; pselect_fptr_t fn_pselect = NULL; poll_fptr_t fn_poll = NULL; ppoll_fptr_t fn_ppoll = NULL; epoll_create_fptr_t fn_epoll_create = NULL; epoll_create1_fptr_t fn_epoll_create1 = NULL; epoll_ctl_fptr_t fn_epoll_ctl = NULL; epoll_wait_fptr_t fn_epoll_wait = NULL; epoll_pwait_fptr_t fn_epoll_pwait = NULL; socketpair_fptr_t fn_socketpair = NULL; pipe_fptr_t fn_pipe = NULL; open_fptr_t fn_open = NULL; creat_fptr_t fn_creat = NULL; dup_fptr_t fn_dup = NULL; dup2_fptr_t fn_dup2 = NULL; clone_fptr_t fn_clone = NULL; fork_fptr_t fn_fork = NULL; vfork_fptr_t fn_vfork = NULL; daemon_fptr_t fn_daemon = NULL; sigaction_fptr_t fn_sigaction = NULL; //////////////////////////////////////////////////////////////////////////////// #define VMA_LOG_CB_ENV_VAR "VMA_LOG_CB_FUNC_PTR" //////////////////////////////////////////////////////////////////////////////// static vma_log_cb_t vma_log_get_cb_func() { vma_log_cb_t log_cb = NULL; const char *const CB_STR = getenv(VMA_LOG_CB_ENV_VAR); if (!CB_STR || !*CB_STR) return NULL; if (1 != sscanf(CB_STR, "%p", &log_cb)) return NULL; return log_cb; } //////////////////////////////////////////////////////////////////////////////// bool vma_log_set_cb_func(vma_log_cb_t log_cb) { char str[64]; sprintf(str, "%p", log_cb); setenv(VMA_LOG_CB_ENV_VAR, str, 1); if (log_cb != vma_log_get_cb_func()) // verify that VMA will be able to read it correctly { unsetenv(VMA_LOG_CB_ENV_VAR); return false; } return true; } //////////////////////////////////////////////////////////////////////////////// static bool vma_set_func_pointers_internal(void *libHandle) { // Set pointers to functions #define SET_FUNC_POINTER(libHandle, func) (fn_##func = (func##_fptr_t)dlsym(libHandle, #func)) bool ret = true; if (!SET_FUNC_POINTER(libHandle, socket)) ret = false; if (!SET_FUNC_POINTER(libHandle, close)) ret = false; if (!SET_FUNC_POINTER(libHandle, shutdown)) ret = false; if (!SET_FUNC_POINTER(libHandle, accept)) ret = false; if (!SET_FUNC_POINTER(libHandle, bind)) ret = false; if (!SET_FUNC_POINTER(libHandle, connect)) ret = false; if (!SET_FUNC_POINTER(libHandle, listen)) ret = false; if (!SET_FUNC_POINTER(libHandle, setsockopt)) ret = false; if (!SET_FUNC_POINTER(libHandle, getsockopt)) ret = false; if (!SET_FUNC_POINTER(libHandle, fcntl)) ret = false; if (!SET_FUNC_POINTER(libHandle, ioctl)) ret = false; if (!SET_FUNC_POINTER(libHandle, getsockname)) ret = false; if (!SET_FUNC_POINTER(libHandle, getpeername)) ret = false; if (!SET_FUNC_POINTER(libHandle, read)) ret = false; if (!SET_FUNC_POINTER(libHandle, readv)) ret = false; if (!SET_FUNC_POINTER(libHandle, recv)) ret = false; if (!SET_FUNC_POINTER(libHandle, recvmsg)) ret = false; if (!SET_FUNC_POINTER(libHandle, recvmmsg)) ret = false; if (!SET_FUNC_POINTER(libHandle, recvfrom)) ret = false; if (!SET_FUNC_POINTER(libHandle, write)) ret = false; if (!SET_FUNC_POINTER(libHandle, writev)) ret = false; if (!SET_FUNC_POINTER(libHandle, send)) ret = false; if (!SET_FUNC_POINTER(libHandle, sendmsg)) ret = false; if (!SET_FUNC_POINTER(libHandle, sendmmsg)) ret = false; if (!SET_FUNC_POINTER(libHandle, sendto)) ret = false; if (!SET_FUNC_POINTER(libHandle, select)) ret = false; if (!SET_FUNC_POINTER(libHandle, pselect)) ret = false; if (!SET_FUNC_POINTER(libHandle, poll)) ret = false; if (!SET_FUNC_POINTER(libHandle, ppoll)) ret = false; if (!SET_FUNC_POINTER(libHandle, epoll_create)) ret = false; if (!SET_FUNC_POINTER(libHandle, epoll_create1)) ret = false; if (!SET_FUNC_POINTER(libHandle, epoll_ctl)) ret = false; if (!SET_FUNC_POINTER(libHandle, epoll_wait)) ret = false; if (!SET_FUNC_POINTER(libHandle, epoll_pwait)) ret = false; if (!SET_FUNC_POINTER(libHandle, socketpair)) ret = false; if (!SET_FUNC_POINTER(libHandle, pipe)) ret = false; if (!SET_FUNC_POINTER(libHandle, open)) ret = false; if (!SET_FUNC_POINTER(libHandle, creat)) ret = false; if (!SET_FUNC_POINTER(libHandle, dup)) ret = false; if (!SET_FUNC_POINTER(libHandle, dup2)) ret = false; if (!SET_FUNC_POINTER(libHandle, clone)) ret = false; if (!SET_FUNC_POINTER(libHandle, fork)) ret = false; if (!SET_FUNC_POINTER(libHandle, vfork)) ret = false; if (!SET_FUNC_POINTER(libHandle, daemon)) ret = false; if (!SET_FUNC_POINTER(libHandle, sigaction)) ret = false; return ret; } //////////////////////////////////////////////////////////////////////////////// bool vma_set_func_pointers(bool loadVma) { void *libHandle = RTLD_DEFAULT; if (loadVma) { const char *libName = "libvma.so"; // libHandle = dlopen(libName, RTLD_NOW); // this was broken in vma_tcp_4.5 because of // symbol: vma_log_set_log_stderr libHandle = dlopen(libName, RTLD_LAZY); if (!libHandle) return false; } return vma_set_func_pointers_internal(libHandle); } //------------------------------------------------------------------------------ bool vma_set_func_pointers(const char *LibVmaPath) { if (!LibVmaPath || !*LibVmaPath) return false; // void * libHandle = dlopen(LibVmaPath, RTLD_NOW); // this was broken in vma_tcp_4.5 because // of symbol: vma_log_set_log_stderr void *libHandle = dlopen(LibVmaPath, RTLD_LAZY); if (!libHandle) return false; return vma_set_func_pointers_internal(libHandle); } sockperf-3.6/src/vma-redirect.h000066400000000000000000000277461336630672200165500ustar00rootroot00000000000000/* * Copyright (c) 2011-2018 Mellanox Technologies Ltd. * 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. * 3. Neither the name of the Mellanox Technologies Ltd nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * 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. */ #ifndef VMA_REDIRECT_H #define VMA_REDIRECT_H #include #include #include #include #include #include #include #ifdef __FreeBSD__ #include #include #else #include #include #endif // ------------------------------------------------------------------- // /** * Expected order of operations: * ============================== * 1. N x vma_setenv() * 2. vma_log_set_cb_func(); * 3. vma_set_func_pointers(); * * all functions return 'true' on success; 'false' - otherwise * * NOTE: including this header will redirect all relevant API calls to pointers * to functions. Hence, you you are allowed to call any of the relevant APIs, * only after successfully completing vma_set_func_pointers()! * */ //------------------------------------------------------------------------------ // The vma_setenv() function adds the variable 'name' to the environment with // the value 'value', only if 'name' does not already exist. If 'name' does exist // in the environment, then the value of 'name' is not changed. static inline bool vma_setenv(const char *name, const char *value) { return setenv(name, value, 0) == 0; } // //------------------------------------------------------------------------------ // NOTE: int log_level is equivalent to VMA_TRACELEVEL (see VMA README.txt) typedef void (*vma_log_cb_t)(int log_level, const char *str); // // NOTE: log_cb will run in context of vma; hence, it must not block the thread bool vma_log_set_cb_func(vma_log_cb_t log_cb); // //------------------------------------------------------------------------------ // loads libvma.so only in case 'loadVma' is set. In any case sets // global pointer variables for ALL vma related function pointers. bool vma_set_func_pointers(bool loadVma); //------------------------------------------------------------------------------ // loads libvma according to the given 'loadVmaPath', then set // global pointer variables for ALL vma related function pointers. bool vma_set_func_pointers(const char *LibVmaPath); /** *----------------------------------------------------------------------------- * typedef for variables that will hold the function-pointers *----------------------------------------------------------------------------- */ typedef int (*socket_fptr_t)(int __domain, int __type, int __protocol); typedef int (*close_fptr_t)(int __fd); typedef int (*shutdown_fptr_t)(int __fd, int __how); typedef int (*accept_fptr_t)(int __fd, struct sockaddr *__addr, socklen_t *__addrlen); typedef int (*bind_fptr_t)(int __fd, const struct sockaddr *__addr, socklen_t __addrlen); typedef int (*connect_fptr_t)(int __fd, const struct sockaddr *__to, socklen_t __tolen); typedef int (*listen_fptr_t)(int __fd, int __backlog); typedef int (*setsockopt_fptr_t)(int __fd, int __level, int __optname, __const void *__optval, socklen_t __optlen); typedef int (*getsockopt_fptr_t)(int __fd, int __level, int __optname, void *__optval, socklen_t *__optlen); typedef int (*fcntl_fptr_t)(int __fd, int __cmd, ...); typedef int (*ioctl_fptr_t)(int __fd, int __request, ...); typedef int (*getsockname_fptr_t)(int __fd, struct sockaddr *__name, socklen_t *__namelen); typedef int (*getpeername_fptr_t)(int __fd, struct sockaddr *__name, socklen_t *__namelen); typedef ssize_t (*read_fptr_t)(int __fd, void *__buf, size_t __nbytes); typedef ssize_t (*readv_fptr_t)(int __fd, const struct iovec *iov, int iovcnt); typedef ssize_t (*recv_fptr_t)(int __fd, void *__buf, size_t __n, int __flags); typedef ssize_t (*recvmsg_fptr_t)(int __fd, struct msghdr *__message, int __flags); typedef ssize_t (*recvmmsg_fptr_t)(int __fd, struct mmsghdr *__mmsghdr, unsigned int __vlen, int __flags, const struct timespec *__timeout); typedef ssize_t (*recvfrom_fptr_t)(int __fd, void *__restrict __buf, size_t __n, int __flags, struct sockaddr *__from, socklen_t *__fromlen); typedef ssize_t (*write_fptr_t)(int __fd, __const void *__buf, size_t __n); typedef ssize_t (*writev_fptr_t)(int __fd, const struct iovec *iov, int iovcnt); typedef ssize_t (*send_fptr_t)(int __fd, __const void *__buf, size_t __n, int __flags); typedef ssize_t (*sendmsg_fptr_t)(int __fd, __const struct msghdr *__message, int __flags); typedef ssize_t (*sendmmsg_fptr_t)(int __fd, struct mmsghdr *__mmsghdr, unsigned int __vlen, int __flags); typedef ssize_t (*sendto_fptr_t)(int __fd, __const void *__buf, size_t __n, int __flags, const struct sockaddr *__to, socklen_t __tolen); typedef int (*select_fptr_t)(int __nfds, fd_set *__readfds, fd_set *__writefds, fd_set *__exceptfds, struct timeval *__timeout); typedef int (*pselect_fptr_t)(int __nfds, fd_set *__readfds, fd_set *__writefds, fd_set *__errorfds, const struct timespec *__timeout, const sigset_t *__sigmask); typedef int (*poll_fptr_t)(struct pollfd *__fds, nfds_t __nfds, int __timeout); typedef int (*ppoll_fptr_t)(struct pollfd *__fds, nfds_t __nfds, const struct timespec *__timeout, const sigset_t *__sigmask); typedef int (*epoll_create_fptr_t)(int __size); typedef int (*epoll_create1_fptr_t)(int __flags); typedef int (*epoll_ctl_fptr_t)(int __epfd, int __op, int __fd, struct epoll_event *__event); typedef int (*epoll_wait_fptr_t)(int __epfd, struct epoll_event *__events, int __maxevents, int __timeout); typedef int (*epoll_pwait_fptr_t)(int __epfd, struct epoll_event *__events, int __maxevents, int __timeout, const sigset_t *sigmask); typedef int (*socketpair_fptr_t)(int __domain, int __type, int __protocol, int __sv[2]); typedef int (*pipe_fptr_t)(int __filedes[2]); typedef int (*open_fptr_t)(__const char *__file, int __oflag, ...); typedef int (*creat_fptr_t)(const char *__pathname, mode_t __mode); typedef int (*dup_fptr_t)(int fildes); typedef int (*dup2_fptr_t)(int fildes, int fildes2); typedef int (*clone_fptr_t)(int (*__fn)(void *), void *__child_stack, int __flags, void *__arg); typedef pid_t (*fork_fptr_t)(void); typedef pid_t (*vfork_fptr_t)(void); typedef int (*daemon_fptr_t)(int __nochdir, int __noclose); typedef int (*sigaction_fptr_t)(int signum, const struct sigaction *act, struct sigaction *oldact); /** *----------------------------------------------------------------------------- * variables to hold the function-pointers *----------------------------------------------------------------------------- */ extern socket_fptr_t fn_socket; extern close_fptr_t fn_close; extern shutdown_fptr_t fn_shutdown; extern accept_fptr_t fn_accept; extern bind_fptr_t fn_bind; extern connect_fptr_t fn_connect; extern listen_fptr_t fn_listen; extern setsockopt_fptr_t fn_setsockopt; extern getsockopt_fptr_t fn_getsockopt; extern fcntl_fptr_t fn_fcntl; extern ioctl_fptr_t fn_ioctl; extern getsockname_fptr_t fn_getsockname; extern getpeername_fptr_t fn_getpeername; extern read_fptr_t fn_read; extern readv_fptr_t fn_readv; extern recv_fptr_t fn_recv; extern recvmsg_fptr_t fn_recvmsg; extern recvmmsg_fptr_t fn_recvmmsg; extern recvfrom_fptr_t fn_recvfrom; extern write_fptr_t fn_write; extern writev_fptr_t fn_writev; extern send_fptr_t fn_send; extern sendmsg_fptr_t fn_sendmsg; extern sendmmsg_fptr_t fn_sendmmsg; extern sendto_fptr_t fn_sendto; extern select_fptr_t fn_select; extern pselect_fptr_t fn_pselect; extern poll_fptr_t fn_poll; extern ppoll_fptr_t fn_ppoll; extern epoll_create_fptr_t fn_epoll_create; extern epoll_create1_fptr_t fn_epoll_create1; extern epoll_ctl_fptr_t fn_epoll_ctl; extern epoll_wait_fptr_t fn_epoll_wait; extern epoll_pwait_fptr_t fn_epoll_pwait; extern socketpair_fptr_t fn_socketpair; extern pipe_fptr_t fn_pipe; extern open_fptr_t fn_open; extern creat_fptr_t fn_creat; extern dup_fptr_t fn_dup; extern dup2_fptr_t fn_dup2; extern clone_fptr_t fn_clone; extern fork_fptr_t fn_fork; extern vfork_fptr_t fn_vfork; extern daemon_fptr_t fn_daemon; extern sigaction_fptr_t fn_sigaction; #ifndef VMA_NO_FUNCTIONS_DEFINES // The following definitions will replace ALL relevant API calls with calls to our function // pointers. // NOTE: before any relevant API call, you MUST set our function pointers thru successful call to // 'vma_set_func_pointers' // (note: these definitions will not catch function prototypes neither combinations like 'struct // sigaction') #define socket(...) fn_socket(__VA_ARGS__) #define close(...) fn_close(__VA_ARGS__) #define shutdown(...) fn_shutdown(__VA_ARGS__) #define accept(...) fn_accept(__VA_ARGS__) #define bind(...) fn_bind(__VA_ARGS__) #define connect(...) fn_connect(__VA_ARGS__) #define listen(...) fn_listen(__VA_ARGS__) #define setsockopt(...) fn_setsockopt(__VA_ARGS__) #define getsockopt(...) fn_getsockopt(__VA_ARGS__) #define fcntl(...) fn_fcntl(__VA_ARGS__) #define ioctl(...) fn_ioctl(__VA_ARGS__) #define getsockname(...) fn_getsockname(__VA_ARGS__) #define getpeername(...) fn_getpeername(__VA_ARGS__) #define read(...) fn_read(__VA_ARGS__) #define readv(...) fn_readv(__VA_ARGS__) #define recv(...) fn_recv(__VA_ARGS__) #define recvmsg(...) fn_recvmsg(__VA_ARGS__) #define recvmmsg(...) fn_recvmmsg(__VA_ARGS__) #define recvfrom(...) fn_recvfrom(__VA_ARGS__) #define write(...) fn_write(__VA_ARGS__) #define writev(...) fn_writev(__VA_ARGS__) #define send(...) fn_send(__VA_ARGS__) #define sendmsg(...) fn_sendmsg(__VA_ARGS__) #define sendmmsg(...) fn_sendmmsg(__VA_ARGS__) #define sendto(...) fn_sendto(__VA_ARGS__) #define select(...) fn_select(__VA_ARGS__) #define pselect(...) fn_pselect(__VA_ARGS__) #define poll(...) fn_poll(__VA_ARGS__) #define ppoll(...) fn_ppoll(__VA_ARGS__) #define epoll_create(...) fn_epoll_create(__VA_ARGS__) #define epoll_create1(...) fn_epoll_create1(__VA_ARGS__) #define epoll_ctl(...) fn_epoll_ctl(__VA_ARGS__) #define epoll_wait(...) fn_epoll_wait(__VA_ARGS__) #define epoll_pwait(...) fn_epoll_pwait(__VA_ARGS__) #define socketpair(...) fn_socketpair(__VA_ARGS__) #define pipe(...) fn_pipe(__VA_ARGS__) #define open(...) fn_open(__VA_ARGS__) #define creat(...) fn_creat(__VA_ARGS__) #define dup(...) fn_dup(__VA_ARGS__) #define dup2(...) fn_dup2(__VA_ARGS__) #define clone(...) fn_clone(__VA_ARGS__) #define fork(...) fn_fork(__VA_ARGS__) #define vfork(...) fn_vfork(__VA_ARGS__) #define daemon(...) fn_daemon(__VA_ARGS__) #define sigaction(...) fn_sigaction(__VA_ARGS__) #endif // VMA_NO_FUNCTIONS_DEFINES #endif // VMA_REDIRECT_H sockperf-3.6/tests/000077500000000000000000000000001336630672200143505ustar00rootroot00000000000000sockperf-3.6/tests/Makefile.am000077500000000000000000000005211336630672200164050ustar00rootroot00000000000000testdir = $(prefix)/etc/sockperf/ test_SCRIPTS = \ avner-analyze.awk \ avner-master-test.sh \ avner-test.sh \ avner-test-orig \ vma_multiplexers_test.sh \ vma_perf_envelope.sh dist_test_SCRIPTS = \ avner-analyze.awk \ avner-master-test.sh \ avner-test.sh \ avner-test-orig \ vma_multiplexers_test.sh \ vma_perf_envelope.sh sockperf-3.6/tests/avner-analyze.awk000077500000000000000000000016121336630672200176330ustar00rootroot00000000000000#!/bin/awk -f # # This script will nicely analyze output file that was created using ./avner-test or ./avner-test2 # /^[ \t]*#/ {print; next} # echo and skip comment line NF !=3 || $3+0 <= 0 {next} # Skip empty or text lines { # handle all other lines nsec = 1000 * $3 sum[$1] += nsec num[$1] ++ sum_sqr[$1] += nsec * nsec } END { for (test in num) { avg[test] = sum[test] / num[test] std = (num[test] > 1) ? sqrt ( (sum_sqr[test] - num[test]*avg[test]*avg[test]) / (num[test] - 1) ) : 0 printf "%s: %12s: avg=%.3fusec (std=%.3f, #Observations=%d)\n", FILENAME, test, avg[test]/1000, std/1000, num[test] } for (test in num) { if (prev) { printf "====> %s: delta_avg (%s_avg - %s_avg) = %.3fusec\n", FILENAME, prev, test, (avg[prev]-avg[test])/1000 } else { printf "====> \n" } prev = test } } sockperf-3.6/tests/avner-master-test.sh000077500000000000000000000066051336630672200202770ustar00rootroot00000000000000#!/bin/bash if [ $# != 1 ] then echo "Usage: $0 " exit 1 fi; IP=$1 LOG_DIR=./log/`hostname` mkdir -p $LOG_DIR function clean_up { # Perform program exit housekeeping kill %1 %2 %3 %4 # kill any running child exit } trap clean_up SIGINT SIGTERM SIGHUP function run_test() { echo -e "\n# >> running test for $RUNTIME; LOG_FILE is: $LOG_DIR/$LOG_FILE\n" echo "# $MSG" | tee -a $LOG_DIR/$LOG_FILE ./avner-test.sh $IP | tee -a $LOG_DIR/$LOG_FILE & sleep $RUNTIME kill %1 echo -e \\a #beep } #export VMA_PATH=/volt/avnerb/vma/libvma.so-4.5 #export VMA_PATH=/volt/avnerb/vma/libvma.so-nosend-norecv #export VMA_PATH=/volt/avnerb/vma/libvma.so-nosocket #export VMA_PATH=/volt/avnerb/vma/libvma.so-norecv #export VMA_PATH=/volt/avnerb/vma/libvma.so-nosend #export VMA_PATH=/volt/avnerb/vma/libvma.so-nosend-norecv-nobind #export BASE_ARG="-c -t 4 -m 14" export VMA_RX_OFFLOAD=0 VMA_UC_OFFLOAD=1 export BASE_ARG="-c -t 4 -m 14 --ping-pong --pps=max" export VMA_PATH=/volt/avnerb/vma/libvma.so-4.5 RUNTIME=300s LOG_FILE=0.eth_server_ucoff-0.pingmax.rx0ff-0.ucoff-1.server-vma-custom-mc-reply-uc-client-vma4.5 MSG="ETH Server-Command: VMA_IGMP=0 VMA_RX_OFFLOAD=1 VMA_UC_OFFLOAD=0 LD_PRELOAD=/volt/avnerb/vma/libvma.so-4.5 ./sockperf -s -i 226.8.8.8 --force_unicast_reply" #run_test export VMA_RX_OFFLOAD=1 VMA_UC_OFFLOAD=1 export BASE_ARG="-c -t 4 -m 14 --ping-pong --pps=max" export VMA_PATH=/volt/avnerb/vma/libvma.so-4.5 RUNTIME=300s LOG_FILE=1.eth_server_ucoff-0.pingmax.rx0ff-1.ucoff-1.server-vma-custom-mc-reply-uc-client-vma4.5 MSG="ETH Server-Command: VMA_IGMP=0 VMA_RX_OFFLOAD=1 VMA_UC_OFFLOAD=0 LD_PRELOAD=/volt/avnerb/vma/libvma.so-4.5 ./sockperf -s -i 226.8.8.8 --force_unicast_reply" #run_test export VMA_RX_OFFLOAD=0 VMA_UC_OFFLOAD=1 export BASE_ARG="-c -t 4 -m 14 --ping-pong --pps=max" export VMA_PATH=/volt/avnerb/vma/libvma.so-norecv RUNTIME=300s LOG_FILE=2.eth_server_ucoff-0.pingmax.rx0ff-0.ucoff-1.server-vma-custom-mc-reply-uc-client-vma-norecv MSG="ETH Server-Command: VMA_IGMP=0 VMA_RX_OFFLOAD=1 VMA_UC_OFFLOAD=0 LD_PRELOAD=/volt/avnerb/vma/libvma.so-4.5 ./sockperf -s -i 226.8.8.8 --force_unicast_reply" #run_test export VMA_RX_OFFLOAD=0 VMA_UC_OFFLOAD=1 export BASE_ARG="-c -t 4 -m 14 --ping-pong --pps=max" export VMA_PATH=/volt/avnerb/vma/libvma.so-4.5 RUNTIME=300s LOG_FILE=3.eth_server_ucoff-1.pingmax.rx0ff-0.ucoff-1.server-vma-custom-mc-reply-uc-client-vma4.5 MSG="ETH Server-Command: VMA_IGMP=0 VMA_RX_OFFLOAD=1 VMA_UC_OFFLOAD=1 LD_PRELOAD=/volt/avnerb/vma/libvma.so-4.5 ./sockperf -s -i 226.8.8.8 --force_unicast_reply" run_test export VMA_RX_OFFLOAD=1 VMA_UC_OFFLOAD=1 export BASE_ARG="-c -t 4 -m 14 --ping-pong --pps=max" export VMA_PATH=/volt/avnerb/vma/libvma.so-4.5 RUNTIME=300s LOG_FILE=4.eth_server_ucoff-1.pingmax.rx0ff-1.ucoff-1.server-vma-custom-mc-reply-uc-client-vma4.5 MSG="ETH Server-Command: VMA_IGMP=0 VMA_RX_OFFLOAD=1 VMA_UC_OFFLOAD=1 LD_PRELOAD=/volt/avnerb/vma/libvma.so-4.5 ./sockperf -s -i 226.8.8.8 --force_unicast_reply" run_test export VMA_RX_OFFLOAD=0 VMA_UC_OFFLOAD=1 export BASE_ARG="-c -t 4 -m 14 --ping-pong --pps=max" export VMA_PATH=/volt/avnerb/vma/libvma.so-norecv RUNTIME=300s LOG_FILE=5.eth_server_ucoff-1.pingmax.rx0ff-0.ucoff-1.server-vma-custom-mc-reply-uc-client-vma-norecv MSG="ETH Server-Command: VMA_IGMP=0 VMA_RX_OFFLOAD=1 VMA_UC_OFFLOAD=1 LD_PRELOAD=/volt/avnerb/vma/libvma.so-4.5 ./sockperf -s -i 226.8.8.8 --force_unicast_reply" run_test sockperf-3.6/tests/avner-test-orig000077500000000000000000000016301336630672200173240ustar00rootroot00000000000000#!/bin/bash #export VMA_IGMP=0 LD_PRELOAD=libvma.so #BASE_ARG="-c -t 10 -m 14 -i 224.99.200.8" BASE_ARG="-c -t 10 -m 14 -F e -f conf/conf25.inp" while true do CMD="udp_lat "; ARG=${BASE_ARG}5; sleep 1 echo -n "$CMD : ";VMA_IGMP=0 LD_PRELOAD=libvma.so $CMD $ARG 2> /dev/null | grep "Summary: Latency is " | awk '{print $5}' #CMD="udp_lat "; ARG=${BASE_ARG}5; sleep 1 #echo -n "$CMD : ";VMA_IGMP=0 LD_PRELOAD=libvma.so $CMD $ARG 2> /dev/null | grep "Summary: Latency is " | awk '{print $5}' CMD="./sockperf "; ARG="${BASE_ARG}4 --ping-pong"; sleep 1 echo -n "$CMD : ";VMA_IGMP=0 LD_PRELOAD=libvma.so $CMD $ARG 2> /dev/null | grep "Summary: Latency is " | awk '{print $5}' #CMD="././sockperf"; ARG="${BASE_ARG}4 --reply-every=1"; sleep 1 #echo -n "$CMD : ";VMA_IGMP=0 LD_PRELOAD=libvma.so $CMD $ARG 2> /dev/null | grep "Summary: Latency is " | awk '{print $5}' echo --- done sockperf-3.6/tests/avner-test.sh000077500000000000000000000017621336630672200170050ustar00rootroot00000000000000#!/bin/bash if [ $# != 1 ] then echo "Usage: $0 " exit 1 fi; IP=$1 function clean_up { # Perform program exit housekeeping kill %1 %2 %3 %4 # kill any running child exit } trap clean_up SIGINT SIGTERM SIGHUP echo \# FILTER = percentile 75 #echo \# FILTER = Message Rate echo \# VMA_PATH = $VMA_PATH echo \# BASE_ARG = $BASE_ARG echo \# Server-IP = $IP export | awk '/VMA/ {print "#", $0}' while true do CMD="./sockperf "; ARG="${BASE_ARG} -i $IP"; sleep 1 echo -n "OS : ";_D_PRELOAD=$VMA_PATH $CMD $ARG 2> /dev/null | awk '/dropped packets/ && $6+$11+$16 {printf("#%s\n#", $0) } /percentile 75/{print $6}' #echo -n "OS : ";_D_PRELOAD=$VMA_PATH $CMD $ARG 2> /dev/null | awk '/Message Rate/{print $6}' sleep 1 echo -n "VMA : ";LD_PRELOAD=$VMA_PATH $CMD $ARG 2> /dev/null | awk '/dropped packets/ && $6+$11+$16 {printf("#%s\n#", $0) } /percentile 75/{print $6}' #echo -n "VMA : ";LD_PRELOAD=$VMA_PATH $CMD $ARG 2> /dev/null | awk '/Message Rate/{print $6}' echo --- done sockperf-3.6/tests/verifier/000077500000000000000000000000001336630672200161635ustar00rootroot00000000000000sockperf-3.6/tests/verifier/README000066400000000000000000000022221336630672200170410ustar00rootroot00000000000000VPERF VERIFIER version 0.01 ================ The README is used to introduce the module and provide instructions on how to install the module, any machine dependencies it may have (for example C compilers and installed libraries) and any other information that should be provided before the module is installed. A README file is required for CPAN modules since CPAN extracts the README file from a module distribution so that people browsing the archive can use it get an idea of the modules uses. It is usually a good idea to provide version information here so that people can decide whether fixes for the module are worth downloading. INSTALLATION To install this module type the following: perl Makefile.PL make make test make install DEPENDENCIES This module requires these other modules and libraries: blah blah blah COPYRIGHT AND LICENCE Put the correct copyright and licence information here. Copyright (C) 2011 by Igor Ivanov This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.8 or, at your option, any later version of Perl 5 you may have available. sockperf-3.6/tests/verifier/doc/000077500000000000000000000000001336630672200167305ustar00rootroot00000000000000sockperf-3.6/tests/verifier/doc/Test Matrix.xls000066400000000000000000002310001336630672200216200ustar00rootroot00000000000000ࡱ;   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~Root Entry  \pCalc Ba= @=@ 8K"1Arial1Arial1Arial1Arial1Arial1Arial1.Courier New CYR GENERAL                + ) , *      h" "X  H  H      H PASS FAIL83ffff̙̙3f3ffff3f3f33333f33333`I(udp-ppMudp-ullrudp-tp7udp-pbtcp-pptcp-ultcp-tpCtcp-pb ~tempX$  3  @@   UDP PING-PONGv.0.7v1.2v2.4r1866r27r36r41#1 - ping-pong w/o argumentstc1PASS"#2 - ping-pong option --dontwarmuptc2#3 - ping-pong option -b10tc3#4 - ping-pong option -b100tc4#5 - ping-pong option -b1000tc5FAIL#6 - ping-pong option -t10tc6#7 - ping-pong option -t30tc7#8 - ping-pong option -m32tc8#9 - ping-pong option -m4096tc9#10 - ping-pong option -m65500tc10#11 - ping-pong option -r10tc11#12 - ping-pong option -r100tc12#13 - ping-pong option -r1024tc13&#14 - ping-pong option -f (10 records)tc14*#15 - ping-pong option -f -Fs (10 records)tc15*#16 - ping-pong option -f -Fp (10 records)tc16*#17 - ping-pong option -f -Fe (10 records)tc17+#18 - ping-pong option -f -Fs (300 records)tc18+#19 - ping-pong option -f -Fp (300 records)tc19+#20 - ping-pong option -f -Fe (300 records)tc20)#21 - ping-pong option -f -Fs --timeout 0tc21)#22 - ping-pong option -f -Fp --timeout 0tc22)#23 - ping-pong option -f -Fe --timeout 0tc23*#24 - ping-pong option -f -Fs --timeout=-1tc24*#25 - ping-pong option -f -Fp --timeout=-1tc25*#26 - ping-pong option -f -Fe --timeout=-1tc26E#27 - ping-pong option -f -Fs --threads-num=2 (one socket per thread)tc27E#28 - ping-pong option -f -Fp --threads-num=2 (one socket per thread)tc28E#29 - ping-pong option -f -Fe --threads-num=2 (one socket per thread)tc29F#30 - ping-pong option -f -Fs --threads-num=10 (two socket per thread)tc30F#31 - ping-pong option -f -Fp --threads-num=10 (two socket per thread)tc31F#32 - ping-pong option -f -Fe --threads-num=10 (two socket per thread)tc32@#33 - ping-pong option -f -Fs --threads-num=100 (on 400 sockets)tc33@#34 - ping-pong option -f -Fp --threads-num=100 (on 400 sockets)tc34@#35 - ping-pong option -f -Fe --threads-num=100 (on 400 sockets)tc358#36 - ping-pong multicast option -f --mc-loopback-enabletc364#37 - ping-pong multicast option -f -Fs (10 records)tc374#38 - ping-pong multicast option -f -Fp (10 records)tc384#39 - ping-pong multicast option -f -Fe (10 records)tc395#40 - ping-pong multicast option -f -Fs (300 records)tc405#41 - ping-pong multicast option -f -Fp (300 records)tc415#42 - ping-pong multicast option -f -Fe (300 records)tc42#43 - ping-pong option --pps=10tc43!#44 - ping-pong option --pps=1000tc44##45 - ping-pong option --pps=100000tc45[#46 - ping-pong unicast option -f -Fs -t20 -m50000 -r512 --threads-num=100 --data-integritytc46]#47 - ping-pong multicast option -f -Fs -t20 -m50000 -r512 --threads-num=100 --data-integritytc47 UDP UNER-LOAD#1 - under-load w/o arguments##2 - under-load option --dontwarmup#3 - under-load option -b10#4 - under-load option -b100#5 - under-load option -b1000#6 - under-load option -t10#7 - under-load option -t30#8 - under-load option -m32#9 - under-load option -m4096#10 - under-load option -m65500#11 - under-load option -r10#12 - under-load option -r100#13 - under-load option -r1024'#14 - under-load option -f (10 records)+#15 - under-load option -f -Fs (10 records)+#16 - under-load option -f -Fp (10 records)+#17 - under-load option -f -Fe (10 records),#18 - under-load option -f -Fs (300 records),#19 - under-load option -f -Fp (300 records),#20 - under-load option -f -Fe (300 records)*#21 - under-load option -f -Fs --timeout 0*#22 - under-load option -f -Fp --timeout 0*#23 - under-load option -f -Fe --timeout 0+#24 - under-load option -f -Fs --timeout=-1+#25 - under-load option -f -Fp --timeout=-1+#26 - under-load option -f -Fe --timeout=-1F#27 - under-load option -f -Fs --threads-num=2 (one socket per thread)F#28 - under-load option -f -Fp --threads-num=2 (one socket per thread)F#29 - under-load option -f -Fe --threads-num=2 (one socket per thread)G#30 - under-load option -f -Fs --threads-num=10 (two socket per thread)G#31 - under-load option -f -Fp --threads-num=10 (two socket per thread)G#32 - under-load option -f -Fe --threads-num=10 (two socket per thread)A#33 - under-load option -f -Fs --threads-num=100 (on 400 sockets)A#34 - under-load option -f -Fp --threads-num=100 (on 400 sockets)A#35 - under-load option -f -Fe --threads-num=100 (on 400 sockets)9#36 - under-load multicast option -f --mc-loopback-enable5#37 - under-load multicast option -f -Fs (10 records)5#38 - under-load multicast option -f -Fp (10 records)5#39 - under-load multicast option -f -Fe (10 records)6#40 - under-load multicast option -f -Fs (300 records)6#41 - under-load multicast option -f -Fp (300 records)6#42 - under-load multicast option -f -Fe (300 records) #43 - under-load option --pps=10"#44 - under-load option --pps=1000$#45 - under-load option --pps=1000003#46 - under-load option --pps=100 --reply-every=1003#47 - under-load option --pps=1000 --reply-every=10UDP THROUGHPUT#1 - throughput w/o arguments##2 - throughput option --dontwarmup#3 - throughput option -b10#4 - throughput option -b100#5 - throughput option -b1000#6 - throughput option -t10#7 - throughput option -t30#8 - throughput option -m32#9 - throughput option -m4096#10 - throughput option -m65500#11 - throughput option -r10#12 - throughput option -r100#13 - throughput option -r1024'#14 - throughput option -f (10 records)+#15 - throughput option -f -Fs (10 records)+#16 - throughput option -f -Fp (10 records)+#17 - throughput option -f -Fe (10 records),#18 - throughput option -f -Fs (300 records),#19 - throughput option -f -Fp (300 records),#20 - throughput option -f -Fe (300 records)*#21 - throughput option -f -Fs --timeout 0*#22 - throughput option -f -Fp --timeout 0*#23 - throughput option -f -Fe --timeout 0+#24 - throughput option -f -Fs --timeout=-1+#25 - throughput option -f -Fp --timeout=-1+#26 - throughput option -f -Fe --timeout=-1F#27 - throughput option -f -Fs --threads-num=2 (one socket per thread)F#28 - throughput option -f -Fp --threads-num=2 (one socket per thread)F#29 - throughput option -f -Fe --threads-num=2 (one socket per thread)G#30 - throughput option -f -Fs --threads-num=10 (two socket per thread)G#31 - throughput option -f -Fp --threads-num=10 (two socket per thread)G#32 - throughput option -f -Fe --threads-num=10 (two socket per thread)A#33 - throughput option -f -Fs --threads-num=100 (on 400 sockets)A#34 - throughput option -f -Fp --threads-num=100 (on 400 sockets)A#35 - throughput option -f -Fe --threads-num=100 (on 400 sockets)9#36 - throughput multicast option -f --mc-loopback-enable5#37 - throughput multicast option -f -Fs (10 records)5#38 - throughput multicast option -f -Fp (10 records)5#39 - throughput multicast option -f -Fe (10 records)6#40 - throughput multicast option -f -Fs (300 records)6#41 - throughput multicast option -f -Fp (300 records)6#42 - throughput multicast option -f -Fe (300 records)"#43 - throughput option --pps=1000 UDP PLAYBACK#1 - playback w/o arguments TCP PING-PONGNONE6#36 - ping-pong -f -Fs (10 records the same addr:port)6#37 - ping-pong -f -Fp (10 records the same addr:port)6#38 - ping-pong -f -Fe (10 records the same addr:port)7#39 - ping-pong -f -Fs (300 records the same addr:port)7#40 - ping-pong -f -Fp (300 records the same addr:port)7#41 - ping-pong -f -Fe (300 records the same addr:port)#42 - ping-pong option --pps=10!#43 - ping-pong option --pps=1000##44 - ping-pong option --pps=100000[#45 - ping-pong unicast option -f -Fs -t20 -m50000 -r512 --threads-num=100 --data-integrity TCP UNER-LOAD7#36 - under-load -f -Fs (10 records the same addr:port)7#37 - under-load -f -Fp (10 records the same addr:port)7#38 - under-load -f -Fe (10 records the same addr:port)8#39 - under-load -f -Fs (300 records the same addr:port)8#40 - under-load -f -Fp (300 records the same addr:port)8#41 - under-load -f -Fe (300 records the same addr:port) #42 - under-load option --pps=10"#43 - under-load option --pps=1000$#44 - under-load option --pps=1000003#45 - under-load o<ption --pps=100 --reply-every=1003#46 - under-load option --pps=1000 --reply-every=10TCP THROUGHPUT"#36 - throughput option --pps=1000 TCP PLAYBACK ~   dMbP?_%*+E!&C&"Times New Roman,1KG=K9"&12&AO&&C&"Times New Roman,1KG=K9"&12Page &P&333333?'333333?(-؂-?)-؂-?" d,,333333?333333?U }  21                                        ~ :                                                                                                                                                 !            " #            $ %            & '            ( )            * +            , -            . /            0 1            2 3            4 5            6 7            8 9            : ;            < =            > ?            @ A            B C              ! " # $ % & ' ( ) * + , - . / 0 1  D E           !F !G ! ! ! ! ! ! ! !  !  "H "I " " " " " " " "  "  #J #K # # # # # # # #  #  $L $M $ $ $ $ $ $ $ $  $  %N %O % % % % % % % %  %  &P &Q & & & & & & & &  &  'R 'S ' ' ' ' ' ' ' '  '  (T (U ( ( ( ( ( ( ( (  (  )V )W ) ) ) ) ) ) ) )  )  *X *Y * * * * * * * *  *  +Z +[ + + + + + + + +  +  ,\ ,] , , , , , , , ,  ,  -^ -_ - - - - - - - -  -  .` .a . . . . . . . .  .  /b /c / / / / / / / /  /  0d 0e 0 0 0 0 0 0 0 0  0  1f 1g 1 1 1 1 1 1 1 1 1   (    3 rX??  - 31] $<%sockperf: data integrity test failed<$ 1 > @1 11 1 1 -8 CONTENTSB}PASSAu-8 <CONTENTSB}FAILAu   dMbP?_%*+E!&C&"Times New Roman,1KG=K9"&12&AO&&C&"Times New Roman,1KG=K9"&12Page &P&333333?'333333?(-؂-?)-؂-?" d,,333333?333333?U } U }  21                                   h     ~ :      i             j             k             l             m             n             o            p            q            r            s            t !            u #            v %            w '            x )            y +            z -            { /            | 1            } 3            ~ 5             7             9             ;             =             ?             A             C              ! " # $ % & ' ( ) * + , - . / 0 1   E           ! !G ! ! ! ! ! ! ! !  !  " "I " " " " " " " "  "  # #K # # # # # # # #  #  $ $M $ $ $ $ $ $ $ $  $  % %O % % % % % % % %  %  & &Q & & & & & & & &  &  ' 'S ' ' ' ' ' ' ' '  '  ( (U ( ( ( ( ( ( ( (  (  ) )W ) ) ) ) ) ) ) )  )  * *Y * * * * * * * *  *  + +[ + + + + + + + +  +  , ,] , , , , , , , ,  ,  - -_ - - - - - - - -  -  . .a . . . . . . . .  .  / /c / / / / / / / /  /  0 0e 0 0 0 0 0 0 0 0  0  1 1g 1 1 1 1 1 1 1 1  1   PH 0(  >@- -- 1 1 -8 CONTENTSB}PASSAu-8 <CONTENTSB}FAILAu1 11 -8 CONTENTSB}PASSAu-8 <CONTENTSB}FAILAu   dMbP?_%*+E!&C&"Times New Roman,1KG=K9"&12&AO&&C&"Times New Roman,1KG=K9"&12Page &P&333333?'333333?(-؂-?)-؂-?" d,,333333?333333?U }  21                                        ~ :                                                                                                                                                 !             #             %             '             )             +             -             /             1             3             5             7             9             ;             =             ?             A             C              ! " # $ % & ' ( ) * + , - ./01  E           ! !G ! ! ! ! ! ! ! !  !  " "I " " " " " " " "  "  # #K # # # # # # # #  #  $ $M $ $ $ $ $ $ $ $  $  % %O % % % % % % % %  %  & &Q & & & & & & & &  &  ' 'S ' ' ' ' ' ' ' '  '  ( (U ( ( ( ( ( ( ( (  (  ) )W ) ) ) ) ) ) ) )  )  * *Y * * * * * * * *  *  + +[ + + + + + + + +  +  , ,] , , , , , , , ,  ,  - -_ - - - - - - - -  -  . / 0 1  PH0 0(   >@  - - -8 CONTENTSB}PASSAu-8 <CONTENTSB}FAILAu&1 1.1 1 -8 CONTENTSB}PASSAu-8 <CONTENTSB}FAILAu   dMbP?_%*+E!&C&"Times New Roman,1KG=K9"&12&AO&&C&"Times New Roman,1KG=K9"&12Page &P&333333?'333333?(-؂-?)-؂-?" d,,333333?333333?U }  21            ~ :                                                !"#$%&'()*+,-./01  ! " # $ % & ' ( ) * + , - . / 0 1  PH@0(  >@    -8 CONTENTSB}PASSAu-8 <CONTENTSB}FAILAu&1 11 1 -8 CONTENTSB}PASSAu-8 <CONTENTSB}FAILAu   dMbP?_%*+E!&C&"Times New Roman,1KG=K9"&12&AO&&C&"Times New Roman,1KG=K9"&12Page &P&333333?'333333?(-؂-?)-؂-?" d,,333333?333333?U }  21                                        ~ :                                                                                                                                                 !            " #            $ %            & '            ( )            * +            , -            . /            0 1            2 3            4 5            6 7            8 9            : ;            < =            > ?            @ A            B C              ! " # $ % & ' ( ) * + , - . / 01 D E           !F !G ! ! ! ! ! ! ! !  !  "H "I " " " " " " " "  "  #J #K # # # # # # # #  #  $L $M $ $ $ $ $ $ $ $  $  %N %O % % % % % % % %  %  & &Q & & & & & & & &  &  ' 'S ' ' ' ' ' ' ' '  '  ( (U ( ( ( ( ( ( ( (  (  ) )W ) ) ) ) ) ) ) )  )  * *Y * * * * * * * *  *  + +[ + + + + + + + +  +  , ,] , , , , , , , ,  ,  - -_ - - - - - - - -  -  . .a . . . . . . . .  .  / /c / / / / / / / /  /  0 1  PHP0(  >@) )) / / -8 CONTENTSB}PASSAu-8 <CONTENTSB}FAILAu&1 101 1 -8 CONTENTSB}PASSAu-8 <CONTENTSB}FAILAu   dMbP?_%*+E!&C&"Times New Roman,1KG=K9"&12&AO&&C&"Times New Roman,1KG=K9"&12Page &P&333333?'333333?(-؂-?)-؂-?" d,,333333?333333?U }  21                                        ~ :      i             j             k             l             m             n             o            p            q            r            s            t !            u #            v %            w '            x )            y +            z -            { /            | 1            } 3            ~ 5             7             9             ;             =             ?             A             C              ! " # $ % & ' ( ) * + , - . / 0 1  E           ! !G ! ! ! ! ! ! ! !  !  " "I " " " " " " " "  "  # #K # # # # # # # #  #  $ $M $ $ $ $ $ $ $ $  $  % %O % % % % % % % %  %  & &Q & & & & & & & &  &  ' 'S ' ' ' ' ' ' ' '  '  ( (U ( ( ( ( ( ( ( (  (  ) )W ) ) ) ) ) ) ) )  )  * *Y * * * * * * * *  *  + +[ + + + + + + + +  +  , ,] , , , , , , , ,  ,  - -_ - - - - - - - -  -  . .a . . . . . . . .  .  / /c / / / / / / / /  /  0 0e 0 0 0 0 0 0 0 0  0  1  `(    3 rX??  + 34] S<Tsockperf: Client.cpp:434:ERROR: Can`t connect socket (errno=111 Connection refused)<S  3 rX??  , 35 ] S<Tsockperf: Client.cpp:434:ERROR: Can`t connect socket (errno=111 Connection refused)<S /  0 >@/ // 0 0 -8 CONTENTSB}PASSAu-8 <CONTENTSB}FAILAu&1 111 1 -8 CONTENTSB}PASSAu-8 <CONTENTSB}FAILAu   dMbP?_%*+E!&C&"Times New Roman,1KG=K9"&12&AO&&C&"Times New Roman,1KG=K9"&12Page &P&333333?'333333?(-؂-?)-؂-?" d,,333333?333333?U }  21                                        ~ :                                                                                                                                               !             #             %             '             )             +             -             /             1             3             5             7             9             ;             =             ?             A             C              ! " # $ % & '()*+,-./01  E           ! !G ! ! ! ! ! ! ! !  !  " "I " " " " " " " "  "  # #K # # # # # # # #  #  $ $M $ $ $ $ $ $ $ $  $  % %O % % % % % % % %  %  & &Q & & & & & & & &  &  ' ( ) * + , - . / 0 1  PHp0(  >@$ $$ & & -8 CONTENTSB}PASSAu-8 <CONTENTSB}FAILAu&1 1'1 1 -8 CONTENTSB}PASSAu-8 <CONTENTSB}FAILAu   dMbP?_%*+E!&C&"Times New Roman,1KG=K9"&12&AO&&C&"Times New Roman,1KG=K9"&12Page &P&333333?'333333?(-؂-?)-؂-?" d,,333333?333333?U }  21            ~ :                                                !"#$%&'()*+,-./01  ! " # $ % & ' ( ) * + , - . / 0 1  PH 0(   >@  1 1 -8 CONTENTSB}PASSAu-8 <CONTENTSB}FAILAu   dMbP?_%*+E!&C&"Times New Roman,1KG=K9"&12&AO&&C&"Times New Roman,1KG=K9"&12Page &P&333333?'333333?(-؂-?)-؂-?" d,,333333?333333?U }  PH$0(  $>@  FMicrosoft Excel 97-TabelleBiff8Oh+'0HPd x  Igor Ivanov Igor Ivanov14@lAQ@@2\@*p՜.+,D՜.+,\Root EntryF@WorkbookCompObjIOle SummaryInformation(DocumentSummaryInformation8tsockperf-3.6/tests/verifier/lib/000077500000000000000000000000001336630672200167315ustar00rootroot00000000000000sockperf-3.6/tests/verifier/lib/TE/000077500000000000000000000000001336630672200172415ustar00rootroot00000000000000sockperf-3.6/tests/verifier/lib/TE/Common.pm000066400000000000000000000047711336630672200210400ustar00rootroot00000000000000## # @file Common.pm # # @brief TE module to define common data. # # ## @class # Container for common data. package TE::Common; use strict; use warnings; use vars qw(@EXPORT); use base qw(Exporter); @EXPORT = qw ( get_error set_error TE_ERR_NONE TE_ERR_FATAL TE_ERR_CONNECT TE_ERR_LOGIN TE_ERR_PROMPT TE_ERR_PERL TE_ERR_TIMEOUT TE_ERR_BREAK TE_ERR_BAD_ARGUMENT TE_ERR_CUSTOM TE_ERR_UNKNOWN ); our $last_error = {code => 0, msg => ''}; our $alias = 'verifier_te'; use constant { TE_ERR_NONE => 0, TE_ERR_FATAL => 1, TE_ERR_CONNECT => 2, TE_ERR_LOGIN => 3, TE_ERR_PROMPT => 4, TE_ERR_PERL => 5, TE_ERR_TIMEOUT => 6, TE_ERR_BREAK => 7, TE_ERR_BAD_ARGUMENT => 8, TE_ERR_CUSTOM => 9, TE_ERR_UNKNOWN => 10, }; our $conf = { options => { 'tasks' => undef, 'username' => "root", 'password' => "password", 'targets' => undef, 'log' => undef, 'screen_log' => 1, 'format_log' => 0, 'silent' => 0, 'progress' => 1, 'out_level' => 2, 'log_level' => 3, 'email' => undef, }, common => { 'app' => 'vperf', 'app_path' => '', 'host' => 'localhost', 'host_ip' => undef, 'flog' => undef, 'fdump' => undef, }, current => { 'target' => 'localhost', }, }; sub get_error { return ( @_ ? $last_error->{msg} : $last_error->{code} ); } sub set_error { my ($code, $msg) = @_; if (!$msg) { $msg = '' if ($code == TE_ERR_NONE); $msg = 'fatal operation' if ($code == TE_ERR_FATAL); $msg = 'unknown remote host' if ($code == TE_ERR_CONNECT); $msg = 'login failed' if ($code == TE_ERR_LOGIN); $msg = 'timed-out waiting for command prompt' if ($code == TE_ERR_PROMPT); $msg = 'perl script error' if ($code == TE_ERR_PERL); $msg = 'pattern match timed-out' if ($code == TE_ERR_TIMEOUT); $msg = 'pattern match timed-out' if ($code == TE_ERR_BREAK); $msg = 'pattern match timed-out' if ($code == TE_ERR_BAD_ARGUMENT); $msg = 'custom error' if ($code == TE_ERR_CUSTOM); $msg = 'unknown error' if ($code >= TE_ERR_UNKNOWN); } $last_error->{code} = $code; $last_error->{msg} = $msg; } 1; sockperf-3.6/tests/verifier/lib/TE/Funclet.pm000066400000000000000000000235521336630672200212060ustar00rootroot00000000000000## # @file Funclet.pm # # @brief TE module to define funclets. # # ## @class # Container for funclets. package TE::Funclet; use strict; use warnings; # External modules #use Net::Telnet; use File::Basename; use Cwd 'abs_path'; # Own modules use TE::Common; use TE::Utility; use TE::Progress; # Define reference to the common global structure my $_options = $TE::Common::conf->{options}; my $_common = $TE::Common::conf->{common}; my $_current = $TE::Common::conf->{current}; # Set of predefined variables that are available inside user script our $HOST = \$_common->{host}; our $HOST_IP = \$_common->{host_ip}; our $TARGET = \$_current->{target}; my $cwd = Cwd::getcwd(); # Common variables and constants my $_timeout = 30; sub __error { my $status = TE_ERR_NONE; $_ = "@_"; $status = TE_ERR_CONNECT if (/^unknown remote host/i); $status = TE_ERR_LOGIN if (/^login failed/i); $status = TE_ERR_PROMPT if (/^timed-out waiting for command prompt/i); $status = TE_ERR_TIMEOUT if (/^pattern match timed-out/i); $status = TE_ERR_UNKNOWN if (!$status); # Set error code set_error($status, "Telnet: $_"); # Display message TE::Utility::error(); # Follow special error behaviour TE::Utility::force_error(); } sub __waitfor { my ($telnet, $node, $timeout, $prompt, $prompt_reg) = @_; my @outputs = (); my $timeout_counter = 0; while( !$telnet->eof() && !get_error()) { my ($prematch, $match) = $telnet->waitfor(Timeout => 1, Match => '/[\n\r]/', Match => $prompt_reg, Errmode => sub { return; }); # Refresh information in status line in case last output # contains printed symbols TE::Progress::update($node, $prematch); push @outputs, $prematch . "\n" if defined($prematch ); if (defined($match)) { $timeout_counter = 0; } else { $timeout_counter ++; } if( (defined($match) && ($match =~ m/$prompt/)) || (defined($timeout) && ($timeout_counter > $timeout))) { # Finish command processing last; } } return @outputs; } ############################################################################### # # Return last error code or error message. # Valid error numbers are all non-zero integer values. This function returns # error number if no arguments are passed and error message in case error code # is passed. # ############################################################################### sub errno { return get_error( @_ ); } ############################################################################### # # Execute Perl script on a host and return array or scalar # ############################################################################### sub perl { my $status = TE_ERR_NONE; my $result = undef; @_ = TE::Utility::clear_array(@_); TE::Utility::debug((caller(0))[3] . ":\n{\n" . join("\n", @_) . "\n}\n"); set_error(TE_ERR_NONE); TE::Progress::update($_common->{host}, 'Processing perl script ...'); my $cmd = join("\n", @_); # Execute script no strict; no warnings; my @outputs = eval($cmd) if (!get_error()); # Save evaluation error my $eval_err = $@; use strict; use warnings; if ( !get_error() && $eval_err ) { set_error(TE_ERR_PERL, "Perl syntax or runtime error: $eval_err"); TE::Utility::error(); TE::Utility::force_error(); } # Form result $result .= join("", @outputs); $status = get_error(); TE::Utility::debug((caller(0))[3] . ": return = $status\n"); return $result; } ############################################################################### # # Execute Shell script on host and return standard output # ############################################################################### sub shell { my $status = TE_ERR_NONE; my $result = ''; @_ = TE::Utility::clear_array(@_); TE::Utility::debug((caller(0))[3] . ":\n{\n" . join("\n", @_) . "\n}\n"); set_error(TE_ERR_NONE); TE::Progress::update($_common->{host}, 'Executing shell command ...'); my (@commands) = @_; foreach (@commands) { next if ($_ eq ''); last if (get_error()); my $cmd = $_; my @outputs = (); TE::Progress::update(undef, $cmd); # Execute script # which means $cmd will 'pipe' its output to SHELL. That means SHELL can be used # to read the output of the command (specifically the stuff the command sends to STDOUT). eval { open SHELL, "$cmd 2>&1 |" or die $! }; my $eval_err = $@; if ( !get_error() && $eval_err ) { set_error(TE_ERR_UNKNOWN, "Current command \'$cmd\': $eval_err"); TE::Utility::error(); TE::Utility::force_error(); } # Form result if (!get_error()) { while () { last if (get_error()); push @outputs, $_ if defined($_); TE::Progress::update(undef, $_); } } close SHELL; # Form result $result .= join("", @outputs); TE::Utility::dump("IN:\n$cmd\nOUT:\n@{[join(\"\", @outputs)]}\n"); } $status = get_error(); TE::Utility::debug((caller(0))[3] . ": return = $status\n"); return $result; } ############################################################################### # # Execute Command Shell procedure on a target and return standard output # ############################################################################### sub execute { my $status = TE_ERR_NONE; my $result = ''; @_ = TE::Utility::clear_array(@_); TE::Utility::debug((caller(0))[3] . ":\n{\n" . join("\n", @_) . "\n}\n"); set_error(TE_ERR_NONE); TE::Progress::update($_common->{host}, 'Executing shell command ...'); my (@commands) = @_; foreach (@commands) { next if ($_ eq ''); last if (get_error()); my $cmd = $_; my @outputs = (); TE::Progress::update(undef, $cmd); # Execute script # which means $cmd will 'pipe' its output to SHELL. That means SHELL can be used # to read the output of the command (specifically the stuff the command sends to STDOUT). $cmd = "ssh $$TARGET " . $cmd; eval { open SHELL, "$cmd 2>&1 |" or die $! }; my $eval_err = $@; if ( !get_error() && $eval_err ) { set_error(TE_ERR_UNKNOWN, "Current command \'$cmd\': $eval_err"); TE::Utility::error(); TE::Utility::force_error(); } # Form result if (!get_error()) { while () { last if (get_error()); push @outputs, $_ if defined($_); TE::Progress::update(undef, $_); } } close SHELL; # Form result $result .= join("", @outputs); TE::Utility::dump("IN:\n$cmd\nOUT:\n@{[join(\"\", @outputs)]}\n"); } $status = get_error(); TE::Utility::debug((caller(0))[3] . ": return = $status\n"); return $result; } ############################################################################### # # Send message to output # display string on the terminal and in log-file. There are several # supported special categories such as 'fatal', 'error', 'trace' and 'debug'. # Category 'fatal' supports setting customer error code. # ############################################################################### sub message { @_ = TE::Utility::clear_array(@_); if (@_ == 0) { # Do nothing return; } elsif (@_ == 1) { # Output message string as is TE::Utility::outlog( -terminal=>1, -file=>1, $_[0] ) if (defined($_[0])); } else { # Process by category if ( $_[0] =~ /^fatal/i ) { # Pass message and user defined return code if ( defined($_[2]) ) { TE::Utility::fatal( $_[1], $_[2] ); } else { TE::Utility::fatal( $_[1] ); } } elsif ( $_[0] =~ /^error/i ) { # Set error code set_error( TE_ERR_CUSTOM, $_[1] ); # Display message TE::Utility::error( $_[1] ); # Follow special error behaviour #TE::Utility::force_error(); } elsif ( $_[0] =~ /^trace/i ) { TE::Utility::trace( $_[1] ); } elsif ( $_[0] =~ /^debug/i ) { TE::Utility::debug( $_[1] ); } elsif ( $_[0] =~ /^dump/i ) { TE::Utility::dump( $_[1] ); } else { TE::Utility::outlog( -terminal=>1, -file=>1, @_ ); } } } ########################################################### # Services (following subroutine are based on primary funclets) ########################################################### sub progress { TE::Progress::update($_common->{host}, @_); sleep(1); } sub fail { message("fatal", @_); } sub error { message("error", @_); } sub die_error { message("error", @_); # Clean status line to prevent log corruption TE::Progress::clean(); # Do die to use capacity of eval operation and switch to process next target # pressure die message to display internal errors die "\n"; } sub execute_nowait { execute(-timeout => -1, @_); } 1; sockperf-3.6/tests/verifier/lib/TE/Progress.pm000066400000000000000000000053531336630672200214110ustar00rootroot00000000000000## # @file Progress.pm # # @brief TE module for Progress object. # # ## @class # Container for Progress object. package TE::Progress; use strict; use warnings; # External modules # Own modules our $object = undef; sub init { # Set default values $object->{_fh} = \*STDERR, $object->{_counter} = 0; $object->{_icons} = ['-', '\\', '|', '/']; $object->{_line} = undef; $object->{_fields} = (); $object->{_width} = 80; } sub update { # Check if it is initialized return if (not defined($object)); my $status_line = undef; my ($node_field, $status_field) = @_; my $icon_field = $object->{_icons}->[$object->{_counter} % scalar(@{$object->{_icons}})]; $status_field = (defined($object->{_fields}->[2]) ? $object->{_fields}->[2] : '') if (not defined($status_field)); $status_field = $1 if ($status_field =~ /([^\n\r]+)/); $status_field = (defined($object->{_fields}->[2]) ? $object->{_fields}->[2] : '') if ($status_field =~ /^([\n\r]+)/); $status_field = (defined($object->{_fields}->[2]) ? $object->{_fields}->[2] : '') if ($status_field eq ''); $node_field = (defined($object->{_fields}->[1]) ? $object->{_fields}->[1] : '') if (not defined($node_field)); $status_line = sprintf("%s(%-1.1s)%s %s[%-30.30s]%s %s%-40.40s%s\r", ($^O =~ /Win/ ? "" : "\e[33m"), $icon_field, ($^O =~ /Win/ ? "" : "\e[0m"), ($^O =~ /Win/ ? "" : "\e[32m"), $node_field, ($^O =~ /Win/ ? "" : "\e[0m"), ($^O =~ /Win/ ? "" : "\e[0m"), $status_field, ($^O =~ /Win/ ? "" : "\e[0m")); $object->{_counter} ++; $object->{_line} = $status_line; $object->{_fields}->[0] = $icon_field; $object->{_fields}->[1] = $node_field; $object->{_fields}->[2] = $status_field; printf ${$object->{_fh}} ("%s\r", $status_line) if defined($status_line); } sub clean { # Check if it is initialized return if (not defined($object)); # Clean status line my $status_line = (" " x $object->{_width}) . ("\b" x $object->{_width}) if defined($object->{_line}); $object->{_line} = $status_line; printf ${$object->{_fh}} ("%s\r", $status_line) if defined($status_line); } sub end { # Check if it is initialized return if (not defined($object)); # Clean status line my $status_line = (" " x $object->{_width}) . ("\b" x $object->{_width}) if defined($object->{_line}); printf ${$object->{_fh}} ("%s\r", $status_line) if defined($status_line); $object = (); $object = undef; } 1; sockperf-3.6/tests/verifier/lib/TE/Utility.pm000066400000000000000000000333501336630672200212460ustar00rootroot00000000000000## # @file Utility.pm # # @brief TE module for different auxiliary functions. # # ## @class # Container for auxiliary functions. package TE::Utility; use strict; use warnings; use vars qw(@EXPORT); use base qw(Exporter); @EXPORT = qw ( te_def_pre_proc te_def_server_proc te_def_client_proc te_def_result_proc te_def_post_proc te_create_feed_file ); # External modules use Sys::Hostname; # Own modules use TE::Common; use TE::Funclet; # Define reference to the common global structure my $_options = $TE::Common::conf->{options}; my $_common = $TE::Common::conf->{common}; my $_current = $TE::Common::conf->{current}; my @passwords; sub add_password { my ($pw) = @_; push @passwords, $pw; } sub get_ip { my $host = ( @_ > 0 ? "@_" : ''); my @raw_ip = gethostbyname($host); my @ip = unpack("C4", $raw_ip[4]); my $dotted_ip = join(".",@ip); return $dotted_ip; } sub clear_array { return grep(defined, @_); } sub force_error { my $code = get_error(); if ( $code != TE_ERR_NONE ) { # Clean status line to prevent log corruption TE::Progress::clean(); # Do die to use capacity of eval operation and switch to process next target # pressure die message to display internal errors die "\n"; } } sub outlog { my $str = ''; my $file_log = $_common->{flog}; my $file_scr = $_common->{fdump}; my @arg = (); my %args = (scalar(@_) % 2 ? (@_,undef) : @_) ; my $argv = join(' , ', @_); my $opt_prefix = ''; my $opt_terminal = 0; my $opt_file = 0; if (exists($args{'-prefix'})) { $opt_prefix = $args{'-prefix'}; $argv =~ s/\-prefix\s,\s$opt_prefix\s?\,?\s?//; } if (exists($args{'-terminal'})) { $opt_terminal = $args{'-terminal'}; $argv =~ s/\-terminal\s,\s$opt_terminal\s?\,?\s?//; } if (exists($args{'-file'})) { $opt_file = $args{'-file'}; $argv =~ s/\-file\s,\s$opt_file\s?\,?\s?//; } if (!scalar(@arg)) { @arg = split(' , ', $argv); } $str = "@arg"; if ($_options->{format_log}) { my $temp = ($_options->{format_log} == 1 ? $_current->{target} : $TE::Common::alias ); $str = "${temp}: ${opt_prefix}$str"; $str =~ s/[\n\r]$//; $str =~ s/[\n\r]/\n${temp}\: ${opt_prefix}/g; $str.="\n"; } # Clean status line to prevent log corruption TE::Progress::clean(); # Save message into log-file if (defined($file_log) && $opt_file) { my $line = $str; if (scalar(@passwords)) { foreach my $pw (@passwords) { $line =~ s/$pw/topsecret/g; } } print $file_log $line; } # Save message into dump-file if (defined($file_scr) && $opt_terminal) { my $line = $str; if (scalar(@passwords)) { foreach my $pw (@passwords) { $line =~ s/$pw/topsecret/g; } } print $file_scr $line; } # Display message on terminal print $str if (($_options->{silent} == 0) && $opt_terminal); # Restore status line TE::Progress::update(undef, "@arg"); } sub fatal { my $out_level = ($_options->{out_level} >= 0 ? 1 : 0); my $log_level = ($_options->{log_level} >= 0 ? 1 : 0); if ($out_level || $log_level) { my $str = "@_"; outlog(-prefix=>'fatal: ', -terminal=>$out_level, -file=>$log_level, $str); # Clean status line in case fatal error only TE::Progress::clean(); # default fatal code my $rc = TE_ERR_FATAL; # user defined code $rc = $_[1] if (defined($_[1])); # last error code $rc = get_error() if (get_error()); exit($rc); } } sub error { my $out_level = ($_options->{out_level} >= 1 ? 1 : 0); my $log_level = ($_options->{log_level} >= 1 ? 1 : 0); if ($out_level || $log_level) { my $code = get_error(); my $str = ( @_ == 0 ? get_error($code) : "@_" ); outlog(-prefix=>'error: ', -terminal=>$out_level, -file=>$log_level, $str); } } sub trace { my $out_level = ($_options->{out_level} >= 2 ? 1 : 0); my $log_level = ($_options->{log_level} >= 2 ? 1 : 0); if ($out_level || $log_level) { my $str = "@_"; outlog(-prefix=>'trace: ', -terminal=>$out_level, -file=>$log_level, $str); } } sub dump { my $out_level = ($_options->{out_level} >= 3 ? 1 : 0); my $log_level = ($_options->{log_level} >= 3 ? 1 : 0); if ($out_level || $log_level) { my $str = "@_"; outlog(-prefix=>'dump: ', -terminal=>$out_level, -file=>$log_level, $str); } } sub debug { my $out_level = ($_options->{out_level} >= 4 ? 1 : 0); my $log_level = ($_options->{log_level} >= 4 ? 1 : 0); if ($out_level || $log_level) { my $str = "@_"; outlog(-prefix=>'debug: ', -terminal=>$out_level, -file=>$log_level, $str); } } sub te_create_playback_file { my @arg = (); my %args = (scalar(@_) % 2 ? (@_,undef) : @_) ; my $argv = join(' , ', @_); my $opt_base = 1.000000; my $opt_size = 0; my $opt_step = 0.000005; my $opt_msg = 12; if (exists($args{'-base'})) { $opt_base = $args{'-base'}; $argv =~ s/\-base\s,\s$opt_base\s?\,?\s?//; } if (exists($args{'-size'})) { $opt_size = $args{'-size'}; $argv =~ s/\-size\s,\s$opt_size\s?\,?\s?//; } if (exists($args{'-step'})) { $opt_step = $args{'-step'}; $argv =~ s/\-step\s,\s$opt_step\s?\,?\s?//; } if (exists($args{'-msg'})) { $opt_msg = $args{'-msg'}; $argv =~ s/\-msg\s,\s$opt_msg\s?\,?\s?//; } if (!scalar(@arg)) { @arg = split(' , ', $argv); } TE::Utility::debug((caller(0))[3] . ":\n{\n" . join("\n", @_) . "\n}\n"); TE::Utility::debug((caller(0))[3] . ":\nBase: $opt_base Size: $opt_size Step: $opt_step Msg: $opt_msg\n"); my $line = ''; my $fpb = undef; my $pb_file = File::Spec->rel2abs('.'); $pb_file .= '/' . ${TE::Common::alias} . '_pb_file_' . $$; # Create feed file open($fpb, "> $pb_file") || TE::Utility::fatal("Can't open $pb_file: $!\n") if defined($pb_file); TE::Utility::dump("PLAYBACK FILE : $pb_file\n"); TE::Utility::dump("-" x 20 . "\n"); for (my $i = 0; $i < $opt_size; $i++) { $line = ""; $line .= sprintf("%0.9f, %d\n", $opt_base + $i * $opt_step, $opt_msg); print $fpb $line; TE::Utility::dump($line); } TE::Utility::dump("-" x 20 . "\n"); close($fpb); return $pb_file; } sub te_create_feed_file { my @arg = (); my %args = (scalar(@_) % 2 ? (@_,undef) : @_) ; my $argv = join(' , ', @_); my $opt_protocol = 'UDP'; my $opt_size = 0; my $opt_addr = get_ip($_current->{target}); my $opt_port = 7000; my $opt_step = 1; # step of port number if (exists($args{'-protocol'})) { $opt_protocol = $args{'-protocol'}; $argv =~ s/\-protocol\s,\s$opt_protocol\s?\,?\s?//; } if (exists($args{'-size'})) { $opt_size = $args{'-size'}; $argv =~ s/\-size\s,\s$opt_size\s?\,?\s?//; } if (exists($args{'-addr'})) { $opt_addr = get_ip($args{'-addr'}); $argv =~ s/\-addr\s,\s$opt_addr\s?\,?\s?//; } if (exists($args{'-port'})) { $opt_port = $args{'-port'}; $argv =~ s/\-port\s,\s$opt_port\s?\,?\s?//; } if (!scalar(@arg)) { @arg = split(' , ', $argv); } TE::Utility::debug((caller(0))[3] . ":\n{\n" . join("\n", @_) . "\n}\n"); TE::Utility::debug((caller(0))[3] . ":\nProtocol: $opt_protocol Addr: $opt_addr Port: $opt_port Size: $opt_size\n"); my $line = ''; my $ffeed = undef; my $feed_file = File::Spec->rel2abs('.'); $feed_file .= '/' . ${TE::Common::alias} . '_feed_file_' . $$; # Create feed file open($ffeed, "> $feed_file") || TE::Utility::fatal("Can't open $feed_file: $!\n") if defined($feed_file); my ($group1,$group2,$group3,$group4) = ( $opt_addr =~ /^(\d+).(\d+).(\d+).(\d+)$/i); $opt_step = 0 if (!$opt_port); $opt_port = 17000 if (!$opt_port); my $port = $opt_port; TE::Utility::dump("FEED FILE : $feed_file\n"); TE::Utility::dump("-" x 20 . "\n"); for (my $i = $opt_port; $i < ($opt_port + $opt_size); $i++) { $line = ""; $line .= 'T:' if ($opt_protocol eq 'TCP'); $line .= "$group1"; $line .= ".$group2"; if ($group1 == 224 && $group4 > 254) { $group3++; $group4 = 3; } $line .= ".$group3"; if ($group1 == 224) { $group4++; } $line .= ".$group4"; $line .= ":$port\n"; $port+=$opt_step; print $ffeed $line; TE::Utility::dump($line); } TE::Utility::dump("-" x 20 . "\n"); close($ffeed); return $feed_file; } sub te_def_server_proc { my $status = 0; my $result = undef; @_ = TE::Utility::clear_array(@_); if (@_ > 0) { my $cmd = ""; $cmd .= "env $_common->{app_env}" if exists($_common->{app_env}) && defined($_common->{app_env}); $cmd .= " $_common->{app_path}\/$_common->{app} "; $cmd .= join(' ', @_); $cmd .= " $_common->{app_arg} " if exists($_common->{app_arg}) && defined($_common->{app_arg}); $cmd =~ s/TARGET\(\)/$_current->{target}/; if ($cmd =~ /FEED\(.*\)/) { my ($group1,$group2,$group3,$group4) = ( $cmd =~ /FEED\((TCP|UDP):(.*):(\d+):(\d+)\)/); my $feed_file = te_create_feed_file(-protocol=>$group1, -addr=>$group2, -port=>$group3, -size=>$group4); $cmd =~ s/FEED\(.*\)/$feed_file/; } $result = TE::Funclet::execute($cmd); } return [$status, $result]; } sub te_def_client_proc { my $status = 0; my $result = undef; @_ = TE::Utility::clear_array(@_); if (@_ > 0) { my $cmd = ""; $cmd .= "env $_common->{app_env}" if exists($_common->{app_env}) && defined($_common->{app_env}); $cmd .= " $_common->{app_path}\/$_common->{app} "; $cmd .= join(' ', @_); $cmd .= " $_common->{app_arg} " if exists($_common->{app_arg}) && defined($_common->{app_arg}); $cmd =~ s/TARGET\(\)/$_current->{target}/; if ($cmd =~ /FEED\(.*\)/) { my ($group1,$group2,$group3,$group4) = ( $cmd =~ /FEED\((TCP|UDP):(.*):(\d+):(\d+)\)/); my $feed_file = te_create_feed_file(-protocol=>$group1, -addr=>$group2, -port=>$group3, -size=>$group4); $cmd =~ s/FEED\(.*\)/$feed_file/; } if ($cmd =~ /PLAYBACK\(.*\)/) { my ($group1,$group2,$group3,$group4) = ( $cmd =~ /PLAYBACK\(([\d\.]+):([\d\.]+):(\d+):(\d+)\)/); my $pb_file = te_create_playback_file(-base=>$group1, -step=>$group2, -msg=>$group3, -size=>$group4); $cmd =~ s/PLAYBACK\(.*\)/$pb_file/; } $result = TE::Funclet::shell($cmd); } return ($status, $result); } sub te_def_result_proc { my $status = 0; @_ = TE::Utility::clear_array(@_); if (@_ == 0) { $status = 1; } elsif (@_ > 0) { my ($arg) = @_; return ($status) if (!defined($arg)); my $server_output = (exists($arg->{server}->{output}) && defined($arg->{server}->{output}) ? $arg->{server}->{output} : ''); my $client_output = (exists($arg->{client}->{output}) && defined($arg->{client}->{output}) ? $arg->{client}->{output} : ''); if ( $status == 0 && $server_output ne '' && (exists($arg->{server}->{success}) && defined($arg->{server}->{success})) ) { my @match_list = @{$arg->{server}->{success}}; foreach my $match (@match_list) { if ( $server_output !~ /$match/) { $status = 1; last; } } } if ( $status == 0 && $server_output ne '' && (exists($arg->{server}->{failure}) && defined($arg->{server}->{failure})) ) { my @match_list = @{$arg->{server}->{failure}}; foreach my $match (@match_list) { if ( $server_output =~ /$match/) { $status = 1; last; } } } if ( $status == 0 && $client_output ne '' && (exists($arg->{client}->{success}) && defined($arg->{client}->{success})) ) { my @match_list = @{$arg->{client}->{success}}; foreach my $match (@match_list) { if ( $client_output !~ /$match/) { $status = 1; last; } } } if ( $status == 0 && $client_output ne '' && (exists($arg->{client}->{failure}) && defined($arg->{client}->{failure})) ) { my @match_list = @{$arg->{client}->{failure}}; foreach my $match (@match_list) { if ( $client_output =~ /$match/) { $status = 1; last; } } } } return ($status); } sub te_def_pre_proc { TE::Funclet::shell("killall $_common->{app}"); TE::Funclet::execute("killall $_common->{app}"); } sub te_def_post_proc { TE::Funclet::shell("pkill -SIGINT $_common->{app}"); TE::Funclet::execute("pkill -SIGINT $_common->{app}"); } 1; sockperf-3.6/tests/verifier/lib/TE/VERSION.pm000066400000000000000000000000301336630672200207150ustar00rootroot00000000000000our ($VERSION) = "0.1.";sockperf-3.6/tests/verifier/lib/TPB.pm000066400000000000000000000023161336630672200177160ustar00rootroot00000000000000## # @file TPB.pm # # @brief Test Suite TCP playback. # # ## @class # Container for common data. package TPB; use strict; use warnings; # Own modules use TE::Common; use TE::Funclet; use TE::Utility; our $test_suite_tcp_pb = [ { name => 'tc1', note => '#1 - playback w/o arguments', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'pb -i TARGET() --tcp --data-file=PLAYBACK(1.000000:0.000005:12:1000)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'Total 1000 messages received'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'SentMessages=1000'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] }, }, post_proc => \&te_def_post_proc, }, ]; 1; sockperf-3.6/tests/verifier/lib/TPP.pm000066400000000000000000001235531336630672200177430ustar00rootroot00000000000000## # @file TPP.pm # # @brief Test Suite TCP ping-pong. # # ## @class # Container for common data. package TPP; use strict; use warnings; # Own modules use TE::Common; use TE::Funclet; use TE::Utility; our $test_suite_tcp_pp = [ { name => 'tc1', note => '#1 - ping-pong w/o arguments', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'pp -i TARGET() --tcp', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'Warmup stage \(sending a few dummy messages\)...'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] }, }, post_proc => \&te_def_post_proc, }, { name => 'tc2', note => '#2 - ping-pong option --dontwarmup', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'pp -i TARGET() --tcp --dontwarmup', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down', 'Warmup stage \(sending a few dummy messages\)...'], } }, post_proc => \&te_def_post_proc, }, { name => 'tc3', note => '#3 - ping-pong option -b10', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'pp -i TARGET() --tcp -b10', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency of burst of 10 messages'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc4', note => '#4 - ping-pong option -b100', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'pp -i TARGET() --tcp -b100', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency of burst of 100 messages'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc5', note => '#5 - ping-pong option -b1000', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'pp -i TARGET() --tcp -b1000', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency of burst of 1000 messages'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc6', note => '#6 - ping-pong option -t10', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'pp -i TARGET() --tcp -t10', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'RunTime=10'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc7', note => '#7 - ping-pong option -t30', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'pp -i TARGET() --tcp -t30', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'RunTime=30'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc8', note => '#8 - ping-pong option -m32', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'pp -i TARGET() --tcp -m32', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc9', note => '#9 - ping-pong option -m4096', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'pp -i TARGET() --tcp -m4096', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc10', note => '#10 - ping-pong option -m65500', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'pp -i TARGET() --tcp -m65500', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc11', note => '#11 - ping-pong option -r10', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'pp -i TARGET() --tcp -r10', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc12', note => '#12 - ping-pong option -r100', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'pp -i TARGET() --tcp -r100', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc13', note => '#13 - ping-pong option -r1024', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'pp -i TARGET() --tcp -r1024', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc14', note => '#14 - ping-pong option -f (10 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:10)', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(TCP:TARGET():17000:10)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc15', note => '#15 - ping-pong option -f -Fs (10 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:10) -F s', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(TCP:TARGET():17000:10) -F s', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using select()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc16', note => '#16 - ping-pong option -f -Fp (10 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:10) -F p', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(TCP:TARGET():17000:10) -F p', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using poll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc17', note => '#17 - ping-pong option -f -Fe (10 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:10) -F e', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(TCP:TARGET():17000:10) -F e', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc18', note => '#18 - ping-pong option -f -Fs (300 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:300) -F s', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(TCP:TARGET():17000:300) -F s', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using select()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc19', note => '#19 - ping-pong option -f -Fp (300 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:300) -F p', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(TCP:TARGET():17000:300) -F p', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using poll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc20', note => '#20 - ping-pong option -f -Fe (300 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:300) -F e', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(TCP:TARGET():17000:300) -F e', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc21', note => '#21 - ping-pong option -f -Fs --timeout 0', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:3) -F s --timeout 0', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(TCP:TARGET():17000:3) -F s --timeout 0', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using select()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc22', note => '#22 - ping-pong option -f -Fp --timeout 0', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:3) -F p --timeout 0', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(TCP:TARGET():17000:3) -F p --timeout 0', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using poll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc23', note => '#23 - ping-pong option -f -Fe --timeout 0', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:3) -F e --timeout 0', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(TCP:TARGET():17000:3) -F e --timeout 0', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc24', note => '#24 - ping-pong option -f -Fs --timeout=-1', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:3) -F s --timeout=-1', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(TCP:TARGET():17000:3) -F s --timeout=-1', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using select()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc25', note => '#25 - ping-pong option -f -Fp --timeout=-1', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:3) -F p --timeout=-1', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(TCP:TARGET():17000:3) -F p --timeout=-1', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using poll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc26', note => '#26 - ping-pong option -f -Fe --timeout=-1', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:3) -F e --timeout=-1', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(TCP:TARGET():17000:3) -F e --timeout=-1', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc27', note => '#27 - ping-pong option -f -Fs --threads-num=2 (one socket per thread)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:2) -F s --threads-num=2', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(TCP:TARGET():17000:2)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc28', note => '#28 - ping-pong option -f -Fp --threads-num=2 (one socket per thread)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:2) -F p --threads-num=2', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(TCP:TARGET():17000:2)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc29', note => '#29 - ping-pong option -f -Fe --threads-num=2 (one socket per thread)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:2) -F e --threads-num=2', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(TCP:TARGET():17000:2)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc30', note => '#30 - ping-pong option -f -Fs --threads-num=10 (two socket per thread)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:20) -F s --threads-num=10', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(TCP:TARGET():17000:20)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc31', note => '#31 - ping-pong option -f -Fp --threads-num=10 (two socket per thread)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:20) -F p --threads-num=10', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(TCP:TARGET():17000:20)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc32', note => '#32 - ping-pong option -f -Fe --threads-num=10 (two socket per thread)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:20) -F e --threads-num=10', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(TCP:TARGET():17000:20)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc33', note => '#33 - ping-pong option -f -Fs --threads-num=100 (on 400 sockets)', pre_proc => \&te_def_pre_proc, server_wakeup => '20', server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:400) -F s --threads-num=100', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(TCP:TARGET():17000:400)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc34', note => '#34 - ping-pong option -f -Fp --threads-num=100 (on 400 sockets)', pre_proc => \&te_def_pre_proc, server_wakeup => '20', server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:400) -F p --threads-num=100', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(TCP:TARGET():17000:400)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc35', note => '#35 - ping-pong option -f -Fe --threads-num=100 (on 400 sockets)', pre_proc => \&te_def_pre_proc, server_wakeup => '20', server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:400) -F e --threads-num=100', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(TCP:TARGET():17000:400)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc36', note => '#36 - ping-pong -f -Fs (10 records the same addr:port)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():0:10) -F s', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(TCP:TARGET():0:10) -F s', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using select()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc37', note => '#37 - ping-pong -f -Fp (10 records the same addr:port)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():0:10) -F p', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(TCP:TARGET():0:10) -F p', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using poll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc38', note => '#38 - ping-pong -f -Fe (10 records the same addr:port)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():0:10) -F e', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(TCP:TARGET():0:10) -F e', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc39', note => '#39 - ping-pong -f -Fs (300 records the same addr:port)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():0:300) -F s', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(TCP:TARGET():0:300) -F s', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using select()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc40', note => '#40 - ping-pong -f -Fp (300 records the same addr:port)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():0:300) -F p', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(TCP:TARGET():0:300) -F p', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using poll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc41', note => '#41 - ping-pong -f -Fe (300 records the same addr:port)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():0:300) -F e', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(TCP:TARGET():0:300) -F e', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc42', note => '#42 - ping-pong option --pps=10', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'pp -i TARGET() --tcp --pps=10', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc43', note => '#43 - ping-pong option --pps=1000', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'pp -i TARGET() --tcp --pps=1000', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc44', note => '#44 - ping-pong option --pps=100000', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'pp -i TARGET() --tcp --pps=100000', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc45', note => '#45 - ping-pong unicast option -f -Fs -t20 -m50000 -r512 --threads-num=100 --data-integrity', pre_proc => \&te_def_pre_proc, server_wakeup => '20', server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:500) -F s --threads-num=100', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(TCP:TARGET():17000:500) -F s -t20 -m50000 -r512 --data-integrity', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using select()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, ]; 1; sockperf-3.6/tests/verifier/lib/TTP.pm000066400000000000000000001051361336630672200177440ustar00rootroot00000000000000## # @file TTP.pm # # @brief Test Suite TCP throughput. # # ## @class # Container for common data. package TTP; use strict; use warnings; # Own modules use TE::Common; use TE::Funclet; use TE::Utility; our $test_suite_tcp_tp = [ { name => 'tc1', note => '#1 - throughput w/o arguments', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'tp -i TARGET() --tcp', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate', 'Warmup stage \(sending a few dummy messages\)...'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] }, }, post_proc => \&te_def_post_proc, }, { name => 'tc2', note => '#2 - throughput option --dontwarmup', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'tp -i TARGET() --tcp --dontwarmup', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down', 'Warmup stage \(sending a few dummy messages\)...'], } }, post_proc => \&te_def_post_proc, }, { name => 'tc3', note => '#3 - throughput option -b10', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'tp -i TARGET() --tcp -b10', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc4', note => '#4 - throughput option -b100', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'tp -i TARGET() --tcp -b100', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc5', note => '#5 - throughput option -b1000', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'tp -i TARGET() --tcp -b1000', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc6', note => '#6 - throughput option -t10', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'tp -i TARGET() --tcp -t10', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc7', note => '#7 - throughput option -t30', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'tp -i TARGET() --tcp -t30', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc8', note => '#8 - throughput option -m32', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'tp -i TARGET() --tcp -m32', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc9', note => '#9 - throughput option -m4096', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'tp -i TARGET() --tcp -m4096', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc10', note => '#10 - throughput option -m65500', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'tp -i TARGET() --tcp -m65500', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc11', note => '#11 - throughput option -r10', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'tp -i TARGET() --tcp -r10', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc12', note => '#12 - throughput option -r100', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'tp -i TARGET() --tcp -r100', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc13', note => '#13 - throughput option -r1024', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'tp -i TARGET() --tcp -r1024', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc14', note => '#14 - throughput option -f (10 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:10)', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(TCP:TARGET():17000:10)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc15', note => '#15 - throughput option -f -Fs (10 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:10) -F s', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(TCP:TARGET():17000:10) -F s', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using select()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc16', note => '#16 - throughput option -f -Fp (10 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:10) -F p', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(TCP:TARGET():17000:10) -F p', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using poll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc17', note => '#17 - throughput option -f -Fe (10 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:10) -F e', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(TCP:TARGET():17000:10) -F e', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc18', note => '#18 - throughput option -f -Fs (300 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:300) -F s', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(TCP:TARGET():17000:300) -F s', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using select()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc19', note => '#19 - throughput option -f -Fp (300 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:300) -F p', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(TCP:TARGET():17000:300) -F p', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using poll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc20', note => '#20 - throughput option -f -Fe (300 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:300) -F e', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(TCP:TARGET():17000:300) -F e', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc21', note => '#21 - throughput option -f -Fs --timeout 0', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:3) -F s --timeout 0', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(TCP:TARGET():17000:3) -F s --timeout 0', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using select()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc22', note => '#22 - throughput option -f -Fp --timeout 0', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:3) -F p --timeout 0', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(TCP:TARGET():17000:3) -F p --timeout 0', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using poll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc23', note => '#23 - throughput option -f -Fe --timeout 0', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:3) -F e --timeout 0', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(TCP:TARGET():17000:3) -F e --timeout 0', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc24', note => '#24 - throughput option -f -Fs --timeout=-1', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:3) -F s --timeout=-1', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(TCP:TARGET():17000:3) -F s --timeout=-1', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using select()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc25', note => '#25 - throughput option -f -Fp --timeout=-1', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:3) -F p --timeout=-1', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(TCP:TARGET():17000:3) -F p --timeout=-1', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using poll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc26', note => '#26 - throughput option -f -Fe --timeout=-1', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:3) -F e --timeout=-1', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(TCP:TARGET():17000:3) -F e --timeout=-1', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc27', note => '#27 - throughput option -f -Fs --threads-num=2 (one socket per thread)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:2) -F s --threads-num=2', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(TCP:TARGET():17000:2)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using select()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc28', note => '#28 - throughput option -f -Fp --threads-num=2 (one socket per thread)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:2) -F p --threads-num=2', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(TCP:TARGET():17000:2)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using poll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc29', note => '#29 - throughput option -f -Fe --threads-num=2 (one socket per thread)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:2) -F e --threads-num=2', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(TCP:TARGET():17000:2)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc30', note => '#30 - throughput option -f -Fs --threads-num=10 (two socket per thread)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:20) -F s --threads-num=10', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(TCP:TARGET():17000:20)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using select()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc31', note => '#31 - throughput option -f -Fp --threads-num=10 (two socket per thread)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:20) -F p --threads-num=10', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(TCP:TARGET():17000:20)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using poll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc32', note => '#32 - throughput option -f -Fe --threads-num=10 (two socket per thread)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:20) -F e --threads-num=10', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(TCP:TARGET():17000:20)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc33', note => '#33 - throughput option -f -Fs --threads-num=100 (on 400 sockets)', pre_proc => \&te_def_pre_proc, server_wakeup => '20', server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:400) -F s --threads-num=100', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(TCP:TARGET():17000:400)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using select()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc34', note => '#34 - throughput option -f -Fp --threads-num=100 (on 400 sockets)', pre_proc => \&te_def_pre_proc, server_wakeup => '20', server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:400) -F p --threads-num=100', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(TCP:TARGET():17000:400)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using poll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc35', note => '#35 - throughput option -f -Fe --threads-num=100 (on 400 sockets)', pre_proc => \&te_def_pre_proc, server_wakeup => '20', server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:400) -F e --threads-num=100', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(TCP:TARGET():17000:400)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc36', note => '#36 - throughput option --tcp --pps=1000', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'tp -i TARGET() --tcp --pps=1000', result_proc => \&te_ttp_result_proc1, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, ]; sub te_ttp_result_proc1 { my $status = 0; @_ = TE::Utility::clear_array(@_); if (@_ == 0) { $status = 1; } elsif (@_ > 0) { my ($arg) = @_; return ($status) if (!defined($arg)); $status = te_def_result_proc(@_); if ($status == 0) { my $server_output = (exists($arg->{server}->{output}) && defined($arg->{server}->{output}) ? $arg->{server}->{output} : ''); my $client_output = (exists($arg->{client}->{output}) && defined($arg->{client}->{output}) ? $arg->{client}->{output} : ''); if ( $status == 0 && $client_output ne '' ) { my $sent_msg = 0; if ($client_output =~ m/Message Rate is (\d+) \[msg\/sec\]/) { $sent_msg = $1; if ( not (grep($_ == $sent_msg, (1000..1002))) ) { $status = 1; } } else { $status = 1; } } } } return ($status); } 1; sockperf-3.6/tests/verifier/lib/TUL.pm000066400000000000000000001327031336630672200177410ustar00rootroot00000000000000## # @file TUL.pm # # @brief Test Suite TCP under-load. # # ## @class # Container for common data. package TUL; use strict; use warnings; # Own modules use TE::Common; use TE::Funclet; use TE::Utility; our $test_suite_tcp_ul = [ { name => 'tc1', note => '#1 - under-load w/o arguments', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'ul -i TARGET() --tcp', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'Warmup stage \(sending a few dummy messages\)...'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] }, }, post_proc => \&te_def_post_proc, }, { name => 'tc2', note => '#2 - under-load option --dontwarmup', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'ul -i TARGET() --tcp --dontwarmup', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down', 'Warmup stage \(sending a few dummy messages\)...'], } }, post_proc => \&te_def_post_proc, }, { name => 'tc3', note => '#3 - under-load option -b10', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'ul -i TARGET() --tcp -b10', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency of burst of 10 messages'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc4', note => '#4 - under-load option -b100', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'ul -i TARGET() --tcp -b100', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency of burst of 100 messages'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc5', note => '#5 - under-load option -b1000', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'ul -i TARGET() --tcp -b1000', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency of burst of 1000 messages'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc6', note => '#6 - under-load option -t10', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'ul -i TARGET() --tcp -t10', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'RunTime=10'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc7', note => '#7 - under-load option -t30', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'ul -i TARGET() --tcp -t30', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'RunTime=30'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc8', note => '#8 - under-load option -m32', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'ul -i TARGET() --tcp -m32', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc9', note => '#9 - under-load option -m4096', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'ul -i TARGET() --tcp -m4096', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc10', note => '#10 - under-load option -m65500', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'ul -i TARGET() --tcp -m65500', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc11', note => '#11 - under-load option -r10', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'ul -i TARGET() --tcp -r10', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc12', note => '#12 - under-load option -r100', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'ul -i TARGET() --tcp -r100', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc13', note => '#13 - under-load option -r1024', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'ul -i TARGET() --tcp -r1024', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc14', note => '#14 - under-load option -f (10 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:10)', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(TCP:TARGET():17000:10)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc15', note => '#15 - under-load option -f -Fs (10 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:10) -F s', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(TCP:TARGET():17000:10) -F s', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using select()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc16', note => '#16 - under-load option -f -Fp (10 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:10) -F p', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(TCP:TARGET():17000:10) -F p', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using poll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc17', note => '#17 - under-load option -f -Fe (10 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:10) -F e', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(TCP:TARGET():17000:10) -F e', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc18', note => '#18 - under-load option -f -Fs (300 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:300) -F s', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(TCP:TARGET():17000:300) -F s', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using select()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc19', note => '#19 - under-load option -f -Fp (300 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:300) -F p', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(TCP:TARGET():17000:300) -F p', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using poll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc20', note => '#20 - under-load option -f -Fe (300 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:300) -F e', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(TCP:TARGET():17000:300) -F e', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc21', note => '#21 - under-load option -f -Fs --timeout 0', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:3) -F s --timeout 0', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(TCP:TARGET():17000:3) -F s --timeout 0', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using select()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc22', note => '#22 - under-load option -f -Fp --timeout 0', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:3) -F p --timeout 0', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(TCP:TARGET():17000:3) -F p --timeout 0', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using poll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc23', note => '#23 - under-load option -f -Fe --timeout 0', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:3) -F e --timeout 0', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(TCP:TARGET():17000:3) -F e --timeout 0', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc24', note => '#24 - under-load option -f -Fs --timeout=-1', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:3) -F s --timeout=-1', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(TCP:TARGET():17000:3) -F s --timeout=-1', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using select()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc25', note => '#25 - under-load option -f -Fp --timeout=-1', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:3) -F p --timeout=-1', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(TCP:TARGET():17000:3) -F p --timeout=-1', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using poll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc26', note => '#26 - under-load option -f -Fe --timeout=-1', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:3) -F e --timeout=-1', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(TCP:TARGET():17000:3) -F e --timeout=-1', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc27', note => '#27 - under-load option -f -Fs --threads-num=2 (one socket per thread)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:2) -F s --threads-num=2', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(TCP:TARGET():17000:2)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc28', note => '#28 - under-load option -f -Fp --threads-num=2 (one socket per thread)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:2) -F p --threads-num=2', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(TCP:TARGET():17000:2)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc29', note => '#29 - under-load option -f -Fe --threads-num=2 (one socket per thread)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:2) -F e --threads-num=2', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(TCP:TARGET():17000:2)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc30', note => '#30 - under-load option -f -Fs --threads-num=10 (two socket per thread)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:20) -F s --threads-num=10', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(TCP:TARGET():17000:20)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc31', note => '#31 - under-load option -f -Fp --threads-num=10 (two socket per thread)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:20) -F p --threads-num=10', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(TCP:TARGET():17000:20)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc32', note => '#32 - under-load option -f -Fe --threads-num=10 (two socket per thread)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:20) -F e --threads-num=10', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(TCP:TARGET():17000:20)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc33', note => '#33 - under-load option -f -Fs --threads-num=100 (on 400 sockets)', pre_proc => \&te_def_pre_proc, server_wakeup => '20', server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:400) -F s --threads-num=100', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(TCP:TARGET():17000:400)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc34', note => '#34 - under-load option -f -Fp --threads-num=100 (on 400 sockets)', pre_proc => \&te_def_pre_proc, server_wakeup => '20', server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:400) -F p --threads-num=100', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(TCP:TARGET():17000:400)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc35', note => '#35 - under-load option -f -Fe --threads-num=100 (on 400 sockets)', pre_proc => \&te_def_pre_proc, server_wakeup => '20', server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():17000:400) -F e --threads-num=100', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(TCP:TARGET():17000:400)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc36', note => '#36 - under-load -f -Fs (10 records the same addr:port)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():0:10) -F s', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(TCP:TARGET():0:10) -F s', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using select()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc37', note => '#37 - under-load -f -Fp (10 records the same addr:port)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():0:10) -F p', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(TCP:TARGET():0:10) -F p', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using poll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc38', note => '#38 - under-load -f -Fe (10 records the same addr:port)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():0:10) -F e', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(TCP:TARGET():0:10) -F e', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc39', note => '#39 - under-load -f -Fs (300 records the same addr:port)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():0:300) -F s', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(TCP:TARGET():0:300) -F s', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using select()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc40', note => '#40 - under-load -f -Fp (300 records the same addr:port)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():0:300) -F p', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(TCP:TARGET():0:300) -F p', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using poll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc41', note => '#41 - under-load -f -Fe (300 records the same addr:port)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(TCP:TARGET():0:300) -F e', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(TCP:TARGET():0:300) -F e', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc42', note => '#42 - under-load option --pps=10', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'ul -i TARGET() --tcp --pps=10', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'No messages were received from the server'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc43', note => '#43 - under-load option --pps=1000', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'ul -i TARGET() --tcp --pps=1000', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc44', note => '#44 - under-load option --pps=100000', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'ul -i TARGET() --tcp --pps=100000', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc45', note => '#45 - under-load option --pps=100 --reply-every=100', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'ul -i TARGET() --tcp --pps=100 --reply-every=100', result_proc => \&te_tul_result_proc1, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'No valid observations found'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc46', note => '#46 - under-load option --pps=1000 --reply-every=10', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET() --tcp', client_proc => \&te_def_client_proc, client_arg => 'ul -i TARGET() --tcp --pps=1000 --reply-every=10', result_proc => \&te_tul_result_proc2, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, ]; sub te_tul_result_proc1 { my $status = 0; @_ = TE::Utility::clear_array(@_); if (@_ == 0) { $status = 1; } elsif (@_ > 0) { my ($arg) = @_; return ($status) if (!defined($arg)); $status = te_def_result_proc(@_); if ($status == 0) { my $server_output = (exists($arg->{server}->{output}) && defined($arg->{server}->{output}) ? $arg->{server}->{output} : ''); my $client_output = (exists($arg->{client}->{output}) && defined($arg->{client}->{output}) ? $arg->{client}->{output} : ''); if ( $status == 0 && $client_output ne '' ) { my $sent_msg = 0; my $recv_msg = 0; if ($client_output =~ m/SentMessages=(\d+)/) { $sent_msg = $1; if ($client_output =~ m/ReceivedMessages=(\d+)/) { $recv_msg = $1; if ( not (grep($_ == $sent_msg, (90..120)) && grep($_ == $recv_msg, (1..2))) ) { $status = 1; } } else { $status = 1; } } else { $status = 1; } } } } return ($status); } sub te_tul_result_proc2 { my $status = 0; @_ = TE::Utility::clear_array(@_); if (@_ == 0) { $status = 1; } elsif (@_ > 0) { my ($arg) = @_; return ($status) if (!defined($arg)); $status = te_def_result_proc(@_); if ($status == 0) { my $server_output = (exists($arg->{server}->{output}) && defined($arg->{server}->{output}) ? $arg->{server}->{output} : ''); my $client_output = (exists($arg->{client}->{output}) && defined($arg->{client}->{output}) ? $arg->{client}->{output} : ''); if ( $status == 0 && $client_output ne '' ) { my $sent_msg = 0; my $recv_msg = 0; if ($client_output =~ m/SentMessages=(\d+)/) { $sent_msg = $1; if ($client_output =~ m/ReceivedMessages=(\d+)/) { $recv_msg = $1; if ( not (grep($_ == $sent_msg, (990..1200)) && grep($_ == $recv_msg, (98..120))) ) { $status = 1; } } else { $status = 1; } } else { $status = 1; } } } } return ($status); } 1; sockperf-3.6/tests/verifier/lib/UPB.pm000066400000000000000000000022661336630672200177230ustar00rootroot00000000000000## # @file UPB.pm # # @brief Test Suite UDP playback. # # ## @class # Container for common data. package UPB; use strict; use warnings; # Own modules use TE::Common; use TE::Funclet; use TE::Utility; our $test_suite_udp_pb = [ { name => 'tc1', note => '#1 - playback w/o arguments', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'pb -i TARGET() --data-file=PLAYBACK(1.000000:0.000005:12:1000)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'Total 1000 messages received'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'SentMessages=1000'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] }, }, post_proc => \&te_def_post_proc, }, ]; 1; sockperf-3.6/tests/verifier/lib/UPP.pm000066400000000000000000001272641336630672200177470ustar00rootroot00000000000000## # @file UPP.pm # # @brief Test Suite UDP ping-pong. # # ## @class # Container for common data. package UPP; use strict; use warnings; # Own modules use TE::Common; use TE::Funclet; use TE::Utility; our $test_suite_udp_pp = [ { name => 'tc1', note => '#1 - ping-pong w/o arguments', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'pp -i TARGET()', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'Warmup stage \(sending a few dummy messages\)...'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] }, }, post_proc => \&te_def_post_proc, }, { name => 'tc2', note => '#2 - ping-pong option --dontwarmup', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'pp -i TARGET() --dontwarmup', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down', 'Warmup stage \(sending a few dummy messages\)...'], } }, post_proc => \&te_def_post_proc, }, { name => 'tc3', note => '#3 - ping-pong option -b10', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'pp -i TARGET() -b10', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency of burst of 10 messages'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc4', note => '#4 - ping-pong option -b100', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'pp -i TARGET() -b100', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency of burst of 100 messages'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc5', note => '#5 - ping-pong option -b200', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'pp -i TARGET() -b200', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency of burst of 200 messages'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc6', note => '#6 - ping-pong option -t10', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'pp -i TARGET() -t10', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'RunTime=10'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc7', note => '#7 - ping-pong option -t30', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'pp -i TARGET() -t30', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'RunTime=30'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc8', note => '#8 - ping-pong option -m32', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'pp -i TARGET() -m32', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc9', note => '#9 - ping-pong option -m4096', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'pp -i TARGET() -m4096', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc10', note => '#10 - ping-pong option -m65500', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'pp -i TARGET() -m65500', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc11', note => '#11 - ping-pong option -r10', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'pp -i TARGET() -r10', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc12', note => '#12 - ping-pong option -r100', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'pp -i TARGET() -r100', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc13', note => '#13 - ping-pong option -r1024', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'pp -i TARGET() -r1024', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc14', note => '#14 - ping-pong option -f (10 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:10)', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(UDP:TARGET():17000:10)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc15', note => '#15 - ping-pong option -f -Fs (10 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:10) -F s', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(UDP:TARGET():17000:10) -F s', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using select()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc16', note => '#16 - ping-pong option -f -Fp (10 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:10) -F p', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(UDP:TARGET():17000:10) -F p', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using poll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc17', note => '#17 - ping-pong option -f -Fe (10 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:10) -F e', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(UDP:TARGET():17000:10) -F e', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc18', note => '#18 - ping-pong option -f -Fs (300 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:300) -F s', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(UDP:TARGET():17000:300) -F s', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using select()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc19', note => '#19 - ping-pong option -f -Fp (300 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:300) -F p', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(UDP:TARGET():17000:300) -F p', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using poll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc20', note => '#20 - ping-pong option -f -Fe (300 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:300) -F e', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(UDP:TARGET():17000:300) -F e', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc21', note => '#21 - ping-pong option -f -Fs --timeout 0', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:3) -F s --timeout 0', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(UDP:TARGET():17000:3) -F s --timeout 0', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using select()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc22', note => '#22 - ping-pong option -f -Fp --timeout 0', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:3) -F p --timeout 0', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(UDP:TARGET():17000:3) -F p --timeout 0', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using poll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc23', note => '#23 - ping-pong option -f -Fe --timeout 0', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:3) -F e --timeout 0', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(UDP:TARGET():17000:3) -F e --timeout 0', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc24', note => '#24 - ping-pong option -f -Fs --timeout=-1', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:3) -F s --timeout=-1', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(UDP:TARGET():17000:3) -F s --timeout=-1', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using select()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc25', note => '#25 - ping-pong option -f -Fp --timeout=-1', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:3) -F p --timeout=-1', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(UDP:TARGET():17000:3) -F p --timeout=-1', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using poll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc26', note => '#26 - ping-pong option -f -Fe --timeout=-1', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:3) -F e --timeout=-1', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(UDP:TARGET():17000:3) -F e --timeout=-1', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc27', note => '#27 - ping-pong option -f -Fs --threads-num=2 (one socket per thread)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:2) -F s --threads-num=2', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(UDP:TARGET():17000:2)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc28', note => '#28 - ping-pong option -f -Fp --threads-num=2 (one socket per thread)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:2) -F p --threads-num=2', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(UDP:TARGET():17000:2)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc29', note => '#29 - ping-pong option -f -Fe --threads-num=2 (one socket per thread)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:2) -F e --threads-num=2', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(UDP:TARGET():17000:2)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc30', note => '#30 - ping-pong option -f -Fs --threads-num=10 (two socket per thread)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:20) -F s --threads-num=10', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(UDP:TARGET():17000:20)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc31', note => '#31 - ping-pong option -f -Fp --threads-num=10 (two socket per thread)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:20) -F p --threads-num=10', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(UDP:TARGET():17000:20)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc32', note => '#32 - ping-pong option -f -Fe --threads-num=10 (two socket per thread)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:20) -F e --threads-num=10', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(UDP:TARGET():17000:20)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc33', note => '#33 - ping-pong option -f -Fs --threads-num=100 (on 400 sockets)', pre_proc => \&te_def_pre_proc, server_wakeup => '20', server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:400) -F s --threads-num=100', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(UDP:TARGET():17000:400)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc34', note => '#34 - ping-pong option -f -Fp --threads-num=100 (on 400 sockets)', pre_proc => \&te_def_pre_proc, server_wakeup => '20', server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:400) -F p --threads-num=100', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(UDP:TARGET():17000:400)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc35', note => '#35 - ping-pong option -f -Fe --threads-num=100 (on 400 sockets)', pre_proc => \&te_def_pre_proc, server_wakeup => '20', server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:400) -F e --threads-num=100', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(UDP:TARGET():17000:400)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc36', note => '#36 - ping-pong multicast option -f --mc-loopback-enable', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:224.4.0.3:7000:10) -F s', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(UDP:224.4.0.3:7000:10) -F s --mc-loopback-enable', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using select()', 'IP = 224.4.'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc37', note => '#37 - ping-pong multicast option -f -Fs (10 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:224.4.0.3:7000:10) -F s', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(UDP:224.4.0.3:7000:10) -F s', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using select()', 'IP = 224.4.'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc38', note => '#38 - ping-pong multicast option -f -Fp (10 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:224.4.0.3:7000:10) -F p', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(UDP:224.4.0.3:7000:10) -F p', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using poll()', 'IP = 224.4.'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc39', note => '#39 - ping-pong multicast option -f -Fe (10 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:224.4.0.3:7000:10) -F e', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(UDP:224.4.0.3:7000:10) -F e', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()', 'IP = 224.4.'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc40', note => '#40 - ping-pong multicast option -f -Fs (300 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:224.4.0.3:7000:300) -F s', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(UDP:224.4.0.3:7000:300) -F s', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using select()', 'IP = 224.4.'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc41', note => '#41 - ping-pong multicast option -f -Fp (300 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:224.4.0.3:7000:300) -F p', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(UDP:224.4.0.3:7000:300) -F p', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using poll()', 'IP = 224.4.'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc42', note => '#42 - ping-pong multicast option -f -Fe (300 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:224.4.0.3:7000:300) -F e', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(UDP:224.4.0.3:7000:300) -F e', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()', 'IP = 224.4.'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc43', note => '#43 - ping-pong option --pps=10', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'pp -i TARGET() --pps=10', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc44', note => '#44 - ping-pong option --pps=1000', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'pp -i TARGET() --pps=1000', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc45', note => '#45 - ping-pong option --pps=100000', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'pp -i TARGET() --pps=100000', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc46', note => '#46 - ping-pong unicast option -f -Fs -t20 -m50000 -r512 --threads-num=100 --data-integrity', pre_proc => \&te_def_pre_proc, server_wakeup => '20', server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:500) -F s --threads-num=100', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(UDP:TARGET():17000:500) -F s -t20 -m50000 -r512 --data-integrity', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using select()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc47', note => '#47 - ping-pong multicast option -f -Fs -t20 -m50000 -r512 --threads-num=100 --data-integrity', pre_proc => \&te_def_pre_proc, server_wakeup => '20', server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:224.4.0.3:17000:500) -F s --threads-num=100', client_proc => \&te_def_client_proc, client_arg => 'pp -f FEED(UDP:224.4.0.3:17000:500) -F s -t20 -m50000 -r512 --data-integrity', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using select()', 'IP = 224.4.'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, ]; 1; sockperf-3.6/tests/verifier/lib/UTP.pm000066400000000000000000001217531336630672200177500ustar00rootroot00000000000000## # @file UTP.pm # # @brief Test Suite UDP throughput. # # ## @class # Container for common data. package UTP; use strict; use warnings; # Own modules use TE::Common; use TE::Funclet; use TE::Utility; our $test_suite_udp_tp = [ { name => 'tc1', note => '#1 - throughput w/o arguments', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'tp -i TARGET()', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate', 'Warmup stage \(sending a few dummy messages\)...'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] }, }, post_proc => \&te_def_post_proc, }, { name => 'tc2', note => '#2 - throughput option --dontwarmup', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'tp -i TARGET() --dontwarmup', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down', 'Warmup stage \(sending a few dummy messages\)...'], } }, post_proc => \&te_def_post_proc, }, { name => 'tc3', note => '#3 - throughput option -b10', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'tp -i TARGET() -b10', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc4', note => '#4 - throughput option -b100', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'tp -i TARGET() -b100', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc5', note => '#5 - throughput option -b1000', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'tp -i TARGET() -b1000', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc6', note => '#6 - throughput option -t10', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'tp -i TARGET() -t10', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc7', note => '#7 - throughput option -t30', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'tp -i TARGET() -t30', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc8', note => '#8 - throughput option -m32', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'tp -i TARGET() -m32', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc9', note => '#9 - throughput option -m4096', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'tp -i TARGET() -m4096', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc10', note => '#10 - throughput option -m65500', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'tp -i TARGET() -m65500', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc11', note => '#11 - throughput option -r10', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'tp -i TARGET() -r10', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc12', note => '#12 - throughput option -r100', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'tp -i TARGET() -r100', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc13', note => '#13 - throughput option -r1024', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'tp -i TARGET() -r1024', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc14', note => '#14 - throughput option -f (10 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:10)', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(UDP:TARGET():17000:10)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc15', note => '#15 - throughput option -f -Fs (10 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:10) -F s', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(UDP:TARGET():17000:10) -F s', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using select()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc16', note => '#16 - throughput option -f -Fp (10 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:10) -F p', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(UDP:TARGET():17000:10) -F p', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using poll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc17', note => '#17 - throughput option -f -Fe (10 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:10) -F e', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(UDP:TARGET():17000:10) -F e', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc18', note => '#18 - throughput option -f -Fs (300 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:300) -F s', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(UDP:TARGET():17000:300) -F s', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using select()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc19', note => '#19 - throughput option -f -Fp (300 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:300) -F p', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(UDP:TARGET():17000:300) -F p', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using poll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc20', note => '#20 - throughput option -f -Fe (300 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:300) -F e', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(UDP:TARGET():17000:300) -F e', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc21', note => '#21 - throughput option -f -Fs --timeout 0', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:3) -F s --timeout 0', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(UDP:TARGET():17000:3) -F s --timeout 0', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using select()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc22', note => '#22 - throughput option -f -Fp --timeout 0', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:3) -F p --timeout 0', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(UDP:TARGET():17000:3) -F p --timeout 0', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using poll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc23', note => '#23 - throughput option -f -Fe --timeout 0', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:3) -F e --timeout 0', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(UDP:TARGET():17000:3) -F e --timeout 0', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc24', note => '#24 - throughput option -f -Fs --timeout=-1', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:3) -F s --timeout=-1', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(UDP:TARGET():17000:3) -F s --timeout=-1', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using select()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc25', note => '#25 - throughput option -f -Fp --timeout=-1', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:3) -F p --timeout=-1', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(UDP:TARGET():17000:3) -F p --timeout=-1', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using poll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc26', note => '#26 - throughput option -f -Fe --timeout=-1', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:3) -F e --timeout=-1', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(UDP:TARGET():17000:3) -F e --timeout=-1', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc27', note => '#27 - throughput option -f -Fs --threads-num=2 (one socket per thread)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:2) -F s --threads-num=2', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(UDP:TARGET():17000:2)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using select()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc28', note => '#28 - throughput option -f -Fp --threads-num=2 (one socket per thread)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:2) -F p --threads-num=2', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(UDP:TARGET():17000:2)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using poll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc29', note => '#29 - throughput option -f -Fe --threads-num=2 (one socket per thread)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:2) -F e --threads-num=2', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(UDP:TARGET():17000:2)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc30', note => '#30 - throughput option -f -Fs --threads-num=10 (two socket per thread)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:20) -F s --threads-num=10', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(UDP:TARGET():17000:20)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using select()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc31', note => '#31 - throughput option -f -Fp --threads-num=10 (two socket per thread)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:20) -F p --threads-num=10', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(UDP:TARGET():17000:20)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using poll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc32', note => '#32 - throughput option -f -Fe --threads-num=10 (two socket per thread)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:20) -F e --threads-num=10', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(UDP:TARGET():17000:20)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc33', note => '#33 - throughput option -f -Fs --threads-num=100 (on 400 sockets)', pre_proc => \&te_def_pre_proc, server_wakeup => '20', server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:400) -F s --threads-num=100', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(UDP:TARGET():17000:400)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using select()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc34', note => '#34 - throughput option -f -Fp --threads-num=100 (on 400 sockets)', pre_proc => \&te_def_pre_proc, server_wakeup => '20', server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:400) -F p --threads-num=100', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(UDP:TARGET():17000:400)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using poll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc35', note => '#35 - throughput option -f -Fe --threads-num=100 (on 400 sockets)', pre_proc => \&te_def_pre_proc, server_wakeup => '20', server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:400) -F e --threads-num=100', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(UDP:TARGET():17000:400)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc36', note => '#36 - throughput multicast option -f --mc-loopback-enable', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:224.4.0.3:17000:10) -F s', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(UDP:224.4.0.3:17000:10) -F s --mc-loopback-enable', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using select()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate', 'IP = 224.4.'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc37', note => '#37 - throughput multicast option -f -Fs (10 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:224.4.0.3:17000:10) -F s', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(UDP:224.4.0.3:17000:10) -F s', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using select()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate', 'IP = 224.4.'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc38', note => '#38 - throughput multicast option -f -Fp (10 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:224.4.0.3:17000:10) -F p', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(UDP:224.4.0.3:17000:10) -F p', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using poll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate', 'IP = 224.4.'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc39', note => '#39 - throughput multicast option -f -Fe (10 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:224.4.0.3:17000:10) -F e', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(UDP:224.4.0.3:17000:10) -F e', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate', 'IP = 224.4.'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc40', note => '#40 - throughput multicast option -f -Fs (300 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:224.4.0.3:17000:300) -F s', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(UDP:224.4.0.3:17000:300) -F s', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using select()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate', 'IP = 224.4.'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc41', note => '#41 - throughput multicast option -f -Fp (300 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:224.4.0.3:17000:300) -F p', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(UDP:224.4.0.3:17000:300) -F p', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using poll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate', 'IP = 224.4.'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc42', note => '#42 - throughput multicast option -f -Fe (300 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:224.4.0.3:17000:300) -F e', client_proc => \&te_def_client_proc, client_arg => 'tp -f FEED(UDP:224.4.0.3:17000:300) -F e', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate', 'IP = 224.4.'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc43', note => '#43 - throughput option --pps=1000', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'tp -i TARGET() --pps=1000', result_proc => \&te_utp_result_proc1, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Message Rate'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, ]; sub te_utp_result_proc1 { my $status = 0; @_ = TE::Utility::clear_array(@_); if (@_ == 0) { $status = 1; } elsif (@_ > 0) { my ($arg) = @_; return ($status) if (!defined($arg)); $status = te_def_result_proc(@_); if ($status == 0) { my $server_output = (exists($arg->{server}->{output}) && defined($arg->{server}->{output}) ? $arg->{server}->{output} : ''); my $client_output = (exists($arg->{client}->{output}) && defined($arg->{client}->{output}) ? $arg->{client}->{output} : ''); if ( $status == 0 && $client_output ne '' ) { my $sent_msg = 0; if ($client_output =~ m/Message Rate is (\d+) \[msg\/sec\]/) { $sent_msg = $1; if ( not (grep($_ == $sent_msg, (1000..1002))) ) { $status = 1; } } else { $status = 1; } } } } return ($status); } 1; sockperf-3.6/tests/verifier/lib/UUL.pm000066400000000000000000001341171336630672200177430ustar00rootroot00000000000000## # @file UUL.pm # # @brief Test Suite UDP under-load. # # ## @class # Container for common data. package UUL; use strict; use warnings; # Own modules use TE::Common; use TE::Funclet; use TE::Utility; our $test_suite_udp_ul = [ { name => 'tc1', note => '#1 - under-load w/o arguments', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'ul -i TARGET()', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'Warmup stage \(sending a few dummy messages\)...'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] }, }, post_proc => \&te_def_post_proc, }, { name => 'tc2', note => '#2 - under-load option --dontwarmup', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'ul -i TARGET() --dontwarmup', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down', 'Warmup stage \(sending a few dummy messages\)...'], } }, post_proc => \&te_def_post_proc, }, { name => 'tc3', note => '#3 - under-load option -b10', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'ul -i TARGET() -b10', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency of burst of 10 messages'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc4', note => '#4 - under-load option -b100', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'ul -i TARGET() -b100', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency of burst of 100 messages'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc5', note => '#5 - under-load option -b1000', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'ul -i TARGET() -b1000', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency of burst of 1000 messages'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc6', note => '#6 - under-load option -t10', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'ul -i TARGET() -t10', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'RunTime=10'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc7', note => '#7 - under-load option -t30', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'ul -i TARGET() -t30', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'RunTime=30'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc8', note => '#8 - under-load option -m32', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'ul -i TARGET() -m32', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc9', note => '#9 - under-load option -m4096', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'ul -i TARGET() -m4096', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc10', note => '#10 - under-load option -m65500', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'ul -i TARGET() -m65500', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc11', note => '#11 - under-load option -r10', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'ul -i TARGET() -r10', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc12', note => '#12 - under-load option -r100', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'ul -i TARGET() -r100', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc13', note => '#13 - under-load option -r1024', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'ul -i TARGET() -r1024', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc14', note => '#14 - under-load option -f (10 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:10)', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(UDP:TARGET():17000:10)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc15', note => '#15 - under-load option -f -Fs (10 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:10) -F s', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(UDP:TARGET():17000:10) -F s', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using select()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc16', note => '#16 - under-load option -f -Fp (10 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:10) -F p', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(UDP:TARGET():17000:10) -F p', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using poll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc17', note => '#17 - under-load option -f -Fe (10 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:10) -F e', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(UDP:TARGET():17000:10) -F e', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc18', note => '#18 - under-load option -f -Fs (300 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:300) -F s', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(UDP:TARGET():17000:300) -F s', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using select()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc19', note => '#19 - under-load option -f -Fp (300 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:300) -F p', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(UDP:TARGET():17000:300) -F p', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using poll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc20', note => '#20 - under-load option -f -Fe (300 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:300) -F e', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(UDP:TARGET():17000:300) -F e', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc21', note => '#21 - under-load option -f -Fs --timeout 0', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:3) -F s --timeout 0', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(UDP:TARGET():17000:3) -F s --timeout 0', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using select()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc22', note => '#22 - under-load option -f -Fp --timeout 0', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:3) -F p --timeout 0', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(UDP:TARGET():17000:3) -F p --timeout 0', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using poll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc23', note => '#23 - under-load option -f -Fe --timeout 0', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:3) -F e --timeout 0', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(UDP:TARGET():17000:3) -F e --timeout 0', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc24', note => '#24 - under-load option -f -Fs --timeout=-1', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:3) -F s --timeout=-1', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(UDP:TARGET():17000:3) -F s --timeout=-1', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using select()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc25', note => '#25 - under-load option -f -Fp --timeout=-1', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:3) -F p --timeout=-1', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(UDP:TARGET():17000:3) -F p --timeout=-1', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using poll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc26', note => '#26 - under-load option -f -Fe --timeout=-1', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:3) -F e --timeout=-1', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(UDP:TARGET():17000:3) -F e --timeout=-1', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc27', note => '#27 - under-load option -f -Fs --threads-num=2 (one socket per thread)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:2) -F s --threads-num=2', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(UDP:TARGET():17000:2)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc28', note => '#28 - under-load option -f -Fp --threads-num=2 (one socket per thread)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:2) -F p --threads-num=2', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(UDP:TARGET():17000:2)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc29', note => '#29 - under-load option -f -Fe --threads-num=2 (one socket per thread)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:2) -F e --threads-num=2', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(UDP:TARGET():17000:2)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc30', note => '#30 - under-load option -f -Fs --threads-num=10 (two socket per thread)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:20) -F s --threads-num=10', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(UDP:TARGET():17000:20)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc31', note => '#31 - under-load option -f -Fp --threads-num=10 (two socket per thread)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:20) -F p --threads-num=10', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(UDP:TARGET():17000:20)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc32', note => '#32 - under-load option -f -Fe --threads-num=10 (two socket per thread)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:20) -F e --threads-num=10', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(UDP:TARGET():17000:20)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc33', note => '#33 - under-load option -f -Fs --threads-num=100 (on 400 sockets)', pre_proc => \&te_def_pre_proc, server_wakeup => '20', server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:400) -F s --threads-num=100', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(UDP:TARGET():17000:400)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc34', note => '#34 - under-load option -f -Fp --threads-num=100 (on 400 sockets)', pre_proc => \&te_def_pre_proc, server_wakeup => '20', server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:400) -F p --threads-num=100', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(UDP:TARGET():17000:400)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc35', note => '#35 - under-load option -f -Fe --threads-num=100 (on 400 sockets)', pre_proc => \&te_def_pre_proc, server_wakeup => '20', server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:TARGET():17000:400) -F e --threads-num=100', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(UDP:TARGET():17000:400)', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc36', note => '#36 - under-load multicast option -f --mc-loopback-enable', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:224.4.0.3:17000:10) -F s', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(UDP:224.4.0.3:17000:10) -F s --mc-loopback-enable', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using select()', 'IP = 224.4.'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc37', note => '#37 - under-load multicast option -f -Fs (10 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:224.4.0.3:17000:10) -F s', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(UDP:224.4.0.3:17000:10) -F s', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using select()', 'IP = 224.4.'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc38', note => '#38 - under-load multicast option -f -Fp (10 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:224.4.0.3:17000:10) -F p', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(UDP:224.4.0.3:17000:10) -F p', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using poll()', 'IP = 224.4.'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc39', note => '#39 - under-load multicast option -f -Fe (10 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:224.4.0.3:17000:10) -F e', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(UDP:224.4.0.3:17000:10) -F e', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()', 'IP = 224.4.'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc40', note => '#40 - under-load multicast option -f -Fs (300 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:224.4.0.3:17000:300) -F s', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(UDP:224.4.0.3:17000:300) -F s', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using select()', 'IP = 224.4.'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc41', note => '#41 - under-load multicast option -f -Fp (300 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:224.4.0.3:17000:300) -F p', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(UDP:224.4.0.3:17000:300) -F p', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using poll()', 'IP = 224.4.'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc42', note => '#42 - under-load multicast option -f -Fe (300 records)', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -f FEED(UDP:224.4.0.3:17000:300) -F e', client_proc => \&te_def_client_proc, client_arg => 'ul -f FEED(UDP:224.4.0.3:17000:300) -F e', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is', 'using epoll()', 'IP = 224.4.'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc43', note => '#43 - under-load option --pps=10', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'ul -i TARGET() --pps=10', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'No messages were received from the server'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc44', note => '#44 - under-load option --pps=1000', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'ul -i TARGET() --pps=1000', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc45', note => '#45 - under-load option --pps=100000', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'ul -i TARGET() --pps=100000', result_proc => \&te_def_result_proc, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc46', note => '#46 - under-load option --pps=100 --reply-every=100', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'ul -i TARGET() --pps=100 --reply-every=100', result_proc => \&te_uul_result_proc1, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'No valid observations found'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, { name => 'tc47', note => '#47 - under-load option --pps=1000 --reply-every=10', pre_proc => \&te_def_pre_proc, server_proc => \&te_def_server_proc, server_arg => 'sr -i TARGET()', client_proc => \&te_def_client_proc, client_arg => 'ul -i TARGET() --pps=1000 --reply-every=10', result_proc => \&te_uul_result_proc2, result_arg => { server => { success => ['Test end', 'interrupted by', 'exit'], failure => ['Segmentation fault', 'Assertion', 'ERROR'] }, client => { success => ['Test ended', 'Summary: Latency is'], failure => ['Segmentation fault', 'Assertion', 'ERROR', 'server down'] } }, post_proc => \&te_def_post_proc, }, ]; sub te_uul_result_proc1 { my $status = 0; @_ = TE::Utility::clear_array(@_); if (@_ == 0) { $status = 1; } elsif (@_ > 0) { my ($arg) = @_; return ($status) if (!defined($arg)); $status = te_def_result_proc(@_); if ($status == 0) { my $server_output = (exists($arg->{server}->{output}) && defined($arg->{server}->{output}) ? $arg->{server}->{output} : ''); my $client_output = (exists($arg->{client}->{output}) && defined($arg->{client}->{output}) ? $arg->{client}->{output} : ''); if ( $status == 0 && $client_output ne '' ) { my $sent_msg = 0; my $recv_msg = 0; if ($client_output =~ m/SentMessages=(\d+)/) { $sent_msg = $1; if ($client_output =~ m/ReceivedMessages=(\d+)/) { $recv_msg = $1; if ( not (grep($_ == $sent_msg, (90..120)) && grep($_ == $recv_msg, (1..2))) ) { $status = 1; } } else { $status = 1; } } else { $status = 1; } } } } return ($status); } sub te_uul_result_proc2 { my $status = 0; @_ = TE::Utility::clear_array(@_); if (@_ == 0) { $status = 1; } elsif (@_ > 0) { my ($arg) = @_; return ($status) if (!defined($arg)); $status = te_def_result_proc(@_); if ($status == 0) { my $server_output = (exists($arg->{server}->{output}) && defined($arg->{server}->{output}) ? $arg->{server}->{output} : ''); my $client_output = (exists($arg->{client}->{output}) && defined($arg->{client}->{output}) ? $arg->{client}->{output} : ''); if ( $status == 0 && $client_output ne '' ) { my $sent_msg = 0; my $recv_msg = 0; if ($client_output =~ m/SentMessages=(\d+)/) { $sent_msg = $1; if ($client_output =~ m/ReceivedMessages=(\d+)/) { $recv_msg = $1; if ( not (grep($_ == $sent_msg, (990..1200)) && grep($_ == $recv_msg, (98..120))) ) { $status = 1; } } else { $status = 1; } } else { $status = 1; } } } } return ($status); } 1; sockperf-3.6/tests/verifier/verifier.pl000077500000000000000000000561131336630672200203440ustar00rootroot00000000000000#!/usr/bin/env perl ## # @file verifier.pl # # @brief SOCKPERF Verification Tool. # @author Igor Ivanov (Igor.Ivanov.Va@gmail.com) # use strict; use warnings; use Cwd; use File::Basename; # Add extra directories to Perl's search path as /lib with tool # additional modules use lib dirname($0) . "/lib"; use lib dirname($0) . "/lib/TE"; use Data::Dumper; use File::Basename; use File::Temp; use File::Basename; use File::Spec; use Sys::Hostname; use TE::Common; use TE::Utility; use TE::Funclet; our ($VERSION) = "0.1."; ########################################################### # Set variables ########################################################### my $module_name=basename($0,".pl"); my $module_script=basename($0); my $module_path=File::Spec->rel2abs(dirname($0)); my $command_line = join(" ", @ARGV); ########################################################### # Set Interrupt Handlers ########################################################### $SIG{'INT'} = \&__abort; # use signal handling, if press ^C, will interrupt and call sub __abort. ########################################################### # Main block ########################################################### use Getopt::Long qw(:config no_ignore_case); my $opt_help; my $opt_version; my $opt_info; my $opt_app; my @opt_target_list; my $opt_username; my $opt_password; my @opt_task_list; my $opt_app_arg; my $opt_app_env; my $opt_mailto; my $opt_silent; my $opt_out_level; my $opt_log_level; my $opt_progress; my $opt_log; my $opt_screen_log; my $opt_format_log; GetOptions ('help|h' => \$opt_help, 'version|v' => \$opt_version, 'info|i' => \$opt_info, 'app|a=s' => \$opt_app, 'target|s=s' => \@opt_target_list, 'username|u=s' => \$opt_username, 'password|p=s' => \$opt_password, 'task|t=s' => \@opt_task_list, 'app-arg|x=s' => \$opt_app_arg, 'app-env|e=s' => \$opt_app_env, 'email|m=s' => \$opt_mailto, 'quiet|q!' => \$opt_silent, 'out-level|o=i' => \$opt_out_level, 'log-level|d=i' => \$opt_log_level, 'progress|p=i' => \$opt_progress, 'log|l=s' => \$opt_log, 'screen-log' => \$opt_screen_log, 'format-log' => \$opt_format_log, ); # Define reference to the common global structure my $_options = $TE::Common::conf->{options}; my $_common = $TE::Common::conf->{common}; my $_current = $TE::Common::conf->{current}; # Set values passed from command line for some parameters $_options->{targets} = [split(/\s*,\s*/,join(',',@opt_target_list))] if scalar(@opt_target_list); $_options->{username} = $opt_username if defined($opt_username); $_options->{password} = $opt_password if defined($opt_password); $_options->{tasks} = [split(/\s*,\s*/,join(',',@opt_task_list))] if scalar(@opt_task_list); $_options->{email} = $opt_mailto if defined($opt_mailto); $_options->{silent} = $opt_silent if defined($opt_silent); $_options->{out_level} = $opt_out_level if defined($opt_out_level); $_options->{out_level} = 0 if ($_options->{silent} == 1); $_options->{log_level} = $opt_log_level if defined($opt_log_level); $_options->{progress} = $opt_progress if defined($opt_progress); $_options->{progress} = 0 if ($_options->{silent} == 1); $_options->{log} = ( defined($opt_log) ? $opt_log : undef ); $_options->{screen_log} = $opt_screen_log if defined($opt_screen_log); $_options->{format_log} = 1 if defined($opt_format_log); if ($opt_help) { __help(''); exit(TE_ERR_NONE); } if ($opt_version) { __version($VERSION); exit(TE_ERR_NONE); } if (defined($opt_app)) { # Check if files existed __verify_opt_file( $opt_app ); $_common->{app} = basename($opt_app); $_common->{app_path} = File::Spec->rel2abs(dirname($opt_app)); $_common->{app_arg} = undef; $_common->{app_arg} = $opt_app_arg if defined($opt_app_arg); $_common->{app_env} = undef; $_common->{app_env} = $opt_app_env if defined($opt_app_env); } $_common->{host} = hostname(); $_common->{host_ip} = TE::Utility::get_ip($_common->{host}); $_current->{target} = hostname(); # Get command-line rest arguments and make them as external variables # they are accessable from user script as $ENV{name} or &shell("echo \$name") foreach (@ARGV) { if ($_ =~ /([^=:]+)\=(.*)/) { # save arguments inside internal oject $_options->{ext}->{$1} = $2; # set them as environment variables $ENV{$1} = $2; } } TE::Utility::debug("\n"); TE::Utility::dump(Dumper($_options)); # Process command line options __setup_task(); if ( defined($opt_info) || (not scalar(@opt_task_list)) ) { __info_task(); } elsif ( scalar(@opt_task_list) ) { __exec_task(); } else { __help(''); } # Send notification by e-mail if ( $opt_mailto ) { TE::Funclet::shell( "cd $module_path; tar -zcf $_options->{log_file}.tgz $_options->{log_file} $_options->{dump_file}" ); my @attachments = ("$_options->{log_file}.tgz"); TE::Utility::debug("Sending results to $opt_mailto ...\n"); __send_results_by_mail($_options->{email}, @attachments); } # Exit with error status exit(get_error()); ########################################################### # Define functions ########################################################### ############################################################################### # # Show help to tool # ############################################################################### sub __help { my ($action)=@_; print ("Usage: $module_script [options...] [arguments...]\n"); print ("Mellanox SOCKPERF Verification Utility -- Version: $VERSION\n\n"); print ("$module_script -s [ip|hostname] -a [absolute path to tool] -t [all|udp-pp|udp-pp:tc1|udp-pp:^tc1$] -l [log file name]\n\n"); print ("\nOptions:\n"); printf (" %-5s %-10s\t%-s\n", '-h,', '--help', "Show the help message and exit."); printf (" %-5s %-10s\t%-s\n", '-v,', '--version', "Output version information and exit."); printf (" %-5s %-10s\t%-s\n", '-i', '--info', "Display detailed information about available tasks."); printf (" %-5s %-10s\t%-s\n", '-a,', '--app', "Application to be used."); printf (" %-5s %-10s\t%-s\n", '-x,', '--app-arg', "Common application arguments."); printf (" %-5s %-10s\t%-s\n", '-e,', '--app-env', "Set environment variables."); printf (" %-5s %-10s\t%-s\n", '-s,', '--target', "List of targets."); printf (" %-5s %-10s\t%-s\n", '-u,', '--username', "Privileged username to target (default: $_options->{username})."); printf (" %-5s %-10s\t%-s\n", '-p,', '--password', "Password to access target (default: $_options->{password})."); printf (" %-5s %-10s\t%-s\n", '-t,', '--task', "Test name."); print ("\nArguments:\n"); printf (" %-5s %-10s\t%-s\n", '-m,', '--email', "e-mail address to get notification."); printf (" %-5s %-10s\t%-s\n", '-o', '--out-level', "Set terminal info level 0..4 (default: 1)."); printf (" %-5s %-10s\t%-s\n", '-d', '--log-level', "Set log-file info level (default: 2)."); printf (" %-5s %-10s\t%-s\n", '', '--[no-]quiet', "Don't display output on the terminal (default: --no-quiet)."); printf (" %-5s %-10s\t%-s\n", '-p,', '--progress', "Enable/Disable status line (default: 1)."); printf (" %-5s %-10s\t%-s\n", '-l,', '--log', "Logging file name."); printf (" %-5s %-10s\t%-s\n", '', '--split-log', "Separate logging files by targets (default: off)."); printf (" %-5s %-10s\t%-s\n", '', '--no-split-log', "Save output in one logging file (default: on)."); printf (" %-5s %-10s\t%-s\n", '', '--format-log', "Enable targetname: labels on output lines"); exit(TE_ERR_NONE); } ############################################################################### # # Display tool version info # ############################################################################### sub __version { printf("$module_name %s\n", @_); exit(TE_ERR_NONE); } ############################################################################### # # Display all available tasks # Parameters: # none - display information about all tasks on a terminal and return one as a string # any - return information about all tasks as a string only # ############################################################################### sub __info_task { my $output_str = ''; { $output_str .= sprintf("Available tasks:\n"); # Calculate max length my $max_length = 0; foreach my $tsuite (@{$_common->{tsuite}}) { $max_length = length($tsuite->{name}) if ($max_length < length($tsuite->{name})); } # Enumerate all sections foreach my $tsuite (@{$_common->{tsuite}}) { next if grep ($_ !~ /$tsuite->{name}/, @{$_options->{tasks}}); $output_str .= sprintf(" %-${max_length}s - %-s\n", $tsuite->{name}, $tsuite->{note} ); } } print $output_str if (@_ == 0) ; return $output_str; } ############################################################################### # # Setup tests # ############################################################################### sub __setup_task { use UPP; use TPP; use UUL; use TUL; use UTP; use TTP; use UPB; use TPB; $_common->{tsuite} = [ { name => 'udp-pp', tcase => $UPP::test_suite_udp_pp, note => 'ping-pong for UDP' }, { name => 'udp-ul', tcase => $UUL::test_suite_udp_ul, note => 'under-load for UDP' }, { name => 'udp-tp', tcase => $UTP::test_suite_udp_tp, note => 'throughput for UDP' }, { name => 'udp-pb', tcase => $UPB::test_suite_udp_pb, note => 'playback for UDP' }, { name => 'tcp-pp', tcase => $TPP::test_suite_tcp_pp, note => 'ping-pong for TCP' }, { name => 'tcp-ul', tcase => $TUL::test_suite_tcp_ul, note => 'under-load for TCP' }, { name => 'tcp-tp', tcase => $TTP::test_suite_tcp_tp, note => 'throughput for TCP' }, { name => 'tcp-pb', tcase => $TPB::test_suite_tcp_pb, note => 'playback for TCP' } ]; } ############################################################################### # # Execute task # ############################################################################### sub __exec_task { my $temp_log = ${TE::Common::alias}; $temp_log .= '-' . $_options->{task} if defined($_options->{task}); $temp_log .= '-' . sprintf("%02d%02d%04d", (localtime(time()))[3], (localtime(time()))[4] + 1, (localtime(time()))[5] + 1900); $temp_log .= '-' . sprintf("%02d%02d%02d", (localtime(time()))[2], (localtime(time()))[1], (localtime(time()))[0]); $temp_log .= '.log'; $_options->{log} = $temp_log if (not defined($_options->{log})); my $log_file = ( exists($_options->{log}) && defined($_options->{log}) ? $_options->{log} : undef ); my($filename, $directory, $suffix) = fileparse($log_file, qr/\.[^.]*/); my $dump_file = ( exists($_options->{screen_log}) && defined($_options->{screen_log}) ? "$filename.dump" : undef ); unlink $log_file if defined($log_file); unlink $dump_file if defined($dump_file); $_options->{log_file} = $log_file if defined($log_file); $_options->{dump_file} = $dump_file if defined($dump_file); # Launch operations on hosts foreach (@{$_options->{targets}}) { $_current->{target} = $_; # Create file for logging open($_common->{flog}, ">> $log_file") || TE::Utility::fatal("Can't open $log_file: $!\n") if defined($log_file); # Create file for dump information if debugging is turned on open($_common->{fdump}, ">> $dump_file") || TE::Utility::fatal("Can't open $dump_file: $!\n") if defined($dump_file); # Form heading TE::Utility::trace("\nMellanox SOCKPERF Verification Tool v$VERSION\n"); TE::Utility::trace("**********************************\n"); my $info_str = ''; $info_str .= sprintf("* Options: %s\n", $command_line); $info_str .= sprintf("* Log file: %s\n", $log_file); $info_str .= sprintf("* Dump file: %s\n", (defined($dump_file) ? $dump_file : 'none')); $info_str .= sprintf("* Host: %s\n", $_common->{host}); $info_str .= sprintf("* Target: %s\n", $_current->{target}); $info_str .= sprintf("* Output level: %s\n", $_options->{out_level}); $info_str .= sprintf("* Log level: %s\n", $_options->{log_level}); TE::Utility::trace($info_str); TE::Utility::trace("**********************************\n"); TE::Utility::trace("\n"); local $SIG{ALRM} = sub { TE::Utility::fatal("ping $_current->{target} unreached. You need to interrupt application\n"); }; alarm 30; { TE::Utility::dump("\nTest Environment Settings\n"); TE::Utility::dump("**********************************\n"); TE::Utility::dump("HOST: $_common->{host}\n"); $info_str = ''; $info_str .= sprintf("* route table: %s\n", TE::Funclet::shell("route")); $info_str .= sprintf("* interfaces: %s\n", TE::Funclet::shell("ifconfig")); TE::Utility::dump($info_str); TE::Utility::dump("TARGET: $_current->{target}\n"); $info_str = ''; $info_str .= sprintf("* route table: %s\n", TE::Funclet::execute("route")); $info_str .= sprintf("* interfaces: %s\n", TE::Funclet::execute("ifconfig")); TE::Utility::dump($info_str); TE::Utility::dump("**********************************\n"); TE::Utility::dump("\n"); } alarm 0; my $start_time = time(); my $num_tests = 0; my $num_passes = 0; TE::Progress::init() if ($_options->{progress}); # Check if this method can be used eval { require threads }; if ($@) { VFA::Utility::fatal("threads can't be loaded.\n"); } use threads; # Launch all tasks in case task list is not defined if (scalar(@{$_options->{tasks}}) == 1 && $_options->{tasks}->[0] eq 'all') { foreach (@{$_common->{tsuite}}) { push(@{$_options->{tasks}}, $_->{name}); } } foreach my $_task (@{$_options->{tasks}}) { my $i = 0; my $j = 0; my ($_tsuite, $_tcase) = split(/:/, $_task); $_current->{task} = $_; for ($i = 0; $i < scalar(@{$_common->{tsuite}}); $i++) { next if (!defined($_common->{tsuite}->[$i]->{tcase})); next if ( (defined($_tsuite)) && ($_common->{tsuite}->[$i]->{name} !~ /$_tsuite/) ); for ($j = 0; $j < scalar(@{$_common->{tsuite}->[$i]->{tcase}}); $j++) { next if ( (defined($_tcase)) && ($_common->{tsuite}->[$i]->{tcase}->[$j]->{name} !~ /$_tcase/) ); my $server_output = ''; my $client_output = ''; my $result_code = 0; my $task = $_common->{tsuite}->[$i]->{tcase}->[$j]; my $thread = undef; TE::Utility::dump("\n"); TE::Utility::dump("**********************************\n"); TE::Utility::dump("* TSUITE : $_common->{tsuite}->[$i]->{name}\n"); TE::Utility::dump("* : $_common->{tsuite}->[$i]->{note}\n") if (defined($_common->{tsuite}->[$i]->{note})); TE::Utility::dump("* TCASE : $_common->{tsuite}->[$i]->{tcase}->[$j]->{name}\n"); TE::Utility::dump("* : $_common->{tsuite}->[$i]->{tcase}->[$j]->{note}\n") if (defined($_common->{tsuite}->[$i]->{tcase}->[$j]->{note})); TE::Utility::dump("**********************************\n"); # Execute task $task->{pre_proc}() if defined($task->{pre_proc}); if (not (defined($result_code) && $result_code)) { my $server_wakeup = ( exists($task->{server_wakeup}) && defined($task->{server_wakeup}) ? $task->{server_wakeup} : 5 ); $thread = threads->create( $task->{server_proc}, $task->{server_arg}) if defined($task->{server_proc}); # Wait for server wake up sleep($server_wakeup); } if (not (defined($result_code) && $result_code)) { local $SIG{ALRM} = sub { TE::Funclet::shell("pkill -SIGINT $_common->{app}") }; alarm 300; ($result_code, $client_output) = $task->{client_proc}($task->{client_arg}) if defined($task->{client_proc}); alarm 0; } # Wait for server thread completion TE::Funclet::execute("pkill -SIGINT $_common->{app}"); if (not (defined($result_code) && $result_code)) { my $res= $thread->join() if defined($thread); ($result_code, $server_output) = @$res; } else { $thread->join() if defined($thread); } if (not (defined($result_code) && $result_code)) { $task->{result_arg}->{server}->{output} = $server_output; $task->{result_arg}->{client}->{output} = $client_output; $result_code = $task->{result_proc}($task->{result_arg}) if defined($task->{result_proc}); } $task->{post_proc}() if defined($task->{post_proc}); # Statistic $num_tests++; $num_passes++ if ( not (defined($result_code) && $result_code) ); # Print result line $info_str = ''; $info_str .= sprintf("%-6.6s %-12.12s %-12.12s %s\n", (not (defined($result_code) && $result_code) ? 'PASS' : 'FAIL'), $_common->{tsuite}->[$i]->{name}, $_common->{tsuite}->[$i]->{tcase}->[$j]->{name}, $_common->{tsuite}->[$i]->{tcase}->[$j]->{note}); TE::Utility::trace($info_str); TE::Utility::dump("\n**********************************\n"); } } } TE::Progress::end(); my $finish_time = time(); TE::Utility::trace("\n"); TE::Utility::trace("**********************************\n"); $info_str = ''; $info_str .= sprintf("* Passed: %d\n", $num_passes); $info_str .= sprintf("* Failed: %d\n", $num_tests - $num_passes); $info_str .= sprintf("* Total: %d\n", $num_tests); $info_str .= sprintf("* Start time: %02d-%02d-%04d %02d:%02d:%02d\n", (localtime($start_time))[3], (localtime($start_time))[4] + 1, (localtime($start_time))[5] + 1900, (localtime($start_time))[2], (localtime($start_time))[1], (localtime($start_time))[0]); $info_str .= sprintf("* Finish time: %02d-%02d-%04d %02d:%02d:%02d\n", (localtime($finish_time))[3], (localtime($finish_time))[4] + 1, (localtime($finish_time))[5] + 1900, (localtime($finish_time))[2], (localtime($finish_time))[1], (localtime($finish_time))[0]); $info_str .= sprintf("* Duration: %d:%02d:%02d\n", ($finish_time - $start_time) / 3600, (($finish_time - $start_time) / 60) % 60, ($finish_time - $start_time) % 60); TE::Utility::trace($info_str); TE::Utility::trace("**********************************\n"); close($_common->{flog}) if defined($_common->{flog}); $_common->{flog} = undef; close($_common->{fdump}) if defined($_common->{fdump}); $_common->{fdump} = undef; } } ############################################################################### # # Check if files directed in command line exists # ############################################################################### sub __verify_opt_file { my (@files)=@_; foreach my $file (@files) { if( ! -e $file) { TE::Utility::fatal("$file doesn't exist\n"); } } } ############################################################################### # # Proxy-aware LWP creator # ############################################################################### sub __get_lwp { my ($url) = @_; my $scheme = $url; $scheme =~ s/^\s*(http[s]*):\/\/.*$/$1/; # Get the proxy corresponding to the scheme my $env_proxy = $ENV{"${scheme}_proxy"}; my $ua = LWP::UserAgent->new(); return undef if (!$ua); if ($env_proxy) { # Ensure the env proxy has the scheme at the prefix $env_proxy = "$scheme://$env_proxy" if ($env_proxy !~ /^\s*http/); $ua->proxy($scheme, $env_proxy); } $ua; } ############################################################################### # # Send files by e-mail # ############################################################################### sub __send_results_by_mail { my ($mail_to, @files) = @_; foreach my $mail_file (@files) { system("echo report is attached | /usr/bin/mutt -s 'breport' -a $mail_file $mail_to"); } } ############################################################################### # # CtrlC Interrupt Handler # ############################################################################### sub __abort { system('stty','echo'); print "\nDo you want to break? Press \'c\' to continue, \'e\' to exit: "; while (1) { my $input = lc(getc()); chomp ($input); exit(TE_ERR_BREAK) if ($input eq 'e'); } } sockperf-3.6/tests/vma_multiplexers_test.sh000077500000000000000000000775551336630672200213710ustar00rootroot00000000000000#!/bin/bash # Copyright (c) 2011 Mellanox Technologies Ltd. # 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. # 3. Neither the name of the Mellanox Technologies Ltd nor the names of its # contributors may be used to endorse or promote products derived from this # software without specific prior written permission. # # 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. #configurable parameters #--------------------------------------------------- MC_GROUP=224.38.37.83 PORT=5001 DURATION=10 #in seconds BW=10G OUTPUT_FILES_PATH="./" INTERFACE="ib0" OVER_VMA="yes" #[yes | not] SOCKPERF_MSG_SIZE="2" #Bytes MC_GROUP_SIZES=(2 20) VMA_IGMP_ENABLE=0 VMA_SELECT_POLL=0 VMA_RX_BUFS=200000 ##################################################### #path #---------------------------------------------------- SOCKPERF_APP=${SOCKPERF_PATH:-sockperf} VMA_LIB=${VMA_PATH:-libvma.so} #other #---------------------------------------------------- VMA_SELECT_POLL_MAX_VAL=1000000 VMA_RX_BUFS_MAX_VAL=200000 RX_FRAMES_4_SOCKPERF=1 RX_USEC=10 UMCAST_VAL=1 DST_NET="224.0.0.0" DST_MASK="240.0.0.0" VMA="vma" TMP_DIR=/tmp TMP_FILE="$TMP_DIR/multiplexer_tmp" ERROR_MESSAGE="!!! Test Failed !!!" ERORR_PROMT="vma_perf_envelope:" ERROR_RESULT="null" PREFIX="" REM_HOST_IP=$1 COMMAND_REDIRECT="1>$TMP_FILE 2>$TMP_FILE.err" TRUE=1 FALSE=0 SUCCSESS=1 BLOCK_FILE="$TMP_DIR/vma_tests_block_file" script_name=$(basename $0) user_name=`whoami` user_id=`who -am | tr " " "\n" | tail -1 | tr -d "(|)"` SUPER_USR=root ##################################################### function run_sockperf_using_select_epoll_poll_with_zero_polling { local vma_select_poll_old=$VMA_SELECT_POLL vma_select_poll_info="" save_coalesce_params update_coalesce_4_sockperf append_tmp_file_and_delete "$TMP_DIR/$log_file.prep" "$log_file" print_message "===============>SOCKPERF Using Select/Poll/Epoll<==============" "$log_file" if [[ "$OVER_VMA" = yes ]]; then vma_select_poll_info="With VMA_SELECT_POLL=0" print_message "|----------------------------------|" "$log_file" print_message "|VMA_SELECT_POLL=0" "$log_file" print_message "|----------------------------------|" "$log_file" fi run_sockperf_using_select_helper "$vma_select_poll_info" run_sockperf_using_poll_helper "$vma_select_poll_info" run_sockperf_using_epoll_helper "$vma_select_poll_info" recreate_coalesce_params tests_finish } function run_sockperf_using_select_epoll_poll_with_full_polling_vma_only { if [[ "$OVER_VMA" = yes ]]; then local vma_select_poll_old=$VMA_SELECT_POLL vma_select_poll_info="" save_coalesce_params update_coalesce_4_sockperf append_tmp_file_and_delete "$TMP_DIR/$log_file.prep" "$log_file" change_command_prefix VMA_SELECT_POLL "$VMA_SELECT_POLL_MAX_VAL" vma_select_poll_info="With VMA_SELECT_POLL=$VMA_SELECT_POLL_MAX_VAL" print_message "===============>SOCKPERF Using Select/Poll/Epoll<==============" "$log_file" print_message "|----------------------------------|" "$log_file" print_message "|VMA_SELECT_POLL=$VMA_SELECT_POLL_MAX_VAL" "$log_file" print_message "|----------------------------------|" "$log_file" run_sockperf_using_select_helper "$vma_select_poll_info" run_sockperf_using_poll_helper "$vma_select_poll_info" run_sockperf_using_epoll_helper "$vma_select_poll_info" change_command_prefix VMA_SELECT_POLL vma_select_poll_old recreate_coalesce_params tests_finish fi } function run_sockperf_using_select_helper { command_str="s" log_str="Select (default timeout 1msec)" prepare_sockperf_using_feed_file_headlines "$log_str" "$1" run_sockperf_with_diff_mc_feed_files "$command_str" "$log_str" command_str="s --timeout 0" log_str="Select (timeout zero)" prepare_sockperf_using_feed_file_headlines "$log_str" "$1" run_sockperf_with_diff_mc_feed_files "$command_str" "$log_str" command_str="s --timeout 1000" log_str="Select (timeout 1 sec)" prepare_sockperf_using_feed_file_headlines "$log_str" "$1" run_sockperf_with_diff_mc_feed_files "$command_str" "$log_str" command_str="s --timeout -1" log_str="Select (timeout infinite)" prepare_sockperf_using_feed_file_headlines "$log_str" "$1" run_sockperf_with_diff_mc_feed_files "$command_str" "$log_str" } function run_sockperf_using_poll_helper { command_str="p" log_str="Poll (default timeout 1msec)" prepare_sockperf_using_feed_file_headlines "$log_str" "$1" run_sockperf_with_diff_mc_feed_files "$command_str" "$log_str" command_str="p --timeout 0" log_str="Poll (timeout zero)" prepare_sockperf_using_feed_file_headlines "$log_str" "$1" run_sockperf_with_diff_mc_feed_files "$command_str" "$log_str" command_str="p --timeout 1000" log_str="Poll (timeout 1 sec)" prepare_sockperf_using_feed_file_headlines "$log_str" "$1" run_sockperf_with_diff_mc_feed_files "$command_str" "$log_str" command_str="p --timeout -1" log_str="Poll (timeout infinite)" prepare_sockperf_using_feed_file_headlines "$log_str" "$1" run_sockperf_with_diff_mc_feed_files "$command_str" "$log_str" } function run_sockperf_using_epoll_helper { command_str="e" log_str="Epoll (default timeout 1msec)" prepare_sockperf_using_feed_file_headlines "$log_str" "$1" run_sockperf_with_diff_mc_feed_files "$command_str" "$log_str" command_str="e --timeout 0" log_str="Epoll (timeout zero)" prepare_sockperf_using_feed_file_headlines "$log_str" "$1" run_sockperf_with_diff_mc_feed_files "$command_str" "$log_str" command_str="e --timeout 1000" log_str="Epoll (timeout 1 sec)" prepare_sockperf_using_feed_file_headlines "$log_str" "$1" run_sockperf_with_diff_mc_feed_files "$command_str" "$log_str" command_str="e --timeout -1" log_str="Epoll (timeout infinite)" prepare_sockperf_using_feed_file_headlines "$log_str" "$1" run_sockperf_with_diff_mc_feed_files "$command_str" "$log_str" } function run_sockperf_with_diff_mc_feed_files { local size_arr_len=${#MC_GROUP_SIZES[*]} print_sockperf_with_feed_files_header "$2" for((i=0; $i < $size_arr_len; i=$((i=$i+1)))) do curr_feed_file_size=${MC_GROUP_SIZES[$i]} feed_file_name="$TMP_DIR/feed_file_$curr_feed_file_size" print_cycle_info $curr_feed_file_size "mc group" create_mc_feed_files "$curr_feed_file_size" "$feed_file_name" run_sockperf_with_feed_file "$feed_file_name" "$1" parse_sockperf_test_results "${MC_GROUP_SIZES[$i]}" remove_mc_feed_files "$feed_file_name" done clean_after_sockperf } function run_sockperf_with_feed_file { sockperf_command_line_srv=${PREFIX}"${SOCKPERF_APP} server -m $SOCKPERF_MSG_SIZE -f $1 -F $2" sockperf_command_line_clt=${PREFIX}"${SOCKPERF_APP} ping-pong -m $SOCKPERF_MSG_SIZE -f $1 -F $2 -t $DURATION" (echo ${SRV_CMMND_LINE_PREF}$sockperf_command_line_srv | tee -a $log_file) >& /dev/null (eval "$sockperf_command_line_srv 2>&1 | tee >> $log_file &") sleep 15 (ssh $REM_HOST_IP "killall sockperf") >& /dev/null (echo "${CLT_CMMND_LINE_PREF} $sockperf_command_line_clt" | tee -a "$TMP_DIR/$log_file.tmp") >& /dev/null (ssh $REM_HOST_IP "sleep 10;$sockperf_command_line_clt 2>&1 | tee >> $TMP_FILE") pkill -2 -f sockperf >& /dev/null sleep 5 } function print_sockperf_with_feed_files_header { print_message "=====================>SOCKPERF With $1<====================" "$log_file" } function tests_finish { eval "cat $TMP_DIR/$log_file.post" | tee -a $log_file >& /dev/null echo "---------------------------------------------------------------" |tee -a $log_file clean } function print_cycle_info { let "cycle_num=$i+1" echo "##################### cycle $cycle_num of $size_arr_len #####################" echo "#$2 size is $1" } function parse_sockperf_test_results { check_sockperf_succss if [[ $success -eq $TRUE ]]; then latency=`ssh $REM_HOST_IP cat $TMP_FILE |tr A-Z a-z|grep latency|tr [="="=] " " |tr -s " "|tr " " "\n"|tail -2|head -1` echo "#average latency is $latency usec" echo $1,$latency >> $res_file else echo "#$ERROR_MESSAGE" echo "$1,${ERROR_RESULT}" >> $res_file fi ssh $REM_HOST_IP "cat $TMP_FILE" | tee -a "$TMP_DIR/$log_file.tmp" >& /dev/null ssh $REM_HOST_IP "rm -rf $TMP_FILE" >& /dev/null } function check_sockperf_succss { local res=0 res=`ssh $REM_HOST_IP "cat $TMP_FILE |tr A-Z a-z |grep latency | wc -l"` if [[ $res -gt 0 ]]; then success=$TRUE else success=$FALSE fi } function prepare_output_files { date=`date +%Y_%m_%d_%H_%M_%S` log_file="${OUTPUT_FILES_PATH}vma_perf_${date}_logs.txt" res_file="${OUTPUT_FILES_PATH}vma_perf_${date}_results.csv" touch $log_file touch $res_file } function prepare_sockperf_using_feed_file_headlines { echo "" >> $res_file echo sockperf Using $1 $2 Test Results >> $res_file echo MC Group Num,Latency >> $res_file } function update_command_line_pref_in_log_file { SRV_CMMND_LINE_PREF="[$srv_hostname "`pwd`"]" CLT_CMMND_LINE_PREF="[$clt_hostname "`ssh $REM_HOST_IP pwd`"]" } function get_hostnames { clt_hostname=`ssh $REM_HOST_IP hostname` srv_hostname=`hostname` update_command_line_pref_in_log_file } function update_command_prefix { PREFIX="" if [[ "$OVER_VMA" = yes ]] ; then if [[ $VMA_IGMP_ENABLE -eq 0 ]] ; then PREFIX="$PREFIX VMA_IGMP=0 " fi if [[ $VMA_SELECT_POLL -ne 0 ]] ; then PREFIX="$PREFIX VMA_SELECT_POLL=$VMA_SELECT_POLL " fi if [[ $VMA_RX_BUFS -ne 0 ]] ; then PREFIX="$PREFIX VMA_RX_BUFS=$VMA_RX_BUFS " fi PREFIX=${PREFIX}"LD_PRELOAD=$VMA_LIB " fi } function change_command_prefix { eval "$1=$2" update_command_prefix } function remove_ifaces { add_curr_route_table_2_log iface_arr_local=`route | grep 2[24][40].0.0.0 | tr -s ' ' | cut -d ' ' -f 8` iface_arr_remote=`ssh $REM_HOST_IP "route | grep 2[24][40].0.0.0 | tr -s ' ' | cut -d ' ' -f 8"` echo "" >> "$TMP_DIR/$log_file.prep" echo "============>Remove interfaces from route table <=============" >> "$TMP_DIR/$log_file.prep" for iface in $iface_arr_local do command="route del -net $DST_NET netmask $DST_MASK dev $iface" (echo "${SRV_CMMND_LINE_PREF} $command" | tee -a $TMP_DIR/$log_file.prep) >& /dev/null eval "$command 2>&1 | tee >> $TMP_DIR/$log_file.prep" done for iface in $iface_arr_remote do command="route del -net $DST_NET netmask $DST_MASK dev $iface" (echo "${CLT_CMMND_LINE_PREF} $command" | tee -a "$TMP_DIR/$log_file.prep") >& /dev/null eval "ssh $REM_HOST_IP "$command" 2>&1 | tee >> $TMP_DIR/$log_file.prep" done } function add_curr_route_table_2_log { (echo "${SRV_CMMND_LINE_PREF} route" | tee -a "$TMP_DIR/$log_file.prep") >& /dev/null eval "route 2>&1 | tee >> $TMP_DIR/$log_file.prep" (echo "${CLT_CMMND_LINE_PREF} route" | tee -a "$TMP_DIR/$log_file.prep") >& /dev/null eval "ssh $REM_HOST_IP "route" 2>&1 | tee >> $TMP_DIR/$log_file.prep" } function recreate_route_table { echo "" >> "$TMP_DIR/$log_file.post" echo "===================>Recreate route table <====================" >> "$TMP_DIR/$log_file.post" command="route del -net $DST_NET netmask $DST_MASK dev $INTERFACE" (echo "${SRV_CMMND_LINE_PREF} $command" | tee -a "$TMP_DIR/$log_file.post") >& /dev/null eval "$command 2>&1 | tee >> $TMP_DIR/$log_file.post" (echo "${CLT_CMMND_LINE_PREF} $command" | tee -a "$TMP_DIR/$log_file.post") >& /dev/null ssh $REM_HOST_IP "$command" 2>&1 | tee >> "$TMP_DIR/$log_file.post" for iface in $iface_arr_local do command="route add -net $DST_NET netmask $DST_MASK dev $iface" (echo "${SRV_CMMND_LINE_PREF} $command" | tee -a "$TMP_DIR/$log_file.post") >& /dev/null eval "$command 2>&1 | tee >> $TMP_DIR/$log_file.post" done for iface in $iface_arr_remote do command="route add -net $DST_NET netmask $DST_MASK dev $iface" (echo "${CLT_CMMND_LINE_PREF} $command" | tee -a "$TMP_DIR/$log_file.post") >& /dev/null (eval "ssh $REM_HOST_IP "$command" 2>&1 | tee >> $TMP_DIR/$log_file.post") >& /dev/null done eval "cat $TMP_DIR/$log_file.post" | tee -a $log_file >& /dev/null clean } function prepare_route_table { echo "" >> "$TMP_DIR/$log_file.prep" echo "=====================>Route table info <======================" >> "$TMP_DIR/$log_file.prep" remove_ifaces echo "" >> "$TMP_DIR/$log_file.prep" echo "============>Add work interface to route table <==============" >> "$TMP_DIR/$log_file.prep" command="route add -net $DST_NET netmask $DST_MASK dev $INTERFACE" (echo "${SRV_CMMND_LINE_PREF} $command" | tee -a "$TMP_DIR/$log_file.prep") >& /dev/null eval "$command 2>&1 | tee >> $TMP_DIR/$log_file.prep" (echo "${CLT_CMMND_LINE_PREF} $command" | tee -a "$TMP_DIR/$log_file.prep") >& /dev/null eval "ssh $REM_HOST_IP "$command" 2>&1 | tee >> $TMP_DIR/$log_file.prep" eval "cat $TMP_DIR/$log_file.prep" | tee -a $log_file >& /dev/null clean } function save_coalesce_params { local_coalesce_params_saved=$TRUE remote_coalesce_params_saved=$TRUE command1="ethtool -c $INTERFACE" echo "" >> "$TMP_DIR/$log_file.prep" echo "===================>Coalesce params info<=====================" >> "$TMP_DIR/$log_file.prep" save_local_coalesce_params "$command1" rx-frames: initial_rx_frames_local save_remote_coalesce_params "$command1" rx-frames: initial_rx_frames_remote rm -f $TMP_FILE >& /dev/null rm -f $TMP_FILE.err >& /dev/null } function save_local_coalesce_params { (echo "${SRV_CMMND_LINE_PREF} $1" | tee -a "$TMP_DIR/$log_file.prep") >& /dev/null eval "$1 $COMMAND_REDIRECT" check_succsess_and_save_param $2 get_coalesce_param eval "$3=$?" if [[ $SUCCSESS -eq $FALSE ]] ;then local_coalesce_params_saved=$FALSE fi } function save_remote_coalesce_params { (echo "${CLT_CMMND_LINE_PREF} $1" | tee -a "$TMP_DIR/$log_file.prep") >& /dev/null eval "(ssh $REM_HOST_IP "$1") $COMMAND_REDIRECT" check_succsess_and_save_param $2 get_coalesce_param eval "$3=$?" if [[ $SUCCSESS -eq $FALSE ]]; then remote_coalesce_params_saved=$FALSE fi } function get_coalesce_param { ret_val=`cat $TMP_FILE | grep $1 | cut -d " " -f 2 2>/dev/null` } function get_umcast_val { umcast_val=`cat $TMP_FILE | tr -d "\n" 2>/dev/null` } function update_coalesce_4_sockperf { local_coalesce_params_changed=$FALSE remote_coalesce_params_changed=$FALSE echo "" >> "$TMP_DIR/$log_file.prep" echo "============>Prepare coalesce params for sockperf<=============" >> "$TMP_DIR/$log_file.prep" update_coalesce_params $RX_FRAMES_4_SOCKPERF } function update_coalesce_params { command="ethtool -C $INTERFACE rx-frames $1" if [[ $local_coalesce_params_saved -eq $TRUE ]]; then if [[ $initial_rx_frames_local -ne $1 ]]; then update_local_coalesce_params fi fi if [[ $remote_coalesce_params_saved -eq $TRUE ]]; then if [[ $initial_rx_frames_remote -ne $1 ]]; then update_remote_coalesce_params fi fi } function update_local_coalesce_params { (echo "${SRV_CMMND_LINE_PREF} $command" | tee -a "$TMP_DIR/$log_file.prep") >& /dev/null eval "$command $COMMAND_REDIRECT" check_command_succss if [[ $SUCCSESS -eq $TRUE ]]; then local_coalesce_params_changed=$TRUE else local_coalesce_params_changed=$FALSE fi } function update_remote_coalesce_params { (echo "${CLT_CMMND_LINE_PREF} $command" | tee -a "$TMP_DIR/$log_file.prep") >& /dev/null eval "(ssh $REM_HOST_IP "$command") $COMMAND_REDIRECT" check_command_succss if [[ $SUCCSESS -eq $TRUE ]]; then remote_coalesce_params_changed=$TRUE else remote_coalesce_params_changed=$FALSE fi } function recreate_coalesce_params { echo "" >> "$TMP_DIR/$log_file.post" echo "==================>Recreate coalesce params<==================" >> "$TMP_DIR/$log_file.post" if [[ $local_coalesce_params_changed -eq $TRUE ]]; then recreate_local_coalesce_params fi if [[ $remote_coalesce_params_changed -eq $TRUE ]]; then recreate_remote_coalesce_params fi } function recreate_local_coalesce_params { local command="ethtool -C $INTERFACE rx-frames $initial_rx_frames_local" (echo "${SRV_CMMND_LINE_PREF} $command" | tee -a "$TMP_DIR/$log_file.post") >& /dev/null eval $command >& /dev/null } function recreate_remote_coalesce_params { local command="ethtool -C $INTERFACE rx-frames $initial_rx_frames_remote" (echo "${CLT_CMMND_LINE_PREF} $command" | tee -a "$TMP_DIR/$log_file.post") >& /dev/null ssh $REM_HOST_IP "$command" >& /dev/null } function save_umcast { local_umcast_saved=$FALSE remote_umcast_saved=$FALSE echo "" >> "$TMP_DIR/$log_file.prep" echo "========================>Umcast info<=========================" >> "$TMP_DIR/$log_file.prep" check_if_infbnd_iface if [[ $is_infiniband -eq $TRUE ]]; then save_local_umcast_val save_remote_umcast_val fi eval "cat $TMP_DIR/$log_file.prep" | tee -a $log_file >& /dev/null clean } function save_local_umcast_val { local command="cat /sys/class/net/$INTERFACE/umcast" (echo "${SRV_CMMND_LINE_PREF} $command" | tee -a "$TMP_DIR/$log_file.prep") >& /dev/null eval "cat /sys/class/net/$INTERFACE/umcast 1>$TMP_FILE 2>$TMP_FILE.err " check_succsess_and_save_param initial_local_umcast_val get_umcast_val if [[ $SUCCSESS -eq $FALSE ]]; then local_umcast_saved=$FALSE else initial_local_umcast_val=$umcast_val local_umcast_saved=$TRUE fi } function save_remote_umcast_val { local command="cat /sys/class/net/$INTERFACE/umcast" (echo "${CLT_CMMND_LINE_PREF} $command" | tee -a "$TMP_DIR/$log_file.prep") >& /dev/null (eval "ssh $REM_HOST_IP cat /sys/class/net/$INTERFACE/umcast") 1>$TMP_FILE 2>$TMP_FILE.err check_succsess_and_save_param initial_remote_umcast_val get_umcast_val if [[ $SUCCSESS -eq $FALSE ]]; then remote_umcast_saved=$FALSE else initial_remote_umcast_val=$umcast_val remote_umcast_saved=$TRUE fi } function update_umcast { echo "" >> "$TMP_DIR/$log_file.prep" echo "===================>Prepare umcast param<====================" >> "$TMP_DIR/$log_file.prep" local_umcast_changed=$FALSE remote_umcast_changed=$FALSE if [[ $initial_local_umcast_val -ne $UMCAST_VAL ]]; then update_local_umcast fi if [[ $initial_remote_umcast_val -ne $UMCAST_VAL ]]; then update_remote_umcast fi eval "cat $TMP_DIR/$log_file.prep" | tee -a $log_file >& /dev/null clean } function update_local_umcast { local command="echo $UMCAST_VAL 1>&/sys/class/net/$INTERFACE/umcast" if [[ $local_umcast_saved -eq $TRUE ]]; then (echo "${SRV_CMMND_LINE_PREF} $command" | tee -a "$TMP_DIR/$log_file.prep") >& /dev/null eval "$command 1>$TMP_FILE 2>$TMP_FILE.err" check_command_succss if [[ $SUCCSESS -eq $TRUE ]]; then local_umcast_changed=$TRUE else local_umcast_changed=$FALSE fi fi } function update_remote_umcast { local command="echo $UMCAST_VAL 1>&/sys/class/net/$INTERFACE/umcast" if [[ $local_umcast_saved -eq $TRUE ]]; then (echo "${SRV_CMMND_LINE_PREF} $command" | tee -a "$TMP_DIR/$log_file.prep") >& /dev/null ssh $REM_HOST_IP "$command" | eval "1>$TMP_FILE 2>$TMP_FILE.err " check_command_succss if [[ $SUCCSESS -eq $TRUE ]]; then remote_umcast_changed=$TRUE else remote_umcast_changed=$FALSE fi fi } function recreate_umcast { echo "" >> "$TMP_DIR/$log_file.post" echo "====================>Recreate umcast value<===================" >> "$TMP_DIR/$log_file.post" if [[ $local_umcast_changed -eq $TRUE ]]; then recreate_local_umcast_val fi if [[ $remote_umcast_changed -eq $TRUE ]]; then recreate_remote_umcast_val fi eval "cat $TMP_DIR/$log_file.post" | tee -a $log_file >& /dev/null } function recreate_local_umcast_val { local command="echo $initial_local_umcast_val 1>&/sys/class/net/$INTERFACE/umcast" (echo "${SRV_CMMND_LINE_PREF} $command" | tee -a "$TMP_DIR/$log_file.post") >& /dev/null eval "$command" >& /dev/null } function recreate_remote_umcast_val { local command="echo $initial_remote_umcast_val 1>&/sys/class/net/$INTERFACE/umcast" (echo "${CLT_CMMND_LINE_PREF} $command" | tee -a "$TMP_DIR/$log_file.post") >& /dev/null ssh $REM_HOST_IP $command >& /dev/null } function clean_after_sockperf { ssh $REM_HOST_IP killall sockperf >& /dev/null pkill -2 -f sockperf >& /dev/null sleep 10 cat "$TMP_DIR/$log_file.tmp" | tee -a $log_file >& /dev/null rm -f "$TMP_DIR/$log_file.tmp" >& /dev/null } function collect_nodes_info_to_file { collect_local_node_info_to_file "$1" collect_remote_node_info_to_file "$1" } function collect_local_node_info_to_file { (echo "======================>Local node info<======================" | tee -a $1) >& /dev/null (echo "--------------------" | tee -a $1) >& /dev/null (hostname | tee -a $1) >& /dev/null (echo -n "OS: " >> $1;cat /etc/issue | grep We | tee -a $1) >& /dev/null (echo -n "CPU: " >> $1;cat /proc/cpuinfo | grep 'model name' | sort -u | awk '{print $4, $5, $6, $7, $9}' | tee -a $1) >& /dev/null (echo -n "Number of CPUs: " >> $1;cat /proc/cpuinfo |grep proce |wc |awk '{print $1}' | tee -a $1) >& /dev/null (echo -n "CPU Type: " >> $1;uname -a | awk '{print $12}' | tee -a $1) >& /dev/null (cat /proc/meminfo |grep [M,m]em | tee -a $1) >& /dev/null (echo -n "Kernel: " >> $1;uname -a | awk '{print $3}' | tee -a $1) >& /dev/null (cat /usr/voltaire/version | tee -a $1) >& /dev/null (ibstat | grep -e "CA type" -e "Firmware version" | tee -a $1) >& /dev/null (ibstatus | grep -e rate -e state | grep -v 'phys state' | tee -a $1) >& /dev/null check_if_infbnd_iface if [[ $is_infiniband -eq $TRUE ]]; then (echo -n "IPoIB mode: " >> $1 ; cat "/sys/class/net/$INTERFACE/mode" | tee -a $1) >& /dev/null fi (ifconfig $INTERFACE | grep MTU | awk '{print $5}' | tee -a $1) >& /dev/null (echo -n "OFED:" >> $1;ofed_info | head -6 | grep OFED | tee -a $1) >& /dev/null (echo -n "VMA:" >> $1;rpm -qa | grep $VMA | tee -a $1) >& /dev/null } function collect_remote_node_info_to_file { (echo "=====================>Remote node info<======================" | tee -a $1) >& /dev/null (echo "--------------------" | tee -a $1) >& /dev/null (ssh $REM_HOST_IP "hostname" | tee -a $1) >& /dev/null (echo -n "OS: " >> $1;ssh $REM_HOST_IP cat /etc/issue | grep We | tee -a $1) >& /dev/null (echo -n "CPU: " >> $1;ssh $REM_HOST_IP cat /proc/cpuinfo | grep 'model name' | sort -u | awk '{print $4, $5, $6, $7, $9}' | tee -a $1) >& /dev/null (echo -n "Number of CPUs: " >> $1;ssh $REM_HOST_IP cat /proc/cpuinfo |grep proce |wc |awk '{print $1}' | tee -a $1) >& /dev/null (echo -n "CPU Type: " >> $1;ssh $REM_HOST_IP uname -a | awk '{print $12}' | tee -a $1) >& /dev/null (ssh $REM_HOST_IP cat /proc/meminfo |grep [M,m]em | tee -a $1) >& /dev/null (echo -n "Kernel: " >> $1;ssh $REM_HOST_IP uname -a | awk '{print $3}' | tee -a $1) >& /dev/null (ssh $REM_HOST_IP "cat /usr/voltaire/version" | tee -a $1) >& /dev/null (ssh $REM_HOST_IP "ibstat | grep -e "CA type" -e 'Firmware version'" | tee -a $1) >& /dev/null (ssh $REM_HOST_IP "ibstatus | grep -e rate -e state | grep -v 'phys state'" | tee -a $1) >& /dev/null to_print="/sys/class/net/$INTERFACE/mode" check_if_infbnd_iface if [[ $is_infiniband -eq $TRUE ]]; then (echo -n "IPoIB mode: " >> $1 ;ssh $REM_HOST_IP "cat $to_print" | tee -a $1) >& /dev/null fi (ssh $REM_HOST_IP ifconfig $INTERFACE | grep MTU | awk '{print $5}' | tee -a $1) >& /dev/null (echo -n "OFED:" >> $1;ssh $REM_HOST_IP ofed_info | head -6 | grep OFED | tee -a $1) >& /dev/null (echo -n "VMA:" >> $1;ssh $REM_HOST_IP rpm -qa | grep $VMA | tee -a $1) >& /dev/null } function print_message { echo $1 | tee -a $2 echo ""| tee -a $2 } function append_tmp_file_and_delete { cat $1 | tee -a $2 >& /dev/null rm -f $1 } function check_command_succss { if [ -s $TMP_FILE.err ]; then eval "cat $TMP_FILE.err 2>&1 | tee >> $TMP_DIR/$log_file.prep" LAST_ERROR=`cat $TMP_FILE.err` SUCCSESS=$FALSE else if [ -s $TMP_FILE ]; then eval "cat $TMP_FILE 2>&1 | tee >> $TMP_DIR/$log_file.prep" fi SUCCSESS=$TRUE fi rm -f $TMP_FILE.err >& /dev/null } function check_succsess_and_save_param { local ret_val=0 check_command_succss if [[ $SUCCSESS -eq $TRUE ]]; then $2 $1 fi return $ret_val } function check_if_infbnd_iface { is_infiniband=$FALSE if [[ $INTERFACE =~ "ib*" ]]; then is_infiniband=$TRUE fi } function discover_local_work_if_ip { LOCAL_IP=`ifconfig $INTERFACE | grep inet |grep -v inet6 | cut -d ':' -f 2| cut -d " " -f 1` >& /dev/null } function calc_file_age { creation_time=`stat -c %Z /tmp/vma_utils_block_file` now=`date +%s` block_file_age=$(($now-$creation_time)) } function get_operator_pid { pid=$$ #pid=`ps -eF |grep $script_name| tr -s ' ' | cut -d ' ' -f 2|head -1` } function write_to_file_operator_details { operating_machine_hostname=`hostname` get_operator_pid rm -f "$2" >& /dev/null touch "$2" >& /dev/null echo -n "$1 " >> "$2" 2>/dev/null echo -n "$pid " >> "$2" 2>/dev/null echo -n "$script_name " >> "$2" 2>/dev/null echo -n "$user_name " >> "$2" 2>/dev/null echo -n "$user_id " >> "$2" 2>/dev/null echo -n "$operating_machine_hostname " >> "$2" 2>/dev/null if [[ $1 == "local" ]]; then st_timestamp=`date` else st_timestamp=`ssh $REM_HOST_IP "date" ` fi echo "$st_timestamp" | tr " " "_" >> "$2" 2>/dev/null } function read_block_file { blocking_pid=`awk -F " " '{print $2}' "$1"` blocking_app=`awk -F " " '{print $3}' "$1"` blocking_username=`awk -F " " '{print $4}' "$1"` blocking_id=`awk -F " " '{print $5}' "$1"` blocking_hostname=`awk -F " " '{print $6}' "$1"` blocking_st_time=`awk -F " " '{print $7}' "$1"` } function print_block_files_details { echo "Blocked Host:$blocked_host" echo "You blocked by:" echo "- application: ${blocking_app} " echo "- user: ${blocking_username} " echo "- users local host ip:${blocking_id} " echo "- blocking proccess with pid: ${blocking_pid} running on host ${blocking_hostname} " echo "- starting time:${blocking_st_time} " echo "- blocking file:${BLOCK_FILE}" } function update_remote_block_file { write_to_file_operator_details "$LOCAL_IP" "${BLOCK_FILE}.rem" scp "${BLOCK_FILE}.rem" "${REM_HOST_IP}:${BLOCK_FILE}" >& /dev/null rm -f "${BLOCK_FILE}.rem" >& /dev/null } function update_local_block_file { write_to_file_operator_details "local" "$BLOCK_FILE" } function update_block_files { discover_local_work_if_ip if [ "$LOCAL_IP" == "" ]; then echo "WARNING: Will be executed without blocking..." else update_local_block_file update_remote_block_file fi } function unblock_local_host { rm -f $BLOCK_FILE >& /dev/null rm -f "${BLOCK_FILE}.rem" >& /dev/null } function unblock_remote_host { ssh $REM_HOST_IP "rm -f $BLOCK_FILE >& /dev/null" >& /dev/null rm -f "${BLOCK_FILE}.rem" >& /dev/null } function unblock { unblock_local_host unblock_remote_host } function check_connection_to_remote_host { ping -w 3 "$1" >& /dev/null test $? -eq 0 && RES=OK || RES=NOT } function check_if_another_proccess_running_on_local_host { eval "ps -eF| grep '$blocking_pid'|grep -v grep|wc -l" > $TMP_FILE RES=`cat $TMP_FILE` } function check_if_another_proccess_running_on_remote_host { RES=0 check_connection_to_remote_host "$1" if [ $RES == "OK" ]; then RES=`sudo ssh ${SUPER_USR}@${1} "ps -eF| grep ${blocking_pid}|grep -v grep|wc -l"` else RES=1 fi } function get_operating_host_ip_or_hostname { RES=0 operating_host_ip=`awk -F " " '{print $1}' "$1"` if [[ $operating_host_ip != "local" ]]; then check_connection_to_remote_host "$operating_host_ip" if [ $RES != "OK" ]; then operating_host_ip=`awk -F " " '{print $6}' "$1"` fi fi } function check_if_operating_host_running_another_proccess { if [ $1 == "local" ]; then check_if_another_proccess_running_on_local_host else check_if_another_proccess_running_on_remote_host "$1" fi } function adjust_operating_host_ip_of_remote_machine { local tmp="" if [ "$1" == "local" ]; then operating_host_ip=$REM_HOST_IP else tmp=`ifconfig|grep $1` if [ "$tmp" != "" ]; then operating_host_ip="local" fi fi } function check_if_remote_host_is_blocked { RES=0 ssh $REM_HOST_IP "cat ${BLOCK_FILE} 2>/dev/null" > "${BLOCK_FILE}.rem" if [ -s "${BLOCK_FILE}.rem" ]; then read_block_file "${BLOCK_FILE}.rem" get_operating_host_ip_or_hostname "${BLOCK_FILE}.rem" adjust_operating_host_ip_of_remote_machine "$operating_host_ip" check_if_operating_host_running_another_proccess "$operating_host_ip" if [[ $RES -le 0 ]]; then unblock_remote_host else read_block_file "$BLOCK_FILE.rem" blocked_host=$REM_HOST_IP print_block_files_details rm -f "${BLOCK_FILE}.rem" >& /dev/null clean exit 1 fi fi } function check_if_local_host_is_blocked { RES=0 if [[ -e $BLOCK_FILE ]]; then read_block_file "$BLOCK_FILE" get_operating_host_ip_or_hostname "${BLOCK_FILE}" check_if_operating_host_running_another_proccess "$operating_host_ip" if [[ $RES -le 0 ]]; then unblock_local_host else blocked_host=`hostname` print_block_files_details clean exit 1 fi fi } function block { check_if_local_host_is_blocked check_if_remote_host_is_blocked update_block_files } function pre_test_checks { check_connection_2_remote_ip clean } function check_connection_2_remote_ip { ssh -o "BatchMode yes" $REM_HOST_IP exit 2>$TMP_FILE.err check_command_succss if [[ $SUCCSESS -ne $TRUE ]]; then echo "vma_perf_envelope error:$LAST_ERROR" clean unblock exit 1 fi } function write_mc_feed_file { x=0 # num of mc groups y=1 # the third number of the mc group port=10005 num=3 # the last number of the mc group while [ $x -lt $1 ] do if [ $num -ge 254 ]; then y=$(($y+1)) num=3 fi echo 224.4.$y.$num:$port >> $2 x=$(($x+1)) port=$(($port+1)) num=$(($num+1)) done } function create_mc_feed_files { write_mc_feed_file $1 $2 copy_feed_file_2_remote_machine $2 >& /dev/null } function copy_feed_file_2_remote_machine { scp $1 "$REM_HOST_IP:/$TMP_DIR" } function remove_mc_feed_files { rm -f $1 >& /dev/null ssh $REM_HOST_IP "rm -f $1" >& /dev/null } function clean { rm -f $TMP_FILE.err >& /dev/null rm -f "$TMP_DIR/$log_file.prep" >& /dev/null rm -f "$TMP_DIR/$log_file.post" >& /dev/null } function write_date_2_log_file { echo "=============================>Date<===========================" >> "$log_file" (echo "${SRV_CMMND_LINE_PREF} date" | tee -a "$log_file") >& /dev/null (date | tee -a $log_file) >& /dev/null } function pre_vma_perf { pre_test_checks get_hostnames prepare_output_files write_date_2_log_file collect_nodes_info_to_file "$log_file" prepare_route_table save_umcast update_umcast clean update_command_prefix } function final_test_message { echo "####################### Generated files #######################" echo "#Test results : $res_file" echo "#Test logs : $log_file" echo "---------------------------------------------------------------" } function post_vma_perf { collect_nodes_info_to_file "$res_file" recreate_route_table recreate_umcast final_test_message write_date_2_log_file clean } function vma_perf { run_sockperf_using_select_epoll_poll_with_zero_polling run_sockperf_using_select_epoll_poll_with_full_polling_vma_only } #main if [ $# = 1 ]; then block pre_vma_perf vma_perf post_vma_perf unblock else echo "Usage: perf " exit fi sockperf-3.6/tests/vma_perf_envelope.sh000077500000000000000000001625651336630672200204220ustar00rootroot00000000000000#!/bin/bash # Copyright (c) 2011 Mellanox Technologies Ltd. # 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. # 3. Neither the name of the Mellanox Technologies Ltd nor the names of its # contributors may be used to endorse or promote products derived from this # software without specific prior written permission. # # 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. #configurable parameters #--------------------------------------------------- MC_GROUP=17.17.17.100 PORT=5001 DURATION=10 #in seconds BW=10G OUTPUT_FILES_PATH="./" INTERFACE="eth3" OVER_VMA="yes" #[yes | not] SOCKPERF_TC1_PPS_ARRAY=(100 1000 10000 50000 100000 500000) # Packet per second SOCKPERF_MSG_SIZE=(14 32 64 128 192 256 512 768 1024 1472 2048 4096 8192 16384 32768 65500) # Bytes IPERF_MSG_SIZE=(14 32 64 128 192 256 512 768 1024 1472 2048 4096 8192 16384 32768 65500) # Bytes SOCKPERF_BURST_SIZE=(2 5 10 25 50 100 250 500 1000 2500 5000 10000 16000 25000 50000 100000 250000 500000) # Message MC_GROUP_SIZES=(1 10 20 30 50 60 64 65 70 80 90 100 150 200 500) # Number of sockets with unique MC groupa in iomux #path #---------------------------------------------------- SOCKPERF_APP=${SOCKPERF_PATH:-sockperf_2.5.132M} VMA_LIB=${VMA_PATH:-libvma.so} ##################################################### #vma default values #--------------------------------------------------- DEFAULT_VMA_IGMP_ENABLE=1 DEFAULT_VMA_RX_POLL_OS_RATIO=10 DEFAULT_VMA_RX_SKIP_OS=100 DEFAULT_VMA_SELECT_POLL=0 DEFAULT_VMA_RX_BUFS=200000 DEFAULT_VMA_THREAD_MODE=1 DEFAULT_VMA_RX_WRE=16000 DEFAULT_VMA_SELECT_POLL=0 DEFAULT_VMA_SELECT_SKIP_OS=4 DEFAULT_VMA_HUGETLB=1 ##################################################### #initial vma values in test #--------------------------------------------------- VMA_IGMP_ENABLE=0 VMA_RX_POLL_OS_RATIO=$DEFAULT_VMA_RX_POLL_OS_RATIO VMA_RX_SKIP_OS=$DEFAULT_VMA_RX_SKIP_OS VMA_RX_BUFS=$DEFAULT_VMA_RX_BUFS VMA_RX_WRE=$DEFAULT_VMA_RX_WRE VMA_SELECT_POLL=$DEFAULT_VMA_SELECT_POLL VMA_SELECT_SKIP_OS=$DEFAULT_VMA_SELECT_SKIP_OS VMA_THREAD_MODE=$DEFAULT_VMA_THREAD_MODE VMA_HUGETLB=$DEFAULT_VMA_HUGETLB ########################################################################### #other Optimal Val #-------------------------------------------------------------------------- VMA_SELECT_POLL_MAX_VAL=1000000 VMA_RX_BUFS_MAX_VAL=200000 VMA_IOMUX_RX_WRE=$DEFAULT_VMA_RX_WRE #3200 VMA_IOMUX_RX_SKIP_OS=$DEFAULT_VMA_RX_SKIP_OS #1000 VMA_IOMUX_SELECT_SKIP_OS=$DEFAULT_VMA_SELECT_SKIP_OS #500 VMA_IOMUX_HUGETLB=$DEFAULT_VMA_HUGETLB #1 MAX_SOCKPERF_MSG_SIZE=65507 ACTIVITY=100000 RX_ADAPTIVE_ETH_THROUGHPUT=on RX_FRAMES_ETH_THROUGHPUT=88 RX_USEC_ETH_THROUGHPUT=16 RX_ADAPTIVE_IB_THROUGHPUT=on RX_FRAMES_IB_THROUGHPUT=16 RX_USEC_IB_THROUGHPUT=10 RX_ADAPTIVE_ETH_LATENCY=off RX_FRAMES_ETH_LATENCY=1 RX_USEC_ETH_LATENCY=0 RX_ADAPTIVE_IB_LATENCY=off RX_FRAMES_IB_LATENCY=1 RX_USEC_IB_LATENCY=0 UMCAST_VAL=1 DST_NET="224.0.0.0" DST_MASK="240.0.0.0" VMA="vma" TMP_DIR=/tmp TMP_FILE="$TMP_DIR/perf_tmp" ERROR_MESSAGE="!!! Test Failed !!!" ERORR_PROMT="vma_perf_envelope:" ERROR_RESULT="null" PREFIX="" REM_HOST_IP=$1 COMMAND_REDIRECT="1>$TMP_FILE 2>$TMP_FILE.err" TRUE=1 FALSE=0 SUCCSESS=1 BLOCK_FILE="$TMP_DIR/vma_tests_block_file" script_name=$(basename $0) user_name=`whoami` user_id=`who -am | tr " " "\n" | tail -1 | tr -d "(|)"` SUPER_USR=root ##################################################### function run_iperf_with_diff_msg_len { wait_time=0 local size_arr_len=${#IPERF_MSG_SIZE[*]} prepare_iperf_headlines save_coalesce_params update_coalesce_4_tr_test append_tmp_file_and_delete "$TMP_DIR/$log_file.prep" "$log_file" print_message "============================>IPERF<============================" "$log_file" for((i=0; $i < $size_arr_len; i=$((i=$i+1)))) do curr_msg_size=${IPERF_MSG_SIZE[$i]} iperf_cycle parse_iperf_test_results done recreate_coalesce_params clean_after_iperf tests_finish } function iperf_cycle { print_cycle_info $curr_msg_size message killall iperf >& /dev/null ssh $REM_HOST_IP killall iperf >& /dev/null iperf_command_line_srv=${PREFIX}"iperf -usB $MC_GROUP -p $PORT -l $curr_msg_size -i 1 -f M" iperf_command_line_clt=${PREFIX}"iperf -uc $MC_GROUP -p $PORT -l $curr_msg_size -t $DURATION -b $BW -i 1 -f M" (echo "${SRV_CMMND_LINE_PREF}$iperf_command_line_srv" | tee -a $log_file) >& /dev/null (ssh $REM_HOST_IP "echo ${CLT_CMMND_LINE_PREF}$iperf_command_line_clt|tee -a $TMP_DIR/$log_file.tmp")>& /dev/null (ssh $REM_HOST_IP "sleep 10;$iperf_command_line_clt 2>&1 | tee >> $TMP_DIR/$log_file.tmp " &) wait_time=$DURATION let "wait_time += 20" (sleep $wait_time;killall -9 iperf >& /dev/null)| (eval "$iperf_command_line_srv 2>&1 | tee >> $TMP_FILE") } function run_sockperf_tc1 { prepare_sockperf_tc1_headlines TC1 save_coalesce_params update_coalesce_4_sockperf append_tmp_file_and_delete "$TMP_DIR/$log_file.prep" "$log_file" print_message "===========================>SOCKPERF TC1<==========================" "$log_file" local size_arr_len=${#SOCKPERF_MSG_SIZE[*]} local pps_arr_len=${#SOCKPERF_TC1_PPS_ARRAY[*]} sockperf_command_line_srv=${PREFIX}"${SOCKPERF_APP} server -i $MC_GROUP -p $PORT -m $MAX_SOCKPERF_MSG_SIZE" (echo ${SRV_CMMND_LINE_PREF}$sockperf_command_line_srv | tee -a $log_file) >& /dev/null (eval "$sockperf_command_line_srv 2>&1 | tee >> $log_file &") for((i=0; $i < $size_arr_len; i=$((i=$i+1)))) do for((j=0; $j < $pps_arr_len; j=$((j=$j+1)))) do curr_msg_size=${SOCKPERF_MSG_SIZE[$i]} curr_pps_value=${SOCKPERF_TC1_PPS_ARRAY[$j]} sockperf_tc1_cycle under-load ${curr_msg_size} ${curr_pps_value} sleep 5 parse_sockperf_tc1_test_results "${curr_msg_size}" "${curr_pps_value}" done done clean_after_sockperf recreate_coalesce_params tests_finish } function run_sockperf_tc9 { prepare_sockperf_tc1_headlines TC9 save_coalesce_params update_coalesce_4_sockperf append_tmp_file_and_delete "$TMP_DIR/$log_file.prep" "$log_file" print_message "===========================>SOCKPERF TC9<==========================" "$log_file" local size_arr_len=${#SOCKPERF_MSG_SIZE[*]} local pps_arr_len=${#SOCKPERF_TC1_PPS_ARRAY[*]} sockperf_command_line_srv=${PREFIX}"${SOCKPERF_APP} server -i $MC_GROUP -p $PORT -m $MAX_SOCKPERF_MSG_SIZE" (echo ${SRV_CMMND_LINE_PREF}$sockperf_command_line_srv | tee -a $log_file) >& /dev/null (eval "$sockperf_command_line_srv 2>&1 | tee >> $log_file &") for((i=0; $i < $size_arr_len; i=$((i=$i+1)))) do for((j=0; $j < $pps_arr_len; j=$((j=$j+1)))) do curr_msg_size=${SOCKPERF_MSG_SIZE[$i]} curr_pps_value=${SOCKPERF_TC1_PPS_ARRAY[$j]} sockperf_tc1_cycle ping-pong ${curr_msg_size} ${curr_pps_value} sleep 5 parse_sockperf_tc1_test_results "${curr_msg_size}" "${curr_pps_value}" done done clean_after_sockperf recreate_coalesce_params tests_finish } function run_sockperf_lat_with_diff_msg_len { prepare_sockperf_headlines save_coalesce_params update_coalesce_4_sockperf append_tmp_file_and_delete "$TMP_DIR/$log_file.prep" "$log_file" print_message "===========================>SOCKPERF<==========================" "$log_file" local size_arr_len=${#SOCKPERF_MSG_SIZE[*]} sockperf_command_line_srv=${PREFIX}"${SOCKPERF_APP} server -i $MC_GROUP -p $PORT -m $MAX_SOCKPERF_MSG_SIZE" (echo ${SRV_CMMND_LINE_PREF}$sockperf_command_line_srv | tee -a $log_file) >& /dev/null (eval "$sockperf_command_line_srv 2>&1 | tee >> $log_file &") for((i=0; $i < $size_arr_len; i=$((i=$i+1)))) do curr_msg_size=${SOCKPERF_MSG_SIZE[$i]} curr_pps_value="max" sockperf_lat_cycle sleep 5 parse_sockperf_test_results "${SOCKPERF_MSG_SIZE[$i]}" done clean_after_sockperf recreate_coalesce_params tests_finish } function run_sockperf_tx_bw_with_diff_msg_len { prepare_sockperf_tx_bw_headlines save_coalesce_params update_coalesce_4_tr_test append_tmp_file_and_delete "$TMP_DIR/$log_file.prep" "$log_file" print_message "========================>SOCKPERF TX BW<=======================" "$log_file" local size_arr_len=${#SOCKPERF_MSG_SIZE[*]} for((i=0; $i < $size_arr_len; i=$((i=$i+1)))) do curr_msg_size=${SOCKPERF_MSG_SIZE[$i]} curr_pps_value="max" sockperf_tx_bw_cycle sleep 5 parse_sockperf_tx_bw_test_results "${SOCKPERF_MSG_SIZE[$i]}" done clean_after_sockperf recreate_coalesce_params tests_finish } function run_sockperf_bw_with_diff_msg_len { prepare_sockperf_bw_headlines save_coalesce_params update_coalesce_4_tr_test append_tmp_file_and_delete "$TMP_DIR/$log_file.prep" "$log_file" print_message "========================>SOCKPERF BW<=========================" "$log_file" local size_arr_len=${#SOCKPERF_MSG_SIZE[*]} for((i=0; $i < $size_arr_len; i=$((i=$i+1)))) do curr_msg_size=${SOCKPERF_MSG_SIZE[$i]} curr_pps_value="max" sockperf_bw_cycle sleep 5 parse_sockperf_bw_test_results "${SOCKPERF_MSG_SIZE[$i]}" done clean_after_sockperf recreate_coalesce_params tests_finish } function run_sockperf_with_diff_burst_size { prepare_sockperf_sending_bursts_headlines save_coalesce_params update_coalesce_4_sockperf append_tmp_file_and_delete "$TMP_DIR/$log_file.prep" "$log_file" print_message "===================>SOCKPERF SENDING BURSTS<===================" "$log_file" local size_arr_len=${#SOCKPERF_BURST_SIZE[*]} local initial_rx_buffs_val=$VMA_RX_BUFS VMA_RX_BUFS=$VMA_RX_BUFS_MAX_VAL update_command_prefix sockperf_command_line_srv=${PREFIX}"${SOCKPERF_APP} server -i $MC_GROUP -p $PORT -m $MAX_SOCKPERF_MSG_SIZE" (echo ${SRV_CMMND_LINE_PREF}$sockperf_command_line_srv | tee -a $log_file) >& /dev/null (eval "$sockperf_command_line_srv 2>&1 | tee >> $log_file &") for((i=0; $i < $size_arr_len; i=$((i=$i+1)))) do curr_burst_size=${SOCKPERF_BURST_SIZE[$i]} curr_pps_value="max" sockperf_sending_bursts_cycle sleep 5 parse_sockperf_test_results "${SOCKPERF_BURST_SIZE[$i]}" done VMA_RX_BUFS=$initial_rx_buffs_val update_command_prefix clean_after_sockperf recreate_coalesce_params tests_finish } function run_sockperf_using_select_epoll_poll_with_zero_polling { local vma_select_poll_old=$VMA_SELECT_POLL vma_select_poll_info="" save_coalesce_params update_coalesce_4_sockperf append_tmp_file_and_delete "$TMP_DIR/$log_file.prep" "$log_file" print_message "===============>SOCKPERF Using Select/Poll/Epoll<==============" "$log_file" if [[ "$OVER_VMA" = yes ]]; then vma_select_poll_info="With VMA_SELECT_POLL=0" print_message "|----------------------------------|" "$log_file" print_message "|VMA_SELECT_POLL=0" "$log_file" print_message "|----------------------------------|" "$log_file" fi run_sockperf_using_select_epoll_poll_helper "$vma_select_poll_info" recreate_coalesce_params tests_finish } function save_shmem_prop { eval "save_local_hugetlb=`cat /proc/sys/vm/nr_hugepages 2>/dev/null`;save_local_shmax=`cat /proc/sys/kernel/shmmax 2>/dev/null`" eval "save_remote_hugetlb=`ssh $REM_HOST_IP 'cat /proc/sys/vm/nr_hugepages 2>/dev/null'`;save_remote_shmax=`ssh $REM_HOST_IP 'cat /proc/sys/kernel/shmmax 2>/dev/null'`" } function recreate_mem_prop { echo "" >> "$TMP_DIR/$log_file.post" echo "================>Recreate number of huge pages <==============" >> "$TMP_DIR/$log_file.post" command="sudo echo $save_local_hugetlb > /proc/sys/kernel/shmmax;sudo echo $save_local_shmax > /proc/sys/vm/nr_hugepages" (echo "${SRV_CMMND_LINE_PREF} $command" | tee -a "$TMP_DIR/$log_file.post") >& /dev/null eval "$command 2>&1 | tee >> $TMP_DIR/$log_file.post" command="sudo echo $save_remote_hugetlb > /proc/sys/kernel/shmmax;sudo echo $save_remote_shmax > /proc/sys/vm/nr_hugepages" (echo "${CLT_CMMND_LINE_PREF} $command" | tee -a "$TMP_DIR/$log_file.post") >& /dev/null eval "ssh $REM_HOST_IP "$command" 2>&1 | tee >> $TMP_DIR/$log_file.post" print_huge_tlb_info "${TMP_DIR}/${log_file}.post" eval "cat $TMP_DIR/$log_file.post" | tee -a $log_file >& /dev/null clean } function print_huge_tlb_info { local file=$1 echo "" >> "$file" echo "=======================>Huge pages info<======================" >> "$file" command="cat /proc/meminfo | grep -i HugePage" (echo "${SRV_CMMND_LINE_PREF} $command" | tee -a "$file") >& /dev/null eval "$command 2>&1 | tee >> $file" (echo "${CLT_CMMND_LINE_PREF} $command" | tee -a "$file") >& /dev/null eval "ssh $REM_HOST_IP "$command" 2>&1 | tee >> $file" } function increase_number_of_hugetlb { print_huge_tlb_info "${TMP_DIR}/${log_file}.prep" echo "" >> "$TMP_DIR/$log_file.prep" echo "================>Update number of huge pages <================" >> "$TMP_DIR/$log_file.prep" command="sudo echo 1000000000 > /proc/sys/kernel/shmmax;sudo echo 400 > /proc/sys/vm/nr_hugepages;cat /proc/meminfo | grep -i HugePage" (echo "${SRV_CMMND_LINE_PREF} $command" | tee -a "$TMP_DIR/$log_file.prep") >& /dev/null eval "$command 2>&1 | tee >> $TMP_DIR/$log_file.prep" (echo "${CLT_CMMND_LINE_PREF} $command" | tee -a "$TMP_DIR/$log_file.prep") >& /dev/null eval "ssh $REM_HOST_IP "$command" 2>&1 | tee >> $TMP_DIR/$log_file.prep" eval "cat $TMP_DIR/$log_file.prep" | tee -a $log_file >& /dev/null clean } function run_sockperf_using_select_epoll_poll_with_full_polling_vma_only { if [[ "$OVER_VMA" = yes ]]; then local vma_select_poll_old=$VMA_SELECT_POLL local vma_select_skip_os_old=$VMA_SELECT_SKIP_OS local vma_rx_skip_os_old=$VMA_RX_SKIP_OS local vma_rx_wre_old=$VMA_RX_WRE local vma_hugetlb_old=$VMA_HUGETLB vma_select_poll_info="" save_coalesce_params update_coalesce_4_sockperf append_tmp_file_and_delete "$TMP_DIR/$log_file.prep" "$log_file" change_command_prefix VMA_SELECT_POLL=$VMA_SELECT_POLL_MAX_VAL VMA_SELECT_SKIP_OS=$VMA_IOMUX_SELECT_SKIP_OS VMA_RX_WRE=$VMA_IOMUX_RX_WRE VMA_HUGETLB=$VMA_IOMUX_HUGETLB VMA_RX_SKIP_OS=$VMA_IOMUX_RX_SKIP_OS vma_select_poll_info="With VMA_SELECT_POLL=$VMA_SELECT_POLL_MAX_VAL" print_message "===============>SOCKPERF Using Select/Poll/Epoll<==============" "$log_file" print_message "|----------------------------------|" "$log_file" print_message "|VMA_SELECT_POLL=$VMA_SELECT_POLL_MAX_VAL" "$log_file" print_message "|----------------------------------|" "$log_file" run_sockperf_using_select_epoll_poll_helper "$vma_select_poll_info" change_command_prefix VMA_SELECT_POLL=$vma_select_poll_old VMA_SELECT_SKIP_OS=$vma_select_skip_os_old VMA_RX_WRE=$vma_rx_wre_old VMA_HUGETLB=$vma_hugetlb_old VMA_RX_SKIP_OS=$vma_rx_skip_os_old recreate_coalesce_params tests_finish fi } function run_sockperf_using_select_epoll_poll_helper { prepare_sockperf_using_feed_file_headlines "Select" "$1" run_sockperf_with_diff_mc_feed_files "s" "Select" prepare_sockperf_using_feed_file_headlines "Epoll" "$1" run_sockperf_with_diff_mc_feed_files "e" "Epoll " prepare_sockperf_using_feed_file_headlines "Poll" "$1" run_sockperf_with_diff_mc_feed_files "p" "Poll " } function run_sockperf_with_diff_mc_feed_files { local size_arr_len=${#MC_GROUP_SIZES[*]} print_sockperf_with_feed_files_header "$2" for((i=0; $i < $size_arr_len; i=$((i=$i+1)))) do curr_feed_file_size=${MC_GROUP_SIZES[$i]} feed_file_name="$TMP_DIR/feed_file_$curr_feed_file_size" print_cycle_info "$curr_feed_file_size" "mc group" create_mc_feed_files "$curr_feed_file_size" "$feed_file_name" run_sockperf_with_feed_file "$feed_file_name" "$1" parse_sockperf_test_results "${MC_GROUP_SIZES[$i]}" remove_mc_feed_files "$feed_file_name" done clean_after_sockperf } function run_sockperf_with_feed_file { sockperf_command_line_srv=${PREFIX}"${SOCKPERF_APP} server -i $MC_GROUP -p $PORT -f $1 -F $2" sockperf_command_line_clt=${PREFIX}"${SOCKPERF_APP} ping-pong -f $1 -F $2 -t $DURATION --pps=max" (echo ${SRV_CMMND_LINE_PREF}$sockperf_command_line_srv | tee -a $log_file) >& /dev/null (eval "$sockperf_command_line_srv 2>&1 | tee >> $log_file &") sleep 15 (ssh $REM_HOST_IP "killall sockperf") >& /dev/null (echo "${CLT_CMMND_LINE_PREF} $sockperf_command_line_clt" | tee -a "$TMP_DIR/$log_file.tmp") >& /dev/null (ssh $REM_HOST_IP "sleep 10;$sockperf_command_line_clt 2>&1 | tee >> $TMP_FILE") pkill -2 -f sockperf >& /dev/null sleep 5 } function print_sockperf_with_feed_files_header { print_message "=====================>SOCKPERF With $1<====================" "$log_file" } function tests_finish { eval "cat $TMP_DIR/$log_file.post" | tee -a $log_file >& /dev/null echo "---------------------------------------------------------------" |tee -a $log_file clean } function sockperf_tc1_cycle { print_cycle_info $2 "message" $3 "pps" (ssh $REM_HOST_IP "killall sockperf") >& /dev/null sockperf_command_line_clt=${PREFIX}"${SOCKPERF_APP} $1 -i $MC_GROUP -p $PORT -m $2 -t $DURATION --pps=$3" (echo "${CLT_CMMND_LINE_PREF} $sockperf_command_line_clt" | tee -a "$TMP_DIR/$log_file.tmp") >& /dev/null (ssh $REM_HOST_IP "sleep 10;$sockperf_command_line_clt 2>&1 | tee >> $TMP_FILE") } function sockperf_lat_cycle { print_cycle_info $curr_msg_size message (ssh $REM_HOST_IP "killall sockperf") >& /dev/null sockperf_command_line_clt=${PREFIX}"${SOCKPERF_APP} ping-pong -i $MC_GROUP -p $PORT -m $curr_msg_size -t $DURATION --pps=$curr_pps_value" (echo "${CLT_CMMND_LINE_PREF} $sockperf_command_line_clt" | tee -a "$TMP_DIR/$log_file.tmp") >& /dev/null (ssh $REM_HOST_IP "sleep 10;$sockperf_command_line_clt 2>&1 | tee >> $TMP_FILE") } function sockperf_tx_bw_cycle { print_cycle_info $curr_msg_size message (ssh $REM_HOST_IP "killall sockperf") >& /dev/null sockperf_command_line_clt=${PREFIX}"${SOCKPERF_APP} throughput -i $MC_GROUP -p $PORT -m $curr_msg_size -t $DURATION -A $ACTIVITY --pps=$curr_pps_value" (echo "${CLT_CMMND_LINE_PREF} $sockperf_command_line_clt" | tee -a "$TMP_DIR/$log_file.tmp") >& /dev/null (ssh $REM_HOST_IP "sleep 10;$sockperf_command_line_clt 2>&1 | tee >> $TMP_FILE") } function sockperf_bw_cycle { print_cycle_info $curr_msg_size message killall -9 sockperf >& /dev/null ssh $REM_HOST_IP killall -9 sockperf >& /dev/null sockperf_command_line_srv=${PREFIX}"${SOCKPERF_APP} server -i $MC_GROUP -p $PORT -m $curr_msg_size -A $ACTIVITY" sockperf_command_line_clt=${PREFIX}"${SOCKPERF_APP} throughput -i $MC_GROUP -p $PORT -m $curr_msg_size -t $DURATION -A $ACTIVITY --pps=$curr_pps_value" (echo ${SRV_CMMND_LINE_PREF}$sockperf_command_line_srv | tee -a $log_file) >& /dev/null (ssh $REM_HOST_IP "echo ${CLT_CMMND_LINE_PREF} $sockperf_command_line_clt | tee -a $TMP_DIR/$log_file.tmp") >& /dev/null (eval "$sockperf_command_line_srv 2>&1 | tee >> $log_file &") (ssh $REM_HOST_IP "killall sockperf") >& /dev/null (echo "${CLT_CMMND_LINE_PREF} $sockperf_command_line_clt" | tee -a "$TMP_DIR/$log_file.tmp") >& /dev/null (ssh $REM_HOST_IP "sleep 5;$sockperf_command_line_clt 2>&1 | tee >> $TMP_FILE") local wait_time=$DURATION let "wait_time += 20" sleep $wait_time killall -2 sockperf } function sockperf_sending_bursts_cycle { print_cycle_info $curr_burst_size burst (ssh $REM_HOST_IP "killall sockperf") >& /dev/null sockperf_command_line_clt=${PREFIX}"${SOCKPERF_APP} ping-pong -i $MC_GROUP -p $PORT -t $DURATION -b $curr_burst_size --pps=$curr_pps_value" (echo "${CLT_CMMND_LINE_PREF} $sockperf_command_line_clt" | tee -a "$TMP_DIR/$log_file.tmp") >& /dev/null (ssh $REM_HOST_IP "sleep 10;$sockperf_command_line_clt 2>&1 | tee >> $TMP_FILE") } function print_cycle_info { let "cycle_i=$i+1" if [[ -n "$3" ]]; then let "cycle_j=$j+1" echo "##################### cycle [$cycle_i][$cycle_j] of [$size_arr_len][$pps_arr_len] #####################" elif [[ -n "$1" ]]; then echo "##################### cycle [$cycle_i] of [$size_arr_len] #####################" fi if [[ -n "$1" ]]; then echo "#$2 size is $1" fi if [[ -n "$3" ]]; then echo "#$4 is $3" fi } function parse_iperf_test_results { local start_time=0 local end_time=0 local warning_msg="" check_iperf_succss if [[ $success -eq $TRUE ]]; then loss=`cat $TMP_FILE | grep % | tail -1 | tr " " "\n" | tail -1 | tr -d '(-)'` avg_pps=`cat $TMP_FILE | grep % | tail -1 | tr "-" " " | tr -s " " | tr '/' '\n' | tail -1 | tr " " '\n' | tail -2 | head -1` #avg_pps=`cat $TMP_FILE | grep % | tail -1 | tr "-" " " | tr -s " " | cut --d=" " -f 12 | cut -d "/" -f 2` start_time=`cat $TMP_FILE|grep %|tail -1|tr "-" " "|tr -s " " | cut --d=" " -f 3 | cut --d="." -f 1` end_time=`cat $TMP_FILE|grep %|tail -1|tr "-" " "|tr -s " " | cut --d=" " -f 4 | cut --d="." -f 1` let "actual_duration=$end_time-$start_time" let "avg_pps=avg_pps/$actual_duration" avg_bw=`cat $TMP_FILE | grep % | tail -1 | tr "-" " " | tr -s " " | cut --d=" " -f 8` echo "#average loss is $loss" echo "#average BW is $avg_bw MBps" echo "#average packet rate is $avg_pps pps" if [[ "$actual_duration" -ne $DURATION ]]; then warning_msg="#vma_perf_envelope:WARNING:missing summarize in iperf" echo "$warning_msg" warning_msg=",$warning_msg" fi echo "${IPERF_MSG_SIZE[$i]},$avg_bw,$loss,${avg_pps}${warning_msg}" >> $res_file else echo "#$ERROR_MESSAGE" echo "${IPERF_MSG_SIZE[$i]},${ERROR_RESULT},${ERROR_RESULT},${ERROR_RESULT}" >> $res_file fi cat $TMP_FILE | tee -a $log_file >& /dev/null rm -rf $TMP_FILE >& /dev/null } function parse_sockperf_tc1_test_results { check_sockperf_succss latency $TMP_FILE if [[ $success -eq $TRUE ]]; then total=`ssh $REM_HOST_IP cat $TMP_FILE |tr A-Z a-z|grep total|tr [="="=] " " |tr -s " "|tr " " "\n"|head -3|tail -1` avg_latency=`ssh $REM_HOST_IP cat $TMP_FILE |tr A-Z a-z|grep latency|tr [="="=] " " |tr -s " "|tr " " "\n"|tail -2|head -1` stddev_latency=`ssh $REM_HOST_IP cat $TMP_FILE |tr A-Z a-z|grep avg-lat|tr [="="=] " " |tr -s " "|tr " " "\n"|tr [=")"=] " "|tail -1` max_latency=`ssh $REM_HOST_IP cat $TMP_FILE |tr A-Z a-z|grep ''|tr [="="=] " " |tr -s " "|tr " " "\n"|tail -1` min_latency=`ssh $REM_HOST_IP cat $TMP_FILE |tr A-Z a-z|grep ''|tr [="="=] " " |tr -s " "|tr " " "\n"|tail -1` percentile_99=`ssh $REM_HOST_IP cat $TMP_FILE |tr A-Z a-z|grep '99.00'|tr [="="=] " " |tr -s " "|tr " " "\n"|tail -1` percentile_99_9=`ssh $REM_HOST_IP cat $TMP_FILE |tr A-Z a-z|grep '99.90'|tr [="="=] " " |tr -s " "|tr " " "\n"|tail -1` percentile_50=`ssh $REM_HOST_IP cat $TMP_FILE |tr A-Z a-z|grep '50.00'|tr [="="=] " " |tr -s " "|tr " " "\n"|tail -1` echo "#total $total observations" echo "#average latency is $avg_latency usec" echo "#std-dev latency is $stddev_latency usec" echo "#min latency is $min_latency usec" echo "#max latency is $max_latency usec" echo "#50.0% percentille is $percentile_50 usec" echo "#99.0% percentille is $percentile_99 usec" echo "#99.9% percentille is $percentile_99_9 usec" echo $1,$2,$avg_latency,$stddev_latency,$min_latency,$max_latency,$percentile_50,$percentile_99,$percentile_99_9,$total >> $res_file else echo "#$ERROR_MESSAGE" echo "$1,$2,${ERROR_RESULT},${ERROR_RESULT},${ERROR_RESULT},${ERROR_RESULT},${ERROR_RESULT},${ERROR_RESULT},${ERROR_RESULT},${ERROR_RESULT}" >> $res_file fi ssh $REM_HOST_IP "cat $TMP_FILE" | tee -a "$TMP_DIR/$log_file.tmp" >& /dev/null ssh $REM_HOST_IP "rm -rf $TMP_FILE" >& /dev/null } function parse_sockperf_test_results { check_sockperf_succss latency $TMP_FILE if [[ $success -eq $TRUE ]]; then latency=`ssh $REM_HOST_IP cat $TMP_FILE |tr A-Z a-z|grep latency|tr [="="=] " " |tr -s " "|tr " " "\n"|tail -2|head -1` echo "#average latency is $latency usec" echo $1,$latency >> $res_file else echo "#$ERROR_MESSAGE" echo "$1,${ERROR_RESULT}" >> $res_file fi ssh $REM_HOST_IP "cat $TMP_FILE" | tee -a "$TMP_DIR/$log_file.tmp" >& /dev/null ssh $REM_HOST_IP "rm -rf $TMP_FILE" >& /dev/null } function parse_sockperf_tx_bw_test_results { check_sockperf_succss rate $TMP_FILE if [[ $success -eq $TRUE ]]; then local pps=`ssh $REM_HOST_IP cat $TMP_FILE |tr A-Z a-z|tail -2|grep "rate"| tr -s " " |cut -d " " -f 6` local bw=`ssh $REM_HOST_IP cat $TMP_FILE |tr A-Z a-z|tail -2|grep "bandwidth"| tr -s " " |cut -d " " -f 5` echo "#average message rate is $pps [msg/sec]" echo "#average bw is $bw MBps" echo $1,$pps,$bw >> $res_file else echo "#$ERROR_MESSAGE" echo "$1,${ERROR_RESULT}" >> $res_file fi ssh $REM_HOST_IP "cat $TMP_FILE" | tee -a "$TMP_DIR/$log_file.tmp" >& /dev/null ssh $REM_HOST_IP "rm -rf $TMP_FILE" >& /dev/null } function parse_sockperf_bw_test_results { check_sockperf_succss total $log_file if [[ $success -eq $TRUE ]]; then local pps=`ssh $REM_HOST_IP cat $TMP_FILE |tr A-Z a-z|tail -2|grep "rate"| tr -s " " |cut -d " " -f 6` local bw=`ssh $REM_HOST_IP cat $TMP_FILE |tr A-Z a-z|tail -2|grep "bandwidth"| tr -s " " |cut -d " " -f 5` local rx_recived=`cat $log_file| grep received |tail -1|tr -s " "|cut -d " " -f 4` local tx_send=`ssh $REM_HOST_IP cat $TMP_FILE| grep sent| tail -1 |tr -s " "| cut -d " " -f 4` local diff=$(($tx_send-$rx_recived)) if [ $diff -lt 0 ]; then diff=0 fi local loss=$(echo "scale=5;($diff/$tx_send)*100"| bc) if [[ $loss =~ "^\." ]]; then loss="0${loss}" fi local d_point=`expr index $loss "\."` d_point=$(($d_point+3)) loss=`expr substr $loss 1 $d_point` echo "#message rate is $pps [msg/sec]" echo "#bw is $bw MBps" echo "#packet loss is ${loss}%" echo $1,$pps,$bw,$loss >> $res_file else echo "#$ERROR_MESSAGE" echo "$1,${ERROR_RESULT}" >> $res_file fi ssh $REM_HOST_IP "cat $TMP_FILE" | tee -a "$TMP_DIR/$log_file.tmp" >& /dev/null ssh $REM_HOST_IP "rm -rf $TMP_FILE" >& /dev/null } function check_sockperf_succss { local res=0 local look_for=$1 local res_file=$2 if [ $res_file = $log_file ]; then res=`cat $res_file |tr A-Z a-z |grep $look_for | wc -l` else res=`ssh $REM_HOST_IP "cat $res_file |tr A-Z a-z |grep $look_for | wc -l"` fi if [[ $res -gt 0 ]]; then success=$TRUE else success=$FALSE fi } function check_iperf_succss { local res=0 res=`cat $TMP_FILE | grep % | wc -l` if [ $res -gt 0 ]; then success=$TRUE else success=$FALSE fi } function prepare_output_files { date=`date +%Y_%m_%d_%H_%M_%S` log_file="${OUTPUT_FILES_PATH}vma_perf_${date}_logs.txt" res_file="${OUTPUT_FILES_PATH}vma_perf_${date}_results.csv" touch $log_file touch $res_file } function prepare_iperf_headlines { echo "" >> $res_file echo Iperf Test Results >> $res_file echo Msg size,Averag RX BW,Average Loss,Packet Rate >> $res_file } function prepare_sockperf_tc1_headlines { echo "" >> $res_file echo $1 Test Results >> $res_file echo Message size,PPS,Average Latency,Max Latency,Min Latency,99% percentile,50% percentile,Total observations >> $res_file } function prepare_sockperf_headlines { echo "" >> $res_file echo SockPerf Test Results >> $res_file echo Message size,Latency >> $res_file } function prepare_sockperf_tx_bw_headlines { echo "" >> $res_file echo SockPerf TX BW Test Results >> $res_file echo Msg size,TX Packet Rate,TX BW >> $res_file } function prepare_sockperf_bw_headlines { echo "" >> $res_file echo SockPerf BW Test Results >> $res_file echo Msg size,TX Packet Rate,TX BW,RX Average Loss %>> $res_file } function prepare_sockperf_sending_bursts_headlines { echo "" >> $res_file echo SockPerf Sending Bursts Test Results >> $res_file echo Burst size,Latency >> $res_file } function prepare_sockperf_using_feed_file_headlines { echo "" >> $res_file echo SockPerf Using $1 $2 Test Results >> $res_file echo MC Group Num,Latency >> $res_file } function update_command_line_pref_in_log_file { SRV_CMMND_LINE_PREF="[$srv_hostname "`pwd`"]" CLT_CMMND_LINE_PREF="[$clt_hostname "`ssh $REM_HOST_IP pwd`"]" } function get_hostnames { clt_hostname=`ssh $REM_HOST_IP hostname` srv_hostname=`hostname` update_command_line_pref_in_log_file } function update_vma_igmp_flag { check_if_infbnd_iface if [[ $is_infiniband -eq $FALSE ]]; then VMA_IGMP_ENABLE=1 fi } function update_command_prefix { PREFIX="" update_vma_igmp_flag if [[ "$OVER_VMA" = yes ]] ; then if [[ $VMA_IGMP_ENABLE -ne $DEFAULT_VMA_IGMP_ENABLE ]] ; then PREFIX="$PREFIX VMA_IGMP=$VMA_IGMP_ENABLE " fi if [[ $VMA_SELECT_POLL -ne $DEFAULT_VMA_SELECT_POLL ]] ; then PREFIX="$PREFIX VMA_SELECT_POLL=$VMA_SELECT_POLL " fi if [[ $VMA_RX_SKIP_OS -ne $DEFAULT_VMA_RX_SKIP_OS ]] ; then PREFIX="$PREFIX VMA_RX_SKIP_OS=$VMA_RX_SKIP_OS " fi if [[ $VMA_RX_BUFS -ne $DEFAULT_VMA_RX_BUFS ]] ; then PREFIX="$PREFIX VMA_RX_BUFS=$VMA_RX_BUFS " fi if [[ $VMA_THREAD_MODE -ne $DEFAULT_VMA_THREAD_MODE ]] ; then PREFIX="$PREFIX VMA_THREAD_MODE=$VMA_THREAD_MODE " fi if [[ $VMA_RX_WRE -ne $DEFAULT_VMA_RX_WRE ]] ; then PREFIX="$PREFIX VMA_RX_WRE=$VMA_RX_WRE " fi if [[ $VMA_SELECT_SKIP_OS -ne $DEFAULT_VMA_SELECT_SKIP_OS ]] ; then PREFIX="$PREFIX VMA_SELECT_SKIP_OS=$VMA_SELECT_SKIP_OS " fi if [[ $VMA_HUGETLB -ne $DEFAULT_VMA_HUGETLB ]] ; then PREFIX="$PREFIX VMA_HUGETLB=$VMA_HUGETLB " fi PREFIX=${PREFIX}"LD_PRELOAD=$VMA_LIB " fi } function change_command_prefix { for curr in $*; do eval "$curr" done; update_command_prefix } function remove_ifaces { add_curr_route_table_2_log iface_arr_local=`route | grep 2[24][40].0.0.0 | tr -s ' ' | cut -d ' ' -f 8` iface_arr_remote=`ssh $REM_HOST_IP "route | grep 2[24][40].0.0.0 | tr -s ' ' | cut -d ' ' -f 8"` echo "" >> "$TMP_DIR/$log_file.prep" echo "============>Remove interfaces from route table <=============" >> "$TMP_DIR/$log_file.prep" for iface in $iface_arr_local do command="sudo route del -net $DST_NET netmask $DST_MASK dev $iface" (echo "${SRV_CMMND_LINE_PREF} $command" | tee -a $TMP_DIR/$log_file.prep) >& /dev/null eval "$command 2>&1 | tee >> $TMP_DIR/$log_file.prep" done for iface in $iface_arr_remote do command="sudo route del -net $DST_NET netmask $DST_MASK dev $iface" (echo "${CLT_CMMND_LINE_PREF} $command" | tee -a "$TMP_DIR/$log_file.prep") >& /dev/null eval "ssh $REM_HOST_IP "$command" 2>&1 | tee >> $TMP_DIR/$log_file.prep" done } function add_curr_route_table_2_log { (echo "${SRV_CMMND_LINE_PREF} route" | tee -a "$TMP_DIR/$log_file.prep") >& /dev/null eval "route 2>&1 | tee >> $TMP_DIR/$log_file.prep" (echo "${CLT_CMMND_LINE_PREF} route" | tee -a "$TMP_DIR/$log_file.prep") >& /dev/null eval "ssh $REM_HOST_IP "route" 2>&1 | tee >> $TMP_DIR/$log_file.prep" } function recreate_route_table { echo "" >> "$TMP_DIR/$log_file.post" echo "===================>Recreate route table <====================" >> "$TMP_DIR/$log_file.post" command="sudo route del -net $DST_NET netmask $DST_MASK dev $INTERFACE" (echo "${SRV_CMMND_LINE_PREF} $command" | tee -a "$TMP_DIR/$log_file.post") >& /dev/null eval "$command 2>&1 | tee >> $TMP_DIR/$log_file.post" (echo "${CLT_CMMND_LINE_PREF} $command" | tee -a "$TMP_DIR/$log_file.post") >& /dev/null ssh $REM_HOST_IP "$command" 2>&1 | tee >> "$TMP_DIR/$log_file.post" for iface in $iface_arr_local do command="sudo route add -net $DST_NET netmask $DST_MASK dev $iface" (echo "${SRV_CMMND_LINE_PREF} $command" | tee -a "$TMP_DIR/$log_file.post") >& /dev/null eval "$command 2>&1 | tee >> $TMP_DIR/$log_file.post" done for iface in $iface_arr_remote do command="sudo route add -net $DST_NET netmask $DST_MASK dev $iface" (echo "${CLT_CMMND_LINE_PREF} $command" | tee -a "$TMP_DIR/$log_file.post") >& /dev/null (eval "ssh $REM_HOST_IP "$command" 2>&1 | tee >> $TMP_DIR/$log_file.post") >& /dev/null done eval "cat $TMP_DIR/$log_file.post" | tee -a $log_file >& /dev/null clean } function prepare_route_table { echo "" >> "$TMP_DIR/$log_file.prep" echo "=====================>Route table info <======================" >> "$TMP_DIR/$log_file.prep" remove_ifaces echo "" >> "$TMP_DIR/$log_file.prep" echo "============>Add work interface to route table <==============" >> "$TMP_DIR/$log_file.prep" command="sudo route add -net $DST_NET netmask $DST_MASK dev $INTERFACE" (echo "${SRV_CMMND_LINE_PREF} $command" | tee -a "$TMP_DIR/$log_file.prep") >& /dev/null eval "$command 2>&1 | tee >> $TMP_DIR/$log_file.prep" (echo "${CLT_CMMND_LINE_PREF} $command" | tee -a "$TMP_DIR/$log_file.prep") >& /dev/null eval "ssh $REM_HOST_IP "$command" 2>&1 | tee >> $TMP_DIR/$log_file.prep" eval "cat $TMP_DIR/$log_file.prep" | tee -a $log_file >& /dev/null clean } function save_coalesce_params { local_coalesce_params_saved=$TRUE remote_coalesce_params_saved=$TRUE command1="sudo ethtool -c $INTERFACE" echo "" >> "$TMP_DIR/$log_file.prep" echo "===================>Coalesce params info<=====================" >> "$TMP_DIR/$log_file.prep" save_local_coalesce_params "$command1" rx-frames: initial_rx_frames_local save_remote_coalesce_params "$command1" rx-frames: initial_rx_frames_remote save_local_coalesce_params "$command1" rx-usecs: initial_rx_usecs_local save_remote_coalesce_params "$command1" rx-usecs: initial_rx_usecs_remote rm -f $TMP_FILE >& /dev/null rm -f $TMP_FILE.err >& /dev/null } function save_local_coalesce_params { (echo "${SRV_CMMND_LINE_PREF} $1" | tee -a "$TMP_DIR/$log_file.prep") >& /dev/null eval "$1 $COMMAND_REDIRECT" check_succsess_and_save_param $2 get_coalesce_param eval "$3=$?" if [[ $SUCCSESS -eq $FALSE ]] ;then local_coalesce_params_saved=$FALSE fi } function save_remote_coalesce_params { (echo "${CLT_CMMND_LINE_PREF} $1" | tee -a "$TMP_DIR/$log_file.prep") >& /dev/null eval "(ssh $REM_HOST_IP "$1") $COMMAND_REDIRECT" check_succsess_and_save_param $2 get_coalesce_param eval "$3=$?" if [[ $SUCCSESS -eq $FALSE ]]; then remote_coalesce_params_saved=$FALSE fi } function get_coalesce_param { ret_val=`cat $TMP_FILE | grep $1 | cut -d " " -f 2 2>/dev/null` } function get_umcast_val { umcast_val=`cat $TMP_FILE | tr -d "\n" 2>/dev/null` } function update_coalesce_4_sockperf { local_coalesce_params_changed=$FALSE remote_coalesce_params_changed=$FALSE echo "" >> "$TMP_DIR/$log_file.prep" echo "============>Prepare coalesce params for sockperf<=============" >> "$TMP_DIR/$log_file.prep" check_if_infbnd_iface if [[ $is_infiniband -eq $TRUE ]]; then update_coalesce_params $RX_FRAMES_IB_LATENCY $RX_USEC_IB_LATENCY $RX_ADAPTIVE_IB_LATENCY else update_coalesce_params $RX_FRAMES_ETH_LATENCY $RX_USEC_ETH_LATENCY $RX_ADAPTIVE_ETH_LATENCY fi } function update_coalesce_4_tr_test { local_coalesce_params_changed=$FALSE remote_coalesce_params_changed=$FALSE echo "" >> "$TMP_DIR/$log_file.prep" echo "========>Prepare coalesce params for throughput test<=========" >> "$TMP_DIR/$log_file.prep" check_if_infbnd_iface if [[ $is_infiniband -eq $TRUE ]]; then update_coalesce_params $RX_FRAMES_IB_THROUGHPUT $RX_USEC_IB_THROUGHPUT $RX_ADAPTIVE_IB_THROUGHPUT else update_coalesce_params $RX_FRAMES_ETH_THROUGHPUT $RX_USEC_ETH_THROUGHPUT $RX_ADAPTIVE_ETH_THROUGHPUT fi } function update_coalesce_params { local rx_frames_val=$1 local rx_usecs_val=$2 local rx_adaptive_val=$3 update_coalesce_param rx-frames $rx_frames_val update_coalesce_param rx-usecs $rx_usecs_val update_coalesce_param adaptive-rx $rx_adaptive_val } function update_coalesce_param { local param_name=$1 local param_val=$2 command="sudo ethtool -C $INTERFACE $param_name $param_val" if [[ $local_coalesce_params_saved -eq $TRUE ]]; then if [[ $initial_rx_frames_local -ne $1 ]]; then update_local_coalesce_params fi fi if [[ $remote_coalesce_params_saved -eq $TRUE ]]; then if [[ $initial_rx_frames_remote -ne $1 ]]; then update_remote_coalesce_params fi fi } function update_local_coalesce_params { (echo "${SRV_CMMND_LINE_PREF} $command" | tee -a "$TMP_DIR/$log_file.prep") >& /dev/null eval "$command $COMMAND_REDIRECT" check_command_succss if [[ $SUCCSESS -eq $TRUE ]]; then local_coalesce_params_changed=$TRUE else local_coalesce_params_changed=$FALSE fi } function update_remote_coalesce_params { (echo "${CLT_CMMND_LINE_PREF} $command" | tee -a "$TMP_DIR/$log_file.prep") >& /dev/null eval "(ssh $REM_HOST_IP "$command") $COMMAND_REDIRECT" check_command_succss if [[ $SUCCSESS -eq $TRUE ]]; then remote_coalesce_params_changed=$TRUE else remote_coalesce_params_changed=$FALSE fi } function recreate_coalesce_params { echo "" >> "$TMP_DIR/$log_file.post" echo "==================>Recreate coalesce params<==================" >> "$TMP_DIR/$log_file.post" if [[ $local_coalesce_params_changed -eq $TRUE ]]; then recreate_local_coalesce_params fi if [[ $remote_coalesce_params_changed -eq $TRUE ]]; then recreate_remote_coalesce_params fi } function recreate_local_coalesce_params { local command="sudo ethtool -C $INTERFACE adaptive-rx $initial_adaptive-rx_local rx-frames $initial_rx_frames_local rx-usecs $initial_rx_usecs_local" (echo "${SRV_CMMND_LINE_PREF} $command" | tee -a "$TMP_DIR/$log_file.post") >& /dev/null eval $command >& /dev/null } function recreate_remote_coalesce_params { local command="sudo ethtool -C $INTERFACE adaptive-rx $initial_adaptive-rx_remote rx-frames $initial_rx_frames_remote rx-usecs $initial_rx_usecs_remote" (echo "${CLT_CMMND_LINE_PREF} $command" | tee -a "$TMP_DIR/$log_file.post") >& /dev/null ssh $REM_HOST_IP "$command" >& /dev/null } function save_umcast { local_umcast_saved=$FALSE remote_umcast_saved=$FALSE echo "" >> "$TMP_DIR/$log_file.prep" echo "========================>Umcast info<=========================" >> "$TMP_DIR/$log_file.prep" check_if_infbnd_iface if [[ "$OVER_VMA" = not ]]; then UMCAST_VAL=0 fi if [[ $is_infiniband -eq $TRUE ]]; then save_local_umcast_val save_remote_umcast_val fi eval "cat $TMP_DIR/$log_file.prep" | tee -a $log_file >& /dev/null clean } function save_local_umcast_val { local command="cat /sys/class/net/$INTERFACE/umcast" (echo "${SRV_CMMND_LINE_PREF} $command" | tee -a "$TMP_DIR/$log_file.prep") >& /dev/null eval "cat /sys/class/net/$INTERFACE/umcast 1>$TMP_FILE 2>$TMP_FILE.err " check_succsess_and_save_param initial_local_umcast_val get_umcast_val if [[ $SUCCSESS -eq $FALSE ]]; then local_umcast_saved=$FALSE else initial_local_umcast_val=$umcast_val local_umcast_saved=$TRUE fi } function save_remote_umcast_val { local command="cat /sys/class/net/$INTERFACE/umcast" (echo "${CLT_CMMND_LINE_PREF} $command" | tee -a "$TMP_DIR/$log_file.prep") >& /dev/null (eval "ssh $REM_HOST_IP cat /sys/class/net/$INTERFACE/umcast") 1>$TMP_FILE 2>$TMP_FILE.err check_succsess_and_save_param initial_remote_umcast_val get_umcast_val if [[ $SUCCSESS -eq $FALSE ]]; then remote_umcast_saved=$FALSE else initial_remote_umcast_val=$umcast_val remote_umcast_saved=$TRUE fi } function update_umcast { echo "" >> "$TMP_DIR/$log_file.prep" echo "===================>Prepare umcast param<====================" >> "$TMP_DIR/$log_file.prep" local_umcast_changed=$FALSE remote_umcast_changed=$FALSE if [[ $initial_local_umcast_val -ne $UMCAST_VAL ]]; then update_local_umcast fi if [[ $initial_remote_umcast_val -ne $UMCAST_VAL ]]; then update_remote_umcast fi eval "cat $TMP_DIR/$log_file.prep" | tee -a $log_file >& /dev/null clean } function update_local_umcast { local command="echo $UMCAST_VAL 1>&/sys/class/net/$INTERFACE/umcast" if [[ $local_umcast_saved -eq $TRUE ]]; then (echo "${SRV_CMMND_LINE_PREF} $command" | tee -a "$TMP_DIR/$log_file.prep") >& /dev/null eval "$command 1>$TMP_FILE 2>$TMP_FILE.err" check_command_succss if [[ $SUCCSESS -eq $TRUE ]]; then local_umcast_changed=$TRUE else local_umcast_changed=$FALSE fi fi } function update_remote_umcast { local command="echo $UMCAST_VAL 1>&/sys/class/net/$INTERFACE/umcast" if [[ $local_umcast_saved -eq $TRUE ]]; then (echo "${CLT_CMMND_LINE_PREF} $command" | tee -a "$TMP_DIR/$log_file.prep") >& /dev/null ssh $REM_HOST_IP "$command" | eval "1>$TMP_FILE 2>$TMP_FILE.err " check_command_succss if [[ $SUCCSESS -eq $TRUE ]]; then remote_umcast_changed=$TRUE else remote_umcast_changed=$FALSE fi fi } function recreate_umcast { echo "" >> "$TMP_DIR/$log_file.post" echo "====================>Recreate umcast value<===================" >> "$TMP_DIR/$log_file.post" if [[ $local_umcast_changed -eq $TRUE ]]; then recreate_local_umcast_val fi if [[ $remote_umcast_changed -eq $TRUE ]]; then recreate_remote_umcast_val fi eval "cat $TMP_DIR/$log_file.post" | tee -a $log_file >& /dev/null } function recreate_local_umcast_val { local command="echo $initial_local_umcast_val 1>&/sys/class/net/$INTERFACE/umcast" (echo "${SRV_CMMND_LINE_PREF} $command" | tee -a "$TMP_DIR/$log_file.post") >& /dev/null eval "$command" >& /dev/null } function recreate_remote_umcast_val { local command="echo $initial_remote_umcast_val 1>&/sys/class/net/$INTERFACE/umcast" (echo "${CLT_CMMND_LINE_PREF} $command" | tee -a "$TMP_DIR/$log_file.post") >& /dev/null ssh $REM_HOST_IP $command >& /dev/null } function clean_after_iperf { killall iperf >& /dev/null ssh $REM_HOST_IP killall iperf >& /dev/null ssh $REM_HOST_IP "cat $TMP_DIR/$log_file.tmp" | tee -a $log_file >& /dev/null ssh $REM_HOST_IP rm -f "$TMP_DIR/$log_file.tmp" >& /dev/null rm -f $TMP_FILE.err >& /dev/null rm -f "$TMP_DIR/$log_file.prep" >& /dev/null } function clean_after_sockperf { ssh $REM_HOST_IP killall sockperf >& /dev/null pkill -2 -f sockperf >& /dev/null sleep 10 cat "$TMP_DIR/$log_file.tmp" | tee -a $log_file >& /dev/null rm -f "$TMP_DIR/$log_file.tmp" >& /dev/null } function collect_nodes_info_to_file { collect_local_node_info_to_file "$1" collect_remote_node_info_to_file "$1" } function collect_local_node_info_to_file { (echo "======================>Local node info<======================" | tee -a $1) >& /dev/null (echo "--------------------" | tee -a $1) >& /dev/null (hostname | tee -a $1) >& /dev/null (echo -n "OS: " >> $1;cat /etc/issue | grep We | tee -a $1) >& /dev/null (echo -n "CPU: " >> $1;cat /proc/cpuinfo | grep 'model name' | sort -u | awk '{print $4, $5, $6, $7, $9}' | tee -a $1) >& /dev/null (echo -n "Number of CPUs: " >> $1;cat /proc/cpuinfo |grep proce |wc |awk '{print $1}' | tee -a $1) >& /dev/null (echo -n "CPU Type: " >> $1;uname -a | awk '{print $12}' | tee -a $1) >& /dev/null (cat /proc/meminfo |grep [M,m]em | tee -a $1) >& /dev/null (echo -n "Kernel: " >> $1;uname -a | awk '{print $3}' | tee -a $1) >& /dev/null (cat /usr/voltaire/version | tee -a $1) >& /dev/null (ibstat | grep -e "CA type" -e "Firmware version" | tee -a $1) >& /dev/null (ibstatus | grep -e rate -e state | grep -v 'phys state' | tee -a $1) >& /dev/null check_if_infbnd_iface if [[ $is_infiniband -eq $TRUE ]]; then (echo -n "IPoIB mode: " >> $1 ; cat "/sys/class/net/$INTERFACE/mode" | tee -a $1) >& /dev/null fi (ifconfig $INTERFACE | grep MTU | awk '{print $5}' | tee -a $1) >& /dev/null (echo -n "OFED:" >> $1;ofed_info | head -6 | grep OFED | tee -a $1) >& /dev/null (echo -n "VMA:" >> $1;rpm -qa | grep $VMA | tee -a $1) >& /dev/null } function collect_remote_node_info_to_file { (echo "=====================>Remote node info<======================" | tee -a $1) >& /dev/null (echo "--------------------" | tee -a $1) >& /dev/null (ssh $REM_HOST_IP "hostname" | tee -a $1) >& /dev/null (echo -n "OS: " >> $1;ssh $REM_HOST_IP cat /etc/issue | grep We | tee -a $1) >& /dev/null (echo -n "CPU: " >> $1;ssh $REM_HOST_IP cat /proc/cpuinfo | grep 'model name' | sort -u | awk '{print $4, $5, $6, $7, $9}' | tee -a $1) >& /dev/null (echo -n "Number of CPUs: " >> $1;ssh $REM_HOST_IP cat /proc/cpuinfo |grep proce |wc |awk '{print $1}' | tee -a $1) >& /dev/null (echo -n "CPU Type: " >> $1;ssh $REM_HOST_IP uname -a | awk '{print $12}' | tee -a $1) >& /dev/null (ssh $REM_HOST_IP cat /proc/meminfo |grep [M,m]em | tee -a $1) >& /dev/null (echo -n "Kernel: " >> $1;ssh $REM_HOST_IP uname -a | awk '{print $3}' | tee -a $1) >& /dev/null (ssh $REM_HOST_IP "cat /usr/voltaire/version" | tee -a $1) >& /dev/null (ssh $REM_HOST_IP "ibstat | grep -e "CA type" -e 'Firmware version'" | tee -a $1) >& /dev/null (ssh $REM_HOST_IP "ibstatus | grep -e rate -e state | grep -v 'phys state'" | tee -a $1) >& /dev/null to_print="/sys/class/net/$INTERFACE/mode" check_if_infbnd_iface if [[ $is_infiniband -eq $TRUE ]]; then (echo -n "IPoIB mode: " >> $1 ;ssh $REM_HOST_IP "cat $to_print" | tee -a $1) >& /dev/null fi (ssh $REM_HOST_IP ifconfig $INTERFACE | grep MTU | awk '{print $5}' | tee -a $1) >& /dev/null (echo -n "OFED:" >> $1;ssh $REM_HOST_IP ofed_info | head -6 | grep OFED | tee -a $1) >& /dev/null (echo -n "VMA:" >> $1;ssh $REM_HOST_IP rpm -qa | grep $VMA | tee -a $1) >& /dev/null } function print_message { echo $1 | tee -a $2 echo ""| tee -a $2 } function append_tmp_file_and_delete { cat $1 | tee -a $2 >& /dev/null rm -f $1 } function check_command_succss { if [ -s $TMP_FILE.err ]; then eval "cat $TMP_FILE.err 2>&1 | tee >> $TMP_DIR/$log_file.prep" LAST_ERROR=`cat $TMP_FILE.err` SUCCSESS=$FALSE else if [ -s $TMP_FILE ]; then eval "cat $TMP_FILE 2>&1 | tee >> $TMP_DIR/$log_file.prep" fi SUCCSESS=$TRUE fi rm -f $TMP_FILE.err >& /dev/null } function check_succsess_and_save_param { local ret_val=0 check_command_succss if [[ $SUCCSESS -eq $TRUE ]]; then $2 $1 fi return $ret_val } function check_if_infbnd_iface { is_infiniband=$FALSE if [[ $INTERFACE =~ "ib*" ]]; then is_infiniband=$TRUE fi } function discover_local_work_if_ip { LOCAL_IP=`ifconfig $INTERFACE | grep inet |grep -v inet6 | cut -d ':' -f 2| cut -d " " -f 1` >& /dev/null } function calc_file_age { creation_time=`stat -c %Z /tmp/vma_utils_block_file` now=`date +%s` block_file_age=$(($now-$creation_time)) } function get_operator_pid { pid=$$ } function write_to_file_operator_details { operating_machine_hostname=`hostname` get_operator_pid rm -f "$2" >& /dev/null touch "$2" >& /dev/null echo -n "$1 " >> "$2" 2>/dev/null echo -n "$pid " >> "$2" 2>/dev/null echo -n "$script_name " >> "$2" 2>/dev/null echo -n "$user_name " >> "$2" 2>/dev/null echo -n "$user_id " >> "$2" 2>/dev/null echo -n "$operating_machine_hostname " >> "$2" 2>/dev/null if [[ $1 == "local" ]]; then st_timestamp=`date` else st_timestamp=`ssh $REM_HOST_IP "date" ` fi echo "$st_timestamp" | tr " " "_" >> "$2" 2>/dev/null } function read_block_file { blocking_pid=`awk -F " " '{print $2}' "$1"` blocking_app=`awk -F " " '{print $3}' "$1"` blocking_username=`awk -F " " '{print $4}' "$1"` blocking_id=`awk -F " " '{print $5}' "$1"` blocking_hostname=`awk -F " " '{print $6}' "$1"` blocking_st_time=`awk -F " " '{print $7}' "$1"` } function print_block_files_details { echo "Blocked Host:$blocked_host" echo "You blocked by:" echo "- application: ${blocking_app} " echo "- user: ${blocking_username} " echo "- users local host ip:${blocking_id} " echo "- blocking proccess with pid: ${blocking_pid} running on host ${blocking_hostname} " echo "- starting time:${blocking_st_time} " echo "- blocking file:${BLOCK_FILE}" } function update_remote_block_file { write_to_file_operator_details "$LOCAL_IP" "${BLOCK_FILE}.rem" scp "${BLOCK_FILE}.rem" "${REM_HOST_IP}:${BLOCK_FILE}" >& /dev/null rm -f "${BLOCK_FILE}.rem" >& /dev/null } function update_local_block_file { write_to_file_operator_details "local" "$BLOCK_FILE" } function update_block_files { discover_local_work_if_ip if [ "$LOCAL_IP" == "" ]; then echo "WARNING: Will be executed without blocking..." else update_local_block_file update_remote_block_file fi } function unblock_local_host { rm -f $BLOCK_FILE >& /dev/null rm -f "${BLOCK_FILE}.rem" >& /dev/null } function unblock_remote_host { ssh $REM_HOST_IP "rm -f $BLOCK_FILE >& /dev/null" >& /dev/null rm -f "${BLOCK_FILE}.rem" >& /dev/null } function unblock { unblock_local_host unblock_remote_host } function check_connection_to_remote_host { ping -w 3 "$1" >& /dev/null test $? -eq 0 && RES=OK || RES=NOT } function check_if_another_proccess_running_on_local_host { eval "ps -eF| grep '$blocking_pid'|grep -v grep|wc -l" > $TMP_FILE RES=`cat $TMP_FILE` } function check_if_another_proccess_running_on_remote_host { RES=0 check_connection_to_remote_host "$1" if [ $RES == "OK" ]; then RES=`sudo ssh ${SUPER_USR}@${1} "ps -eF| grep ${blocking_pid}|grep -v grep|wc -l"` else RES=1 fi } function get_operating_host_ip_or_hostname { RES=0 operating_host_ip=`awk -F " " '{print $1}' "$1"` if [[ $operating_host_ip != "local" ]]; then check_connection_to_remote_host "$operating_host_ip" if [ $RES != "OK" ]; then operating_host_ip=`awk -F " " '{print $6}' "$1"` fi fi } function check_if_operating_host_running_another_proccess { if [ $1 == "local" ]; then check_if_another_proccess_running_on_local_host else check_if_another_proccess_running_on_remote_host "$1" fi } function adjust_operating_host_ip_of_remote_machine { local tmp="" if [ "$1" == "local" ]; then operating_host_ip=$REM_HOST_IP else tmp=`ifconfig|grep $1` if [ "$tmp" != "" ]; then operating_host_ip="local" fi fi } function check_if_remote_host_is_blocked { RES=0 ssh $REM_HOST_IP "cat ${BLOCK_FILE} 2>/dev/null" > "${BLOCK_FILE}.rem" if [ -s "${BLOCK_FILE}.rem" ]; then read_block_file "${BLOCK_FILE}.rem" get_operating_host_ip_or_hostname "${BLOCK_FILE}.rem" adjust_operating_host_ip_of_remote_machine "$operating_host_ip" check_if_operating_host_running_another_proccess "$operating_host_ip" if [[ $RES -le 0 ]]; then unblock_remote_host else read_block_file "$BLOCK_FILE.rem" blocked_host=$REM_HOST_IP print_block_files_details rm -f "${BLOCK_FILE}.rem" >& /dev/null clean exit 1 fi fi } function check_if_local_host_is_blocked { RES=0 if [[ -e $BLOCK_FILE ]]; then read_block_file "$BLOCK_FILE" get_operating_host_ip_or_hostname "${BLOCK_FILE}" check_if_operating_host_running_another_proccess "$operating_host_ip" if [[ $RES -le 0 ]]; then unblock_local_host else blocked_host=`hostname` print_block_files_details clean exit 1 fi fi } function block { check_if_local_host_is_blocked check_if_remote_host_is_blocked update_block_files } function pre_test_checks { check_connection_2_remote_ip clean } function check_connection_2_remote_ip { ssh -o "BatchMode yes" $REM_HOST_IP exit 2>$TMP_FILE.err check_command_succss if [[ $SUCCSESS -ne $TRUE ]]; then echo "vma_perf_envelope error:$LAST_ERROR" clean unblock exit 1 fi } function write_mc_feed_file { local mc_grp_ctr=0 # num of mc groups local mc_addr_part_3=1 # the third number of the mc group local port=10005 local mc_addr_part_4=3 # the last number of the mc group local mc_grp_num=$1 local file_name=$2 if [ -e $file_name ]; then rm -f $file_name >& /dev/null fi while [ $mc_grp_ctr -lt $mc_grp_num ] do if [ $mc_addr_part_4 -ge 254 ]; then mc_addr_part_3=$(($mc_addr_part_3+1)) mc_addr_part_4=3 fi echo 224.4.$mc_addr_part_3.$mc_addr_part_4:$port >> $file_name mc_grp_ctr=$(($mc_grp_ctr+1)) port=$(($port+1)) mc_addr_part_4=$(($mc_addr_part_4+1)) done } function create_mc_feed_files { write_mc_feed_file $1 $2 copy_feed_file_2_remote_machine $2 >& /dev/null } function copy_feed_file_2_remote_machine { scp $1 "$REM_HOST_IP:/$TMP_DIR" } function remove_mc_feed_files { rm -f $1 >& /dev/null ssh $REM_HOST_IP "rm -f $1" >& /dev/null } function run_iperf { check_if_iperf_avaibale clean if [[ $iperf_is_installed -ne $TRUE ]]; then echo "$ERORR_PROMT iperf tool not found on one of the machines, skipping iperf test" else run_iperf_with_diff_msg_len fi } function check_if_iperf_avaibale { local_iperf_is_installed=$FALSE remote_iperf_is_installed=$FALSE iperf_is_installed=$FALSE which iperf 2>$TMP_FILE.err 1>/dev/null check_command_succss if [[ $SUCCSESS -ne $FALSE ]]; then local_iperf_is_installed=$TRUE else echo "$ERORR_PROMT iperf not found on local machine " fi ssh $REM_HOST_IP "which iperf" 2>$TMP_FILE.err 1>/dev/null check_command_succss if [[ $SUCCSESS -ne $FALSE ]]; then remote_iperf_is_installed=$TRUE else echo "$ERORR_PROMT iperf not found on remote machine " fi if [[ $local_iperf_is_installed -eq $TRUE ]]; then if [[ $remote_iperf_is_installed -eq $TRUE ]]; then iperf_is_installed=$TRUE fi fi } function clean { rm -f $TMP_FILE.err >& /dev/null rm -f "$TMP_DIR/$log_file.prep" >& /dev/null rm -f "$TMP_DIR/$log_file.post" >& /dev/null ssh $REM_HOST_IP rm -f "$TMP_DIR/$log_file.tmp" >& /dev/null rm -rf $TMP_FILE >& /dev/null } function write_date_2_log_file { echo "=============================>Date<===========================" >> "$log_file" (echo "${SRV_CMMND_LINE_PREF} date" | tee -a "$log_file") >& /dev/null (date | tee -a $log_file) >& /dev/null } function pre_vma_perf { pre_test_checks get_hostnames prepare_output_files write_date_2_log_file collect_nodes_info_to_file "$log_file" prepare_route_table save_shmem_prop increase_number_of_hugetlb save_umcast update_umcast clean update_command_prefix } function final_test_message { echo "####################### Generated files #######################" echo "#Test results : $res_file" echo "#Test logs : $log_file" echo "---------------------------------------------------------------" } function post_vma_perf { collect_nodes_info_to_file "$res_file" recreate_route_table recreate_mem_prop recreate_umcast final_test_message write_date_2_log_file clean } function vma_perf { case $1 in 'tc1') # TC1: run_sockperf_tc1 ;; 'tc2') # TC2: run_sockperf_lat_with_diff_msg_len ;; 'tc3') # TC3: run_sockperf_tx_bw_with_diff_msg_len ;; 'tc4') # TC4: run_sockperf_bw_with_diff_msg_len ;; 'tc5') # TC5: run_sockperf_with_diff_burst_size ;; 'tc6') # TC6: run_iperf ;; 'tc7') # TC7: run_sockperf_using_select_epoll_poll_with_zero_polling ;; 'tc8') # TC8: run_sockperf_using_select_epoll_poll_with_full_polling_vma_only ;; 'tc9') # TC9: run_sockperf_tc9 ;; *) run_sockperf_tc1 run_sockperf_lat_with_diff_msg_len run_sockperf_tx_bw_with_diff_msg_len run_sockperf_bw_with_diff_msg_len run_sockperf_with_diff_burst_size run_iperf run_sockperf_using_select_epoll_poll_with_zero_polling run_sockperf_using_select_epoll_poll_with_full_polling_vma_only run_sockperf_tc9 ;; esac } #main if [ $# -ge 1 ]; then block pre_vma_perf vma_perf "$2" post_vma_perf unblock else echo "Usage: perf " echo "tc1 run under-load with various --msg_size --pps." echo "tc2 run ping-pong with various --msg_size --pps=max." echo "tc3 run throughput (tx) with various --msg_size --pps=max." echo "tc4 run throughput with various --msg_size --pps=max." echo "tc5 run ping-pong with diff_burst_size." echo "tc6 run iperf." echo "tc7 run sockperf using select epoll poll with zero polling." echo "tc8 run sockperf using select epoll poll with zero polling vma only." echo "tc9 run ping-pong with various --msg_size --pps." exit fi sockperf-3.6/tools/000077500000000000000000000000001336630672200143465ustar00rootroot00000000000000sockperf-3.6/tools/Makefile.am000077500000000000000000000002261336630672200164050ustar00rootroot00000000000000tooldir = $(prefix)/sbin/sockperf/ sbin_SCRIPTS = \ filter.awk \ gen1.awk \ gen2.awk dist_sbin_SCRIPTS = \ filter.awk \ gen1.awk \ gen2.awk sockperf-3.6/tools/filter.awk000077500000000000000000000010231336630672200163360ustar00rootroot00000000000000#!/bin/awk -f BEGIN { # this syntax will allow --assign var=val in command line if (!RANGE_START_USEC) RANGE_START_USEC = 20 if (!RANGE_START_END) RANGE_END_USEC = 1000*1000*1000 if (!DECIMAL_DIGITS) DECIMAL_DIGITS = 9 dataStarted = 0 } $1 == "txTime," {dataStarted = 1; print "txTime, usecLat"} { if (!dataStarted) print else { usecLat = 1000*1000*($2 - $1)/2 if (RANGE_START_USEC <= usecLat && usecLat <= RANGE_END_USEC ) printf "%.*f, %.3f\n", DECIMAL_DIGITS, $1, usecLat } } sockperf-3.6/tools/gen1.awk000077500000000000000000000012071336630672200157070ustar00rootroot00000000000000#!/bin/awk -f BEGIN { print "# ==== playback file for sockperf - generated by gen1.awk ====" PPS = 200*1000 NUM_RECORDS = PPS # 30*1000 runtime = NUM_RECORDS/PPS interval = 1/PPS baseTime = 1 printf "#baseTime=%f; PPS=%d; runtime=%f; interval=%lf; NUM_RECORDS=%d\n", baseTime, PPS, runtime, interval, NUM_RECORDS deltaSize = 0 minSize = 12 maxSize = 50000 - minSize t = baseTime s = 0 printf "# file contains %d records\n", NUM_RECORDS for (i = 0; i < NUM_RECORDS; i++) { t += interval s += deltaSize printf("%.9lf, %d\n", t, minSize+s%maxSize) } printf "#%d records were written successfuly\n", NUM_RECORDS } sockperf-3.6/tools/gen2.awk000077500000000000000000000035001336630672200157060ustar00rootroot00000000000000#!/bin/awk -f # # this awk script generates playback files to be played with ./sockperf --playback command # the input for this script is file with lines of the format: # startTime; duration; startPPS; endPPS; msgSize # example for such a file is: # 1 2 100 100 12 # 3 1 100 10 12 # 4 10 10 100 12 # BEGIN { print "# ==== playback file for sockperf - generated by gen2.awk ====" } # file start => echo all orig lines as block of comments FNR == 1 && FILENAME != "-" { print "#---> echoing the content of the given input file: " FILENAME system("sed 's/^/#> /' " FILENAME) print "#<--- end of input file: " FILENAME } {print "#> " $0} # echo orig line as comment line /^[ \t]*$/ {next} # skip empty line /^[ \t]*#/ {next} # skip comment line NF < 5 {error = 1; exit 1} # too few fields # this will be executed for any input line { runtime = 0; startTime = $1; duration = $2; startPPS=$3; endPPS=$4; msgSize=$5 if (startTime < t) { error = 1; exit 2} # file is un-ordered if (duration <= 0 || startPPS <= 0 || endPPS <= 0 || msgSize < 14 || msgSize > 65000) { error = 1; exit 3} ppsGradient = (endPPS - startPPS) / duration #pps = startPPS #runtime += 1/pps printf ("#startTime=%f; duration=%f; startPPS=%f; endPPS=%f; msgSize=%d; ppsGradient=%f\n", startTime, duration, startPPS, endPPS, msgSize, ppsGradient) print("#txTime, msgSize") # print header while (runtime <= duration) { t = startTime + runtime printf("%.9lf, %d\n", t, msgSize) # actual printing of the record #TODO: 12 digits! pps = startPPS + ppsGradient * runtime runtime += 1/pps counter++ } } END { if (!error) printf "# ==== file generation completed successfuly with %d records ====\n", counter else printf " ====> error has occured during file generation [file=%s : line=%d] <====\n", FILENAME, FNR } sockperf-3.6/version000066400000000000000000000000041336630672200146100ustar00rootroot000000000000003.6 sockperf-3.6/win/000077500000000000000000000000001336630672200140035ustar00rootroot00000000000000sockperf-3.6/win/README.txt000066400000000000000000000010611336630672200154770ustar00rootroot00000000000000Sockperf - Windows support ========================== Not supported features (Windows): - Poll/Epoll. - RDTSC - Unlike in Linux, there's only one option for time handling. It is done using QueryPerformanceFrequency() and QueryPerformanceCounter() methoods. - VMA integration. - Daemonizing Sockperf process. - Message flags: MSG_DONTWAIT, MSG_NOSIGNAL. Notes/TODO's: - Modify type 'int' to type 'SOCK'. - Add windows installer. - Split os_abstact to os_win and os_linux. - Add regular expression check for the feed file. - Add colors (drops, errors, etc.) sockperf-3.6/win/project/000077500000000000000000000000001336630672200154515ustar00rootroot00000000000000sockperf-3.6/win/project/sockperf.vcxproj000066400000000000000000000214261336630672200207070ustar00rootroot00000000000000 Debug Win32 Debug x64 Release Win32 Release x64 {14C716DD-3174-4735-94F5-7FB120221E17} Win32Proj sockperf WinSockperf Application true v110 Unicode Application true v110 Unicode Application false v110 true Unicode Application false v110 true Unicode true true false false Level3 Disabled WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) Console true Ws2_32.lib;Dbghelp.lib;%(AdditionalDependencies) Level3 Disabled WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) Console true Ws2_32.lib;Dbghelp.lib;%(AdditionalDependencies) Level3 MaxSpeed true true WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) Console true true true Ws2_32.lib;Dbghelp.lib Level3 MaxSpeed true true WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true Console true true true Ws2_32.lib;User32.lib;Dbghelp.lib