aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-03 18:28:31 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-03 18:28:31 -0800
commit8eb453f761a608a321986303fd8fefecb463fd6a (patch)
tree4b825dc642cb6eb9a060e54bf8d69288fbee4904
parentacbeb739a2260972afbd58233fc8939fe5014e3c (diff)
downloadnetperf-8eb453f761a608a321986303fd8fefecb463fd6a.tar.gz
auto import from //depot/cupcake/@135843
-rw-r--r--Android.mk42
-rw-r--r--MODULE_LICENSE_HP43
-rw-r--r--config.h351
-rw-r--r--hist.h116
-rw-r--r--netcpu.h19
-rw-r--r--netcpu_kstat.c415
-rw-r--r--netcpu_kstat10.c559
-rw-r--r--netcpu_looper.c656
-rw-r--r--netcpu_none.c67
-rw-r--r--netcpu_ntperf.c497
-rw-r--r--netcpu_osx.c149
-rw-r--r--netcpu_perfstat.c351
-rw-r--r--netcpu_procstat.c265
-rw-r--r--netcpu_pstat.c307
-rw-r--r--netcpu_pstatnew.c398
-rw-r--r--netcpu_sysctl.c127
-rw-r--r--netlib.c4161
-rw-r--r--netlib.h621
-rw-r--r--netperf.c284
-rw-r--r--netperf_version.h1
-rw-r--r--netserver.c1022
-rw-r--r--netsh.c1002
-rw-r--r--netsh.h149
-rw-r--r--nettest_bsd.c12333
-rw-r--r--nettest_bsd.h471
-rw-r--r--nettest_dlpi.c3798
-rw-r--r--nettest_dlpi.h215
-rw-r--r--nettest_sctp.c4869
-rw-r--r--nettest_sctp.h128
-rw-r--r--nettest_sdp.c3553
-rw-r--r--nettest_sdp.h170
-rw-r--r--nettest_unix.c3431
-rw-r--r--nettest_unix.h198
-rw-r--r--nettest_xti.c6026
-rw-r--r--nettest_xti.h264
35 files changed, 0 insertions, 47058 deletions
diff --git a/Android.mk b/Android.mk
deleted file mode 100644
index a0d5b80..0000000
--- a/Android.mk
+++ /dev/null
@@ -1,42 +0,0 @@
-# Copyright (C) 2008 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-L_DEFS := -DHAVE_CONFIG_H -UAF_INET6
-L_CFLAGS := $(L_DEFS)
-L_USE_CPU_SOURCE := netcpu_none.c
-
-L_COMMON_SRC := hist.h netlib.c netsh.c nettest_bsd.c nettest_dlpi.c \
- nettest_unix.c nettest_xti.c nettest_sctp.c nettest_sdp.c
-
-netperf_SOURCES := netperf.c $(L_COMMON_SRC) $(L_USE_CPU_SOURCE)
-netserver_SOURCES := netserver.c $(L_COMMON_SRC) $(L_USE_CPU_SOURCE)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := netperf
-LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
-LOCAL_MODULE_TAGS := tests eng
-LOCAL_CFLAGS := $(L_CFLAGS)
-LOCAL_SRC_FILES := $(netperf_SOURCES)
-include $(BUILD_EXECUTABLE)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := netserver
-LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
-LOCAL_MODULE_TAGS := tests eng
-LOCAL_CFLAGS := $(L_CFLAGS)
-LOCAL_SRC_FILES := $(netserver_SOURCES)
-include $(BUILD_EXECUTABLE)
-
diff --git a/MODULE_LICENSE_HP b/MODULE_LICENSE_HP
deleted file mode 100644
index 3f3ceb2..0000000
--- a/MODULE_LICENSE_HP
+++ /dev/null
@@ -1,43 +0,0 @@
-
-
- Copyright (C) 1993 Hewlett-Packard Company
- ALL RIGHTS RESERVED.
-
- The enclosed software and documentation includes copyrighted works
- of Hewlett-Packard Co. For as long as you comply with the following
- limitations, you are hereby authorized to (i) use, reproduce, and
- modify the software and documentation, and to (ii) distribute the
- software and documentation, including modifications, for
- non-commercial purposes only.
-
- 1. The enclosed software and documentation is made available at no
- charge in order to advance the general development of
- high-performance networking products.
-
- 2. You may not delete any copyright notices contained in the
- software or documentation. All hard copies, and copies in
- source code or object code form, of the software or
- documentation (including modifications) must contain at least
- one of the copyright notices.
-
- 3. The enclosed software and documentation has not been subjected
- to testing and quality control and is not a Hewlett-Packard Co.
- product. At a future time, Hewlett-Packard Co. may or may not
- offer a version of the software and documentation as a product.
-
- 4. THE SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS".
- HEWLETT-PACKARD COMPANY DOES NOT WARRANT THAT THE USE,
- REPRODUCTION, MODIFICATION OR DISTRIBUTION OF THE SOFTWARE OR
- DOCUMENTATION WILL NOT INFRINGE A THIRD PARTY'S INTELLECTUAL
- PROPERTY RIGHTS. HP DOES NOT WARRANT THAT THE SOFTWARE OR
- DOCUMENTATION IS ERROR FREE. HP DISCLAIMS ALL WARRANTIES,
- EXPRESS AND IMPLIED, WITH REGARD TO THE SOFTWARE AND THE
- DOCUMENTATION. HP SPECIFICALLY DISCLAIMS ALL WARRANTIES OF
- MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
-
- 5. HEWLETT-PACKARD COMPANY WILL NOT IN ANY EVENT BE LIABLE FOR ANY
- DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES
- (INCLUDING LOST PROFITS) RELATED TO ANY USE, REPRODUCTION,
- MODIFICATION, OR DISTRIBUTION OF THE SOFTWARE OR DOCUMENTATION.
-
-
diff --git a/config.h b/config.h
deleted file mode 100644
index 5c89615..0000000
--- a/config.h
+++ /dev/null
@@ -1,351 +0,0 @@
-/* config.h. Generated from config.h.in by configure. */
-/* config.h.in. Generated from configure.ac by autoheader. */
-
-/* Define to one to enable dirty buffer support. May affect results. */
-/* #undef DIRTY */
-
-#undef AF_INET6
-
-/* Define to 1 if you have the `alarm' function. */
-#define HAVE_ALARM 1
-
-/* Define to 1 if you have the <arpa/inet.h> header file. */
-#define HAVE_ARPA_INET_H 1
-
-/* Define to 1 if you have the `bindprocessor' function. */
-/* #undef HAVE_BINDPROCESSOR */
-
-/* Define to 1 if you have the `bind_to_cpu_id' function. */
-/* #undef HAVE_BIND_TO_CPU_ID */
-
-/* Define to 1 if you have the `bzero' function. */
-#define HAVE_BZERO 1
-
-/* Define to 1 if you have the <endian.h> header file. */
-/* #define HAVE_ENDIAN_H 1 */
-
-/* Define to 1 if you have the <errno.h> header file. */
-#define HAVE_ERRNO_H 1
-
-/* Define to 1 if you have the <fcntl.h> header file. */
-#define HAVE_FCNTL_H 1
-
-/* Define to 1 if you have the `fork' function. */
-#define HAVE_FORK 1
-
-/* Define to 1 if you have the `getaddrinfo' function. */
-#define HAVE_GETADDRINFO 1
-
-/* Define to 1 if you have the `gethostbyname' function. */
-#define HAVE_GETHOSTBYNAME 1
-
-/* Define to 1 if you have the `gethrtime' function. */
-/* #undef HAVE_GETHRTIME */
-
-/* Define to 1 if you have the `getnameinfo' function. */
-#define HAVE_GETNAMEINFO 1
-
-/* Define to 1 if you have the `getpagesize' function. */
-#define HAVE_GETPAGESIZE 1
-
-/* Define to 1 if you have the `gettimeofday' function. */
-#define HAVE_GETTIMEOFDAY 1
-
-/* Define to one to include ICSC-EXS tests. */
-/* #undef HAVE_ICSC_EXS */
-
-/* Define to 1 if you have the `inet_ntoa' function. */
-#define HAVE_INET_NTOA 1
-
-/* Define to 1 if you have the `inet_ntop' function. */
-#define HAVE_INET_NTOP 1
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#define HAVE_INTTYPES_H 1
-
-/* Define to 1 if you have the `exs' library (-lexs). */
-/* #undef HAVE_LIBEXS */
-
-/* Define to 1 if you have the `kstat' library (-lkstat). */
-/* #undef HAVE_LIBKSTAT */
-
-/* Define to 1 if you have the `m' library (-lm). */
-#define HAVE_LIBM 1
-
-/* Define to 1 if you have the `mach' library (-lmach). */
-/* #undef HAVE_LIBMACH */
-
-/* Define to 1 if you have the `nsl' library (-lnsl). */
-/* #undef HAVE_LIBNSL */
-
-/* Define to 1 if you have the `perfstat' library (-lperfstat). */
-/* #undef HAVE_LIBPERFSTAT */
-
-/* Define to 1 if you have the `sctp' library (-lsctp). */
-/* #undef HAVE_LIBSCTP */
-
-/* Define to 1 if you have the `sdp' library (-lsdp). */
-/* #undef HAVE_LIBSDP */
-
-/* Define to 1 if you have the `sendfile' library (-lsendfile). */
-/* #undef HAVE_LIBSENDFILE */
-
-/* Define to 1 if you have the `socket' library (-lsocket). */
-/* #undef HAVE_LIBSOCKET */
-
-/* Define to 1 if you have the <limits.h> header file. */
-#define HAVE_LIMITS_H 1
-
-/* Define to 1 if you have the <malloc.h> header file. */
-/* #define HAVE_MALLOC_H 1 */
-
-/* Define to 1 if you have the `memcpy' function. */
-#define HAVE_MEMCPY 1
-
-/* Define to 1 if you have the <memory.h> header file. */
-#define HAVE_MEMORY_H 1
-
-/* Define to 1 if you have the `memset' function. */
-#define HAVE_MEMSET 1
-
-/* Define to 1 if you have a working `mmap' system call. */
-#define HAVE_MMAP 1
-
-/* Define to 1 if you have the `mpctl' function. */
-/* #undef HAVE_MPCTL */
-
-/* Define to 1 if you have the `munmap' function. */
-#define HAVE_MUNMAP 1
-
-/* Define to 1 if you have the <netdb.h> header file. */
-#define HAVE_NETDB_H 1
-
-/* Define to 1 if you have the <netinet/in.h> header file. */
-#define HAVE_NETINET_IN_H 1
-
-/* Define to 1 if you have the <netinet/sctp.h> header file. */
-/* #undef HAVE_NETINET_SCTP_H */
-
-/* Define to 1 if you have the `processor_bind' function. */
-/* #undef HAVE_PROCESSOR_BIND */
-
-/* Define to 1 if you have the `sched_setaffinity' function. */
-/* #define HAVE_SCHED_SETAFFINITY 1 */
-
-/* Define to 1 if `struct sctp_event_subscribe' has a
- `sctp_adaptation_layer_event' member */
-/* #undef HAVE_SCTP_ADAPTATION_LAYER_EVENT */
-
-/* Define to 1 if you have the `select' function. */
-#define HAVE_SELECT 1
-
-/* Define to 1 if you have the `sendfile' function. */
-/* #undef HAVE_SENDFILE */
-
-/* Define to 1 if you have the <signal.h> header file. */
-#define HAVE_SIGNAL_H 1
-
-/* Define to 1 if you have the `socket' function. */
-#define HAVE_SOCKET 1
-
-/* Define to 1 if you have the `sqrt' function. */
-#define HAVE_SQRT 1
-
-/* Define to 1 if stdbool.h conforms to C99. */
-#define HAVE_STDBOOL_H 1
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#define HAVE_STDINT_H 1
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the `strcasecmp' function. */
-#define HAVE_STRCASECMP 1
-
-/* Define to 1 if you have the `strchr' function. */
-#define HAVE_STRCHR 1
-
-/* Define to 1 if you have the <strings.h> header file. */
-#define HAVE_STRINGS_H 1
-
-/* Define to 1 if you have the <string.h> header file. */
-#define HAVE_STRING_H 1
-
-/* Define to 1 if you have the `strstr' function. */
-#define HAVE_STRSTR 1
-
-/* Define to 1 if you have the `strtoul' function. */
-#define HAVE_STRTOUL 1
-
-/* Define to 1 if <netinet/in.h> defines `struct sockaddr_storage' */
-#define HAVE_STRUCT_SOCKADDR_STORAGE 1
-
-/* Define to 1 if you have the <sys/ioctl.h> header file. */
-#define HAVE_SYS_IOCTL_H 1
-
-/* Define to 1 if you have the <sys/mman.h> header file. */
-#define HAVE_SYS_MMAN_H 1
-
-/* Define to 1 if you have the <sys/param.h> header file. */
-#define HAVE_SYS_PARAM_H 1
-
-/* Define to 1 if you have the <sys/select.h> header file. */
-#define HAVE_SYS_SELECT_H 1
-
-/* Define to 1 if you have the <sys/socket.h> header file. */
-#define HAVE_SYS_SOCKET_H 1
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#define HAVE_SYS_STAT_H 1
-
-/* Define to 1 if you have the <sys/time.h> header file. */
-#define HAVE_SYS_TIME_H 1
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#define HAVE_SYS_TYPES_H 1
-
-/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
-#define HAVE_SYS_WAIT_H 1
-
-/* Define to 1 if you have the `uname' function. */
-#define HAVE_UNAME 1
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#define HAVE_UNISTD_H 1
-
-/* Define to 1 if you have the `vfork' function. */
-#define HAVE_VFORK 1
-
-/* Define to 1 if you have the <vfork.h> header file. */
-/* #undef HAVE_VFORK_H */
-
-/* Define to 1 if `fork' works. */
-#define HAVE_WORKING_FORK 1
-
-/* Define to 1 if `vfork' works. */
-#define HAVE_WORKING_VFORK 1
-
-/* Define to 1 if the system has the type `_Bool'. */
-#define HAVE__BOOL 1
-
-/* Define to 1 if `h_errno' is declared by <netdb.h> */
-#define H_ERRNO_DECLARED 1
-
-/* Name of package */
-#define PACKAGE "netperf"
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT ""
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME "netperf"
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "netperf 2.4.4"
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME "netperf"
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION "2.4.4"
-
-/* Define as the return type of signal handlers (`int' or `void'). */
-#define RETSIGTYPE void
-
-/* Define to the type of arg 1 for `select'. */
-#define SELECT_TYPE_ARG1 int
-
-/* Define to the type of args 2, 3 and 4 for `select'. */
-#define SELECT_TYPE_ARG234 (fd_set *)
-
-/* Define to the type of arg 5 for `select'. */
-#define SELECT_TYPE_ARG5 (struct timeval *)
-
-/* Define to 1 if the `setpgrp' function takes no argument. */
-#define SETPGRP_VOID 1
-
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
-#define TIME_WITH_SYS_TIME 1
-
-/* Use Solaris's kstat interface to measure CPU util. */
-/* #undef USE_KSTAT */
-
-/* Use looper/soaker processes to measure CPU util. */
-/* #undef USE_LOOPER */
-
-/* Use MacOS X's host_info interface to measure CPU util. */
-/* #undef USE_OSX */
-
-/* Use AIX's perfstat interface to measure CPU util. */
-/* #undef USE_PERFSTAT */
-
-/* Use Linux's procstat interface to measure CPU util. */
-#define USE_PROC_STAT 1
-
-/* Use HP-UX's pstat interface to measure CPU util. */
-/* #undef USE_PSTAT */
-
-/* Use FreeBSD's sysctl interface to measure CPU util. */
-/* #undef USE_SYSCTL */
-
-/* Version number of package */
-#define VERSION "2.4.4"
-
-/* Define to one to enable demo support. May affect results. */
-/* #undef WANT_DEMO */
-
-/* Define to one to include DLPI tests. */
-/* #undef WANT_DLPI */
-
-/* Define to one to enable initial _RR burst support. May affect results. */
-/* #undef WANT_FIRST_BURST */
-
-/* Define to one to enable histogram support. May affect results. */
-/* #undef WANT_HISTOGRAM */
-
-/* Define to one to enable paced operation support. May affect results. */
-/* #undef WANT_INTERVALS */
-
-/* Define to one to include SCTP tests. */
-/* #define WANT_SCTP 1 */
-
-/* Define to one to include SDP tests. */
-/* #undef WANT_SDP */
-
-/* Define to one to spin waiting on paced operation. WILL AFFEFCT CPU
- UTILIZATION */
-/* #undef WANT_SPIN */
-
-/* Define to one to include Unix Domain socket tests. */
-/* #undef WANT_UNIX */
-
-/* Define to one to include XTI tests. */
-/* #undef WANT_XTI */
-
-/* Number of bits in a file offset, on hosts where this is settable. */
-/* #undef _FILE_OFFSET_BITS */
-
-/* Define for large files, on AIX-style hosts. */
-/* #undef _LARGE_FILES */
-
-/* Define to empty if `const' does not conform to ANSI C. */
-/* #undef const */
-
-/* type to use in place of socklen_t if not defined */
-#define netperf_socklen_t size_t
-
-/* Define to `long int' if <sys/types.h> does not define. */
-/* #undef off_t */
-
-/* Define to `int' if <sys/types.h> does not define. */
-/* #undef pid_t */
-
-/* Define to `unsigned int' if <sys/types.h> does not define. */
-/* #undef size_t */
-
-/* Define as `fork' if `vfork' does not work. */
-/* #undef vfork */
diff --git a/hist.h b/hist.h
deleted file mode 100644
index b2ed22b..0000000
--- a/hist.h
+++ /dev/null
@@ -1,116 +0,0 @@
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
-/* hist.h
-
- Given a time difference in microseconds, increment one of 61
- different buckets:
-
- 0 - 9 in increments of 1 usec
- 0 - 9 in increments of 10 usecs
- 0 - 9 in increments of 100 usecs
- 0 - 9 in increments of 1 msec
- 0 - 9 in increments of 10 msecs
- 0 - 9 in increments of 100 msecs
- 0 - 9 in increments of 1 sec
- 0 - 9 in increments of 10 sec
- > 100 secs
-
- This will allow any time to be recorded to within an accuracy of
- 10%, and provides a compact representation for capturing the
- distribution of a large number of time differences (e.g.
- request-response latencies).
-
- Colin Low 10/6/93
- Rick Jones 2004-06-15 - extend to 1 and 10 usec
-*/
-#ifndef _HIST_INCLUDED
-#define _HIST_INCLUDED
-
-#ifdef IRIX
-#include <sys/time.h>
-#endif /* IRIX */
-
-#if defined(HAVE_GET_HRT)
-#include "hrt.h"
-#endif
-
-struct histogram_struct {
- int unit_usec[10];
- int ten_usec[10];
- int hundred_usec[10];
- int unit_msec[10];
- int ten_msec[10];
- int hundred_msec[10];
- int unit_sec[10];
- int ten_sec[10];
- int ridiculous;
- int total;
-};
-
-typedef struct histogram_struct *HIST;
-
-/*
- HIST_new - return a new, cleared histogram data type
-*/
-
-HIST HIST_new(void);
-
-/*
- HIST_clear - reset a histogram by clearing all totals to zero
-*/
-
-void HIST_clear(HIST h);
-
-/*
- HIST_add - add a time difference to a histogram. Time should be in
- microseconds.
-*/
-
-void HIST_add(register HIST h, int time_delta);
-
-/*
- HIST_report - create an ASCII report on the contents of a histogram.
- Currently printsto standard out
-*/
-
-void HIST_report(HIST h);
-
-/*
- HIST_timestamp - take a timestamp suitable for use in a histogram.
-*/
-
-#ifdef HAVE_GETHRTIME
-void HIST_timestamp(hrtime_t *timestamp);
-#elif defined(HAVE_GET_HRT)
-void HIST_timestamp(hrt_t *timestamp);
-#elif defined(WIN32)
-void HIST_timestamp(LARGE_INTEGER *timestamp);
-#else
-void HIST_timestamp(struct timeval *timestamp);
-#endif
-
-/*
- delta_micro - calculate the difference in microseconds between two
- timestamps
-*/
-#ifdef HAVE_GETHRTIME
-int delta_micro(hrtime_t *begin, hrtime_t *end);
-#elif defined(HAVE_GET_HRT)
-int delta_micro(hrt_t *begin, hrt_t *end);
-#elif defined(WIN32)
-int delta_micro(LARGE_INTEGER *begin, LARGE_INTEGER *end);
-#else
-int delta_micro(struct timeval *begin, struct timeval *end);
-#endif
-
-#endif
-
diff --git a/netcpu.h b/netcpu.h
deleted file mode 100644
index 58d1e1c..0000000
--- a/netcpu.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/* This should define all the common routines etc exported by the
- various netcpu_mumble.c files raj 2005-01-26 */
-
-extern void cpu_util_init(void);
-extern void cpu_util_terminate(void);
-extern int get_cpu_method();
-
-#ifdef WIN32
-/* +*+ temp until I figure out what header this is in; I know it's
- there someplace... */
-typedef unsigned __int64 uint64_t;
-#endif
-
-extern void get_cpu_idle(uint64_t *res);
-extern float calibrate_idle_rate(int iterations, int interval);
-extern float calc_cpu_util_internal(float elapsed);
-extern void cpu_start_internal(void);
-extern void cpu_stop_internal(void);
-
diff --git a/netcpu_kstat.c b/netcpu_kstat.c
deleted file mode 100644
index 6320658..0000000
--- a/netcpu_kstat.c
+++ /dev/null
@@ -1,415 +0,0 @@
-char netcpu_kstat_id[]="\
-@(#)netcpu_kstat.c Version 2.4.0";
-
-#if HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <stdio.h>
-
-#if HAVE_INTTYPES_H
-# include <inttypes.h>
-#else
-# if HAVE_STDINT_H
-# include <stdint.h>
-# endif
-#endif
-
-#if HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-#if HAVE_STRINGS_H
-# include <strings.h>
-#endif
-#if STDC_HEADERS
-# include <stdlib.h>
-# include <stddef.h>
-#else
-# if HAVE_STDLIB_H
-# include <stdlib.h>
-# endif
-#endif
-
-#include <kstat.h>
-#include <sys/sysinfo.h>
-
-#include "netsh.h"
-#include "netlib.h"
-
-/* the lib_start_count and lib_end_count arrays hold the starting
- and ending values of whatever is counting when the system is
- idle. The rate at which this increments during a test is compared
- with a previous calibrarion to arrive at a CPU utilization
- percentage. raj 2005-01-26 */
-static uint64_t lib_start_count[MAXCPUS];
-static uint64_t lib_end_count[MAXCPUS];
-
-static kstat_t *cpu_ks[MAXCPUS]; /* the addresses that kstat will
- need to pull the cpu info from
- the kstat interface. at least I
- think that is what this is :) raj
- 8/2000 */
-
-#define UPDKCID(nk,ok) \
-if (nk == -1) { \
- perror("kstat_read "); \
- exit(1); \
-} \
-if (nk != ok)\
- goto kcid_changed;
-
-static kstat_ctl_t *kc = NULL;
-static kid_t kcid = 0;
-
-/* do the initial open of the kstat interface, get the chain id's all
- straightened-out and set-up the addresses for get_kstat_idle to do
- its thing. liberally borrowed from the sources to TOP. raj 8/2000 */
-
-static int
-open_kstat()
-{
- kstat_t *ks;
- kid_t nkcid;
- int i;
- int changed = 0;
- static int ncpu = 0;
-
- kstat_named_t *kn;
-
- if (debug) {
- fprintf(where,"open_kstat: enter\n");
- fflush(where);
- }
-
- /*
- * 0. kstat_open
- */
-
- if (!kc)
- {
- kc = kstat_open();
- if (!kc)
- {
- perror("kstat_open ");
- exit(1);
- }
- changed = 1;
- kcid = kc->kc_chain_id;
- }
-#ifdef rickwasstupid
- else {
- fprintf(where,"open_kstat double open!\n");
- fflush(where);
- exit(1);
- }
-#endif
-
- /* keep doing it until no more changes */
- kcid_changed:
-
- if (debug) {
- fprintf(where,"passing kcid_changed\n");
- fflush(where);
- }
-
- /*
- * 1. kstat_chain_update
- */
- nkcid = kstat_chain_update(kc);
- if (nkcid)
- {
- /* UPDKCID will abort if nkcid is -1, so no need to check */
- changed = 1;
- kcid = nkcid;
- }
- UPDKCID(nkcid,0);
-
- if (debug) {
- fprintf(where,"kstat_lookup for unix/system_misc\n");
- fflush(where);
- }
-
- ks = kstat_lookup(kc, "unix", 0, "system_misc");
- if (kstat_read(kc, ks, 0) == -1) {
- perror("kstat_read");
- exit(1);
- }
-
-
- if (changed) {
-
- /*
- * 2. get data addresses
- */
-
- ncpu = 0;
-
- kn = kstat_data_lookup(ks, "ncpus");
- if (kn && kn->value.ui32 > lib_num_loc_cpus) {
- fprintf(stderr,"number of CPU's mismatch!");
- exit(1);
- }
-
- for (ks = kc->kc_chain; ks;
- ks = ks->ks_next)
- {
- if (strncmp(ks->ks_name, "cpu_stat", 8) == 0)
- {
- nkcid = kstat_read(kc, ks, NULL);
- /* if kcid changed, pointer might be invalid. we'll deal
- wtih changes at this stage, but will not accept them
- when we are actually in the middle of reading
- values. hopefully this is not going to be a big
- issue. raj 8/2000 */
- UPDKCID(nkcid, kcid);
-
- if (debug) {
- fprintf(where,"cpu_ks[%d] getting %p\n",ncpu,ks);
- fflush(where);
- }
-
- cpu_ks[ncpu] = ks;
- ncpu++;
- if (ncpu > lib_num_loc_cpus)
- {
- /* with the check above, would we ever hit this? */
- fprintf(stderr,
- "kstat finds too many cpus %d: should be %d\n",
- ncpu,lib_num_loc_cpus);
- exit(1);
- }
- }
- }
- /* note that ncpu could be less than ncpus, but that's okay */
- changed = 0;
- }
-}
-
-/* return the value of the idle tick counter for the specified CPU */
-static long
-get_kstat_idle(cpu)
- int cpu;
-{
- cpu_stat_t cpu_stat;
- kid_t nkcid;
-
- if (debug) {
- fprintf(where,
- "get_kstat_idle reading with kc %x and ks %p\n",
- kc,
- cpu_ks[cpu]);
- }
-
- nkcid = kstat_read(kc, cpu_ks[cpu], &cpu_stat);
- /* if kcid changed, pointer might be invalid, fail the test */
- UPDKCID(nkcid, kcid);
-
- return(cpu_stat.cpu_sysinfo.cpu[CPU_IDLE]);
-
- kcid_changed:
- perror("kcid changed midstream and I cannot deal with that!");
- exit(1);
-}
-
-void
-cpu_util_init(void)
-{
- open_kstat();
- return;
-}
-
-void
-cpu_util_terminate(void)
-{
- return;
-}
-
-int
-get_cpu_method(void)
-{
- return KSTAT;
-}
-
-void
-get_cpu_idle(uint64_t *res)
-{
-
- int i;
-
- /* this open may be redundant */
- open_kstat();
-
- for (i = 0; i < lib_num_loc_cpus; i++){
- res[i] = get_kstat_idle(i);
- }
- return;
-}
-
-float
-calibrate_idle_rate(int iterations, int interval)
-{
-
- long
- firstcnt[MAXCPUS],
- secondcnt[MAXCPUS];
-
- float
- elapsed,
- temp_rate,
- rate[MAXTIMES],
- local_maxrate;
-
- long
- sec,
- usec;
-
- int
- i,
- j;
-
- struct timeval time1, time2 ;
- struct timezone tz;
-
- if (debug) {
- fprintf(where,"calling open_kstat from calibrate_kstat\n");
- fflush(where);
- }
-
- open_kstat();
-
- if (iterations > MAXTIMES) {
- iterations = MAXTIMES;
- }
-
- local_maxrate = (float)-1.0;
-
- for(i = 0; i < iterations; i++) {
- rate[i] = (float)0.0;
- for (j = 0; j < lib_num_loc_cpus; j++) {
- firstcnt[j] = get_kstat_idle(j);
- }
- gettimeofday (&time1, &tz);
- sleep(interval);
- gettimeofday (&time2, &tz);
-
- if (time2.tv_usec < time1.tv_usec)
- {
- time2.tv_usec += 1000000;
- time2.tv_sec -=1;
- }
- sec = time2.tv_sec - time1.tv_sec;
- usec = time2.tv_usec - time1.tv_usec;
- elapsed = (float)sec + ((float)usec/(float)1000000.0);
-
- if(debug) {
- fprintf(where, "Calibration for kstat counter run: %d\n",i);
- fprintf(where,"\tsec = %ld usec = %ld\n",sec,usec);
- fprintf(where,"\telapsed time = %g\n",elapsed);
- }
-
- for (j = 0; j < lib_num_loc_cpus; j++) {
- secondcnt[j] = get_kstat_idle(j);
- if(debug) {
- /* I know that there are situations where compilers know about */
- /* long long, but the library functions do not... raj 4/95 */
- fprintf(where,
- "\tfirstcnt[%d] = 0x%8.8lx%8.8lx secondcnt[%d] = 0x%8.8lx%8.8lx\n",
- j,
- firstcnt[j],
- firstcnt[j],
- j,
- secondcnt[j],
- secondcnt[j]);
- }
- /* we assume that it would wrap no more than once. we also */
- /* assume that the result of subtracting will "fit" raj 4/95 */
- temp_rate = (secondcnt[j] >= firstcnt[j]) ?
- (float)(secondcnt[j] - firstcnt[j])/elapsed :
- (float)(secondcnt[j]-firstcnt[j]+MAXLONG)/elapsed;
- if (temp_rate > rate[i]) rate[i] = temp_rate;
- if(debug) {
- fprintf(where,"\trate[%d] = %g\n",i,rate[i]);
- fflush(where);
- }
- if (local_maxrate < rate[i]) local_maxrate = rate[i];
- }
- }
- if(debug) {
- fprintf(where,"\tlocal maxrate = %g per sec. \n",local_maxrate);
- fflush(where);
- }
- return local_maxrate;
-}
-
-float
-calc_cpu_util_internal(float elapsed_time)
-{
- int i;
- float correction_factor;
- float actual_rate;
-
- lib_local_cpu_util = (float)0.0;
- /* It is possible that the library measured a time other than */
- /* the one that the user want for the cpu utilization */
- /* calculations - for example, tests that were ended by */
- /* watchdog timers such as the udp stream test. We let these */
- /* tests tell up what the elapsed time should be. */
-
- if (elapsed_time != 0.0) {
- correction_factor = (float) 1.0 +
- ((lib_elapsed - elapsed_time) / elapsed_time);
- }
- else {
- correction_factor = (float) 1.0;
- }
-
- for (i = 0; i < lib_num_loc_cpus; i++) {
-
- /* it would appear that on some systems, in loopback, nice is
- *very* effective, causing the looper process to stop dead in its
- tracks. if this happens, we need to ensure that the calculation
- does not go south. raj 6/95 and if we run completely out of idle,
- the same thing could in theory happen to the USE_KSTAT path. raj
- 8/2000 */
-
- if (lib_end_count[i] == lib_start_count[i]) {
- lib_end_count[i]++;
- }
-
- actual_rate = (lib_end_count[i] > lib_start_count[i]) ?
- (float)(lib_end_count[i] - lib_start_count[i])/lib_elapsed :
- (float)(lib_end_count[i] - lib_start_count[i] +
- MAXLONG)/ lib_elapsed;
- if (debug) {
- fprintf(where,
- "calc_cpu_util: actual_rate on processor %d is %f start %lx end %lx\n",
- i,
- actual_rate,
- lib_start_count[i],
- lib_end_count[i]);
- }
- lib_local_per_cpu_util[i] = (lib_local_maxrate - actual_rate) /
- lib_local_maxrate * 100;
- lib_local_cpu_util += lib_local_per_cpu_util[i];
- }
- /* we want the average across all n processors */
- lib_local_cpu_util /= (float)lib_num_loc_cpus;
-
- lib_local_cpu_util *= correction_factor;
- return lib_local_cpu_util;
-
-
-}
-
-void
-cpu_start_internal(void)
-{
- get_cpu_idle(lib_start_count);
- return;
-}
-
-void
-cpu_stop_internal(void)
-{
- get_cpu_idle(lib_end_count);
-}
diff --git a/netcpu_kstat10.c b/netcpu_kstat10.c
deleted file mode 100644
index 299e66d..0000000
--- a/netcpu_kstat10.c
+++ /dev/null
@@ -1,559 +0,0 @@
-char netcpu_kstat10_id[]="\
-@(#)netcpu_kstat10.c (c) Copyright 2005-2007, Hewlett-Packard Company Version 2.4.3";
-
-#if HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <stdio.h>
-
-#if HAVE_INTTYPES_H
-# include <inttypes.h>
-#else
-# if HAVE_STDINT_H
-# include <stdint.h>
-# endif
-#endif
-
-#if HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-#if HAVE_STRINGS_H
-# include <strings.h>
-#endif
-#if STDC_HEADERS
-# include <stdlib.h>
-# include <stddef.h>
-#else
-# if HAVE_STDLIB_H
-# include <stdlib.h>
-# endif
-#endif
-
-#include <errno.h>
-
-#include <kstat.h>
-#include <sys/sysinfo.h>
-
-#include "netsh.h"
-#include "netlib.h"
-
-static kstat_ctl_t *kc = NULL;
-static kid_t kcid = 0;
-
-typedef struct cpu_time_counters {
- uint64_t idle;
- uint64_t user;
- uint64_t kernel;
- uint64_t interrupt;
-} cpu_time_counters_t;
-
-static cpu_time_counters_t starting_cpu_counters[MAXCPUS];
-static cpu_time_counters_t ending_cpu_counters[MAXCPUS];
-static cpu_time_counters_t delta_cpu_counters[MAXCPUS];
-static cpu_time_counters_t corrected_cpu_counters[MAXCPUS];
-
-static void
-print_cpu_time_counters(char *name, int instance, cpu_time_counters_t *counters)
-{
- fprintf(where,"%s[%d]:\n",name,instance);
- fprintf(where,
- "\t idle %llu\n",counters[instance].idle);
- fprintf(where,
- "\t user %llu\n",counters[instance].user);
- fprintf(where,
- "\t kernel %llu\n",counters[instance].kernel);
- fprintf(where,
- "\t interrupt %llu\n",counters[instance].interrupt);
-}
-
-void
-cpu_util_init(void)
-{
- kc = kstat_open();
-
- if (kc == NULL) {
- fprintf(where,
- "cpu_util_init: kstat_open: errno %d %s\n",
- errno,
- strerror(errno));
- fflush(where);
- exit(-1);
- }
- return;
-}
-
-void
-cpu_util_terminate(void)
-{
- kstat_close(kc);
- return;
-}
-
-int
-get_cpu_method(void)
-{
- return KSTAT_10;
-}
-
-static void
-print_unexpected_statistic_warning(char *who, char *what, char *why)
-{
- if (why) {
- fprintf(where,
- "WARNING! WARNING! WARNING! WARNING!\n");
- fprintf(where,
- "%s found an unexpected %s statistic %.16s\n",
- who,
- why,
- what);
- }
- else {
- fprintf(where,
- "%s is ignoring statistic %.16s\n",
- who,
- what);
- }
-}
-
-static void
-get_cpu_counters(int cpu_num, cpu_time_counters_t *counters)
-{
-
- kstat_t *ksp;
- int found=0;
- kid_t nkcid;
- kstat_named_t *knp;
- int i;
-
- ksp = kstat_lookup(kc, "cpu", cpu_num, "sys");
- if ((ksp) && (ksp->ks_type == KSTAT_TYPE_NAMED)) {
- /* happiness and joy, keep going */
- nkcid = kstat_read(kc, ksp, NULL);
- if (nkcid != -1) {
- /* happiness and joy, keep going. we could consider adding a
- "found < 3" to the end conditions, but then we wouldn't
- search to the end and find that Sun added some nsec. we
- probably want to see if they add an nsec. raj 2005-01-28 */
- for (i = ksp->ks_ndata, knp = ksp->ks_data;
- i > 0;
- knp++,i--) {
- /* we would be hosed if the same name could appear twice */
- if (!strcmp("cpu_nsec_idle",knp->name)) {
- found++;
- counters[cpu_num].idle = knp->value.ui64;
- }
- else if (!strcmp("cpu_nsec_user",knp->name)) {
- found++;
- counters[cpu_num].user = knp->value.ui64;
- }
- else if (!strcmp("cpu_nsec_kernel",knp->name)) {
- found++;
- counters[cpu_num].kernel = knp->value.ui64;
- }
- else if (strstr(knp->name,"nsec")) {
- /* finding another nsec here means Sun have changed
- something and we need to warn the user. raj 2005-01-28 */
- print_unexpected_statistic_warning("get_cpu_counters",
- knp->name,
- "nsec");
- }
- else if (debug >=2) {
-
- /* might want to tell people about what we are skipping.
- however, only display other names debug >=2. raj
- 2005-01-28
- */
-
- print_unexpected_statistic_warning("get_cpu_counters",
- knp->name,
- NULL);
- }
- }
- if (3 == found) {
- /* happiness and joy */
- return;
- }
- else {
- fprintf(where,
- "get_cpu_counters could not find one or more of the expected counters!\n");
- fflush(where);
- exit(-1);
- }
- }
- else {
- /* the kstat_read returned an error or the chain changed */
- fprintf(where,
- "get_cpu_counters: kstat_read failed or chain id changed %d %s\n",
- errno,
- strerror(errno));
- fflush(where);
- exit(-1);
- }
- }
- else {
- /* the lookup failed or found the wrong type */
- fprintf(where,
- "get_cpu_counters: kstat_lookup failed for module 'cpu' instance %d name 'sys' and KSTAT_TYPE_NAMED: errno %d %s\n",
- cpu_num,
- errno,
- strerror(errno));
- fflush(where);
- exit(-1);
- }
-}
-
-static void
-get_interrupt_counters(int cpu_num, cpu_time_counters_t *counters)
-{
- kstat_t *ksp;
- int found=0;
- kid_t nkcid;
- kstat_named_t *knp;
- int i;
-
- ksp = kstat_lookup(kc, "cpu", cpu_num, "intrstat");
-
- counters[cpu_num].interrupt = 0;
- if ((ksp) && (ksp->ks_type == KSTAT_TYPE_NAMED)) {
- /* happiness and joy, keep going */
- nkcid = kstat_read(kc, ksp, NULL);
- if (nkcid != -1) {
- /* happiness and joy, keep going. we could consider adding a
- "found < 15" to the end conditions, but then we wouldn't
- search to the end and find that Sun added some "time." we
- probably want to see if they add a "nsec." raj 2005-01-28 */
- for (i = ksp->ks_ndata, knp = ksp->ks_data;
- i > 0;
- knp++,i--) {
- if (strstr(knp->name,"time")) {
- found++;
- counters[cpu_num].interrupt += knp->value.ui64;
- }
- else if (debug >=2) {
-
- /* might want to tell people about what we are skipping.
- however, only display other names debug >=2. raj
- 2005-01-28
- */
-
- print_unexpected_statistic_warning("get_cpu_counters",
- knp->name,
- NULL);
- }
- }
- if (15 == found) {
- /* happiness and joy */
- return;
- }
- else {
- fprintf(where,
- "get_cpu_counters could not find one or more of the expected counters!\n");
- fflush(where);
- exit(-1);
- }
- }
- else {
- /* the kstat_read returned an error or the chain changed */
- fprintf(where,
- "get_cpu_counters: kstat_read failed or chain id changed %d %s\n",
- errno,
- strerror(errno));
- fflush(where);
- exit(-1);
- }
- }
- else {
- /* the lookup failed or found the wrong type */
- fprintf(where,
- "get_cpu_counters: kstat_lookup failed for module 'cpu' instance %d class 'intrstat' and KSTAT_TYPE_NAMED: errno %d %s\n",
- cpu_num,
- errno,
- strerror(errno));
- fflush(where);
- exit(-1);
- }
-
-}
-
-static void
-get_cpu_time_counters(cpu_time_counters_t *counters)
-{
-
- int i;
-
- for (i = 0; i < lib_num_loc_cpus; i++){
- get_cpu_counters(i, counters);
- get_interrupt_counters(i, counters);
- }
-
- return;
-}
-
-/* the kstat10 mechanism, since it is based on actual nanosecond
- counters is not going to use a comparison to an idle rate. so, the
- calibrate_idle_rate routine will be rather simple :) raj 2005-01-28
- */
-
-float
-calibrate_idle_rate(int iterations, int interval)
-{
- return 0.0;
-}
-
-float
-calc_cpu_util_internal(float elapsed_time)
-{
- int i;
- float correction_factor;
- float actual_rate;
-
- uint64_t total_cpu_nsec;
-
- /* multiply by 100 and divide by total and you get whole
- percentages. multiply by 1000 and divide by total and you get
- tenths of percentages. multiply by 10000 and divide by total and
- you get hundredths of percentages. etc etc etc raj 2005-01-28 */
-
-#define CALC_PERCENT 100
-#define CALC_TENTH_PERCENT 1000
-#define CALC_HUNDREDTH_PERCENT 10000
-#define CALC_THOUSANDTH_PERCENT 100000
-#define CALC_ACCURACY CALC_THOUSANDTH_PERCENT
-
- uint64_t fraction_idle;
- uint64_t fraction_user;
- uint64_t fraction_kernel;
- uint64_t fraction_interrupt;
-
- uint64_t interrupt_idle;
- uint64_t interrupt_user;
- uint64_t interrupt_kernel;
-
- lib_local_cpu_util = (float)0.0;
-
- /* It is possible that the library measured a time other than */
- /* the one that the user want for the cpu utilization */
- /* calculations - for example, tests that were ended by */
- /* watchdog timers such as the udp stream test. We let these */
- /* tests tell up what the elapsed time should be. */
-
- if (elapsed_time != 0.0) {
- correction_factor = (float) 1.0 +
- ((lib_elapsed - elapsed_time) / elapsed_time);
- }
- else {
- correction_factor = (float) 1.0;
- }
-
- for (i = 0; i < lib_num_loc_cpus; i++) {
-
- /* this is now the fun part. we have the nanoseconds _allegedly_
- spent in user, idle and kernel. We also have nanoseconds spent
- servicing interrupts. Sadly, in the developer's finite wisdom,
- the interrupt time accounting is in parallel with the other
- accounting. this means that time accounted in user, kernel or
- idle will also include time spent in interrupt. for netperf's
- porpoises we do not really care about that for user and kernel,
- but we certainly do care for idle. the $64B question becomes -
- how to "correct" for this?
-
- we could just subtract interrupt time from idle. that has the
- virtue of simplicity and also "punishes" Sun for doing
- something that seems to be so stupid. however, we probably
- have to be "fair" even to the allegedly stupid so the other
- mechanism, suggested by a Sun engineer is to subtract interrupt
- time from each of user, kernel and idle in proportion to their
- numbers. then we sum the corrected user, kernel and idle along
- with the interrupt time and use that to calculate a new idle
- percentage and thus a CPU util percentage.
-
- that is what we will attempt to do here. raj 2005-01-28
-
- of course, we also have to wonder what we should do if there is
- more interrupt time than the sum of user, kernel and idle.
- that is a theoretical possibility I suppose, but for the
- time-being, one that we will blythly ignore, except perhaps for
- a quick check. raj 2005-01-31
- */
-
- /* we ass-u-me that these counters will never wrap during a
- netperf run. this may not be a particularly safe thing to
- do. raj 2005-01-28 */
- delta_cpu_counters[i].idle = ending_cpu_counters[i].idle -
- starting_cpu_counters[i].idle;
- delta_cpu_counters[i].user = ending_cpu_counters[i].user -
- starting_cpu_counters[i].user;
- delta_cpu_counters[i].kernel = ending_cpu_counters[i].kernel -
- starting_cpu_counters[i].kernel;
- delta_cpu_counters[i].interrupt = ending_cpu_counters[i].interrupt -
- starting_cpu_counters[i].interrupt;
-
- if (debug) {
- print_cpu_time_counters("delta_cpu_counters",i,delta_cpu_counters);
- }
-
- /* for this summation, we do not include interrupt time */
- total_cpu_nsec =
- delta_cpu_counters[i].idle +
- delta_cpu_counters[i].user +
- delta_cpu_counters[i].kernel;
-
- if (debug) {
- fprintf(where,"total_cpu_nsec %llu\n",total_cpu_nsec);
- }
-
- if (delta_cpu_counters[i].interrupt > total_cpu_nsec) {
- /* we are not in Kansas any more Toto, and I am not quite sure
- the best way to get our tails out of here so let us just
- punt. raj 2005-01-31 */
- fprintf(where,
- "WARNING! WARNING! WARNING! WARNING! WARNING! \n");
- fprintf(where,
- "calc_cpu_util_internal: more interrupt time than others combined!\n");
- fprintf(where,
- "\tso CPU util cannot be estimated\n");
- fprintf(where,
- "\t delta[%d].interrupt %llu\n",i,delta_cpu_counters[i].interrupt);
- fprintf(where,
- "\t delta[%d].idle %llu\n",i,delta_cpu_counters[i].idle);
- fprintf(where,
- "\t delta[%d].user %llu\n",i,delta_cpu_counters[i].user);
- fprintf(where,
- "\t delta[%d].kernel %llu\n",i,delta_cpu_counters[i].kernel);
- fflush(where);
-
- lib_local_cpu_util = -1.0;
- lib_local_per_cpu_util[i] = -1.0;
- return -1.0;
- }
-
- /* and now some fun with integer math. i initially tried to
- promote things to long doubled but that didn't seem to result
- in happiness and joy. raj 2005-01-28 */
-
- fraction_idle =
- (delta_cpu_counters[i].idle * CALC_ACCURACY) / total_cpu_nsec;
-
- fraction_user =
- (delta_cpu_counters[i].user * CALC_ACCURACY) / total_cpu_nsec;
-
- fraction_kernel =
- (delta_cpu_counters[i].kernel * CALC_ACCURACY) / total_cpu_nsec;
-
- /* ok, we have our fractions, now we want to take that fraction of
- the interrupt time and subtract that from the bucket. */
-
- interrupt_idle = ((delta_cpu_counters[i].interrupt * fraction_idle) /
- CALC_ACCURACY);
-
- interrupt_user = ((delta_cpu_counters[i].interrupt * fraction_user) /
- CALC_ACCURACY);
-
- interrupt_kernel = ((delta_cpu_counters[i].interrupt * fraction_kernel) /
- CALC_ACCURACY);
-
- if (debug) {
- fprintf(where,
- "\tfraction_idle %llu interrupt_idle %llu\n",
- fraction_idle,
- interrupt_idle);
- fprintf(where,
- "\tfraction_user %llu interrupt_user %llu\n",
- fraction_user,
- interrupt_user);
- fprintf(where,"\tfraction_kernel %llu interrupt_kernel %llu\n",
- fraction_kernel,
- interrupt_kernel);
- }
-
- corrected_cpu_counters[i].idle = delta_cpu_counters[i].idle -
- interrupt_idle;
-
- corrected_cpu_counters[i].user = delta_cpu_counters[i].user -
- interrupt_user;
-
- corrected_cpu_counters[i].kernel = delta_cpu_counters[i].kernel -
- interrupt_kernel;
-
- corrected_cpu_counters[i].interrupt = delta_cpu_counters[i].interrupt;
-
- if (debug) {
- print_cpu_time_counters("corrected_cpu_counters",
- i,
- corrected_cpu_counters);
- }
-
- /* I was going to checkfor going less than zero, but since all the
- calculations are in unsigned quantities that would seem to be a
- triffle silly... raj 2005-01-28 */
-
- /* ok, now we sum the numbers again, this time including interrupt
- */
-
- total_cpu_nsec =
- corrected_cpu_counters[i].idle +
- corrected_cpu_counters[i].user +
- corrected_cpu_counters[i].kernel +
- corrected_cpu_counters[i].interrupt;
-
- /* and recalculate our fractions we are really only going to use
- fraction_idle, but lets calculate the rest just for the heck of
- it. one day we may want to display them. raj 2005-01-28 */
-
- /* multiply by 100 and divide by total and you get whole
- percentages. multiply by 1000 and divide by total and you get
- tenths of percentages. multiply by 10000 and divide by total
- and you get hundredths of percentages. etc etc etc raj
- 2005-01-28 */
- fraction_idle =
- (corrected_cpu_counters[i].idle * CALC_ACCURACY) / total_cpu_nsec;
-
- fraction_user =
- (corrected_cpu_counters[i].user * CALC_ACCURACY) / total_cpu_nsec;
-
- fraction_kernel =
- (corrected_cpu_counters[i].kernel * CALC_ACCURACY) / total_cpu_nsec;
-
- fraction_interrupt =
- (corrected_cpu_counters[i].interrupt * CALC_ACCURACY) / total_cpu_nsec;
-
- if (debug) {
- fprintf(where,"\tfraction_idle %lu\n",fraction_idle);
- fprintf(where,"\tfraction_user %lu\n",fraction_user);
- fprintf(where,"\tfraction_kernel %lu\n",fraction_kernel);
- fprintf(where,"\tfraction_interrupt %lu\n",fraction_interrupt);
- }
-
- /* and finally, what is our CPU utilization? */
- lib_local_per_cpu_util[i] = 100.0 - (((float)fraction_idle /
- (float)CALC_ACCURACY) * 100.0);
- if (debug) {
- fprintf(where,
- "lib_local_per_cpu_util[%d] %g\n",
- i,
- lib_local_per_cpu_util[i]);
- }
- lib_local_cpu_util += lib_local_per_cpu_util[i];
- }
- /* we want the average across all n processors */
- lib_local_cpu_util /= (float)lib_num_loc_cpus;
-
- lib_local_cpu_util *= correction_factor;
- return lib_local_cpu_util;
-
-
-}
-
-void
-cpu_start_internal(void)
-{
- get_cpu_time_counters(starting_cpu_counters);
- return;
-}
-
-void
-cpu_stop_internal(void)
-{
- get_cpu_time_counters(ending_cpu_counters);
-}
diff --git a/netcpu_looper.c b/netcpu_looper.c
deleted file mode 100644
index b76c7c9..0000000
--- a/netcpu_looper.c
+++ /dev/null
@@ -1,656 +0,0 @@
-char netcpu_looper_id[]="\
-@(#)netcpu_looper.c (c) Copyright 2005-2007. Version 2.4.3";
-
-/* netcpu_looper.c
-
- Implement the soaker process specific portions of netperf CPU
- utilization measurements. These are broken-out into a separate file
- to make life much nicer over in netlib.c which had become a maze of
- twisty, CPU-util-related, #ifdefs, all different. raj 2005-01-26
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-
-#ifdef HAVE_FCNTL_H
-# include <fcntl.h>
-#endif
-#if HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-#if defined(HAVE_MMAP) || defined(HAVE_SYS_MMAN_H)
-# include <sys/mman.h>
-#else
-# error netcpu_looper requires mmap
-#endif
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
-#if HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-
-#if HAVE_SYS_WAIT_H
-# include <sys/wait.h>
-#endif
-
-#ifdef HAVE_SIGNAL_H
-#include <signal.h>
-#endif
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-
-#include "netsh.h"
-#include "netlib.h"
-
-#define PAGES_PER_CHILD 2
-
-/* the lib_start_count and lib_end_count arrays hold the starting
- and ending values of whatever is counting when the system is
- idle. The rate at which this increments during a test is compared
- with a previous calibrarion to arrive at a CPU utilization
- percentage. raj 2005-01-26 */
-static uint64_t lib_start_count[MAXCPUS];
-static uint64_t lib_end_count[MAXCPUS];
-
-static int *cpu_mappings;
-
-static int lib_idle_fd;
-static uint64_t *lib_idle_address[MAXCPUS];
-static long *lib_base_pointer;
-static pid_t lib_idle_pids[MAXCPUS];
-static int lib_loopers_running=0;
-
-/* we used to use this code to bind the loopers, but since we have
- decided to enable processor affinity for the actual
- netperf/netserver processes we will use that affinity routine,
- which happens to know about more systems than this */
-
-#ifdef NOTDEF
-static void
-bind_to_processor(int child_num)
-{
- /* This routine will bind the calling process to a particular */
- /* processor. We are not choosy as to which processor, so it will be */
- /* the process id mod the number of processors - shifted by one for */
- /* those systems which name processor starting from one instead of */
- /* zero. on those systems where I do not yet know how to bind a */
- /* process to a processor, this routine will be a no-op raj 10/95 */
-
- /* just as a reminder, this is *only* for the looper processes, not */
- /* the actual measurement processes. those will, should, MUST float */
- /* or not float from CPU to CPU as controlled by the operating */
- /* system defaults. raj 12/95 */
-
-#ifdef __hpux
-#include <sys/syscall.h>
-#include <sys/mp.h>
-
- int old_cpu = -2;
-
- if (debug) {
- fprintf(where,
- "child %d asking for CPU %d as pid %d with %d CPUs\n",
- child_num,
- (child_num % lib_num_loc_cpus),
- getpid(),
- lib_num_loc_cpus);
- fflush(where);
- }
-
- SETPROCESS((child_num % lib_num_loc_cpus), getpid());
- return;
-
-#else
-#if defined(__sun) && defined(__SVR4)
- /* should only be Solaris */
-#include <sys/processor.h>
-#include <sys/procset.h>
-
- int old_binding;
-
- if (debug) {
- fprintf(where,
- "bind_to_processor: child %d asking for CPU %d as pid %d with %d CPUs\n",
- child_num,
- (child_num % lib_num_loc_cpus),
- getpid(),
- lib_num_loc_cpus);
- fflush(where);
- }
-
- if (processor_bind(P_PID,
- getpid(),
- (child_num % lib_num_loc_cpus),
- &old_binding) != 0) {
- fprintf(where,"bind_to_processor: unable to perform processor binding\n");
- fprintf(where," errno %d\n",errno);
- fflush(where);
- }
- return;
-#else
-#ifdef WIN32
-
- if (!SetThreadAffinityMask(GetCurrentThread(), (ULONG_PTR)1 << (child_num % lib_num_loc_cpus))) {
- perror("SetThreadAffinityMask failed");
- fflush(stderr);
- }
-
- if (debug) {
- fprintf(where,
- "bind_to_processor: child %d asking for CPU %d of %d CPUs\n",
- child_num,
- (child_num % lib_num_loc_cpus),
- lib_num_loc_cpus);
- fflush(where);
- }
-
-#endif
- return;
-#endif /* __sun && _SVR4 */
-#endif /* __hpux */
-}
-#endif
-
- /* sit_and_spin will just spin about incrementing a value */
- /* this value will either be in a memory mapped region on Unix shared */
- /* by each looper process, or something appropriate on Windows/NT */
- /* (malloc'd or such). This routine is reasonably ugly in that it has */
- /* priority manipulating code for lots of different operating */
- /* systems. This routine never returns. raj 1/96 */
-
-static void
-sit_and_spin(int child_index)
-
-{
- uint64_t *my_counter_ptr;
-
- /* only use C stuff if we are not WIN32 unless and until we */
- /* switch from CreateThread to _beginthread. raj 1/96 */
-#ifndef WIN32
- /* we are the child. we could decide to exec some separate */
- /* program, but that doesn't really seem worthwhile - raj 4/95 */
- if (debug > 1) {
- fprintf(where,
- "Looper child %d is born, pid %d\n",
- child_index,
- getpid());
- fflush(where);
- }
-
-#endif /* WIN32 */
-
- /* reset our base pointer to be at the appropriate offset */
- my_counter_ptr = (uint64_t *) ((char *)lib_base_pointer +
- (netlib_get_page_size() *
- PAGES_PER_CHILD * child_index));
-
- /* in the event we are running on an MP system, it would */
- /* probably be good to bind the soaker processes to specific */
- /* processors. I *think* this is the most reasonable thing to */
- /* do, and would be closes to simulating the information we get */
- /* on HP-UX with pstat. I could put all the system-specific code */
- /* here, but will "abstract it into another routine to keep this */
- /* area more readable. I'll probably do the same thine with the */
- /* "low pri code" raj 10/95 */
-
- /* since we are "flying blind" wrt where we should bind the looper
- processes, we want to use the cpu_map that was prepared by netlib
- rather than assume that the CPU ids on the system start at zero
- and are contiguous. raj 2006-04-03 */
- bind_to_specific_processor(child_index % lib_num_loc_cpus,1);
-
- for (*my_counter_ptr = 0L;
- ;
- (*my_counter_ptr)++) {
- if (!(*lib_base_pointer % 1)) {
- /* every once and again, make sure that our process priority is */
- /* nice and low. also, by making system calls, it may be easier */
- /* for us to be pre-empted by something that needs to do useful */
- /* work - like the thread of execution actually sending and */
- /* receiving data across the network :) */
-#ifdef _AIX
- int pid,prio;
-
- prio = PRIORITY;
- pid = getpid();
- /* if you are not root, this call will return EPERM - why one */
- /* cannot change one's own priority to lower value is beyond */
- /* me. raj 2/26/96 */
- setpri(pid, prio);
-#else /* _AIX */
-#ifdef __sgi
- int pid,prio;
-
- prio = PRIORITY;
- pid = getpid();
- schedctl(NDPRI, pid, prio);
- sginap(0);
-#else /* __sgi */
-#ifdef WIN32
- SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_IDLE);
-#else /* WIN32 */
-#if defined(__sun) && defined(__SVR4)
-#include <sys/types.h>
-#include <sys/priocntl.h>
-#include <sys/rtpriocntl.h>
-#include <sys/tspriocntl.h>
- /* I would *really* like to know how to use priocntl to make the */
- /* priority low for this looper process. however, either my mind */
- /* is addled, or the manpage in section two for priocntl is not */
- /* terribly helpful - for one, it has no examples :( so, if you */
- /* can help, I'd love to hear from you. in the meantime, we will */
- /* rely on nice(39). raj 2/26/96 */
- nice(39);
-#else /* __sun && __SVR4 */
- nice(39);
-#endif /* __sun && _SVR4 */
-#endif /* WIN32 */
-#endif /* __sgi */
-#endif /* _AIX */
- }
- }
-}
-
-
-
- /* this routine will start all the looper processes or threads for */
- /* measuring CPU utilization. */
-
-static void
-start_looper_processes()
-{
-
- unsigned int i, file_size;
-
- /* we want at least two pages for each processor. the */
- /* child for any one processor will write to the first of his two */
- /* pages, and the second page will be a buffer in case there is page */
- /* prefetching. if your system pre-fetches more than a single page, */
- /* well, you'll have to modify this or live with it :( raj 4/95 */
-
- file_size = ((netlib_get_page_size() * PAGES_PER_CHILD) *
- lib_num_loc_cpus);
-
-#ifndef WIN32
-
- /* we we are not using WINDOWS NT (or 95 actually :), then we want */
- /* to create a memory mapped region so we can see all the counting */
- /* rates of the loopers */
-
- /* could we just use an anonymous memory region for this? it is */
- /* possible that using a mmap()'ed "real" file, while convenient for */
- /* debugging, could result in some filesystem activity - like */
- /* metadata updates? raj 4/96 */
- lib_idle_fd = open("/tmp/netperf_cpu",O_RDWR | O_CREAT | O_EXCL);
-
- if (lib_idle_fd == -1) {
- fprintf(where,"create_looper: file creation; errno %d\n",errno);
- fflush(where);
- exit(1);
- }
-
- if (chmod("/tmp/netperf_cpu",0644) == -1) {
- fprintf(where,"create_looper: chmod; errno %d\n",errno);
- fflush(where);
- exit(1);
- }
-
- /* with the file descriptor in place, lets be sure that the file is */
- /* large enough. */
-
- if (truncate("/tmp/netperf_cpu",file_size) == -1) {
- fprintf(where,"create_looper: truncate: errno %d\n",errno);
- fflush(where);
- exit(1);
- }
-
- /* the file should be large enough now, so we can mmap it */
-
- /* if the system does not have MAP_VARIABLE, just define it to */
- /* be zero. it is only used/needed on HP-UX (?) raj 4/95 */
-#ifndef MAP_VARIABLE
-#define MAP_VARIABLE 0x0000
-#endif /* MAP_VARIABLE */
-#ifndef MAP_FILE
-#define MAP_FILE 0x0000
-#endif /* MAP_FILE */
- if ((lib_base_pointer = (long *)mmap(NULL,
- file_size,
- PROT_READ | PROT_WRITE,
- MAP_FILE | MAP_SHARED | MAP_VARIABLE,
- lib_idle_fd,
- 0)) == (long *)-1) {
- fprintf(where,"create_looper: mmap: errno %d\n",errno);
- fflush(where);
- exit(1);
- }
-
-
- if (debug > 1) {
- fprintf(where,"num CPUs %d, file_size %d, lib_base_pointer %p\n",
- lib_num_loc_cpus,
- file_size,
- lib_base_pointer);
- fflush(where);
- }
-
- /* we should have a valid base pointer. lets fork */
-
- for (i = 0; i < (unsigned int)lib_num_loc_cpus; i++) {
- switch (lib_idle_pids[i] = fork()) {
- case -1:
- perror("netperf: fork");
- exit(1);
- case 0:
- /* we are the child. we could decide to exec some separate */
- /* program, but that doesn't really seem worthwhile - raj 4/95 */
-
- signal(SIGTERM, SIG_DFL);
- sit_and_spin(i);
-
- /* we should never really get here, but if we do, just exit(0) */
- exit(0);
- break;
- default:
- /* we must be the parent */
- lib_idle_address[i] = (uint64_t *) ((char *)lib_base_pointer +
- (netlib_get_page_size() *
- PAGES_PER_CHILD * i));
- if (debug) {
- fprintf(where,"lib_idle_address[%d] is %p\n",
- i,
- lib_idle_address[i]);
- fflush(where);
- }
- }
- }
-#else
- /* we are compiled -DWIN32 */
- if ((lib_base_pointer = malloc(file_size)) == NULL) {
- fprintf(where,
- "create_looper_process could not malloc %d bytes\n",
- file_size);
- fflush(where);
- exit(1);
- }
-
- /* now, create all the threads */
- for(i = 0; i < (unsigned int)lib_num_loc_cpus; i++) {
- long place_holder;
- if ((lib_idle_pids[i] = CreateThread(0,
- 0,
- (LPTHREAD_START_ROUTINE)sit_and_spin,
- (LPVOID)(ULONG_PTR)i,
- 0,
- &place_holder)) == NULL ) {
- fprintf(where,
- "create_looper_process: CreateThread failed\n");
- fflush(where);
- /* I wonder if I need to look for other threads to kill? */
- exit(1);
- }
- lib_idle_address[i] = (long *) ((char *)lib_base_pointer +
- (netlib_get_page_size() *
- PAGES_PER_CHILD * i));
- if (debug) {
- fprintf(where,"lib_idle_address[%d] is %p\n",
- i,
- lib_idle_address[i]);
- fflush(where);
- }
- }
-#endif /* WIN32 */
-
- /* we need to have the looper processes settled-in before we do */
- /* anything with them, so lets sleep for say 30 seconds. raj 4/95 */
-
- sleep(30);
-}
-
-void
-cpu_util_init(void)
-{
- cpu_method = LOOPER;
-
- /* we want to get the looper processes going */
- if (!lib_loopers_running) {
- start_looper_processes();
- lib_loopers_running = 1;
- }
-
- return;
-}
-
-/* clean-up any left-over CPU util resources - looper processes,
- files, whatever. raj 2005-01-26 */
-void
-cpu_util_terminate() {
-
-#ifdef WIN32
- /* it would seem that if/when the process exits, all the threads */
- /* will go away too, so I don't think I need any explicit thread */
- /* killing calls here. raj 1/96 */
-#else
-
- int i;
-
- /* now go through and kill-off all the child processes */
- for (i = 0; i < lib_num_loc_cpus; i++){
- /* SIGKILL can leave core files behind - thanks to Steinar Haug */
- /* for pointing that out. */
- kill(lib_idle_pids[i],SIGTERM);
- }
- lib_loopers_running = 0;
- /* reap the children */
- while(waitpid(-1, NULL, WNOHANG) > 0) { }
-
- /* finally, unlink the mmaped file */
- munmap((caddr_t)lib_base_pointer,
- ((netlib_get_page_size() * PAGES_PER_CHILD) *
- lib_num_loc_cpus));
- unlink("/tmp/netperf_cpu");
-#endif
- return;
-}
-
-int
-get_cpu_method(void)
-{
- return LOOPER;
-}
-
- /* calibrate_looper */
-
- /* Loop a number of iterations, sleeping interval seconds each and */
- /* count how high the idle counter gets each time. Return the */
- /* measured cpu rate to the calling routine. raj 4/95 */
-
-float
-calibrate_idle_rate (int iterations, int interval)
-{
-
- uint64_t
- firstcnt[MAXCPUS],
- secondcnt[MAXCPUS];
-
- float
- elapsed,
- temp_rate,
- rate[MAXTIMES],
- local_maxrate;
-
- long
- sec,
- usec;
-
- int
- i,
- j;
-
- struct timeval time1, time2 ;
- struct timezone tz;
-
- if (iterations > MAXTIMES) {
- iterations = MAXTIMES;
- }
-
- local_maxrate = (float)-1.0;
-
- for(i = 0; i < iterations; i++) {
- rate[i] = (float)0.0;
- for (j = 0; j < lib_num_loc_cpus; j++) {
- firstcnt[j] = *(lib_idle_address[j]);
- }
- gettimeofday (&time1, &tz);
- sleep(interval);
- gettimeofday (&time2, &tz);
-
- if (time2.tv_usec < time1.tv_usec)
- {
- time2.tv_usec += 1000000;
- time2.tv_sec -=1;
- }
- sec = time2.tv_sec - time1.tv_sec;
- usec = time2.tv_usec - time1.tv_usec;
- elapsed = (float)sec + ((float)usec/(float)1000000.0);
-
- if(debug) {
- fprintf(where, "Calibration for counter run: %d\n",i);
- fprintf(where,"\tsec = %ld usec = %ld\n",sec,usec);
- fprintf(where,"\telapsed time = %g\n",elapsed);
- }
-
- for (j = 0; j < lib_num_loc_cpus; j++) {
- secondcnt[j] = *(lib_idle_address[j]);
- if(debug) {
- /* I know that there are situations where compilers know about */
- /* long long, but the library fucntions do not... raj 4/95 */
- fprintf(where,
- "\tfirstcnt[%d] = 0x%8.8lx%8.8lx secondcnt[%d] = 0x%8.8lx%8.8lx\n",
- j,
- (uint32_t)(firstcnt[j]>>32),
- (uint32_t)(firstcnt[j]&0xffffffff),
- j,
- (uint32_t)(secondcnt[j]>>32),
- (uint32_t)(secondcnt[j]&0xffffffff));
- }
- /* we assume that it would wrap no more than once. we also */
- /* assume that the result of subtracting will "fit" raj 4/95 */
- temp_rate = (secondcnt[j] >= firstcnt[j]) ?
- (float)(secondcnt[j] - firstcnt[j])/elapsed :
- (float)(secondcnt[j]-firstcnt[j]+MAXLONG)/elapsed;
- if (temp_rate > rate[i]) rate[i] = temp_rate;
- if(debug) {
- fprintf(where,"\trate[%d] = %g\n",i,rate[i]);
- fflush(where);
- }
- if (local_maxrate < rate[i]) local_maxrate = rate[i];
- }
- }
- if(debug) {
- fprintf(where,"\tlocal maxrate = %g per sec. \n",local_maxrate);
- fflush(where);
- }
- return local_maxrate;
-}
-
-
-void
-get_cpu_idle (uint64_t *res)
-{
- int i;
-
- for (i = 0; i < lib_num_loc_cpus; i++){
- res[i] = *lib_idle_address[i];
- }
-
-}
-
-float
-calc_cpu_util_internal(float elapsed_time)
-{
- int i;
- float correction_factor;
- float actual_rate;
-
- lib_local_cpu_util = (float)0.0;
- /* It is possible that the library measured a time other than */
- /* the one that the user want for the cpu utilization */
- /* calculations - for example, tests that were ended by */
- /* watchdog timers such as the udp stream test. We let these */
- /* tests tell up what the elapsed time should be. */
-
- if (elapsed_time != 0.0) {
- correction_factor = (float) 1.0 +
- ((lib_elapsed - elapsed_time) / elapsed_time);
- }
- else {
- correction_factor = (float) 1.0;
- }
-
- for (i = 0; i < lib_num_loc_cpus; i++) {
-
- /* it would appear that on some systems, in loopback, nice is
- *very* effective, causing the looper process to stop dead in its
- tracks. if this happens, we need to ensure that the calculation
- does not go south. raj 6/95 and if we run completely out of idle,
- the same thing could in theory happen to the USE_KSTAT path. raj
- 8/2000 */
-
- if (lib_end_count[i] == lib_start_count[i]) {
- lib_end_count[i]++;
- }
-
- actual_rate = (lib_end_count[i] > lib_start_count[i]) ?
- (float)(lib_end_count[i] - lib_start_count[i])/lib_elapsed :
- (float)(lib_end_count[i] - lib_start_count[i] +
- MAXLONG)/ lib_elapsed;
- if (debug) {
- fprintf(where,
- "calc_cpu_util: actual_rate on processor %d is %f start 0x%8.8lx%8.8lx end 0x%8.8lx%8.8lx\n",
- i,
- actual_rate,
- (uint32_t)(lib_start_count[i]>>32),
- (uint32_t)(lib_start_count[i]&0xffffffff),
- (uint32_t)(lib_end_count[i]>>32),
- (uint32_t)(lib_end_count[i]&0xffffffff));
- }
- lib_local_per_cpu_util[i] = (lib_local_maxrate - actual_rate) /
- lib_local_maxrate * 100;
- lib_local_cpu_util += lib_local_per_cpu_util[i];
- }
- /* we want the average across all n processors */
- lib_local_cpu_util /= (float)lib_num_loc_cpus;
-
- lib_local_cpu_util *= correction_factor;
- return lib_local_cpu_util;
-
-
-}
-void
-cpu_start_internal(void)
-{
- get_cpu_idle(lib_start_count);
- return;
-}
-
-void
-cpu_stop_internal(void)
-{
- get_cpu_idle(lib_end_count);
-}
diff --git a/netcpu_none.c b/netcpu_none.c
deleted file mode 100644
index f71b240..0000000
--- a/netcpu_none.c
+++ /dev/null
@@ -1,67 +0,0 @@
-char netcpu_none_id[]="\
-@(#)netcpu_none.c (c) Copyright 2005, Hewlett-Packard Company, Version 2.4.0";
-
-#if HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <stdio.h>
-
-#if HAVE_INTTYPES_H
-# include <inttypes.h>
-#else
-# if HAVE_STDINT_H
-# include <stdint.h>
-# endif
-#endif
-
-#include "netsh.h"
-#include "netlib.h"
-
-void
-cpu_util_init(void)
-{
- return;
-}
-
-void
-cpu_util_terminate(void)
-{
- return;
-}
-
-int
-get_cpu_method(void)
-{
- return CPU_UNKNOWN;
-}
-
-void
-get_cpu_idle(uint64_t *res)
-{
- return;
-}
-
-float
-calibrate_idle_rate(int iterations, int interval)
-{
- return 0.0;
-}
-
-float
-calc_cpu_util_internal(float elapsed_time)
-{
- return -1.0;
-}
-
-void
-cpu_start_internal(void)
-{
- return;
-}
-
-void
-cpu_stop_internal(void)
-{
- return;
-}
diff --git a/netcpu_ntperf.c b/netcpu_ntperf.c
deleted file mode 100644
index e8d8f76..0000000
--- a/netcpu_ntperf.c
+++ /dev/null
@@ -1,497 +0,0 @@
-char netcpu_ntperf_id[]="\
-@(#)netcpu_ntperf.c (c) Copyright 2005-2007, Hewlett-Packard Company, Version 2.4.3";
-
-#if HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <stdio.h>
-
-#if HAVE_INTTYPES_H
-# include <inttypes.h>
-#else
-# if HAVE_STDINT_H
-# include <stdint.h>
-# endif
-#endif
-
-#if 0
-#include <limits.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-#include <string.h>
-#endif
-
-#include <assert.h>
-
-#include <process.h>
-#include <time.h>
-
-#include <windows.h>
-#include <assert.h>
-
-#include <winsock2.h>
-// If you are trying to compile on Windows 2000 or NT 4.0 you may
-// need to define DONT_IPV6 in the "sources" files.
-#ifndef DONT_IPV6
-#include <ws2tcpip.h>
-#endif
-
-#include "netsh.h"
-#include "netlib.h"
-
-//
-// System CPU time information class.
-// Used to get CPU time information.
-//
-// SDK\inc\ntexapi.h
-// Function x8: SystemProcessorPerformanceInformation
-// DataStructure: SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
-//
-
-#define SystemProcessorPerformanceInformation 0x08
-
-typedef struct
-{
- LARGE_INTEGER IdleTime;
- LARGE_INTEGER KernelTime;
- LARGE_INTEGER UserTime;
- LARGE_INTEGER DpcTime;
- LARGE_INTEGER InterruptTime;
- LONG InterruptCount;
-} SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION, *PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION;
-
-//
-// Calls to get the information
-//
-typedef ULONG (__stdcall *NT_QUERY_SYSTEM_INFORMATION)(
- ULONG SystemInformationClass,
- PVOID SystemInformation,
- ULONG SystemInformationLength,
- PULONG ReturnLength
- );
-
-NT_QUERY_SYSTEM_INFORMATION NtQuerySystemInformation = NULL;
-
-
-static LARGE_INTEGER TickHz = {0,0};
-
-_inline LARGE_INTEGER ReadPerformanceCounter(VOID)
-{
- LARGE_INTEGER Counter;
- QueryPerformanceCounter(&Counter);
-
- return(Counter);
-} // ReadperformanceCounter
-
-
-/* The NT performance data is accessed through the NtQuerySystemInformation
- call. References to the PDH.DLL have been deleted. This structure
- is the root for these data structures. */
-
-typedef struct sPerfObj
-{
- LARGE_INTEGER StartTime;
- LARGE_INTEGER EndTime;
- SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION StartInfo[MAXCPUS +1];
- SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION EndInfo[MAXCPUS +1];
-} PerfObj, *PPerfObj;
-
-static PerfObj *PerfCntrs;
-
-// Forward declarations
-
-PerfObj *InitPerfCntrs();
-void RestartPerfCntrs(PerfObj *PerfCntrs);
-double ReportPerfCntrs(PerfObj *PerfCntrs); /* returns CPU utilization */
-void ClosePerfCntrs(PerfObj *PerfCntrs);
-
-
-void
-cpu_util_init(void)
-{
- if (NtQuerySystemInformation == NULL) {
- // Open the performance counter interface
- PerfCntrs = InitPerfCntrs();
- }
- return;
-}
-
-void
-cpu_util_terminate(void)
-{
- return;
-}
-
-int
-get_cpu_method(void)
-{
- return NT_METHOD;
-}
-
-typedef unsigned __int64 uint64_t;
-
-void
-get_cpu_idle(uint64_t *res)
-{
- RestartPerfCntrs(PerfCntrs);
- return;
-}
-
-float
-calibrate_idle_rate(int iterations, int interval)
-{
- return (float)0.0;
-}
-
-
-/*
- InitPerfCntrs() -
-
- Changed to no longer access the NT performance registry interfaces.
- A direct call to NtQuerySystemInformation (an undocumented NT API)
- is made instead. Parameters determined by decompilation of ntkrnlmp
- and ntdll.
-*/
-
-
-PerfObj *InitPerfCntrs()
-{
- PerfObj *NewPerfCntrs;
- DWORD NTVersion;
- DWORD status;
- SYSTEM_INFO SystemInfo;
-
- GetSystemInfo(&SystemInfo);
-
- NewPerfCntrs = (PerfObj *)GlobalAlloc(GPTR, sizeof(PerfObj));
- assert(NewPerfCntrs != NULL);
-
- ZeroMemory((PCHAR)NewPerfCntrs, sizeof(PerfObj));
-
- // get NT version
- NTVersion = GetVersion();
- if (NTVersion >= 0x80000000)
- {
- fprintf(stderr, "Not running on Windows NT\n");
- exit(1);
- }
-
- // locate the calls we need in NTDLL
- //Lint
- NtQuerySystemInformation =
- (NT_QUERY_SYSTEM_INFORMATION)GetProcAddress( GetModuleHandle("ntdll.dll"),
- "NtQuerySystemInformation" );
-
- if ( !(NtQuerySystemInformation) )
- {
- //Lint
- status = GetLastError();
- fprintf(stderr, "GetProcAddressFailed, status: %X\n", status);
- exit(1);
- }
-
- // setup to measure timestamps with the high resolution timers.
- if (QueryPerformanceFrequency(&TickHz) == FALSE)
- {
- fprintf(stderr,"MAIN - QueryPerformanceFrequency Failed!\n");
- exit(2);
- }
-
- RestartPerfCntrs(NewPerfCntrs);
-
- return(NewPerfCntrs);
-} /* InitPerfCntrs */
-
-/*
- RestartPerfCntrs() -
-
- The Performance counters must be read twice to produce rate and
- percentage results. This routine is called before the start of a
- benchmark to establish the initial counters. It must be called a
- second time after the benchmark completes to collect the final state
- of the performance counters. ReportPerfCntrs is called to print the
- results after the benchmark completes.
-*/
-
-void RestartPerfCntrs(PerfObj *PerfCntrs)
-{
- DWORD returnLength = 0; //Lint
- DWORD returnNumCPUs; //Lint
- DWORD i;
-
- DWORD status;
- SYSTEM_INFO SystemInfo;
-
- GetSystemInfo(&SystemInfo);
-
- // Move previous data from EndInfo to StartInfo.
- CopyMemory((PCHAR)&PerfCntrs->StartInfo[0],
- (PCHAR)&PerfCntrs->EndInfo[0],
- sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)*(MAXCPUS +1));
-
- PerfCntrs->StartTime = PerfCntrs->EndTime;
-
- // get the current CPUTIME information
- if ( (status = NtQuerySystemInformation( SystemProcessorPerformanceInformation,
- (PCHAR)&PerfCntrs->EndInfo[0], sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)*MAXCPUS,
- &returnLength )) != 0)
- {
- fprintf(stderr, "NtQuery failed, status: %X\n", status);
- exit(1);
- }
-
- PerfCntrs->EndTime = ReadPerformanceCounter();
-
- // Validate that NtQuery returned a reasonable amount of data
- if ((returnLength % sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)) != 0)
- {
- fprintf(stderr, "NtQuery didn't return expected amount of data\n");
- fprintf(stderr, "Expected a multiple of %i, returned %i\n",
- sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION), returnLength);
- exit(1);
- }
- returnNumCPUs = returnLength / sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION);
-
- if (returnNumCPUs != (int)SystemInfo.dwNumberOfProcessors)
- {
- fprintf(stderr, "NtQuery didn't return expected amount of data\n");
- fprintf(stderr, "Expected data for %i CPUs, returned %i\n",
- (int)SystemInfo.dwNumberOfProcessors, returnNumCPUs);
- exit(1);
- }
-
- // Zero entries not returned by NtQuery
- ZeroMemory((PCHAR)&PerfCntrs->EndInfo[returnNumCPUs],
- sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)*
- (MAXCPUS +1 - returnNumCPUs));
-
- // Total all of the CPUs
- // KernelTime needs to be fixed-up; it includes both idle &
- // true kernel time
- // Note that kernel time also includes DpcTime & InterruptTime, but
- // I like this.
- for (i=0; i < returnNumCPUs; i++)
- {
- PerfCntrs->EndInfo[i].KernelTime.QuadPart -= PerfCntrs->EndInfo[i].IdleTime.QuadPart;
- PerfCntrs->EndInfo[MAXCPUS].IdleTime.QuadPart += PerfCntrs->EndInfo[i].IdleTime.QuadPart;
- PerfCntrs->EndInfo[MAXCPUS].KernelTime.QuadPart += PerfCntrs->EndInfo[i].KernelTime.QuadPart;
- PerfCntrs->EndInfo[MAXCPUS].UserTime.QuadPart += PerfCntrs->EndInfo[i].UserTime.QuadPart;
- PerfCntrs->EndInfo[MAXCPUS].DpcTime.QuadPart += PerfCntrs->EndInfo[i].DpcTime.QuadPart;
- PerfCntrs->EndInfo[MAXCPUS].InterruptTime.QuadPart += PerfCntrs->EndInfo[i].InterruptTime.QuadPart;
- PerfCntrs->EndInfo[MAXCPUS].InterruptCount += PerfCntrs->EndInfo[i].InterruptCount;
- }
-
-} /* RestartPerfCntrs */
-
-/*
- ReportPerfCntrs() -
- This routine reports the results of the various performance
- counters.
-*/
-
-double ReportPerfCntrs(PerfObj *PerfCntrs)
-{
- double tot_CPU_Util;
- int i;
- int duration; // in 100 usecs
-
- LARGE_INTEGER ActualDuration;
-
- SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION DeltaInfo[MAXCPUS +1];
-
- LARGE_INTEGER TotalCPUTime[MAXCPUS +1];
-
- SYSTEM_INFO SystemInfo;
-
- GetSystemInfo(&SystemInfo);
-
- for (i=0; i <= MAXCPUS; i++)
- {
- DeltaInfo[i].IdleTime.QuadPart = PerfCntrs->EndInfo[i].IdleTime.QuadPart -
- PerfCntrs->StartInfo[i].IdleTime.QuadPart;
- DeltaInfo[i].KernelTime.QuadPart = PerfCntrs->EndInfo[i].KernelTime.QuadPart -
- PerfCntrs->StartInfo[i].KernelTime.QuadPart;
- DeltaInfo[i].UserTime.QuadPart = PerfCntrs->EndInfo[i].UserTime.QuadPart -
- PerfCntrs->StartInfo[i].UserTime.QuadPart;
- DeltaInfo[i].DpcTime.QuadPart = PerfCntrs->EndInfo[i].DpcTime.QuadPart -
- PerfCntrs->StartInfo[i].DpcTime.QuadPart;
- DeltaInfo[i].InterruptTime.QuadPart = PerfCntrs->EndInfo[i].InterruptTime.QuadPart -
- PerfCntrs->StartInfo[i].InterruptTime.QuadPart;
- DeltaInfo[i].InterruptCount = PerfCntrs->EndInfo[i].InterruptCount -
- PerfCntrs->StartInfo[i].InterruptCount;
-
- TotalCPUTime[i].QuadPart =
- DeltaInfo[i].IdleTime.QuadPart +
- DeltaInfo[i].KernelTime.QuadPart +
- DeltaInfo[i].UserTime.QuadPart;
- // KernelTime already includes DpcTime & InterruptTime!
- // + DeltaInfo[i].DpcTime.QuadPart +
- // DeltaInfo[i].InterruptTime.QuadPart;
- }
-
- tot_CPU_Util = 100.0*(1.0 - (double)DeltaInfo[MAXCPUS].IdleTime.QuadPart/(double)TotalCPUTime[MAXCPUS].QuadPart); //Lint
-
- // Re-calculate duration, since we may have stoped early due to cntr-C.
- ActualDuration.QuadPart = PerfCntrs->EndTime.QuadPart -
- PerfCntrs->StartTime.QuadPart;
-
- // convert to 1/10 milliseconds (100 usec)
- ActualDuration.QuadPart = (ActualDuration.QuadPart*10000)/TickHz.QuadPart;
- duration = ActualDuration.LowPart;
-
- if (verbosity > 1)
- {
- fprintf(where,"ActualDuration (ms): %d\n", duration/10);
- }
-
- if (verbosity > 1)
- {
- fprintf(where, "%% CPU _Total");
- if ((int)SystemInfo.dwNumberOfProcessors > 1)
- {
- for (i=0; i < (int)SystemInfo.dwNumberOfProcessors; i++)
- {
- fprintf(where, "\t CPU %i", i);
- }
- }
- fprintf(where, "\n");
-
- fprintf(where, "Busy %5.2f", tot_CPU_Util);
- if ((int)SystemInfo.dwNumberOfProcessors > 1)
- {
- for (i=0; i < (int)SystemInfo.dwNumberOfProcessors; i++)
- {
- fprintf(where, "\t %5.2f",
- 100.0*(1.0 - (double)DeltaInfo[i].IdleTime.QuadPart/(double)TotalCPUTime[i].QuadPart)); //Lint
- }
- }
- fprintf(where, "\n");
-
- fprintf(where, "Kernel %5.2f",
- 100.0*(double)DeltaInfo[MAXCPUS].KernelTime.QuadPart/(double)TotalCPUTime[MAXCPUS].QuadPart); //Lint
-
- if ((int)SystemInfo.dwNumberOfProcessors > 1)
- {
- for (i=0; i < (int)SystemInfo.dwNumberOfProcessors; i++)
- {
- fprintf(where, "\t %5.2f",
- 100.0*(double)DeltaInfo[i].KernelTime.QuadPart/(double)TotalCPUTime[i].QuadPart); //Lint
- }
- }
- fprintf(where, "\n");
-
- fprintf(where, "User %5.2f",
- 100.0*(double)DeltaInfo[MAXCPUS].UserTime.QuadPart/(double)TotalCPUTime[MAXCPUS].QuadPart);
-
- if ((int)SystemInfo.dwNumberOfProcessors > 1)
- {
- for (i=0; i < (int)SystemInfo.dwNumberOfProcessors; i++)
- {
- fprintf(where, "\t %5.2f",
- 100.0*(double)DeltaInfo[i].UserTime.QuadPart/TotalCPUTime[i].QuadPart); //Lint
- }
- }
- fprintf(where, "\n");
-
- fprintf(where, "Dpc %5.2f",
- 100.0*(double)DeltaInfo[MAXCPUS].DpcTime.QuadPart/(double)TotalCPUTime[MAXCPUS].QuadPart); //Lint
-
- if ((int)SystemInfo.dwNumberOfProcessors > 1)
- {
- for (i=0; i < (int)SystemInfo.dwNumberOfProcessors; i++)
- {
- fprintf(where, "\t %5.2f",
- 100.0*(double)DeltaInfo[i].DpcTime.QuadPart/(double)TotalCPUTime[i].QuadPart); //Lint
- }
- }
- fprintf(where, "\n");
-
- fprintf(where, "Interrupt %5.2f",
- 100.0*(double)DeltaInfo[MAXCPUS].InterruptTime.QuadPart/(double)TotalCPUTime[MAXCPUS].QuadPart); //Lint
-
- if ((int)SystemInfo.dwNumberOfProcessors > 1)
- {
- for (i=0; i < (int)SystemInfo.dwNumberOfProcessors; i++)
- {
- fprintf(where, "\t %5.2f",
- 100.0*(double)DeltaInfo[i].InterruptTime.QuadPart/TotalCPUTime[i].QuadPart); //Lint
- }
- }
- fprintf(where, "\n\n");
-
- fprintf(where, "Interrupt/Sec. %5.1f",
- (double)DeltaInfo[MAXCPUS].InterruptCount*10000.0/(double)duration);
-
- if ((int)SystemInfo.dwNumberOfProcessors > 1)
- {
- for (i=0; i < (int)SystemInfo.dwNumberOfProcessors; i++)
- {
- fprintf(where, "\t %5.1f",
- (double)DeltaInfo[i].InterruptCount*10000.0/(double)duration);
- }
- }
- fprintf(where, "\n\n");
- fflush(where);
- }
-
- return (tot_CPU_Util);
-
-} /* ReportPerfCntrs */
-
-/*
- ClosePerfCntrs() -
-
- This routine cleans up the performance counter APIs.
-*/
-
-void ClosePerfCntrs(PerfObj *PerfCntrs)
-{
- GlobalFree(PerfCntrs);
-
- NtQuerySystemInformation = NULL;
-} /* ClosePerfCntrs */
-
-void
-cpu_start_internal(void)
-{
- RestartPerfCntrs(PerfCntrs);
-}
-
-void
-cpu_stop_internal(void)
-{
- RestartPerfCntrs(PerfCntrs);
-}
-
-float
-calc_cpu_util_internal(float elapsed_time)
-{
- float correction_factor;
- lib_local_cpu_util = (float)0.0;
- /* It is possible that the library measured a time other than */
- /* the one that the user want for the cpu utilization */
- /* calculations - for example, tests that were ended by */
- /* watchdog timers such as the udp stream test. We let these */
- /* tests tell up what the elapsed time should be. */
-
- if (elapsed_time != 0.0) {
- correction_factor = (float) 1.0 +
- ((lib_elapsed - elapsed_time) / elapsed_time);
- }
- else {
- correction_factor = (float) 1.0;
- }
-
- if (debug) {
- fprintf(where, "correction factor: %f\n", correction_factor);
- }
-
- lib_local_cpu_util = (float)ReportPerfCntrs(PerfCntrs);
- lib_local_cpu_util *= correction_factor;
- return lib_local_cpu_util;
-
-}
diff --git a/netcpu_osx.c b/netcpu_osx.c
deleted file mode 100644
index 2132be1..0000000
--- a/netcpu_osx.c
+++ /dev/null
@@ -1,149 +0,0 @@
-char netcpu_sysctl_id[]="\
-@(#)netcpu_osx.c Version 2.4.3";
-
-#if HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <stdio.h>
-
-#if HAVE_INTTYPES_H
-# include <inttypes.h>
-#else
-# if HAVE_STDINT_H
-# include <stdint.h>
-# endif
-#endif
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-#if HAVE_LIMITS_H
-# include <limits.h>
-# ifndef LONG_LONG_MAX
-# define LONG_LONG_MAX LLONG_MAX
-# endif /* LONG_LONG_MAX */
-#endif
-
-
-#include <errno.h>
-
-#include <mach/host_info.h>
-#include <mach/mach_types.h>
-/* it would seem that on 10.3.9 mach_msg_type_number_t is in
- <mach/message.h> so we'll see about including that one too.
- hopefully it still exists in 10.4. if not, we will need to add some
- .h file checks in configure so we can use "HAVE_mumble" ifdefs
- here */
-#include <mach/message.h>
-
-#include "netsh.h"
-#include "netlib.h"
-
-#define UNSIGNED_DIFFERENCE(x,y) (x >= y ? x - y : (0 - y) + x )
-
-static host_cpu_load_info_data_t lib_start_ticks;
-static host_cpu_load_info_data_t lib_end_ticks;
-
-static mach_port_t lib_host_port;
-
-void
-cpu_util_init(void)
-{
- lib_host_port = mach_host_self();
- return;
-}
-
-void
-cpu_util_terminate(void)
-{
- mach_port_deallocate(lib_host_port);
- return;
-}
-
-int
-get_cpu_method(void)
-{
- return OSX;
-}
-
-void
-get_cpu_idle(uint64_t *res)
-{
- return;
-}
-
-void
-get_host_ticks(host_cpu_load_info_t info)
-{
- mach_msg_type_number_t count;
-
- count = HOST_CPU_LOAD_INFO_COUNT;
- host_statistics(lib_host_port, HOST_CPU_LOAD_INFO, (host_info_t)info, &count);
- return;
-}
-
-/* calibrate_sysctl - perform the idle rate calculation using the
- sysctl call - typically on BSD */
-
-float
-calibrate_idle_rate(int iterations, int interval)
-{
- return (float)0.0;
-}
-
-float
-calc_cpu_util_internal(float elapsed_time)
-{
- float correction_factor;
- natural_t userticks, systicks, idleticks, totalticks;
-
- lib_local_cpu_util = (float)0.0;
- /* It is possible that the library measured a time other than */
- /* the one that the user want for the cpu utilization */
- /* calculations - for example, tests that were ended by */
- /* watchdog timers such as the udp stream test. We let these */
- /* tests tell up what the elapsed time should be. */
-
- if (elapsed_time != 0.0) {
- correction_factor = (float) 1.0 +
- ((lib_elapsed - elapsed_time) / elapsed_time);
- }
- else {
- correction_factor = (float) 1.0;
- }
-
- if (debug) {
- fprintf(where, "correction factor: %f\n", correction_factor);
- }
-
- userticks = UNSIGNED_DIFFERENCE((lib_end_ticks.cpu_ticks[CPU_STATE_USER] + lib_end_ticks.cpu_ticks[CPU_STATE_NICE]),
- (lib_start_ticks.cpu_ticks[CPU_STATE_USER] + lib_start_ticks.cpu_ticks[CPU_STATE_NICE]));
- systicks = UNSIGNED_DIFFERENCE(lib_end_ticks.cpu_ticks[CPU_STATE_SYSTEM], lib_start_ticks.cpu_ticks[CPU_STATE_SYSTEM]);
- idleticks = UNSIGNED_DIFFERENCE(lib_end_ticks.cpu_ticks[CPU_STATE_IDLE], lib_start_ticks.cpu_ticks[CPU_STATE_IDLE]);
- totalticks = userticks + systicks + idleticks;
-
- lib_local_cpu_util = ((float)userticks + (float)systicks)/(float)totalticks * 100.0f;
- lib_local_cpu_util *= correction_factor;
-
- return lib_local_cpu_util;
-
-}
-void
-cpu_start_internal(void)
-{
- get_host_ticks(&lib_start_ticks);
-}
-
-void
-cpu_stop_internal(void)
-{
- get_host_ticks(&lib_end_ticks);
-}
diff --git a/netcpu_perfstat.c b/netcpu_perfstat.c
deleted file mode 100644
index f928a25..0000000
--- a/netcpu_perfstat.c
+++ /dev/null
@@ -1,351 +0,0 @@
-char netcpu_perfstat_id[]="\
-@(#)netcpu_perfstat.c Version 2.4.0";
-
-#if HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <stdio.h>
-
-#if HAVE_INTTYPES_H
-# include <inttypes.h>
-#else
-# if HAVE_STDINT_H
-# include <stdint.h>
-# endif
-#endif
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
-#if HAVE_LIMITS_H
-# include <limits.h>
-# ifndef LONG_LONG_MAX
-# define LONG_LONG_MAX LLONG_MAX
-# endif /* LONG_LONG_MAX */
-#endif
-
-#include <errno.h>
-
-#include "netsh.h"
-#include "netlib.h"
-
-/* the lib_start_count and lib_end_count arrays hold the starting
- and ending values of whatever is counting when the system is
- idle. The rate at which this increments during a test is compared
- with a previous calibration to arrive at a CPU utilization
- percentage. raj 2005-01-26 */
-static uint64_t lib_start_count[MAXCPUS];
-static uint64_t lib_end_count[MAXCPUS];
-
-
-void
-cpu_util_init(void)
-{
- return;
-}
-
-void
-cpu_util_terminate(void)
-{
- return;
-}
-
-int
-get_cpu_method(void)
-{
- return PERFSTAT;
-}
-
-void
-get_cpu_idle(uint64_t *res)
-{
- perfstat_cpu_t *perfstat_buffer;
- perfstat_cpu_t *per_cpu_pointer;
- perfstat_id_t name;
- int i,ret;
-
- /* a name of "" will cause us to start from the beginning */
- strcpy(name.name,"");
- perfstat_buffer = (perfstat_cpu_t *)malloc(lib_num_loc_cpus *
- sizeof(perfstat_cpu_t));
- if (perfstat_buffer == NULL) {
- fprintf(where,
- "cpu_start: malloc failed errno %d\n",
- errno);
- fflush(where);
- exit(-1);
- }
-
- /* happiness and joy, keep going */
- ret = perfstat_cpu(&name,
- perfstat_buffer,
- sizeof(perfstat_cpu_t),
- lib_num_loc_cpus);
-
- if ((ret == -1) ||
- (ret != lib_num_loc_cpus)) {
- fprintf(where,
- "cpu_start: perfstat_cpu failed/count off; errno %d cpus %d count %d\n",
- errno,
- lib_num_loc_cpus,
- ret);
- fflush(where);
- exit(-1);
- }
-
- per_cpu_pointer = perfstat_buffer;
- for (i = 0; i < lib_num_loc_cpus; i++){
- res[i] = per_cpu_pointer->idle;
- per_cpu_pointer++;
- }
- free(perfstat_buffer);
-
- return;
-}
-
-float
-calibrate_idle_rate(int iterations, int interval)
-{
- unsigned long long
- firstcnt[MAXCPUS],
- secondcnt[MAXCPUS];
-
- float
- elapsed,
- temp_rate,
- rate[MAXTIMES],
- local_maxrate;
-
- long
- sec,
- usec;
-
- int
- i,
- j;
-
- struct timeval time1, time2 ;
- struct timezone tz;
-
- perfstat_cpu_t *perfstat_buffer;
- perfstat_cpu_t *per_cpu_pointer;
- perfstat_id_t name;
- int ret;
-
- if (debug) {
- fprintf(where,"enter calibrate_perfstat\n");
- fflush(where);
- }
-
- if (iterations > MAXTIMES) {
- iterations = MAXTIMES;
- }
-
- local_maxrate = (float)-1.0;
-
- perfstat_buffer = (perfstat_cpu_t *)malloc(lib_num_loc_cpus *
- sizeof(perfstat_cpu_t));
- if (perfstat_buffer == NULL) {
- fprintf(where,
- "calibrate_perfstat: malloc failed errno %d\n",
- errno);
- fflush(where);
- exit(-1);
- }
-
- for(i = 0; i < iterations; i++) {
- rate[i] = (float)0.0;
- /* a name of "" will cause us to start from the beginning */
- strcpy(name.name,"");
-
- /* happiness and joy, keep going */
- ret = perfstat_cpu(&name,
- perfstat_buffer,
- sizeof(perfstat_cpu_t),
- lib_num_loc_cpus);
-
- if ((ret == -1) ||
- (ret != lib_num_loc_cpus)) {
- fprintf(where,
- "calibrate_perfstat: perfstat_cpu failed/count off; errno %d cpus %d count %d\n",
- errno,
- lib_num_loc_cpus,
- ret);
- fflush(where);
- exit(-1);
- }
-
- per_cpu_pointer = perfstat_buffer;
- for (j = 0; j < lib_num_loc_cpus; j++) {
- firstcnt[j] = per_cpu_pointer->idle;
- per_cpu_pointer++;
- }
- gettimeofday (&time1, &tz);
- sleep(interval);
- gettimeofday (&time2, &tz);
-
- if (time2.tv_usec < time1.tv_usec)
- {
- time2.tv_usec += 1000000;
- time2.tv_sec -=1;
- }
- sec = time2.tv_sec - time1.tv_sec;
- usec = time2.tv_usec - time1.tv_usec;
- elapsed = (float)sec + ((float)usec/(float)1000000.0);
-
- /* happiness and joy, keep going */
- ret = perfstat_cpu(&name,
- perfstat_buffer,
- sizeof(perfstat_cpu_t),
- lib_num_loc_cpus);
-
- if ((ret == -1) ||
- (ret != lib_num_loc_cpus)) {
- fprintf(where,
- "calibrate_perfstat: perfstat_cpu failed/count off; errno %d cpus %d count %d\n",
- errno,
- lib_num_loc_cpus,
- ret);
- fflush(where);
- exit(-1);
- }
-
- per_cpu_pointer = perfstat_buffer;
-
- if(debug) {
- fprintf(where, "Calibration for perfstat counter run: %d\n",i);
- fprintf(where,"\tsec = %ld usec = %ld\n",sec,usec);
- fprintf(where,"\telapsed time = %g\n",elapsed);
- }
-
- for (j = 0; j < lib_num_loc_cpus; j++) {
- secondcnt[j] = per_cpu_pointer->idle;
- per_cpu_pointer++;
- if(debug) {
- /* I know that there are situations where compilers know about */
- /* long long, but the library functions do not... raj 4/95 */
- fprintf(where,
- "\tfirstcnt[%d] = 0x%8.8lx%8.8lx secondcnt[%d] = 0x%8.8lx%8.8lx\n",
- j,
- firstcnt[j],
- firstcnt[j],
- j,
- secondcnt[j],
- secondcnt[j]);
- }
- /* we assume that it would wrap no more than once. we also */
- /* assume that the result of subtracting will "fit" raj 4/95 */
- temp_rate = (secondcnt[j] >= firstcnt[j]) ?
- (float)(secondcnt[j] - firstcnt[j])/elapsed :
- (float)(secondcnt[j]-firstcnt[j]+MAXLONG)/elapsed;
- if (temp_rate > rate[i]) rate[i] = temp_rate;
- if(debug) {
- fprintf(where,"\trate[%d] = %g\n",i,rate[i]);
- fflush(where);
- }
- if (local_maxrate < rate[i]) local_maxrate = rate[i];
- }
- }
- if(debug) {
- fprintf(where,"\tlocal maxrate = %g per sec. \n",local_maxrate);
- fflush(where);
- }
- free(perfstat_buffer);
- return local_maxrate;
-}
-
-float
-calc_cpu_util_internal(float elapsed_time)
-{
- int i;
-
- float actual_rate;
- float correction_factor;
-
- lib_local_cpu_util = (float)0.0;
- /* It is possible that the library measured a time other than */
- /* the one that the user want for the cpu utilization */
- /* calculations - for example, tests that were ended by */
- /* watchdog timers such as the udp stream test. We let these */
- /* tests tell up what the elapsed time should be. */
-
- if (elapsed_time != 0.0) {
- correction_factor = (float) 1.0 +
- ((lib_elapsed - elapsed_time) / elapsed_time);
- }
- else {
- correction_factor = (float) 1.0;
- }
-
- /* this looks just like the looper case. at least I think it */
- /* should :) raj 4/95 */
- for (i = 0; i < lib_num_loc_cpus; i++) {
-
- /* we assume that the two are not more than a long apart. I */
- /* know that this is bad, but trying to go from long longs to */
- /* a float (perhaps a double) is boggling my mind right now. */
- /* raj 4/95 */
-
- long long
- diff;
-
- if (lib_end_count[i] >= lib_start_count[i]) {
- diff = lib_end_count[i] - lib_start_count[i];
- }
- else {
- diff = lib_end_count[i] - lib_start_count[i] + LONG_LONG_MAX;
- }
- actual_rate = (float) diff / lib_elapsed;
- lib_local_per_cpu_util[i] = (lib_local_maxrate - actual_rate) /
- lib_local_maxrate * 100;
- lib_local_cpu_util += lib_local_per_cpu_util[i];
- if (debug) {
- fprintf(where,
- "calc_cpu_util: actual_rate on cpu %d is %g max_rate %g cpu %6.2f\n",
- i,
- actual_rate,
- lib_local_maxrate,
- lib_local_per_cpu_util[i]);
- }
- }
-
- /* we want the average across all n processors */
- lib_local_cpu_util /= (float)lib_num_loc_cpus;
-
- if (debug) {
- fprintf(where,
- "calc_cpu_util: average across CPUs is %g\n",lib_local_cpu_util);
- }
-
- lib_local_cpu_util *= correction_factor;
-
- if (debug) {
- fprintf(where,
- "calc_cpu_util: returning %g\n",lib_local_cpu_util);
- }
-
- return lib_local_cpu_util;
-
-}
-void
-cpu_start_internal(void)
-{
- get_cpu_idle(lib_start_count);
- return;
-}
-
-void
-cpu_stop_internal(void)
-{
- get_cpu_idle(lib_end_count);
-}
-
diff --git a/netcpu_procstat.c b/netcpu_procstat.c
deleted file mode 100644
index 5bdadea..0000000
--- a/netcpu_procstat.c
+++ /dev/null
@@ -1,265 +0,0 @@
-char netcpu_procstat_id[]="\
-@(#)netcpu_procstat.c (c) Copyright 2005-2007 Version 2.4.3";
-
-/* netcpu_procstat.c
-
- Implement the /proc/stat specific portions of netperf CPU
- utilization measurements. These are broken-out into a separate file
- to make life much nicer over in netlib.c which had become a maze of
- twisty, CPU-util-related, #ifdefs, all different. raj 2005-01-26
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-
-#ifdef HAVE_FCNTL_H
-# include <fcntl.h>
-#endif
-#if HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-#if STDC_HEADERS
-# include <stdlib.h>
-# include <stddef.h>
-#else
-# if HAVE_STDLIB_H
-# include <stdlib.h>
-# endif
-#endif
-
-#include <string.h>
-
-#include "netsh.h"
-#include "netlib.h"
-
-/* the lib_start_count and lib_end_count arrays hold the starting
- and ending values of whatever is counting when the system is
- idle. The rate at which this increments during a test is compared
- with a previous calibrarion to arrive at a CPU utilization
- percentage. raj 2005-01-26 */
-static uint64_t lib_start_count[MAXCPUS];
-static uint64_t lib_end_count[MAXCPUS];
-
-
-/* The max. length of one line of /proc/stat cpu output */
-#define CPU_LINE_LENGTH ((8 * sizeof (long) / 3 + 1) * 4 + 8)
-#define PROC_STAT_FILE_NAME "/proc/stat"
-#define N_CPU_LINES(nr) (nr == 1 ? 1 : 1 + nr)
-
-static int proc_stat_fd = -1;
-static char *proc_stat_buf = NULL;
-static int proc_stat_buflen = 0;
-
-void
-cpu_util_init(void)
-{
-
- if (debug) {
- fprintf(where,
- "cpu_util_init enter, proc_stat_fd %d proc_stat_buf %p\n",
- proc_stat_fd,
- proc_stat_buf);
- fflush(where);
- }
- if (proc_stat_fd < 0) {
- proc_stat_fd = open (PROC_STAT_FILE_NAME, O_RDONLY, NULL);
- if (proc_stat_fd < 0) {
- fprintf (stderr, "Cannot open %s!\n", PROC_STAT_FILE_NAME);
- exit (1);
- };
- };
-
- if (!proc_stat_buf) {
- proc_stat_buflen = N_CPU_LINES (lib_num_loc_cpus) * CPU_LINE_LENGTH;
- if (debug) {
- fprintf(where,
- "lib_num_loc_cpus %d lines %d CPU_LINE_LENGTH %d proc_stat_buflen %d\n",
- lib_num_loc_cpus,
- N_CPU_LINES(lib_num_loc_cpus),
- CPU_LINE_LENGTH,
- proc_stat_buflen);
- fflush(where);
- }
- proc_stat_buf = (char *)malloc (proc_stat_buflen);
- if (!proc_stat_buf) {
- fprintf (stderr, "Cannot allocate buffer memory!\n");
- exit (1);
- }
- }
- return;
-}
-
-void
-cpu_util_terminate(void)
-{
- close(proc_stat_fd);
- proc_stat_fd = -1;
- free(proc_stat_buf);
- proc_stat_buf = NULL;
- return;
-}
-
-int
-get_cpu_method()
-{
- return PROC_STAT;
-}
-
-float
-calibrate_idle_rate (int iterations, int interval)
-{
- if (proc_stat_fd < 0) {
- proc_stat_fd = open (PROC_STAT_FILE_NAME, O_RDONLY, NULL);
- if (proc_stat_fd < 0) {
- fprintf (stderr, "Cannot open %s!\n", PROC_STAT_FILE_NAME);
- exit (1);
- };
- };
-
- if (!proc_stat_buf) {
- proc_stat_buflen = N_CPU_LINES (lib_num_loc_cpus) * CPU_LINE_LENGTH;
- if (debug) {
- fprintf(where,
- "calibrate: lib_num_loc_cpus %d lines %d CPU_LINE_LENGTH %d proc_stat_buflen %d\n",
- lib_num_loc_cpus,
- N_CPU_LINES(lib_num_loc_cpus),
- CPU_LINE_LENGTH,
- proc_stat_buflen);
- fflush(where);
- }
- proc_stat_buf = (char *)malloc (proc_stat_buflen);
- if (!proc_stat_buf) {
- fprintf (stderr, "Cannot allocate buffer memory!\n");
- exit (1);
- };
- };
-
- return sysconf (_SC_CLK_TCK);
-}
-
-void
-get_cpu_idle (uint64_t *res)
-{
- int space;
- int i;
- int n = lib_num_loc_cpus;
- char *p = proc_stat_buf;
-
- lseek (proc_stat_fd, 0, SEEK_SET);
- read (proc_stat_fd, p, proc_stat_buflen);
-
- if (debug) {
- fprintf(where,"proc_stat_buf '%.*s'\n",proc_stat_buflen,p);
- fflush(where);
- }
- /* Skip first line (total) on SMP */
- if (n > 1) p = strchr (p, '\n');
-
- /* Idle time is the 4th space-separated token */
- for (i = 0; i < n; i++) {
- for (space = 0; space < 4; space ++) {
- p = strchr (p, ' ');
- while (*++p == ' ');
- };
- res[i] = strtoul (p, &p, 10);
- if (debug) {
- fprintf(where,"res[%d] is %llu\n",i,res[i]);
- fflush(where);
- }
- p = strchr (p, '\n');
- };
-
-}
-
-/* take the initial timestamp and start collecting CPU utilization if
- requested */
-
-void
-measure_cpu_start()
-{
- cpu_method = PROC_STAT;
- get_cpu_idle(lib_start_count);
-}
-
-/* collect final CPU utilization raw data */
-void
-measure_cpu_stop()
-{
- get_cpu_idle(lib_end_count);
-}
-
-float
-calc_cpu_util_internal(float elapsed_time)
-{
- int i;
-
- float actual_rate;
- float correction_factor;
-
- lib_local_cpu_util = (float)0.0;
- /* It is possible that the library measured a time other than */
- /* the one that the user want for the cpu utilization */
- /* calculations - for example, tests that were ended by */
- /* watchdog timers such as the udp stream test. We let these */
- /* tests tell up what the elapsed time should be. */
-
- if (elapsed_time != 0.0) {
- correction_factor = (float) 1.0 +
- ((lib_elapsed - elapsed_time) / elapsed_time);
- }
- else {
- correction_factor = (float) 1.0;
- }
-
- for (i = 0; i < lib_num_loc_cpus; i++) {
-
- /* it would appear that on some systems, in loopback, nice is
- *very* effective, causing the looper process to stop dead in its
- tracks. if this happens, we need to ensure that the calculation
- does not go south. raj 6/95 and if we run completely out of idle,
- the same thing could in theory happen to the USE_KSTAT path. raj
- 8/2000 */
-
- if (lib_end_count[i] == lib_start_count[i]) {
- lib_end_count[i]++;
- }
-
- actual_rate = (lib_end_count[i] > lib_start_count[i]) ?
- (float)(lib_end_count[i] - lib_start_count[i])/lib_elapsed :
- (float)(lib_end_count[i] - lib_start_count[i] +
- MAXLONG)/ lib_elapsed;
- lib_local_per_cpu_util[i] = (lib_local_maxrate - actual_rate) /
- lib_local_maxrate * 100;
- if (debug) {
- fprintf(where,
- "calc_cpu_util: actual_rate on processor %d is %f start %llx end %llx util %f\n",
- i,
- actual_rate,
- lib_start_count[i],
- lib_end_count[i],
- lib_local_per_cpu_util[i]);
- }
- lib_local_cpu_util += lib_local_per_cpu_util[i];
- }
- /* we want the average across all n processors */
- lib_local_cpu_util /= (float)lib_num_loc_cpus;
-
- lib_local_cpu_util *= correction_factor;
- return lib_local_cpu_util;
-}
-
-void
-cpu_start_internal(void)
-{
- get_cpu_idle(lib_start_count);
- return;
-}
-
-void
-cpu_stop_internal(void)
-{
- get_cpu_idle(lib_end_count);
-}
diff --git a/netcpu_pstat.c b/netcpu_pstat.c
deleted file mode 100644
index 08f27c1..0000000
--- a/netcpu_pstat.c
+++ /dev/null
@@ -1,307 +0,0 @@
-char netcpu_pstat_id[]="\
-@(#)netcpu_pstat.c (c) Copyright 2005, Hewlett-Packard Company, Version 2.4.0";
-
-#if HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <stdio.h>
-
-#if HAVE_INTTYPES_H
-# include <inttypes.h>
-#else
-# if HAVE_STDINT_H
-# include <stdint.h>
-# endif
-#endif
-
-#if HAVE_LIMITS_H
-# include <limits.h>
-#endif
-
-#include <sys/dk.h>
-#include <sys/pstat.h>
-
-#ifndef PSTAT_IPCINFO
-# error Sorry, pstat() CPU utilization on 10.0 and later only
-#endif
-
-#include "netsh.h"
-#include "netlib.h"
-
-/* the lib_start_count and lib_end_count arrays hold the starting
- and ending values of whatever is counting when the system is
- idle. The rate at which this increments during a test is compared
- with a previous calibrarion to arrive at a CPU utilization
- percentage. raj 2005-01-26 */
-static uint64_t lib_start_count[MAXCPUS];
-static uint64_t lib_end_count[MAXCPUS];
-
-void
-cpu_util_init(void)
-{
- return;
-}
-
-void
-cpu_util_terminate(void)
-{
- return;
-}
-
-int
-get_cpu_method(void)
-{
- return HP_IDLE_COUNTER;
-}
-
-void
-get_cpu_idle(uint64_t *res)
-{
- /* get the idle sycle counter for each processor */
- struct pst_processor *psp;
- union overlay_u {
- long long full;
- long word[2];
- } *overlay;
-
- psp = (struct pst_processor *)malloc(lib_num_loc_cpus * sizeof(*psp));
- if (psp == NULL) {
- printf("malloc(%d) failed!\n", lib_num_loc_cpus * sizeof(*psp));
- exit(1);
- }
- if (pstat_getprocessor(psp, sizeof(*psp), lib_num_loc_cpus, 0) != -1) {
- int i;
- for (i = 0; i < lib_num_loc_cpus; i++) {
- overlay = (union overlay_u *)&(res[i]);
- overlay->word[0] = psp[i].psp_idlecycles.psc_hi;
- overlay->word[1] = psp[i].psp_idlecycles.psc_lo;
- if(debug) {
- fprintf(where,
- "\tres[%d] = 0x%8.8x%8.8x\n",
- i,
- hi_32(&res[i]),
- lo_32(&res[i]));
- fflush(where);
- }
- }
- free(psp);
- }
-}
-
-/* calibrate_pstat
- Loop a number of iterations, sleeping wait_time seconds each and
- count how high the idle counter gets each time. Return the measured
- cpu rate to the calling routine. */
-
-float
-calibrate_idle_rate(int iterations, int interval)
-{
-
- uint64_t
- firstcnt[MAXCPUS],
- secondcnt[MAXCPUS];
-
- float
- elapsed,
- temp_rate,
- rate[MAXTIMES],
- local_maxrate;
-
- long
- sec,
- usec;
-
- int
- i,
- j;
-
- long count;
-
- struct timeval time1, time2;
- struct timezone tz;
-
- struct pst_processor *psp;
-
- if (iterations > MAXTIMES) {
- iterations = MAXTIMES;
- }
-
- local_maxrate = -1.0;
-
- psp = (struct pst_processor *)malloc(lib_num_loc_cpus * sizeof(*psp));
- if (psp == NULL) {
- printf("malloc(%d) failed!\n", lib_num_loc_cpus * sizeof(*psp));
- exit(1);
- }
-
- for(i = 0; i < iterations; i++) {
- rate[i] = 0.0;
- /* get the idle sycle counter for each processor */
- if (pstat_getprocessor(psp, sizeof(*psp), lib_num_loc_cpus, 0) != -1) {
- for (j = 0; j < lib_num_loc_cpus; j++) {
- union overlay_u {
- long long full;
- long word[2];
- } *overlay;
- overlay = (union overlay_u *)&(firstcnt[j]);
- overlay->word[0] = psp[j].psp_idlecycles.psc_hi;
- overlay->word[1] = psp[j].psp_idlecycles.psc_lo;
- }
- }
- else {
- fprintf(where,"pstat_getprocessor failure errno %d\n",errno);
- fflush(where);
- exit(1);
- }
-
- gettimeofday (&time1, &tz);
- sleep(interval);
- gettimeofday (&time2, &tz);
-
- if (time2.tv_usec < time1.tv_usec)
- {
- time2.tv_usec += 1000000;
- time2.tv_sec -=1;
- }
- sec = time2.tv_sec - time1.tv_sec;
- usec = time2.tv_usec - time1.tv_usec;
- elapsed = (float)sec + ((float)usec/(float)1000000.0);
-
- if(debug) {
- fprintf(where, "Calibration for counter run: %d\n",i);
- fprintf(where,"\tsec = %ld usec = %ld\n",sec,usec);
- fprintf(where,"\telapsed time = %g\n",elapsed);
- }
-
- if (pstat_getprocessor(psp, sizeof(*psp), lib_num_loc_cpus, 0) != -1) {
- for (j = 0; j < lib_num_loc_cpus; j++) {
- union overlay_u {
- long long full;
- long word[2];
- } *overlay;
- overlay = (union overlay_u *)&(secondcnt[j]);
- overlay->word[0] = psp[j].psp_idlecycles.psc_hi;
- overlay->word[1] = psp[j].psp_idlecycles.psc_lo;
- if(debug) {
- /* I know that there are situations where compilers know about */
- /* long long, but the library fucntions do not... raj 4/95 */
- fprintf(where,
- "\tfirstcnt[%d] = 0x%8.8x%8.8x secondcnt[%d] = 0x%8.8x%8.8x\n",
- j,
- hi_32(&firstcnt[j]),
- lo_32(&firstcnt[j]),
- j,
- hi_32(&secondcnt[j]),
- lo_32(&secondcnt[j]));
- }
- temp_rate = (secondcnt[j] >= firstcnt[j]) ?
- (float)(secondcnt[j] - firstcnt[j] )/elapsed :
- (float)(secondcnt[j] - firstcnt[j] + LONG_LONG_MAX)/elapsed;
- if (temp_rate > rate[i]) rate[i] = temp_rate;
- if(debug) {
- fprintf(where,"\trate[%d] = %g\n",i,rate[i]);
- fflush(where);
- }
- if (local_maxrate < rate[i]) local_maxrate = rate[i];
- }
- }
- else {
- fprintf(where,"pstat failure; errno %d\n",errno);
- fflush(where);
- exit(1);
- }
- }
- if(debug) {
- fprintf(where,"\tlocal maxrate = %g per sec. \n",local_maxrate);
- fflush(where);
- }
- return local_maxrate;
-
-}
-
-float
-calc_cpu_util_internal(float elapsed_time)
-{
- int i;
-
- float actual_rate;
- float correction_factor;
-
- lib_local_cpu_util = (float)0.0;
- /* It is possible that the library measured a time other than */
- /* the one that the user want for the cpu utilization */
- /* calculations - for example, tests that were ended by */
- /* watchdog timers such as the udp stream test. We let these */
- /* tests tell up what the elapsed time should be. */
-
- if (elapsed_time != 0.0) {
- correction_factor = (float) 1.0 +
- ((lib_elapsed - elapsed_time) / elapsed_time);
- }
- else {
- correction_factor = (float) 1.0;
- }
-
- /* this looks just like the looper case. at least I think it */
- /* should :) raj 4/95 */
- for (i = 0; i < lib_num_loc_cpus; i++) {
-
- /* we assume that the two are not more than a long apart. I */
- /* know that this is bad, but trying to go from long longs to */
- /* a float (perhaps a double) is boggling my mind right now. */
- /* raj 4/95 */
-
- long long
- diff;
-
- if (lib_end_count[i] >= lib_start_count[i]) {
- diff = lib_end_count[i] - lib_start_count[i];
- }
- else {
- diff = lib_end_count[i] - lib_start_count[i] + LONG_LONG_MAX;
- }
- actual_rate = (float) diff / lib_elapsed;
- lib_local_per_cpu_util[i] = (lib_local_maxrate - actual_rate) /
- lib_local_maxrate * 100;
- lib_local_cpu_util += lib_local_per_cpu_util[i];
- if (debug) {
- fprintf(where,
- "calc_cpu_util: actual_rate on cpu %d is %g max_rate %g cpu %6.2f\n",
- i,
- actual_rate,
- lib_local_maxrate,
- lib_local_per_cpu_util[i]);
- }
- }
-
- /* we want the average across all n processors */
- lib_local_cpu_util /= (float)lib_num_loc_cpus;
-
- if (debug) {
- fprintf(where,
- "calc_cpu_util: average across CPUs is %g\n",lib_local_cpu_util);
- }
-
- lib_local_cpu_util *= correction_factor;
-
- if (debug) {
- fprintf(where,
- "calc_cpu_util: returning %g\n",lib_local_cpu_util);
- }
-
- return lib_local_cpu_util;
-
-}
-void
-cpu_start_internal(void)
-{
- get_cpu_idle(lib_start_count);
- return;
-}
-
-void
-cpu_stop_internal(void)
-{
- get_cpu_idle(lib_end_count);
-}
diff --git a/netcpu_pstatnew.c b/netcpu_pstatnew.c
deleted file mode 100644
index fd2d036..0000000
--- a/netcpu_pstatnew.c
+++ /dev/null
@@ -1,398 +0,0 @@
-char netcpu_pstatnew_id[]="\
-@(#)netcpu_pstatnew.c (c) Copyright 2005, Hewlett-Packard Company, Version 2.4.1";
-
-/* since we "know" that this interface is available only on 11.23 and
- later, and that 11.23 and later are strictly 64-bit kernels, we can
- arbitrarily set _PSTAT64 here and not have to worry about it up in
- the configure script and makefiles. raj 2005/09/06 */
-
-#if HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <stdio.h>
-
-#if HAVE_INTTYPES_H
-# include <inttypes.h>
-#else
-# if HAVE_STDINT_H
-# include <stdint.h>
-# endif
-#endif
-
-#include <unistd.h>
-
-#if HAVE_LIMITS_H
-# include <limits.h>
-#endif
-
-#include <sys/dk.h>
-#include <sys/pstat.h>
-
-/* HP-UX 11.23 seems to have added three other cycle counters to the
- original psp_idlecycles - one for user, one for kernel and one for
- interrupt. so, we can now use those to calculate CPU utilization
- without requiring any calibration phase. raj 2005-02-16 */
-
-#ifndef PSTAT_IPCINFO
-# error Sorry, pstat() CPU utilization on 10.0 and later only
-#endif
-
-typedef struct cpu_time_counters {
- uint64_t idle;
- uint64_t user;
- uint64_t kernel;
- uint64_t interrupt;
-} cpu_time_counters_t;
-
-uint64_t lib_iticksperclktick;
-
-#include "netsh.h"
-#include "netlib.h"
-
-/* the lib_start_count and lib_end_count arrays hold the starting
- and ending values of whatever is counting when the system is
- idle. The rate at which this increments during a test is compared
- with a previous calibrarion to arrive at a CPU utilization
- percentage. raj 2005-01-26 */
-
-static cpu_time_counters_t starting_cpu_counters[MAXCPUS];
-static cpu_time_counters_t ending_cpu_counters[MAXCPUS];
-static cpu_time_counters_t delta_cpu_counters[MAXCPUS];
-
-void
-cpu_util_init(void)
-{
- return;
-}
-
-void
-cpu_util_terminate(void)
-{
- return;
-}
-
-int
-get_cpu_method(void)
-{
- return HP_IDLE_COUNTER;
-}
-
-void
-get_cpu_counters(cpu_time_counters_t *res)
-{
- /* get the idle sycle counter for each processor. now while on a
- 64-bit kernel the ".psc_hi" and ".psc_lo" fields are 64 bits,
- only the bottom 32-bits are actually valid. don't ask me
- why, that is just the way it is. soo, we shift the psc_hi
- value by 32 bits and then just sum-in the psc_lo value. raj
- 2005/09/06 */
- struct pst_processor *psp;
-
- psp = (struct pst_processor *)malloc(lib_num_loc_cpus * sizeof(*psp));
- if (psp == NULL) {
- printf("malloc(%d) failed!\n", lib_num_loc_cpus * sizeof(*psp));
- exit(1);
- }
- if (pstat_getprocessor(psp, sizeof(*psp), lib_num_loc_cpus, 0) != -1) {
- int i;
- /* we use lib_iticksperclktick in our sanity checking. we
- ass-u-me it is the same value for each CPU - famous last
- words no doubt. raj 2005/09/06 */
- lib_iticksperclktick = psp[0].psp_iticksperclktick;
- for (i = 0; i < lib_num_loc_cpus; i++) {
- res[i].idle = (((uint64_t)psp[i].psp_idlecycles.psc_hi << 32) +
- psp[i].psp_idlecycles.psc_lo);
- if(debug) {
- fprintf(where,
- "\tidle[%d] = 0x%"PRIx64" ",
- i,
- res[i].idle);
- fflush(where);
- }
- res[i].user = (((uint64_t)psp[i].psp_usercycles.psc_hi << 32) +
- psp[i].psp_usercycles.psc_lo);
- if(debug) {
- fprintf(where,
- "user[%d] = 0x%"PRIx64" ",
- i,
- res[i].user);
- fflush(where);
- }
- res[i].kernel = (((uint64_t)psp[i].psp_systemcycles.psc_hi << 32) +
- psp[i].psp_systemcycles.psc_lo);
- if(debug) {
- fprintf(where,
- "kern[%d] = 0x%"PRIx64" ",
- i,
- res[i].kernel);
- fflush(where);
- }
- res[i].interrupt = (((uint64_t)psp[i].psp_interruptcycles.psc_hi << 32) +
- psp[i].psp_interruptcycles.psc_lo);
- if(debug) {
- fprintf(where,
- "intr[%d] = 0x%"PRIx64"\n",
- i,
- res[i].interrupt);
- fflush(where);
- }
- }
- free(psp);
- }
-}
-
-/* calibrate_pstatnew
- there really isn't anything much to do here since we have all the
- counters and use their ratios for CPU util measurement. raj
- 2005-02-16 */
-
-float
-calibrate_idle_rate(int iterations, int interval)
-{
- return 0.0;
-}
-
-static void
-print_cpu_time_counters(char *name, int instance, cpu_time_counters_t *counters)
-{
- fprintf(where,"%s[%d]:\n",name,instance);
- fprintf(where,
- "\t idle %llu\n",counters[instance].idle);
- fprintf(where,
- "\t user %llu\n",counters[instance].user);
- fprintf(where,
- "\t kernel %llu\n",counters[instance].kernel);
- fprintf(where,
- "\t interrupt %llu\n",counters[instance].interrupt);
-}
-
-float
-calc_cpu_util_internal(float elapsed_time)
-{
- int i;
-
- uint64_t total_cpu_cycles;
- uint64_t sanity_cpu_cycles;
-
-#ifndef USE_INTEGER_MATH
- double fraction_idle;
- double fraction_user;
- double fraction_kernel;
- double fraction_interrupt;
- double estimated_fraction_interrupt;
-#else
- uint64_t fraction_idle;
- uint64_t fraction_user;
- uint64_t fraction_kernel;
- uint64_t fraction_interrupt;
- uint64_t estimated_fraction_interrupt;
-
-#define CALC_PERCENT 100
-#define CALC_TENTH_PERCENT 1000
-#define CALC_HUNDREDTH_PERCENT 10000
-#define CALC_THOUSANDTH_PERCENT 100000
-#define CALC_ACCURACY CALC_THOUSANDTH_PERCENT
-
-#endif /* USE_INTEGER_MATH */
- float actual_rate;
- float correction_factor;
-
- lib_local_cpu_util = (float)0.0;
-
- /* It is possible that the library measured a time other than */
- /* the one that the user want for the cpu utilization */
- /* calculations - for example, tests that were ended by */
- /* watchdog timers such as the udp stream test. We let these */
- /* tests tell up what the elapsed time should be. */
-
- if (elapsed_time != 0.0) {
- correction_factor = (float) 1.0 +
- ((lib_elapsed - elapsed_time) / elapsed_time);
- }
- else {
- correction_factor = (float) 1.0;
- }
-
- /* calculate our sanity check on cycles */
- if (debug) {
- fprintf(where,
- "lib_elapsed %g _SC_CLK_TCK %d lib_iticksperclktick %"PRIu64"\n",
- lib_elapsed,
- sysconf(_SC_CLK_TCK),
- lib_iticksperclktick);
- }
-
- /* Ok, elsewhere I may have said that HP-UX 11.23 does the "right"
- thing in measuring user, kernel, interrupt and idle all together
- instead of overlapping interrupt with the others like an OS that
- shall not be named. However.... it seems there is a bug in the
- accounting for interrupt cycles, whereby the cycles do not get
- properly accounted. The sum of user, kernel, interrupt and idle
- does not equal the clock rate multiplied by the elapsed time.
- Some cycles go missing.
-
- Since we see agreement between netperf and glance/vsar with the
- old "pstat" mechanism, we can presume that the accounting for
- idle cycles is sufficiently accurate. So, while we will still do
- math with user, kernel and interrupt cycles, we will only
- caculate CPU utilization based on the ratio of idle to _real_
- total cycles. I am told that a "future release" of HP-UX will
- fix the interupt cycle accounting. raj 2005/09/14 */
-
- /* calculate what the sum of CPU cycles _SHOULD_ be */
- sanity_cpu_cycles = (uint64_t) ((double)lib_elapsed *
- (double) sysconf(_SC_CLK_TCK) * (double)lib_iticksperclktick);
-
- /* this looks just like the looper case. at least I think it */
- /* should :) raj 4/95 */
- for (i = 0; i < lib_num_loc_cpus; i++) {
-
- /* we ass-u-me that these counters will never wrap during a
- netperf run. this may not be a particularly safe thing to
- do. raj 2005-01-28 */
- delta_cpu_counters[i].idle = ending_cpu_counters[i].idle -
- starting_cpu_counters[i].idle;
- delta_cpu_counters[i].user = ending_cpu_counters[i].user -
- starting_cpu_counters[i].user;
- delta_cpu_counters[i].kernel = ending_cpu_counters[i].kernel -
- starting_cpu_counters[i].kernel;
- delta_cpu_counters[i].interrupt = ending_cpu_counters[i].interrupt -
- starting_cpu_counters[i].interrupt;
-
- if (debug) {
- print_cpu_time_counters("delta_cpu_counters",i,delta_cpu_counters);
- }
-
- /* now get the sum, which we ass-u-me does not overflow a 64-bit
- counter. raj 2005-02-16 */
- total_cpu_cycles =
- delta_cpu_counters[i].idle +
- delta_cpu_counters[i].user +
- delta_cpu_counters[i].kernel +
- delta_cpu_counters[i].interrupt;
-
- if (debug) {
- fprintf(where,
- "total_cpu_cycles %"PRIu64" sanity_cpu_cycles %"PRIu64" missing %"PRIu64"\n",
- total_cpu_cycles,
- sanity_cpu_cycles,
- sanity_cpu_cycles - total_cpu_cycles);
- }
-
- /* since HP-UX 11.23 does the _RIGHT_ thing and idle/user/kernel
- does _NOT_ overlap with interrupt, we do not have to apply any
- correction kludge. raj 2005-02-16 */
-
-#ifndef USE_INTEGER_MATH
- /* when the accounting for interrupt time gets its act together,
- we can use total_cpu_cycles rather than sanity_cpu_cycles, but
- until then, use sanity_cpu_ccles. raj 2005/09/14 */
-
- fraction_idle = (double)delta_cpu_counters[i].idle /
- (double)sanity_cpu_cycles;
-
- fraction_user = (double)delta_cpu_counters[i].user /
- (double)sanity_cpu_cycles;
-
- fraction_kernel = (double) delta_cpu_counters[i].kernel /
- (double)sanity_cpu_cycles;
-
- fraction_interrupt = (double)delta_cpu_counters[i].interrupt /
- (double)sanity_cpu_cycles;
-
- /* ass-u-me that it is only interrupt that is bogus, and assign
- all the "missing" cycles to it. raj 2005/09/14 */
- estimated_fraction_interrupt = ((double)delta_cpu_counters[i].interrupt +
- (sanity_cpu_cycles - total_cpu_cycles)) /
- (double)sanity_cpu_cycles;
-
- if (debug) {
- fprintf(where,"\tfraction_idle %g\n",fraction_idle);
- fprintf(where,"\tfraction_user %g\n",fraction_user);
- fprintf(where,"\tfraction_kernel %g\n",fraction_kernel);
- fprintf(where,"\tfraction_interrupt %g WARNING, possibly under-counted!\n",fraction_interrupt);
- fprintf(where,"\testimated_fraction_interrupt %g\n",
- estimated_fraction_interrupt);
- }
-
- /* and finally, what is our CPU utilization? */
- lib_local_per_cpu_util[i] = 100.0 - (fraction_idle * 100.0);
-#else
- /* and now some fun with integer math. i initially tried to
- promote things to long doubled but that didn't seem to result
- in happiness and joy. raj 2005-01-28 */
-
- /* multiply by 100 and divide by total and you get whole
- percentages. multiply by 1000 and divide by total and you get
- tenths of percentages. multiply by 10000 and divide by total
- and you get hundredths of percentages. etc etc etc raj
- 2005-01-28 */
-
- /* when the accounting for interrupt time gets its act together,
- we can use total_cpu_cycles rather than sanity_cpu_cycles, but
- until then, use sanity_cpu_ccles. raj 2005/09/14 */
-
- fraction_idle =
- (delta_cpu_counters[i].idle * CALC_ACCURACY) / sanity_cpu_cycles;
-
- fraction_user =
- (delta_cpu_counters[i].user * CALC_ACCURACY) / sanity_cpu_cycles;
-
- fraction_kernel =
- (delta_cpu_counters[i].kernel * CALC_ACCURACY) / sanity_cpu_cycles;
-
- fraction_interrupt =
- (delta_cpu_counters[i].interrupt * CALC_ACCURACY) / sanity_cpu_cycles;
-
-
- estimated_fraction_interrupt =
- ((delta_cpu_counters[i].interrupt +
- (sanity_cpu_cycles - total_cpu_cycles)) *
- CALC_ACCURACY) / sanity_cpu_cycles;
-
- if (debug) {
- fprintf(where,"\tfraction_idle %"PRIu64"\n",fraction_idle);
- fprintf(where,"\tfraction_user %"PRIu64"\n",fraction_user);
- fprintf(where,"\tfraction_kernel %"PRIu64"\n",fraction_kernel);
- fprintf(where,"\tfraction_interrupt %"PRIu64"WARNING, possibly under-counted!\n",fraction_interrupt);
- fprintf(where,"\testimated_fraction_interrupt %"PRIu64"\n",
- estimated_fraction_interrupt);
- }
-
- /* and finally, what is our CPU utilization? */
- lib_local_per_cpu_util[i] = 100.0 - (((float)fraction_idle /
- (float)CALC_ACCURACY) * 100.0);
-#endif
- if (debug) {
- fprintf(where,
- "lib_local_per_cpu_util[%d] %g\n",
- i,
- lib_local_per_cpu_util[i]);
- }
- lib_local_cpu_util += lib_local_per_cpu_util[i];
- }
- /* we want the average across all n processors */
- lib_local_cpu_util /= (float)lib_num_loc_cpus;
-
- lib_local_cpu_util *= correction_factor;
-
- if (debug) {
- fprintf(where,
- "calc_cpu_util: returning %g\n",lib_local_cpu_util);
- }
-
- return lib_local_cpu_util;
-
-}
-void
-cpu_start_internal(void)
-{
- get_cpu_counters(starting_cpu_counters);
-}
-
-void
-cpu_stop_internal(void)
-{
- get_cpu_counters(ending_cpu_counters);
-}
diff --git a/netcpu_sysctl.c b/netcpu_sysctl.c
deleted file mode 100644
index 919f62c..0000000
--- a/netcpu_sysctl.c
+++ /dev/null
@@ -1,127 +0,0 @@
-char netcpu_sysctl_id[]="\
-@(#)netcpu_sysctl.c Version 2.4.3";
-
-#if HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <stdio.h>
-#include <unistd.h>
-
-#if HAVE_INTTYPES_H
-# include <inttypes.h>
-#else
-# if HAVE_STDINT_H
-# include <stdint.h>
-# endif
-#endif
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-#if HAVE_LIMITS_H
-# include <limits.h>
-# ifndef LONG_LONG_MAX
-# define LONG_LONG_MAX LLONG_MAX
-# endif /* LONG_LONG_MAX */
-#endif
-
-
-#include <errno.h>
-
-/* need to have some sort of check for sys/sysctl.h versus sysctl.h */
-#include <sys/sysctl.h>
-
-
-/* this has been liberally cut and pasted from <sys/resource.h> on
- FreeBSD. in general, this would be a bad idea, but I don't want to
- have to do a _KERNEL define to get these and that is what
- sys/resource.h seems to want. raj 2002-03-03 */
-#define CP_USER 0
-#define CP_NICE 1
-#define CP_SYS 2
-#define CP_INTR 3
-#define CP_IDLE 4
-#define CPUSTATES 5
-
-
-#include "netsh.h"
-#include "netlib.h"
-
-static long lib_start_count[CPUSTATES];
-static long lib_end_count[CPUSTATES];
-
-void
-cpu_util_init(void)
-{
- return;
-}
-
-void
-cpu_util_terminate(void)
-{
- return;
-}
-
-int
-get_cpu_method(void)
-{
- return SYSCTL;
-}
-
-static void
-get_cpu_time(long *cpu_time)
-{
- size_t cpu_time_len = CPUSTATES * sizeof (cpu_time[0]);
-
- if (sysctlbyname("kern.cp_time", cpu_time, &cpu_time_len, NULL, 0) == -1) {
- fprintf (stderr, "Cannot get CPU time!\n");
- exit (1);
- }
-}
-
-/* calibrate_sysctl - perform the idle rate calculation using the
- sysctl call - typically on BSD */
-
-float
-calibrate_idle_rate(int iterations, int interval)
-{
- return sysconf (_SC_CLK_TCK);
-}
-
-float
-calc_cpu_util_internal(float elapsed_time)
-{
- long sum_idle, sum_busy;
- int i;
-
- for (sum_busy = 0, i = 0; i < CPUSTATES; i++) {
- if (i != CP_IDLE)
- sum_busy += lib_end_count[i] - lib_start_count[i];
- }
-
- sum_idle = lib_end_count[CP_IDLE] - lib_start_count[CP_IDLE];
- lib_local_cpu_util = (float)sum_busy / (float)(sum_busy + sum_idle);
- lib_local_cpu_util *= 100.0;
-
- return lib_local_cpu_util;
-
-}
-void
-cpu_start_internal(void)
-{
- get_cpu_time(lib_start_count);
-}
-
-void
-cpu_stop_internal(void)
-{
- get_cpu_time(lib_end_count);
-}
diff --git a/netlib.c b/netlib.c
deleted file mode 100644
index bee93c8..0000000
--- a/netlib.c
+++ /dev/null
@@ -1,4161 +0,0 @@
-char netlib_id[]="\
-@(#)netlib.c (c) Copyright 1993-2007 Hewlett-Packard Company. Version 2.4.3";
-
-
-/****************************************************************/
-/* */
-/* netlib.c */
-/* */
-/* the common utility routines available to all... */
-/* */
-/* establish_control() establish the control socket */
-/* calibrate_local_cpu() do local cpu calibration */
-/* calibrate_remote_cpu() do remote cpu calibration */
-/* send_request() send a request to the remote */
-/* recv_response() receive a response from remote */
-/* send_response() send a response to the remote */
-/* recv_request() recv a request from the remote */
-/* dump_request() dump request contents */
-/* dump_response() dump response contents */
-/* cpu_start() start measuring cpu */
-/* cpu_stop() stop measuring cpu */
-/* calc_cpu_util() calculate the cpu utilization */
-/* calc_service_demand() calculate the service demand */
-/* calc_thruput() calulate the tput in units */
-/* calibrate() really calibrate local cpu */
-/* identify_local() print local host information */
-/* identify_remote() print remote host information */
-/* format_number() format the number (KB, MB,etc) */
-/* format_units() return the format in english */
-/* msec_sleep() sleep for some msecs */
-/* start_timer() start a timer */
-/* */
-/* the routines you get when WANT_DLPI is defined... */
-/* */
-/* dl_open() open a file descriptor and */
-/* attach to the card */
-/* dl_mtu() find the MTU of the card */
-/* dl_bind() bind the sap do the card */
-/* dl_connect() sender's have of connect */
-/* dl_accpet() receiver's half of connect */
-/* dl_set_window() set the window size */
-/* dl_stats() retrieve statistics */
-/* dl_send_disc() initiate disconnect (sender) */
-/* dl_recv_disc() accept disconnect (receiver) */
-/****************************************************************/
-
-/****************************************************************/
-/* */
-/* Global include files */
-/* */
-/****************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
- /* It would seem that most of the includes being done here from */
- /* "sys/" actually have higher-level wrappers at just /usr/include. */
- /* This is based on a spot-check of a couple systems at my disposal. */
- /* If you have trouble compiling you may want to add "sys/" raj 10/95 */
-#include <limits.h>
-#include <signal.h>
-#ifdef MPE
-# define NSIG _NSIG
-#endif /* MPE */
-#include <sys/types.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-#include <string.h>
-#include <assert.h>
-#ifdef HAVE_ENDIAN_H
-#include <endian.h>
-#endif
-
-
-#ifndef WIN32
- /* at some point, I would like to get rid of all these "sys/" */
- /* includes where appropriate. if you have a system that requires */
- /* them, speak now, or your system may not comile later revisions of */
- /* netperf. raj 1/96 */
-#include <unistd.h>
-#include <sys/stat.h>
-#include <sys/times.h>
-#ifndef MPE
-#include <time.h>
-#include <sys/time.h>
-#endif /* MPE */
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <errno.h>
-#include <sys/utsname.h>
-#if !defined(MPE) && !defined(__VMS)
-#include <sys/param.h>
-#endif /* MPE */
-
-#else /* WIN32 */
-
-#include <process.h>
-#include <time.h>
-#include <winsock2.h>
-#define netperf_socklen_t socklen_t
-#include <windows.h>
-
-/* the only time someone should need to define DONT_IPV6 in the
- "sources" file is if they are trying to compile on Windows 2000 or
- NT4 and I suspect this may not be their only problem :) */
-#ifndef DONT_IPV6
-#include <ws2tcpip.h>
-#endif
-
-#include <windows.h>
-
-#define SIGALRM (14)
-#define sleep(x) Sleep((x)*1000)
-
-#endif /* WIN32 */
-
-#ifdef _AIX
-#include <sys/select.h>
-#include <sys/sched.h>
-#include <sys/pri.h>
-#define PRIORITY PRI_LOW
-#else/* _AIX */
-#ifdef __sgi
-#include <sys/prctl.h>
-#include <sys/schedctl.h>
-#define PRIORITY NDPLOMIN
-#endif /* __sgi */
-#endif /* _AIX */
-
-#ifdef WANT_DLPI
-#include <sys/stream.h>
-#include <sys/stropts.h>
-#include <sys/poll.h>
-#ifdef __osf__
-#include <sys/dlpihdr.h>
-#else /* __osf__ */
-#include <sys/dlpi.h>
-#ifdef __hpux
-#include <sys/dlpi_ext.h>
-#endif /* __hpux */
-#endif /* __osf__ */
-#endif /* WANT_DLPI */
-
-#ifdef HAVE_MPCTL
-#include <sys/mpctl.h>
-#endif
-
-#if !defined(HAVE_GETADDRINFO) || !defined(HAVE_GETNAMEINFO)
-# include "missing/getaddrinfo.h"
-#endif
-
-
-#ifdef WANT_HISTOGRAM
-#include "hist.h"
-#endif /* WANT_HISTOGRAM */
-/****************************************************************/
-/* */
-/* Local Include Files */
-/* */
-/****************************************************************/
-#define NETLIB
-#include "netlib.h"
-#include "netsh.h"
-#include "netcpu.h"
-
-/****************************************************************/
-/* */
-/* Global constants, macros and variables */
-/* */
-/****************************************************************/
-
-#if defined(WIN32) || defined(__VMS)
-struct timezone {
- int dummy ;
- } ;
-#ifndef __VMS
-SOCKET win_kludge_socket = INVALID_SOCKET;
-SOCKET win_kludge_socket2 = INVALID_SOCKET;
-#endif /* __VMS */
-#endif /* WIN32 || __VMS */
-
-#ifndef LONG_LONG_MAX
-#define LONG_LONG_MAX 9223372036854775807LL
-#endif /* LONG_LONG_MAX */
-
- /* older versions of netperf knew about the HP kernel IDLE counter. */
- /* this is now obsolete - in favor of either pstat(), times, or a */
- /* process-level looper process. we also now require support for the */
- /* "long" integer type. raj 4/95. */
-
-int
- lib_num_loc_cpus, /* the number of cpus in the system */
- lib_num_rem_cpus; /* how many we think are in the remote */
-
-#define PAGES_PER_CHILD 2
-
-int lib_use_idle;
-int cpu_method;
-
-struct timeval time1, time2;
-struct timezone tz;
-float lib_elapsed,
- lib_local_maxrate,
- lib_remote_maxrate,
- lib_local_cpu_util,
- lib_remote_cpu_util;
-
-float lib_local_per_cpu_util[MAXCPUS];
-int lib_cpu_map[MAXCPUS];
-
-int *request_array;
-int *response_array;
-
-/* INVALID_SOCKET == INVALID_HANDLE_VALUE == (unsigned int)(~0) == -1 */
-SOCKET netlib_control = INVALID_SOCKET;
-SOCKET server_sock = INVALID_SOCKET;
-
-/* global variables to hold the value for processor affinity */
-int local_proc_affinity,remote_proc_affinity = -1;
-
-/* these are to allow netperf to be run easily through those evil,
- end-to-end breaking things known as firewalls */
-char local_data_port[10];
-char remote_data_port[10];
-
-char *local_data_address=NULL;
-char *remote_data_address=NULL;
-
-int local_data_family=AF_UNSPEC;
-int remote_data_family=AF_UNSPEC;
-
- /* in the past, I was overlaying a structure on an array of ints. now */
- /* I am going to have a "real" structure, and point an array of ints */
- /* at it. the real structure will be forced to the same alignment as */
- /* the type "double." this change will mean that pre-2.1 netperfs */
- /* cannot be mixed with 2.1 and later. raj 11/95 */
-
-union netperf_request_struct netperf_request;
-union netperf_response_struct netperf_response;
-
-FILE *where;
-
-char libfmt = '?';
-
-#ifdef WANT_DLPI
-/* some stuff for DLPI control messages */
-#define DLPI_DATA_SIZE 2048
-
-unsigned long control_data[DLPI_DATA_SIZE];
-struct strbuf control_message = {DLPI_DATA_SIZE, 0, (char *)control_data};
-
-#endif /* WANT_DLPI */
-
-#ifdef WIN32
-HANDLE hAlarm = INVALID_HANDLE_VALUE;
-#endif
-
-int times_up;
-
-#ifdef WIN32
- /* we use a getopt implementation from net.sources */
-/*
- * get option letter from argument vector
- */
-int
- opterr = 1, /* should error messages be printed? */
- optind = 1, /* index into parent argv vector */
- optopt; /* character checked for validity */
-char
- *optarg; /* argument associated with option */
-
-#define EMSG ""
-
-#endif /* WIN32 */
-
-static int measuring_cpu;
-int
-netlib_get_page_size(void) {
-
- /* not all systems seem to have the sysconf for page size. for
- those which do not, we will assume that the page size is 8192
- bytes. this should be more than enough to be sure that there is
- no page or cache thrashing by looper processes on MP
- systems. otherwise that's really just too bad - such systems
- should define _SC_PAGE_SIZE - raj 4/95 */
-
-#ifndef _SC_PAGE_SIZE
-#ifdef WIN32
-
-SYSTEM_INFO SystemInfo;
-
- GetSystemInfo(&SystemInfo);
-
- return SystemInfo.dwPageSize;
-#else
- return(8192L);
-#endif /* WIN32 */
-#else
- return(sysconf(_SC_PAGE_SIZE));
-#endif /* _SC_PAGE_SIZE */
-
-}
-
-
-#ifdef WANT_INTERVALS
-static unsigned int usec_per_itvl;
-
-
-void
-stop_itimer()
-
-{
-
- struct itimerval new_interval;
- struct itimerval old_interval;
-
- new_interval.it_interval.tv_sec = 0;
- new_interval.it_interval.tv_usec = 0;
- new_interval.it_value.tv_sec = 0;
- new_interval.it_value.tv_usec = 0;
- if (setitimer(ITIMER_REAL,&new_interval,&old_interval) != 0) {
- /* there was a problem arming the interval timer */
- perror("netperf: setitimer");
- exit(1);
- }
- return;
-}
-#endif /* WANT_INTERVALS */
-
-
-
-#ifdef WIN32
-static void
-error(char *pch)
-{
- if (!opterr) {
- return; /* without printing */
- }
- fprintf(stderr, "%s: %s: %c\n",
- (NULL != program) ? program : "getopt", pch, optopt);
-}
-
-int
-getopt(int argc, char **argv, char *ostr)
-{
- static char *place = EMSG; /* option letter processing */
- register char *oli; /* option letter list index */
-
- if (!*place) {
- /* update scanning pointer */
- if (optind >= argc || *(place = argv[optind]) != '-' || !*++place) {
- return EOF;
- }
- if (*place == '-') {
- /* found "--" */
- ++optind;
- place = EMSG ; /* Added by shiva for Netperf */
- return EOF;
- }
- }
-
- /* option letter okay? */
- if ((optopt = (int)*place++) == (int)':'
- || !(oli = strchr(ostr, optopt))) {
- if (!*place) {
- ++optind;
- }
- error("illegal option");
- return BADCH;
- }
- if (*++oli != ':') {
- /* don't need argument */
- optarg = NULL;
- if (!*place)
- ++optind;
- } else {
- /* need an argument */
- if (*place) {
- optarg = place; /* no white space */
- } else if (argc <= ++optind) {
- /* no arg */
- place = EMSG;
- error("option requires an argument");
- return BADCH;
- } else {
- optarg = argv[optind]; /* white space */
- }
- place = EMSG;
- ++optind;
- }
- return optopt; /* return option letter */
-}
-#endif /* WIN32 */
-
-/*----------------------------------------------------------------------------
- * WIN32 implementation of perror, does not deal very well with WSA errors
- * The stdlib.h version of perror only deals with the ancient XENIX error codes.
- *
- * +*+SAF Why can't all WSA errors go through GetLastError? Most seem to...
- *--------------------------------------------------------------------------*/
-
-#ifdef WIN32
-void PrintWin32Error(FILE *stream, LPSTR text)
-{
- LPSTR szTemp;
- DWORD dwResult;
- DWORD dwError;
-
- dwError = GetLastError();
- dwResult = FormatMessage(
- FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ARGUMENT_ARRAY,
- NULL,
- dwError,
- LANG_NEUTRAL,
- (LPTSTR)&szTemp,
- 0,
- NULL );
-
- if (dwResult)
- fprintf(stream, "%s: %s\n", text, szTemp);
- else
- fprintf(stream, "%s: error 0x%x\n", text, dwError);
- fflush(stream);
-
- if (szTemp)
- LocalFree((HLOCAL)szTemp);
-}
-#endif /* WIN32 */
-
-
-char *
-inet_ttos(int type)
-{
- switch (type) {
- case SOCK_DGRAM:
- return("SOCK_DGRAM");
- break;
- case SOCK_STREAM:
- return("SOCK_STREAM");
- break;
- default:
- return("SOCK_UNKNOWN");
- }
-}
-
-
-
-char unknown[32];
-
-char *
-inet_ptos(int protocol) {
- switch (protocol) {
- case IPPROTO_TCP:
- return("IPPROTO_TCP");
- break;
- case IPPROTO_UDP:
- return("IPPROTO_UDP");
- break;
-#if defined(IPPROTO_SCTP)
- case IPPROTO_SCTP:
- return("IPPROTO_SCTP");
- break;
-#endif
- default:
- snprintf(unknown,sizeof(unknown),"IPPROTO_UNKNOWN(%d)",protocol);
- return(unknown);
- }
-}
-
-/* one of these days, this should not be required */
-#ifndef AF_INET_SDP
-#define AF_INET_SDP 27
-#define PF_INET_SDP AF_INET_SDP
-#endif
-
-char *
-inet_ftos(int family)
-{
- switch(family) {
- case AF_INET:
- return("AF_INET");
- break;
-#if defined(AF_INET6)
- case AF_INET6:
- return("AF_INET6");
- break;
-#endif
-#if defined(AF_INET_SDP)
- case AF_INET_SDP:
- return("AF_INET_SDP");
- break;
-#endif
- default:
- return("AF_UNSPEC");
- }
-}
-
-int
-inet_nton(int af, const void *src, char *dst, int cnt)
-
-{
-
- switch (af) {
- case AF_INET:
- /* magic constants again... :) */
- if (cnt >= 4) {
- memcpy(dst,src,4);
- return 4;
- }
- else {
- Set_errno(ENOSPC);
- return(-1);
- }
- break;
-#if defined(AF_INET6)
- case AF_INET6:
- if (cnt >= 16) {
- memcpy(dst,src,16);
- return(16);
- }
- else {
- Set_errno(ENOSPC);
- return(-1);
- }
- break;
-#endif
- default:
- Set_errno(EAFNOSUPPORT);
- return(-1);
- }
-}
-
-double
-ntohd(double net_double)
-
-{
- /* we rely on things being nicely packed */
- union {
- double whole_thing;
- unsigned int words[2];
- unsigned char bytes[8];
- } conv_rec;
-
- unsigned char scratch;
- int i;
-
- /* on those systems where ntohl is a no-op, we want to return the */
- /* original value, unchanged */
-
- if (ntohl(1L) == 1L) {
- return(net_double);
- }
-
- conv_rec.whole_thing = net_double;
-
- /* we know that in the message passing routines that ntohl will have */
- /* been called on the 32 bit quantities. we need to put those back */
- /* the way they belong before we swap */
- conv_rec.words[0] = htonl(conv_rec.words[0]);
- conv_rec.words[1] = htonl(conv_rec.words[1]);
-
- /* now swap */
- for (i=0; i<= 3; i++) {
- scratch = conv_rec.bytes[i];
- conv_rec.bytes[i] = conv_rec.bytes[7-i];
- conv_rec.bytes[7-i] = scratch;
- }
-
-#if defined(__FLOAT_WORD_ORDER) && defined(__BYTE_ORDER)
- if (__FLOAT_WORD_ORDER != __BYTE_ORDER) {
- /* Fixup mixed endian floating point machines */
- unsigned int scratch = conv_rec.words[0];
- conv_rec.words[0] = conv_rec.words[1];
- conv_rec.words[1] = scratch;
- }
-#endif
-
- return(conv_rec.whole_thing);
-
-}
-
-double
-htond(double host_double)
-
-{
- /* we rely on things being nicely packed */
- union {
- double whole_thing;
- unsigned int words[2];
- unsigned char bytes[8];
- } conv_rec;
-
- unsigned char scratch;
- int i;
-
- /* on those systems where ntohl is a no-op, we want to return the */
- /* original value, unchanged */
-
- if (ntohl(1L) == 1L) {
- return(host_double);
- }
-
- conv_rec.whole_thing = host_double;
-
- /* now swap */
- for (i=0; i<= 3; i++) {
- scratch = conv_rec.bytes[i];
- conv_rec.bytes[i] = conv_rec.bytes[7-i];
- conv_rec.bytes[7-i] = scratch;
- }
-
-#if defined(__FLOAT_WORD_ORDER) && defined(__BYTE_ORDER)
- if (__FLOAT_WORD_ORDER != __BYTE_ORDER) {
- /* Fixup mixed endian floating point machines */
- unsigned int scratch = conv_rec.words[0];
- conv_rec.words[0] = conv_rec.words[1];
- conv_rec.words[1] = scratch;
- }
-#endif
-
- /* we know that in the message passing routines htonl will */
- /* be called on the 32 bit quantities. we need to set things up so */
- /* that when this happens, the proper order will go out on the */
- /* network */
- conv_rec.words[0] = htonl(conv_rec.words[0]);
- conv_rec.words[1] = htonl(conv_rec.words[1]);
-
- return(conv_rec.whole_thing);
-
-}
-
-
-/* one of these days, this should be abstracted-out just like the CPU
- util stuff. raj 2005-01-27 */
-int
-get_num_cpus()
-
-{
-
- /* on HP-UX, even when we use the looper procs we need the pstat */
- /* call */
-
- int temp_cpus;
-
-#ifdef __hpux
-#include <sys/pstat.h>
-
- struct pst_dynamic psd;
-
- if (pstat_getdynamic((struct pst_dynamic *)&psd,
- (size_t)sizeof(psd), (size_t)1, 0) != -1) {
- temp_cpus = psd.psd_proc_cnt;
- }
- else {
- temp_cpus = 1;
- }
-
-#else
- /* MW: <unistd.h> was included for non-Windows systems above. */
- /* Thus if _SC_NPROC_ONLN is defined, we should be able to use sysconf. */
-#ifdef _SC_NPROCESSORS_ONLN
- temp_cpus = sysconf(_SC_NPROCESSORS_ONLN);
-
-#ifdef USE_PERFSTAT
- temp_cpus = perfstat_cpu(NULL,NULL, sizeof(perfstat_cpu_t), 0);
-#endif /* USE_PERFSTAT */
-
-#else /* no _SC_NPROCESSORS_ONLN */
-
-#ifdef WIN32
- SYSTEM_INFO SystemInfo;
- GetSystemInfo(&SystemInfo);
-
- temp_cpus = SystemInfo.dwNumberOfProcessors;
-#else
- /* we need to know some other ways to do this, or just fall-back on */
- /* a global command line option - raj 4/95 */
- temp_cpus = shell_num_cpus;
-#endif /* WIN32 */
-#endif /* _SC_NPROCESSORS_ONLN */
-#endif /* __hpux */
-
- if (temp_cpus > MAXCPUS) {
- fprintf(where,
- "Sorry, this system has more CPUs (%d) than I can handle (%d).\n",
- temp_cpus,
- MAXCPUS);
- fprintf(where,
- "Please alter MAXCPUS in netlib.h and recompile.\n");
- fflush(where);
- exit(1);
- }
-
- return(temp_cpus);
-
-}
-
-#ifdef WIN32
-#ifdef __GNUC__
- #define S64_SUFFIX(x) x##LL
-#else
- #define S64_SUFFIX(x) x##i64
-#endif
-
-/*
- * Number of 100 nanosecond units from 1/1/1601 to 1/1/1970
- */
-#define EPOCH_BIAS S64_SUFFIX(116444736000000000)
-
-/*
- * Union to facilitate converting from FILETIME to unsigned __int64
- */
-typedef union {
- unsigned __int64 ft_scalar;
- FILETIME ft_struct;
-} FT;
-
-void
-gettimeofday( struct timeval *tv , struct timezone *not_used )
-{
- FT nt_time;
- __int64 UnixTime; /* microseconds since 1/1/1970 */
-
- GetSystemTimeAsFileTime( &(nt_time.ft_struct) );
-
- UnixTime = ((nt_time.ft_scalar - EPOCH_BIAS) / S64_SUFFIX(10));
- tv->tv_sec = (long)(time_t)(UnixTime / S64_SUFFIX(1000000));
- tv->tv_usec = (unsigned long)(UnixTime % S64_SUFFIX(1000000));
-}
-#endif /* WIN32 */
-
-
-
-/************************************************************************/
-/* */
-/* signal catcher */
-/* */
-/************************************************************************/
-
-void
-#if defined(__hpux)
-catcher(sig, code, scp)
- int sig;
- int code;
- struct sigcontext *scp;
-#else
-catcher(int sig)
-#endif /* __hpux || __VMS */
-{
-
-#ifdef __hpux
- if (debug > 2) {
- fprintf(where,"caught signal %d ",sig);
- if (scp) {
- fprintf(where,"while in syscall %d\n",
- scp->sc_syscall);
- }
- else {
- fprintf(where,"null scp\n");
- }
- fflush(where);
- }
-#endif /* RAJ_DEBUG */
-
- switch(sig) {
-
- case SIGINT:
- fprintf(where,"netperf: caught SIGINT\n");
- fflush(where);
- exit(1);
- break;
- case SIGALRM:
- if (--test_len_ticks == 0) {
- /* the test is over */
- if (times_up != 0) {
- fprintf(where,"catcher: timer popped with times_up != 0\n");
- fflush(where);
- }
- times_up = 1;
-#if defined(WANT_INTERVALS) && !defined(WANT_SPIN)
- stop_itimer();
-#endif /* WANT_INTERVALS */
- break;
- }
- else {
-#ifdef WANT_INTERVALS
-#ifdef __hpux
- /* the test is not over yet and we must have been using the */
- /* interval timer. if we were in SYS_SIGSUSPEND we want to */
- /* re-start the system call. Otherwise, we want to get out of */
- /* the sigsuspend call. I NEED TO KNOW HOW TO DO THIS FOR OTHER */
- /* OPERATING SYSTEMS. If you know how, please let me know. rick */
- /* jones <raj@cup.hp.com> */
- if (scp->sc_syscall != SYS_SIGSUSPEND) {
- if (debug > 2) {
- fprintf(where,
- "catcher: Time to send burst > interval!\n");
- fflush(where);
- }
- scp->sc_syscall_action = SIG_RESTART;
- }
-#endif /* __hpux */
-#else /* WANT_INTERVALS */
- fprintf(where,
- "catcher: interval timer running unexpectedly!\n");
- fflush(where);
- times_up = 1;
-#endif /* WANT_INTERVALS */
- break;
- }
- }
- return;
-}
-
-
-void
-install_signal_catchers()
-
-{
- /* just a simple little routine to catch a bunch of signals */
-
-#ifndef WIN32
- struct sigaction action;
- int i;
-
- fprintf(where,"installing catcher for all signals\n");
- fflush(where);
-
- sigemptyset(&(action.sa_mask));
- action.sa_handler = catcher;
-
-#ifdef SA_INTERRUPT
- action.sa_flags = SA_INTERRUPT;
-#else /* SA_INTERRUPT */
- action.sa_flags = 0;
-#endif /* SA_INTERRUPT */
-
-
- for (i = 1; i <= NSIG; i++) {
- if (i != SIGALRM) {
- if (sigaction(i,&action,NULL) != 0) {
- fprintf(where,
- "Could not install signal catcher for sig %d, errno %d\n",
- i,
- errno);
- fflush(where);
-
- }
- }
- }
-#else
- return;
-#endif /* WIN32 */
-}
-
-
-#ifdef WIN32
-#define SIGALRM (14)
-void
-emulate_alarm( int seconds )
-{
- DWORD ErrorCode;
-
- /* Wait on this event for parm seconds. */
-
- ErrorCode = WaitForSingleObject(hAlarm, seconds*1000);
- if (ErrorCode == WAIT_FAILED)
- {
- perror("WaitForSingleObject failed");
- exit(1);
- }
-
- if (ErrorCode == WAIT_TIMEOUT)
- {
- /* WaitForSingleObject timed out; this means the timer
- wasn't canceled. */
-
- times_up = 1;
-
- /* We have yet to find a good way to fully emulate the effects */
- /* of signals and getting EINTR from system calls under */
- /* winsock, so what we do here is close the socket out from */
- /* under the other thread. It is rather kludgy, but should be */
- /* sufficient to get this puppy shipped. The concept can be */
- /* attributed/blamed :) on Robin raj 1/96 */
-
- if (win_kludge_socket != INVALID_SOCKET) {
- closesocket(win_kludge_socket);
- }
- if (win_kludge_socket2 != INVALID_SOCKET) {
- closesocket(win_kludge_socket2);
- }
- }
-}
-
-#endif /* WIN32 */
-
-void
-start_timer(int time)
-{
-
-#ifdef WIN32
- /*+*+SAF What if StartTimer is called twice without the first timer */
- /*+*+SAF expiring? */
-
- DWORD thread_id ;
- HANDLE tHandle;
-
- if (hAlarm == (HANDLE) INVALID_HANDLE_VALUE)
- {
- /* Create the Alarm event object */
- hAlarm = CreateEvent(
- (LPSECURITY_ATTRIBUTES) NULL, /* no security */
- FALSE, /* auto reset event */
- FALSE, /* init. state = reset */
- (void *)NULL); /* unnamed event object */
- if (hAlarm == (HANDLE) INVALID_HANDLE_VALUE)
- {
- perror("CreateEvent failure");
- exit(1);
- }
- }
- else
- {
- ResetEvent(hAlarm);
- }
-
-
- tHandle = CreateThread(0,
- 0,
- (LPTHREAD_START_ROUTINE)emulate_alarm,
- (LPVOID)(ULONG_PTR)time,
- 0,
- &thread_id ) ;
- CloseHandle(tHandle);
-
-#else /* not WIN32 */
-
-struct sigaction action;
-
-if (debug) {
- fprintf(where,"About to start a timer for %d seconds.\n",time);
- fflush(where);
-}
-
- action.sa_handler = catcher;
- sigemptyset(&(action.sa_mask));
- sigaddset(&(action.sa_mask),SIGALRM);
-
-#ifdef SA_INTERRUPT
- /* on some systems (SunOS 4.blah), system calls are restarted. we do */
- /* not want that */
- action.sa_flags = SA_INTERRUPT;
-#else /* SA_INTERRUPT */
- action.sa_flags = 0;
-#endif /* SA_INTERRUPT */
-
- if (sigaction(SIGALRM, &action, NULL) < 0) {
- fprintf(where,"start_timer: error installing alarm handler ");
- fprintf(where,"errno %d\n",errno);
- fflush(where);
- exit(1);
- }
-
- /* this is the easy case - just set the timer for so many seconds */
- if (alarm(time) != 0) {
- fprintf(where,
- "error starting alarm timer, errno %d\n",
- errno);
- fflush(where);
- }
-#endif /* WIN32 */
-
- test_len_ticks = 1;
-
-}
-
-
- /* this routine will disable any running timer */
-void
-stop_timer()
-{
-#ifndef WIN32
- alarm(0);
-#else
- /* at some point we may need some win32 equivalent */
- if (hAlarm != (HANDLE) INVALID_HANDLE_VALUE)
- {
- SetEvent(hAlarm);
- }
-#endif /* WIN32 */
-
-}
-
-
-#ifdef WANT_INTERVALS
- /* this routine will enable the interval timer and set things up so */
- /* that for a timed test the test will end at the proper time. it */
- /* should detect the presence of POSIX.4 timer_* routines one of */
- /* these days */
-void
-start_itimer(unsigned int interval_len_msec )
-{
-
- unsigned int ticks_per_itvl;
-
- struct itimerval new_interval;
- struct itimerval old_interval;
-
- /* if -DWANT_INTERVALS was used, we will use the ticking of the itimer to */
- /* tell us when the test is over. while the user will be specifying */
- /* some number of milliseconds, we know that the interval timer is */
- /* really in units of 1/HZ. so, to prevent the test from running */
- /* "long" it would be necessary to keep this in mind when calculating */
- /* the number of itimer events */
-
- ticks_per_itvl = ((interval_wate * sysconf(_SC_CLK_TCK) * 1000) /
- 1000000);
-
- if (ticks_per_itvl == 0) ticks_per_itvl = 1;
-
- /* how many usecs in each interval? */
- usec_per_itvl = ticks_per_itvl * (1000000 / sysconf(_SC_CLK_TCK));
-
- /* how many times will the timer pop before the test is over? */
- if (test_time > 0) {
- /* this was a timed test */
- test_len_ticks = (test_time * 1000000) / usec_per_itvl;
- }
- else {
- /* this was not a timed test, use MAXINT */
- test_len_ticks = INT_MAX;
- }
-
- if (debug) {
- fprintf(where,"setting the interval timer to %d sec %d usec ",
- usec_per_itvl / 1000000,
- usec_per_itvl % 1000000);
- fprintf(where,"test len %d ticks\n",
- test_len_ticks);
- fflush(where);
- }
-
- /* if this was not a timed test, then we really aught to enable the */
- /* signal catcher raj 2/95 */
-
- new_interval.it_interval.tv_sec = usec_per_itvl / 1000000;
- new_interval.it_interval.tv_usec = usec_per_itvl % 1000000;
- new_interval.it_value.tv_sec = usec_per_itvl / 1000000;
- new_interval.it_value.tv_usec = usec_per_itvl % 1000000;
- if (setitimer(ITIMER_REAL,&new_interval,&old_interval) != 0) {
- /* there was a problem arming the interval timer */
- perror("netperf: setitimer");
- exit(1);
- }
-}
-#endif /* WANT_INTERVALS */
-
-void
-netlib_init_cpu_map() {
-
- int i;
-#ifdef HAVE_MPCTL
- int num;
- i = 0;
- /* I go back and forth on whether this should be the system-wide set
- of calls, or if the processor set versions (sans the _SYS) should
- be used. at the moment I believe that the system-wide version
- should be used. raj 2006-04-03 */
- num = mpctl(MPC_GETNUMSPUS_SYS,0,0);
- lib_cpu_map[i] = mpctl(MPC_GETFIRSTSPU_SYS,0,0);
- for (i = 1;((i < num) && (i < MAXCPUS)); i++) {
- lib_cpu_map[i] = mpctl(MPC_GETNEXTSPU_SYS,lib_cpu_map[i-1],0);
- }
- /* from here, we set them all to -1 because if we launch more
- loopers than actual CPUs, well, I'm not sure why :) */
- for (; i < MAXCPUS; i++) {
- lib_cpu_map[i] = -1;
- }
-
-#else
- /* we assume that there is indeed a contiguous mapping */
- for (i = 0; i < MAXCPUS; i++) {
- lib_cpu_map[i] = i;
- }
-#endif
-}
-
-
-/****************************************************************/
-/* */
-/* netlib_init() */
-/* */
-/* initialize the performance library... */
-/* */
-/****************************************************************/
-
-void
-netlib_init()
-{
- int i;
-
- where = stdout;
-
- request_array = (int *)(&netperf_request);
- response_array = (int *)(&netperf_response);
-
- for (i = 0; i < MAXCPUS; i++) {
- lib_local_per_cpu_util[i] = 0.0;
- }
-
- /* on those systems where we know that CPU numbers may not start at
- zero and be contiguous, we provide a way to map from a
- contiguous, starting from 0 CPU id space to the actual CPU ids.
- at present this is only used for the netcpu_looper stuff because
- we ass-u-me that someone setting processor affinity from the
- netperf commandline will provide a "proper" CPU identifier. raj
- 2006-04-03 */
-
- netlib_init_cpu_map();
-
- if (debug) {
- fprintf(where,
- "netlib_init: request_array at %p\n",
- request_array);
- fprintf(where,
- "netlib_init: response_array at %p\n",
- response_array);
-
- fflush(where);
- }
-
-}
-
- /* this routine will conver the string into an unsigned integer. it */
- /* is used primarily for the command-line options taking a number */
- /* (such as the socket size) which could be rather large. If someone */
- /* enters 32M, then the number will be converted to 32 * 1024 * 1024. */
- /* If they inter 32m, the number will be converted to 32 * 1000 * */
- /* 1000 */
-unsigned int
-convert(char *string)
-
-{
- unsigned int base;
- base = atoi(string);
- if (strstr(string,"K")) {
- base *= 1024;
- }
- if (strstr(string,"M")) {
- base *= (1024 * 1024);
- }
- if (strstr(string,"G")) {
- base *= (1024 * 1024 * 1024);
- }
- if (strstr(string,"k")) {
- base *= (1000);
- }
- if (strstr(string,"m")) {
- base *= (1000 * 1000);
- }
- if (strstr(string,"g")) {
- base *= (1000 * 1000 * 1000);
- }
- return(base);
-}
-
-/* this routine is like convert, but it is used for an interval time
- specification instead of stuff like socket buffer or send sizes.
- it converts everything to microseconds for internal use. if there
- is an 'm' at the end it assumes the user provided milliseconds, s
- will imply seconds, u will imply microseconds. in the future n
- will imply nanoseconds but for now it will be ignored. if there is
- no suffix or an unrecognized suffix, it will be assumed the user
- provided milliseconds, which was the long-time netperf default. one
- of these days, we should probably revisit that nanosecond business
- wrt the return value being just an int rather than a uint64_t or
- something. raj 2006-02-06 */
-
-unsigned int
-convert_timespec(char *string) {
-
- unsigned int base;
- base = atoi(string);
- if (strstr(string,"m")) {
- base *= 1000;
- }
- else if (strstr(string,"u")) {
- base *= (1);
- }
- else if (strstr(string,"s")) {
- base *= (1000 * 1000);
- }
- else {
- base *= (1000);
- }
- return(base);
-}
-
-
- /* this routine will allocate a circular list of buffers for either */
- /* send or receive operations. each of these buffers will be aligned */
- /* and offset as per the users request. the circumference of this */
- /* ring will be controlled by the setting of send_width. the buffers */
- /* will be filled with data from the file specified in fill_file. if */
- /* fill_file is an empty string, the buffers will not be filled with */
- /* any particular data */
-
-struct ring_elt *
-allocate_buffer_ring(int width, int buffer_size, int alignment, int offset)
-{
-
- struct ring_elt *first_link = NULL;
- struct ring_elt *temp_link = NULL;
- struct ring_elt *prev_link;
-
- int i;
- int malloc_size;
- int bytes_left;
- int bytes_read;
- int do_fill;
-
- FILE *fill_source;
- char default_fill[] = "netperf";
- int fill_cursor = 0;
-
- malloc_size = buffer_size + alignment + offset;
-
- /* did the user wish to have the buffers pre-filled with data from a */
- /* particular source? */
- if (strcmp(fill_file,"") == 0) {
- do_fill = 0;
- fill_source = NULL;
- }
- else {
- do_fill = 1;
- fill_source = (FILE *)fopen(fill_file,"r");
- if (fill_source == (FILE *)NULL) {
- perror("Could not open requested fill file");
- exit(1);
- }
- }
-
- assert(width >= 1);
-
- prev_link = NULL;
- for (i = 1; i <= width; i++) {
- /* get the ring element */
- temp_link = (struct ring_elt *)malloc(sizeof(struct ring_elt));
- if (temp_link == NULL) {
- printf("malloc(%u) failed!\n", sizeof(struct ring_elt));
- exit(1);
- }
- /* remember the first one so we can close the ring at the end */
- if (i == 1) {
- first_link = temp_link;
- }
- temp_link->buffer_base = (char *)malloc(malloc_size);
- if (temp_link == NULL) {
- printf("malloc(%d) failed!\n", malloc_size);
- exit(1);
- }
-
-#ifndef WIN32
- temp_link->buffer_ptr = (char *)(( (long)(temp_link->buffer_base) +
- (long)alignment - 1) &
- ~((long)alignment - 1));
-#else
- temp_link->buffer_ptr = (char *)(( (ULONG_PTR)(temp_link->buffer_base) +
- (ULONG_PTR)alignment - 1) &
- ~((ULONG_PTR)alignment - 1));
-#endif
- temp_link->buffer_ptr += offset;
- /* is where the buffer fill code goes. */
- if (do_fill) {
- char *bufptr = temp_link->buffer_ptr;
- bytes_left = buffer_size;
- while (bytes_left) {
- if (((bytes_read = (int)fread(bufptr,
- 1,
- bytes_left,
- fill_source)) == 0) &&
- (feof(fill_source))){
- rewind(fill_source);
- }
- bufptr += bytes_read;
- bytes_left -= bytes_read;
- }
- }
- else {
- /* use the default fill to ID our data traffic on the
- network. it ain't exactly pretty, but it should work */
- int j;
- char *bufptr = temp_link->buffer_ptr;
- for (j = 0; j < buffer_size; j++) {
- bufptr[j] = default_fill[fill_cursor];
- fill_cursor += 1;
- /* the Windows DDK compiler with an x86_64 target wants a cast
- here */
- if (fill_cursor > (int)strlen(default_fill)) {
- fill_cursor = 0;
- }
- }
-
- }
- temp_link->next = prev_link;
- prev_link = temp_link;
- }
- if (first_link) { /* SAF Prefast made me do it... */
- first_link->next = temp_link;
- }
-
- return(first_link); /* it's a circle, doesn't matter which we return */
-}
-
-/* this routine will dirty the first dirty_count bytes of the
- specified buffer and/or read clean_count bytes from the buffer. it
- will go N bytes at a time, the only question is how large should N
- be and if we should be going continguously, or based on some
- assumption of cache line size */
-
-void
-access_buffer(char *buffer_ptr,int length, int dirty_count, int clean_count) {
-
- char *temp_buffer;
- char *limit;
- int i, dirty_totals;
-
- temp_buffer = buffer_ptr;
- limit = temp_buffer + length;
- dirty_totals = 0;
-
- for (i = 0;
- ((i < dirty_count) && (temp_buffer < limit));
- i++) {
- *temp_buffer += (char)i;
- dirty_totals += *temp_buffer;
- temp_buffer++;
- }
-
- for (i = 0;
- ((i < clean_count) && (temp_buffer < limit));
- i++) {
- dirty_totals += *temp_buffer;
- temp_buffer++;
- }
-
- if (debug > 100) {
- fprintf(where,
- "This was here to try to avoid dead-code elimination %d\n",
- dirty_totals);
- fflush(where);
- }
-}
-
-
-#ifdef HAVE_ICSC_EXS
-
-#include <sys/mman.h>
-#include <sys/exs.h>
-
- /* this routine will allocate a circular list of buffers for either */
- /* send or receive operations. each of these buffers will be aligned */
- /* and offset as per the users request. the circumference of this */
- /* ring will be controlled by the setting of send_width. the buffers */
- /* will be filled with data from the file specified in fill_file. if */
- /* fill_file is an empty string, the buffers will not be filled with */
- /* any particular data */
-
-struct ring_elt *
-allocate_exs_buffer_ring (int width, int buffer_size, int alignment, int offset, exs_mhandle_t *mhandlep)
-{
-
- struct ring_elt *first_link;
- struct ring_elt *temp_link;
- struct ring_elt *prev_link;
-
- int i;
- int malloc_size;
- int bytes_left;
- int bytes_read;
- int do_fill;
-
- FILE *fill_source;
-
- int mmap_size;
- char *mmap_buffer, *mmap_buffer_aligned;
-
- malloc_size = buffer_size + alignment + offset;
-
- /* did the user wish to have the buffers pre-filled with data from a */
- /* particular source? */
- if (strcmp (fill_file, "") == 0) {
- do_fill = 0;
- fill_source = NULL;
- } else {
- do_fill = 1;
- fill_source = (FILE *) fopen (fill_file, "r");
- if (fill_source == (FILE *) NULL) {
- perror ("Could not open requested fill file");
- exit (1);
- }
- }
-
- assert (width >= 1);
-
- if (debug) {
- fprintf (where, "allocate_exs_buffer_ring: "
- "width=%d buffer_size=%d alignment=%d offset=%d\n",
- width, buffer_size, alignment, offset);
- }
-
- /* allocate shared memory */
- mmap_size = width * malloc_size;
- mmap_buffer = (char *) mmap ((caddr_t)NULL, mmap_size+NBPG-1,
- PROT_READ|PROT_WRITE,
- MAP_SHARED|MAP_ANONYMOUS, -1, 0);
- if (mmap_buffer == NULL) {
- perror ("allocate_exs_buffer_ring: mmap failed");
- exit (1);
- }
- mmap_buffer_aligned = (char *) ((uintptr_t)mmap_buffer & ~(NBPG-1));
- if (debug) {
- fprintf (where, "allocate_exs_buffer_ring: "
- "mmap buffer size=%d address=0x%p aligned=0x%p\n",
- mmap_size, mmap_buffer, mmap_buffer_aligned);
- }
-
- /* register shared memory */
- *mhandlep = exs_mregister ((void *)mmap_buffer_aligned, (size_t)mmap_size, 0);
- if (*mhandlep == EXS_MHANDLE_INVALID) {
- perror ("allocate_exs_buffer_ring: exs_mregister failed");
- exit (1);
- }
- if (debug) {
- fprintf (where, "allocate_exs_buffer_ring: mhandle=%d\n",
- *mhandlep);
- }
-
- /* allocate ring elements */
- first_link = (struct ring_elt *) malloc (width * sizeof (struct ring_elt));
- if (first_link == NULL) {
- printf ("malloc(%d) failed!\n", width * sizeof (struct ring_elt));
- exit (1);
- }
-
- /* initialize buffer ring */
- prev_link = first_link + width - 1;
-
- for (i = 0, temp_link = first_link; i < width; i++, temp_link++) {
-
- temp_link->buffer_base = (char *) mmap_buffer_aligned + (i*malloc_size);
-#ifndef WIN32
- temp_link->buffer_ptr = (char *)
- (((long)temp_link->buffer_base + (long)alignment - 1) &
- ~((long)alignment - 1));
-#else
- temp_link->buffer_ptr = (char *)
- (((ULONG_PTR)temp_link->buffer_base + (ULONG_PTR)alignment - 1) &
- ~((ULONG_PTR)alignment - 1));
-#endif
- temp_link->buffer_ptr += offset;
-
- if (debug) {
- fprintf (where, "allocate_exs_buffer_ring: "
- "buffer: index=%d base=0x%p ptr=0x%p\n",
- i, temp_link->buffer_base, temp_link->buffer_ptr);
- }
-
- /* is where the buffer fill code goes. */
- if (do_fill) {
- bytes_left = buffer_size;
- while (bytes_left) {
- if (((bytes_read = (int) fread (temp_link->buffer_ptr,
- 1,
- bytes_left,
- fill_source)) == 0) &&
- (feof (fill_source))) {
- rewind (fill_source);
- }
- bytes_left -= bytes_read;
- }
- }
-
- /* do linking */
- prev_link->next = temp_link;
- prev_link = temp_link;
- }
-
- return (first_link); /* it's a circle, doesn't matter which we return */
-}
-
-#endif /* HAVE_ICSC_EXS */
-
-
-
-#ifdef HAVE_SENDFILE
-/* this routine will construct a ring of sendfile_ring_elt structs
- that the routine sendfile_tcp_stream() will use to get parameters
- to its calls to sendfile(). It will setup the ring to point at the
- file specified in the global -F option that is already used to
- pre-fill buffers in the send() case. 08/2000
-
- if there is no file specified in a global -F option, we will create
- a tempoarary file and fill it with random data and use that
- instead. raj 2007-08-09 */
-
-struct sendfile_ring_elt *
-alloc_sendfile_buf_ring(int width,
- int buffer_size,
- int alignment,
- int offset)
-
-{
-
- struct sendfile_ring_elt *first_link = NULL;
- struct sendfile_ring_elt *temp_link = NULL;
- struct sendfile_ring_elt *prev_link;
-
- int i;
- int fildes;
- struct stat statbuf;
-
- /* if the user has not specified a file with the -F option, we will
- fail the test. otherwise, go ahead and try to open the
- file. 08/2000 */
- if (strcmp(fill_file,"") == 0) {
- /* use an temp file for the fill file */
- char *temp_file;
- int *temp_buffer;
-
- /* make sure we have at least an ints worth, even if the user is
- using an insane buffer size for a sendfile test. we are
- ass-u-me-ing that malloc will return something at least aligned
- on an int boundary... */
- temp_buffer = (int *) malloc(buffer_size + sizeof(int));
- if (temp_buffer) {
- /* ok, we have the buffer we are going to write, lets get a
- temporary filename */
- temp_file = tmpnam(NULL);
- if (NULL != temp_file) {
- fildes = open(temp_file,O_RDWR | O_EXCL | O_CREAT,0600);
- if (-1 != fildes) {
- int count;
- int *int_ptr;
-
- /* initialize the random number generator */
- srand(getpid());
-
- /* unlink the file so it goes poof when we
- exit. unless/until shown to be a problem we will
- blissfully ignore the return value. raj 2007-08-09 */
- unlink(temp_file);
-
- /* now fill-out the file with at least buffer_size * width bytes */
- for (count = 0; count < width; count++) {
- /* fill the buffer with random data. it doesn't have to be
- really random, just "random enough" :) we do this here rather
- than up above because we want each write to the file to be
- different random data */
- int_ptr = temp_buffer;
- for (i = 0; i <= buffer_size/sizeof(int); i++) {
- *int_ptr = rand();
- int_ptr++;
- }
- if (write(fildes,temp_buffer,buffer_size+sizeof(int)) !=
- buffer_size + sizeof(int)) {
- perror("allocate_sendfile_buf_ring: incomplete write");
- exit(-1);
- }
- }
- }
- else {
- perror("allocate_sendfile_buf_ring: could not open tempfile");
- exit(-1);
- }
- }
- else {
- perror("allocate_sendfile_buf_ring: could not allocate temp name");
- exit(-1);
- }
- }
- else {
- perror("alloc_sendfile_buf_ring: could not allocate buffer for file");
- exit(-1);
- }
- }
- else {
- /* the user pointed us at a file, so try it */
- fildes = open(fill_file , O_RDONLY);
- if (fildes == -1){
- perror("alloc_sendfile_buf_ring: Could not open requested file");
- exit(1);
- }
- /* make sure there is enough file there to allow us to make a
- complete ring. that way we do not need additional logic in the
- ring setup to deal with wrap-around issues. we might want that
- someday, but not just now. 08/2000 */
- if (stat(fill_file,&statbuf) != 0) {
- perror("alloc_sendfile_buf_ring: could not stat file");
- exit(1);
- }
- if (statbuf.st_size < (width * buffer_size)) {
- /* the file is too short */
- fprintf(stderr,"alloc_sendfile_buf_ring: specified file too small.\n");
- fprintf(stderr,"file must be larger than send_width * send_size\n");
- fflush(stderr);
- exit(1);
- }
- }
-
- /* so, at this point we know that fildes is a descriptor which
- references a file of sufficient size for our nefarious
- porpoises. raj 2007-08-09 */
-
- prev_link = NULL;
- for (i = 1; i <= width; i++) {
- /* get the ring element. we should probably make sure the malloc()
- was successful, but for now we'll just let the code bomb
- mysteriously. 08/2000 */
-
- temp_link = (struct sendfile_ring_elt *)
- malloc(sizeof(struct sendfile_ring_elt));
- if (temp_link == NULL) {
- printf("malloc(%u) failed!\n", sizeof(struct sendfile_ring_elt));
- exit(1);
- }
-
- /* remember the first one so we can close the ring at the end */
-
- if (i == 1) {
- first_link = temp_link;
- }
-
- /* now fill-in the fields of the structure with the apropriate
- stuff. just how should we deal with alignment and offset I
- wonder? until something better comes-up, I think we will just
- ignore them. 08/2000 */
-
- temp_link->fildes = fildes; /* from which file do we send? */
- temp_link->offset = offset; /* starting at which offset? */
- offset += buffer_size; /* get ready for the next elt */
- temp_link->length = buffer_size; /* how many bytes to send */
- temp_link->hdtrl = NULL; /* no header or trailer */
- temp_link->flags = 0; /* no flags */
-
- /* is where the buffer fill code went. */
-
- temp_link->next = prev_link;
- prev_link = temp_link;
- }
- /* close the ring */
- first_link->next = temp_link;
-
- return(first_link); /* it's a dummy ring */
-}
-
-#endif /* HAVE_SENDFILE */
-
-
- /***********************************************************************/
- /* */
- /* dump_request() */
- /* */
- /* display the contents of the request array to the user. it will */
- /* display the contents in decimal, hex, and ascii, with four bytes */
- /* per line. */
- /* */
- /***********************************************************************/
-
-void
-dump_request()
-{
-int counter = 0;
-fprintf(where,"request contents:\n");
-for (counter = 0; counter < ((sizeof(netperf_request)/4)-3); counter += 4) {
- fprintf(where,"%d:\t%8x %8x %8x %8x \t|%4.4s| |%4.4s| |%4.4s| |%4.4s|\n",
- counter,
- request_array[counter],
- request_array[counter+1],
- request_array[counter+2],
- request_array[counter+3],
- (char *)&request_array[counter],
- (char *)&request_array[counter+1],
- (char *)&request_array[counter+2],
- (char *)&request_array[counter+3]);
-}
-fflush(where);
-}
-
-
- /***********************************************************************/
- /* */
- /* dump_response() */
- /* */
- /* display the content of the response array to the user. it will */
- /* display the contents in decimal, hex, and ascii, with four bytes */
- /* per line. */
- /* */
- /***********************************************************************/
-
-void
-dump_response()
-{
-int counter = 0;
-
-fprintf(where,"response contents\n");
-for (counter = 0; counter < ((sizeof(netperf_response)/4)-3); counter += 4) {
- fprintf(where,"%d:\t%8x %8x %8x %8x \t>%4.4s< >%4.4s< >%4.4s< >%4.4s<\n",
- counter,
- response_array[counter],
- response_array[counter+1],
- response_array[counter+2],
- response_array[counter+3],
- (char *)&response_array[counter],
- (char *)&response_array[counter+1],
- (char *)&response_array[counter+2],
- (char *)&response_array[counter+3]);
-}
-fflush(where);
-}
-
- /*
-
- format_number()
-
- return a pointer to a formatted string containing the value passed
- translated into the units specified. It assumes that the base units
- are bytes. If the format calls for bits, it will use SI units (10^)
- if the format calls for bytes, it will use CS units (2^)... This
- routine should look familiar to uses of the latest ttcp...
-
- we would like to use "t" or "T" for transactions, but probably
- should leave those for terabits and terabytes respectively, so for
- transactions, we will use "x" which will, by default, do absolutely
- nothing to the result. why? so we don't have to special case code
- elsewhere such as in the TCP_RR-as-bidirectional test case.
-
- */
-
-
-char *
-format_number(double number)
-{
- static char fmtbuf[64];
-
- switch (libfmt) {
- case 'K':
- snprintf(fmtbuf, sizeof(fmtbuf), "%-7.2f" , number / 1024.0);
- break;
- case 'M':
- snprintf(fmtbuf, sizeof(fmtbuf), "%-7.2f", number / 1024.0 / 1024.0);
- break;
- case 'G':
- snprintf(fmtbuf, sizeof(fmtbuf), "%-7.2f", number / 1024.0 / 1024.0 / 1024.0);
- break;
- case 'k':
- snprintf(fmtbuf, sizeof(fmtbuf), "%-7.2f", number * 8 / 1000.0);
- break;
- case 'm':
- snprintf(fmtbuf, sizeof(fmtbuf), "%-7.2f", number * 8 / 1000.0 / 1000.0);
- break;
- case 'g':
- snprintf(fmtbuf, sizeof(fmtbuf), "%-7.2f", number * 8 / 1000.0 / 1000.0 / 1000.0);
- break;
- case 'x':
- snprintf(fmtbuf, sizeof(fmtbuf), "%-7.2f", number);
- break;
- default:
- snprintf(fmtbuf, sizeof(fmtbuf), "%-7.2f", number / 1024.0);
- }
-
- return fmtbuf;
-}
-
-char
-format_cpu_method(int method)
-{
-
- char method_char;
-
- switch (method) {
- case CPU_UNKNOWN:
- method_char = 'U';
- break;
- case HP_IDLE_COUNTER:
- method_char = 'I';
- break;
- case PSTAT:
- method_char = 'P';
- break;
- case KSTAT:
- method_char = 'K';
- break;
- case KSTAT_10:
- method_char = 'M';
- break;
- case PERFSTAT:
- method_char = 'E';
- break;
- case TIMES: /* historical only, completely unsuitable
- for netperf's purposes */
- method_char = 'T';
- break;
- case GETRUSAGE: /* historical only, completely unsuitable
- for netperf;s purposes */
- method_char = 'R';
- break;
- case LOOPER:
- method_char = 'L';
- break;
- case NT_METHOD:
- method_char = 'N';
- break;
- case PROC_STAT:
- method_char = 'S';
- break;
- case SYSCTL:
- method_char = 'C';
- break;
- case OSX:
- method_char = 'O';
- break;
- default:
- method_char = '?';
- }
-
- return method_char;
-
-}
-
-char *
-format_units()
-{
- static char unitbuf[64];
-
- switch (libfmt) {
- case 'K':
- strcpy(unitbuf, "KBytes");
- break;
- case 'M':
- strcpy(unitbuf, "MBytes");
- break;
- case 'G':
- strcpy(unitbuf, "GBytes");
- break;
- case 'k':
- strcpy(unitbuf, "10^3bits");
- break;
- case 'm':
- strcpy(unitbuf, "10^6bits");
- break;
- case 'g':
- strcpy(unitbuf, "10^9bits");
- break;
- case 'x':
- strcpy(unitbuf, "Trans");
- break;
-
- default:
- strcpy(unitbuf, "KBytes");
- }
-
- return unitbuf;
-}
-
-
-/****************************************************************/
-/* */
-/* shutdown_control() */
-/* */
-/* tear-down the control connection between me and the server. */
-/****************************************************************/
-
-void
-shutdown_control()
-{
-
- char *buf = (char *)&netperf_response;
- int buflen = sizeof(netperf_response);
-
- /* stuff for select, use fd_set for better compliance */
- fd_set readfds;
- struct timeval timeout;
-
- if (debug) {
- fprintf(where,
- "shutdown_control: shutdown of control connection requested.\n");
- fflush(where);
- }
-
- /* first, we say that we will be sending no more data on the */
- /* connection */
- if (shutdown(netlib_control,1) == SOCKET_ERROR) {
- Print_errno(where,
- "shutdown_control: error in shutdown");
- fflush(where);
- exit(1);
- }
-
- /* Now, we hang on a select waiting for the socket to become */
- /* readable to receive the shutdown indication from the remote. this */
- /* will be "just" like the recv_response() code */
-
- /* we only select once. it is assumed that if the response is split */
- /* (which should not be happening, that we will receive the whole */
- /* thing and not have a problem ;-) */
-
- FD_ZERO(&readfds);
- FD_SET(netlib_control,&readfds);
- timeout.tv_sec = 60; /* wait one minute then punt */
- timeout.tv_usec = 0;
-
- /* select had better return one, or there was either a problem or a */
- /* timeout... */
- if (select(FD_SETSIZE,
- &readfds,
- 0,
- 0,
- &timeout) != 1) {
- Print_errno(where,
- "shutdown_control: no response received");
- fflush(where);
- exit(1);
- }
-
- /* we now assume that the socket has come ready for reading */
- recv(netlib_control, buf, buflen,0);
-
-}
-
-/*
- bind_to_specific_processor will bind the calling process to the
- processor in "processor" It has lots of ugly ifdefs to deal with
- all the different ways systems do processor affinity. this is a
- generalization of work initially done by stephen burger. raj
- 2004/12/13 */
-
-void
-bind_to_specific_processor(int processor_affinity, int use_cpu_map)
-{
-
- int mapped_affinity;
-
- /* this is in place because the netcpu_looper processor affinity
- ass-u-me-s a contiguous CPU id space starting with 0. for the
- regular netperf/netserver affinity, we ass-u-me the user has used
- a suitable CPU id even when the space is not contiguous and
- starting from zero */
- if (use_cpu_map) {
- mapped_affinity = lib_cpu_map[processor_affinity];
- }
- else {
- mapped_affinity = processor_affinity;
- }
-
-#ifdef HAVE_MPCTL
- /* indeed, at some point it would be a good idea to check the return
- status and pass-along notification of error... raj 2004/12/13 */
- mpctl(MPC_SETPROCESS_FORCE, mapped_affinity, getpid());
-#elif HAVE_PROCESSOR_BIND
-#include <sys/types.h>
-#include <sys/processor.h>
-#include <sys/procset.h>
- processor_bind(P_PID,P_MYID,mapped_affinity,NULL);
-#elif HAVE_BINDPROCESSOR
-#include <sys/processor.h>
- /* this is the call on AIX. It takes a "what" of BINDPROCESS or
- BINDTHRAD, then "who" and finally "where" which is a CPU number
- or it seems PROCESSOR_CLASS_ANY there also seems to be a mycpu()
- call to return the current CPU assignment. this is all based on
- the sys/processor.h include file. from empirical testing, it
- would seem that the my_cpu() call returns the current CPU on
- which we are running rather than the CPU binding, so it's return
- value will not tell you if you are bound vs unbound. */
- bindprocessor(BINDPROCESS,getpid(),(cpu_t)mapped_affinity);
-#elif HAVE_SCHED_SETAFFINITY
-#include <sched.h>
- /* in theory this should cover systems with more CPUs than bits in a
- long, without having to specify __USE_GNU. we "cheat" by taking
- defines from /usr/include/bits/sched.h, which we ass-u-me is
- included by <sched.h>. If they are not there we will just
- fall-back on what we had before, which is to use just the size of
- an unsigned long. raj 2006-09-14 */
-
-#if defined(__CPU_SETSIZE)
-#define NETPERF_CPU_SETSIZE __CPU_SETSIZE
-#define NETPERF_CPU_SET(cpu, cpusetp) __CPU_SET(cpu, cpusetp)
-#define NETPERF_CPU_ZERO(cpusetp) __CPU_ZERO (cpusetp)
- typedef cpu_set_t netperf_cpu_set_t;
-#else
-#define NETPERF_CPU_SETSIZE sizeof(unsigned long)
-#define NETPERF_CPU_SET(cpu, cpusetp) *cpusetp = 1 << cpu
-#define NETPERF_CPU_ZERO(cpusetp) *cpusetp = (unsigned long)0
- typedef unsigned long netperf_cpu_set_t;
-#endif
-
- netperf_cpu_set_t netperf_cpu_set;
- unsigned int len = sizeof(netperf_cpu_set);
-
- if (mapped_affinity < 8*sizeof(netperf_cpu_set)) {
- NETPERF_CPU_ZERO(&netperf_cpu_set);
- NETPERF_CPU_SET(mapped_affinity,&netperf_cpu_set);
-
- if (sched_setaffinity(getpid(), len, &netperf_cpu_set)) {
- if (debug) {
- fprintf(stderr, "failed to set PID %d's CPU affinity errno %d\n",
- getpid(),errno);
- fflush(stderr);
- }
- }
- }
- else {
- if (debug) {
- fprintf(stderr,
- "CPU number larger than pre-compiled limits. Consider a recompile.\n");
- fflush(stderr);
- }
- }
-
-#elif HAVE_BIND_TO_CPU_ID
- /* this is the one for Tru64 */
-#include <sys/types.h>
-#include <sys/resource.h>
-#include <sys/processor.h>
-
- /* really should be checking a return code one of these days. raj
- 2005/08/31 */
-
- bind_to_cpu_id(getpid(), mapped_affinity,0);
-
-#elif WIN32
-
- {
- ULONG_PTR AffinityMask;
- ULONG_PTR ProcessAffinityMask;
- ULONG_PTR SystemAffinityMask;
-
- if ((mapped_affinity < 0) ||
- (mapped_affinity > MAXIMUM_PROCESSORS)) {
- fprintf(where,
- "Invalid processor_affinity specified: %d\n", mapped_affinity); fflush(where);
- return;
- }
-
- if (!GetProcessAffinityMask(
- GetCurrentProcess(),
- &ProcessAffinityMask,
- &SystemAffinityMask))
- {
- perror("GetProcessAffinityMask failed");
- fflush(stderr);
- exit(1);
- }
-
- AffinityMask = (ULONG_PTR)1 << mapped_affinity;
-
- if (AffinityMask & ProcessAffinityMask) {
- if (!SetThreadAffinityMask( GetCurrentThread(), AffinityMask)) {
- perror("SetThreadAffinityMask failed");
- fflush(stderr);
- }
- } else if (debug) {
- fprintf(where,
- "Processor affinity set to CPU# %d\n", mapped_affinity);
- fflush(where);
- }
- }
-
-#else
- if (debug) {
- fprintf(where,
- "Processor affinity not available for this platform!\n");
- fflush(where);
- }
-#endif
-}
-
-
-/*
- * Sets a socket to non-blocking operation.
- */
-int
-set_nonblock (SOCKET sock)
-{
-#ifdef WIN32
- unsigned long flags = 1;
- return (ioctlsocket(sock, FIONBIO, &flags) != SOCKET_ERROR);
-#else
- return (fcntl(sock, F_SETFL, O_NONBLOCK) != -1);
-#endif
-}
-
-
-
- /***********************************************************************/
- /* */
- /* send_request() */
- /* */
- /* send a netperf request on the control socket to the remote half of */
- /* the connection. to get us closer to intervendor interoperability, */
- /* we will call htonl on each of the int that compose the message to */
- /* be sent. the server-half of the connection will call the ntohl */
- /* routine to undo any changes that may have been made... */
- /* */
- /***********************************************************************/
-
-void
-send_request()
-{
- int counter=0;
-
- /* display the contents of the request if the debug level is high */
- /* enough. otherwise, just send the darned thing ;-) */
-
- if (debug > 1) {
- fprintf(where,"entered send_request...contents before htonl:\n");
- dump_request();
- }
-
- /* pass the processor affinity request value to netserver */
- /* this is a kludge and I know it. sgb 8/11/04 */
-
- netperf_request.content.dummy = remote_proc_affinity;
-
- /* put the entire request array into network order. We do this */
- /* arbitrarily rather than trying to figure-out just how much */
- /* of the request array contains real information. this should */
- /* be simpler, and at any rate, the performance of sending */
- /* control messages for this benchmark is not of any real */
- /* concern. */
-
- for (counter=0;counter < sizeof(netperf_request)/4; counter++) {
- request_array[counter] = htonl(request_array[counter]);
- }
-
- if (debug > 1) {
- fprintf(where,"send_request...contents after htonl:\n");
- dump_request();
-
- fprintf(where,
- "\nsend_request: about to send %u bytes from %p\n",
- sizeof(netperf_request),
- &netperf_request);
- fflush(where);
- }
-
- if (send(netlib_control,
- (char *)&netperf_request,
- sizeof(netperf_request),
- 0) != sizeof(netperf_request)) {
- perror("send_request: send call failure");
-
- exit(1);
- }
-}
-
-/***********************************************************************/
- /* */
- /* send_response() */
- /* */
- /* send a netperf response on the control socket to the remote half of */
- /* the connection. to get us closer to intervendor interoperability, */
- /* we will call htonl on each of the int that compose the message to */
- /* be sent. the other half of the connection will call the ntohl */
- /* routine to undo any changes that may have been made... */
- /* */
- /***********************************************************************/
-
-void
-send_response()
-{
- int counter=0;
- int bytes_sent;
-
- /* display the contents of the request if the debug level is high */
- /* enough. otherwise, just send the darned thing ;-) */
-
- if (debug > 1) {
- fprintf(where,
- "send_response: contents of %u ints before htonl\n",
- sizeof(netperf_response)/4);
- dump_response();
- }
-
- /* put the entire response_array into network order. We do this */
- /* arbitrarily rather than trying to figure-out just how much of the */
- /* request array contains real information. this should be simpler, */
- /* and at any rate, the performance of sending control messages for */
- /* this benchmark is not of any real concern. */
-
- for (counter=0;counter < sizeof(netperf_response)/4; counter++) {
- response_array[counter] = htonl(response_array[counter]);
- }
-
- if (debug > 1) {
- fprintf(where,
- "send_response: contents after htonl\n");
- dump_response();
- fprintf(where,
- "about to send %u bytes from %p\n",
- sizeof(netperf_response),
- &netperf_response);
- fflush(where);
- }
-
- /*KC*/
- if ((bytes_sent = send(server_sock,
- (char *)&netperf_response,
- sizeof(netperf_response),
- 0)) != sizeof(netperf_response)) {
- perror("send_response: send call failure");
- fprintf(where, "BytesSent: %d\n", bytes_sent);
- exit(1);
- }
-
-}
-
- /***********************************************************************/
- /* */
- /* recv_request() */
- /* */
- /* receive the remote's request on the control socket. we will put */
- /* the entire response into host order before giving it to the */
- /* calling routine. hopefully, this will go most of the way to */
- /* insuring intervendor interoperability. if there are any problems, */
- /* we will just punt the entire situation. */
- /* */
- /***********************************************************************/
-
-void
-recv_request()
-{
-int tot_bytes_recvd,
- bytes_recvd,
- bytes_left;
-char *buf = (char *)&netperf_request;
-int buflen = sizeof(netperf_request);
-int counter;
-
-tot_bytes_recvd = 0;
- bytes_recvd = 0; /* nt_lint; bytes_recvd uninitialized if buflen == 0 */
-bytes_left = buflen;
-while ((tot_bytes_recvd != buflen) &&
- ((bytes_recvd = recv(server_sock, buf, bytes_left,0)) > 0 )) {
- tot_bytes_recvd += bytes_recvd;
- buf += bytes_recvd;
- bytes_left -= bytes_recvd;
-}
-
-/* put the request into host order */
-
-for (counter = 0; counter < sizeof(netperf_request)/sizeof(int); counter++) {
- request_array[counter] = ntohl(request_array[counter]);
-}
-
-if (debug) {
- fprintf(where,
- "recv_request: received %d bytes of request.\n",
- tot_bytes_recvd);
- fflush(where);
-}
-
-if (bytes_recvd == SOCKET_ERROR) {
- Print_errno(where,
- "recv_request: error on recv");
- fflush(where);
- exit(1);
-}
-
-if (bytes_recvd == 0) {
- /* the remote has shutdown the control connection, we should shut it */
- /* down as well and exit */
-
- if (debug) {
- fprintf(where,
- "recv_request: remote requested shutdown of control\n");
- fflush(where);
- }
-
- if (netlib_control != INVALID_SOCKET) {
- shutdown_control();
- }
- exit(0);
-}
-
-if (tot_bytes_recvd < buflen) {
- if (debug > 1)
- dump_request();
-
- fprintf(where,
- "recv_request: partial request received of %d bytes\n",
- tot_bytes_recvd);
- fflush(where);
- exit(1);
-}
-
- if (debug > 1) {
- dump_request();
- }
-
- /* get the processor affinity request value from netperf */
- /* this is a kludge and I know it. sgb 8/11/04 */
-
- local_proc_affinity = netperf_request.content.dummy;
-
- if (local_proc_affinity != -1) {
- bind_to_specific_processor(local_proc_affinity,0);
- }
-
-}
-
- /*
-
- recv_response_timed()
-
- receive the remote's response on the control socket. we will put the
- entire response into host order before giving it to the calling
- routine. hopefully, this will go most of the way to insuring
- intervendor interoperability. if there are any problems, we will just
- punt the entire situation.
-
- The call to select at the beginning is to get us out of hang
- situations where the remote gives-up but we don't find-out about
- it. This seems to happen only rarely, but it would be nice to be
- somewhat robust ;-)
-
- The "_timed" part is to allow the caller to add (or I suppose
- subtract) from the length of timeout on the select call. this was
- added since not all the CPU utilization mechanisms require a 40
- second calibration, and we used to have an aribtrary 40 second sleep
- in "calibrate_remote_cpu" - since we don't _always_ need that, we
- want to simply add 40 seconds to the select() timeout from that call,
- but don't want to change all the "recv_response" calls in the code
- right away. sooo, we push the functionality of the old
- recv_response() into a new recv_response_timed(addl_timout) call, and
- have recv_response() call recv_response_timed(0). raj 2005-05-16
-
- */
-
-
-void
-recv_response_timed(int addl_time)
-{
-int tot_bytes_recvd,
- bytes_recvd = 0,
- bytes_left;
-char *buf = (char *)&netperf_response;
-int buflen = sizeof(netperf_response);
-int counter;
-
- /* stuff for select, use fd_set for better compliance */
-fd_set readfds;
-struct timeval timeout;
-
-tot_bytes_recvd = 0;
-bytes_left = buflen;
-
-/* zero out the response structure */
-
-/* BUG FIX SJB 2/4/93 - should be < not <= */
-for (counter = 0; counter < sizeof(netperf_response)/sizeof(int); counter++) {
- response_array[counter] = 0;
-}
-
- /* we only select once. it is assumed that if the response is split */
- /* (which should not be happening, that we will receive the whole */
- /* thing and not have a problem ;-) */
-
-FD_ZERO(&readfds);
-FD_SET(netlib_control,&readfds);
-timeout.tv_sec = 120 + addl_time; /* wait at least two minutes
- before punting - the USE_LOOPER
- CPU stuff may cause remote's to
- have a bit longer time of it
- than 60 seconds would allow.
- triggered by fix from Jeff
- Dwork. */
-timeout.tv_usec = 0;
-
- /* select had better return one, or there was either a problem or a */
- /* timeout... */
-
-if ((counter = select(FD_SETSIZE,
- &readfds,
- 0,
- 0,
- &timeout)) != 1) {
- fprintf(where,
- "netperf: receive_response: no response received. errno %d counter %d\n",
- errno,
- counter);
- exit(1);
-}
-
-while ((tot_bytes_recvd != buflen) &&
- ((bytes_recvd = recv(netlib_control, buf, bytes_left,0)) > 0 )) {
- tot_bytes_recvd += bytes_recvd;
- buf += bytes_recvd;
- bytes_left -= bytes_recvd;
-}
-
-if (debug) {
- fprintf(where,"recv_response: received a %d byte response\n",
- tot_bytes_recvd);
- fflush(where);
-}
-
-/* put the response into host order */
-
-for (counter = 0; counter < sizeof(netperf_response)/sizeof(int); counter++) {
- response_array[counter] = ntohl(response_array[counter]);
-}
-
-if (bytes_recvd == SOCKET_ERROR) {
- perror("recv_response");
- exit(1);
-}
-if (tot_bytes_recvd < buflen) {
- fprintf(stderr,
- "recv_response: partial response received: %d bytes\n",
- tot_bytes_recvd);
- fflush(stderr);
- if (debug > 1)
- dump_response();
- exit(1);
-}
-if (debug > 1) {
- dump_response();
-}
-}
-
-void
-recv_response()
-{
- recv_response_timed(0);
-}
-
-
-
-#if defined(USE_PSTAT) || defined (USE_SYSCTL)
-int
-hi_32(big_int)
- long long *big_int;
-{
- union overlay_u {
- long long dword;
- long words[2];
- } *overlay;
-
- overlay = (union overlay_u *)big_int;
- /* on those systems which are byte swapped, we really wish to */
- /* return words[1] - at least I think so - raj 4/95 */
- if (htonl(1L) == 1L) {
- /* we are a "normal" :) machine */
- return(overlay->words[0]);
- }
- else {
- return(overlay->words[1]);
- }
-}
-
-int
-lo_32(big_int)
- long long *big_int;
-{
- union overlay_u {
- long long dword;
- long words[2];
- } *overlay;
-
- overlay = (union overlay_u *)big_int;
- /* on those systems which are byte swapped, we really wish to */
- /* return words[0] - at least I think so - raj 4/95 */
- if (htonl(1L) == 1L) {
- /* we are a "normal" :) machine */
- return(overlay->words[1]);
- }
- else {
- return(overlay->words[0]);
- }
-}
-
-#endif /* USE_PSTAT || USE_SYSCTL */
-
-
-void libmain()
-{
-fprintf(where,"hello world\n");
-fprintf(where,"debug: %d\n",debug);
-}
-
-
-void
-set_sock_buffer (SOCKET sd, enum sock_buffer which, int requested_size, int *effective_sizep)
-{
-#ifdef SO_SNDBUF
- int optname = (which == SEND_BUFFER) ? SO_SNDBUF : SO_RCVBUF;
- netperf_socklen_t sock_opt_len;
-
- /* seems that under Windows, setting a value of zero is how one
- tells the stack you wish to enable copy-avoidance. Knuth only
- knows what it will do on other stacks, but it might be
- interesting to find-out, so we won't bother #ifdef'ing the change
- to allow asking for 0 bytes. Courtesy of SAF, 2007-05 raj
- 2007-05-31 */
- if (requested_size >= 0) {
- if (setsockopt(sd, SOL_SOCKET, optname,
- (char *)&requested_size, sizeof(int)) < 0) {
- fprintf(where, "netperf: set_sock_buffer: %s option: errno %d\n",
- (which == SEND_BUFFER) ? "SO_SNDBUF" : "SO_RCVBUF",
- errno);
- fflush(where);
- exit(1);
- }
- if (debug > 1) {
- fprintf(where, "netperf: set_sock_buffer: %s of %d requested.\n",
- (which == SEND_BUFFER) ? "SO_SNDBUF" : "SO_RCVBUF",
- requested_size);
- fflush(where);
- }
- }
-
- /* Now, we will find-out what the size actually became, and report */
- /* that back to the user. If the call fails, we will just report a -1 */
- /* back to the initiator for the recv buffer size. */
-
- sock_opt_len = sizeof(netperf_socklen_t);
- if (getsockopt(sd, SOL_SOCKET, optname, (char *)effective_sizep,
- &sock_opt_len) < 0) {
- fprintf(where, "netperf: set_sock_buffer: getsockopt %s: errno %d\n",
- (which == SEND_BUFFER) ? "SO_SNDBUF" : "SO_RCVBUF", errno);
- fflush(where);
- *effective_sizep = -1;
- }
-
- if (debug) {
- fprintf(where, "netperf: set_sock_buffer: "
- "%s socket size determined to be %d\n",
- (which == SEND_BUFFER) ? "send" : "receive", *effective_sizep);
- fflush(where);
- }
-#else /* SO_SNDBUF */
- *effective_size = -1;
-#endif /* SO_SNDBUF */
-}
-
-void
-dump_addrinfo(FILE *dumploc, struct addrinfo *info,
- char *host, char *port, int family)
-{
- struct sockaddr *ai_addr;
- struct addrinfo *temp;
- temp=info;
-
- fprintf(dumploc, "getaddrinfo returned the following for host '%s' ", host);
- fprintf(dumploc, "port '%s' ", port);
- fprintf(dumploc, "family %s\n", inet_ftos(family));
- while (temp) {
- /* seems that Solaris 10 GA bits will not give a canonical name
- for ::0 or 0.0.0.0, and their fprintf() cannot deal with a null
- pointer, so we have to check for a null pointer. probably a
- safe thing to do anyway, eventhough it was not necessary on
- linux or hp-ux. raj 2005-02-09 */
- if (temp->ai_canonname) {
- fprintf(dumploc,
- "\tcannonical name: '%s'\n",temp->ai_canonname);
- }
- else {
- fprintf(dumploc,
- "\tcannonical name: '%s'\n","(nil)");
- }
- fprintf(dumploc,
- "\tflags: %x family: %s: socktype: %s protocol %s addrlen %d\n",
- temp->ai_flags,
- inet_ftos(temp->ai_family),
- inet_ttos(temp->ai_socktype),
- inet_ptos(temp->ai_protocol),
- temp->ai_addrlen);
- ai_addr = temp->ai_addr;
- if (ai_addr != NULL) {
- fprintf(dumploc,
- "\tsa_family: %s sadata: %d %d %d %d %d %d\n",
- inet_ftos(ai_addr->sa_family),
- (u_char)ai_addr->sa_data[0],
- (u_char)ai_addr->sa_data[1],
- (u_char)ai_addr->sa_data[2],
- (u_char)ai_addr->sa_data[3],
- (u_char)ai_addr->sa_data[4],
- (u_char)ai_addr->sa_data[5]);
- }
- temp = temp->ai_next;
- }
- fflush(dumploc);
-}
-
-/*
- establish_control()
-
-set-up the control connection between netperf and the netserver so we
-can actually run some tests. if we cannot establish the control
-connection, that may or may not be a good thing, so we will let the
-caller decide what to do.
-
-to assist with pesky end-to-end-unfriendly things like firewalls, we
-allow the caller to specify both the remote hostname and port, and the
-local addressing info. i believe that in theory it is possible to
-have an IPv4 endpoint and an IPv6 endpoint communicate with one
-another, but for the time being, we are only going to take-in one
-requested address family parameter. this means that the only way
-(iirc) that we might get a mixed-mode connection would be if the
-address family is specified as AF_UNSPEC, and getaddrinfo() returns
-different families for the local and server names.
-
-the "names" can also be IP addresses in ASCII string form.
-
-raj 2003-02-27 */
-
-SOCKET
-establish_control_internal(char *hostname,
- char *port,
- int remfam,
- char *localhost,
- char *localport,
- int locfam)
-{
- int not_connected;
- SOCKET control_sock;
- int count;
- int error;
-
- struct addrinfo hints;
- struct addrinfo *local_res;
- struct addrinfo *remote_res;
- struct addrinfo *local_res_temp;
- struct addrinfo *remote_res_temp;
-
- if (debug) {
- fprintf(where,
- "establish_control called with host '%s' port '%s' remfam %s\n",
- hostname,
- port,
- inet_ftos(remfam));
- fprintf(where,
- "\t\tlocal '%s' port '%s' locfam %s\n",
- localhost,
- localport,
- inet_ftos(locfam));
- fflush(where);
- }
-
- /* first, we do the remote */
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = remfam;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = IPPROTO_TCP;
- hints.ai_flags = 0|AI_CANONNAME;
- count = 0;
- do {
- error = getaddrinfo((char *)hostname,
- (char *)port,
- &hints,
- &remote_res);
- count += 1;
- if (error == EAI_AGAIN) {
- if (debug) {
- fprintf(where,"Sleeping on getaddrinfo EAI_AGAIN\n");
- fflush(where);
- }
- sleep(1);
- }
- } while ((error == EAI_AGAIN) && (count <= 5));
-
- if (error) {
- printf("establish control: could not resolve remote '%s' port '%s' af %s",
- hostname,
- port,
- inet_ftos(remfam));
- printf("\n\tgetaddrinfo returned %d %s\n",
- error,
- gai_strerror(error));
- return(INVALID_SOCKET);
- }
-
- if (debug) {
- dump_addrinfo(where, remote_res, hostname, port, remfam);
- }
-
- /* now we do the local */
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = locfam;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = IPPROTO_TCP;
- hints.ai_flags = AI_PASSIVE|AI_CANONNAME;
- count = 0;
- do {
- count += 1;
- error = getaddrinfo((char *)localhost,
- (char *)localport,
- &hints,
- &local_res);
- if (error == EAI_AGAIN) {
- if (debug) {
- fprintf(where,
- "Sleeping on getaddrinfo(%s,%s) EAI_AGAIN count %d \n",
- localhost,
- localport,
- count);
- fflush(where);
- }
- sleep(1);
- }
- } while ((error == EAI_AGAIN) && (count <= 5));
-
- if (error) {
- printf("establish control: could not resolve local '%s' port '%s' af %s",
- localhost,
- localport,
- inet_ftos(locfam));
- printf("\n\tgetaddrinfo returned %d %s\n",
- error,
- gai_strerror(error));
- return(INVALID_SOCKET);
- }
-
- if (debug) {
- dump_addrinfo(where, local_res, localhost, localport, locfam);
- }
-
- not_connected = 1;
- local_res_temp = local_res;
- remote_res_temp = remote_res;
- /* we want to loop through all the possibilities. looping on the
- local addresses will be handled within the while loop. I suppose
- these is some more "C-expert" way to code this, but it has not
- lept to mind just yet :) raj 2003-02024 */
-
- while (remote_res_temp != NULL) {
-
- /* I am guessing that we should use the address family of the
- local endpoint, and we will not worry about mixed family types
- - presumeably the stack or other transition mechanisms will be
- able to deal with that for us. famous last words :) raj 2003-02-26 */
- control_sock = socket(local_res_temp->ai_family,
- SOCK_STREAM,
- 0);
- if (control_sock == INVALID_SOCKET) {
- /* at some point we'll need a more generic "display error"
- message for when/if we use GUIs and the like. unlike a bind
- or connect failure, failure to allocate a socket is
- "immediately fatal" and so we return to the caller. raj 2003-02-24 */
- if (debug) {
- perror("establish_control: unable to allocate control socket");
- }
- return(INVALID_SOCKET);
- }
-
- /* if we are going to control the local enpoint addressing, we
- need to call bind. of course, we should probably be setting one
- of the SO_REUSEmumble socket options? raj 2005-02-04 */
- if (bind(control_sock,
- local_res_temp->ai_addr,
- local_res_temp->ai_addrlen) == 0) {
- if (debug) {
- fprintf(where,
- "bound control socket to %s and %s\n",
- localhost,
- localport);
- }
-
- if (connect(control_sock,
- remote_res_temp->ai_addr,
- remote_res_temp->ai_addrlen) == 0) {
- /* we have successfully connected to the remote netserver */
- if (debug) {
- fprintf(where,
- "successful connection to remote netserver at %s and %s\n",
- hostname,
- port);
- }
- not_connected = 0;
- /* this should get us out of the while loop */
- break;
- } else {
- /* the connect call failed */
- if (debug) {
- fprintf(where,
- "establish_control: connect failed, errno %d %s\n",
- errno,
- strerror(errno));
- fprintf(where, " trying next address combination\n");
- fflush(where);
- }
- }
- }
- else {
- /* the bind failed */
- if (debug) {
- fprintf(where,
- "establish_control: bind failed, errno %d %s\n",
- errno,
- strerror(errno));
- fprintf(where, " trying next address combination\n");
- fflush(where);
- }
- }
-
- if ((local_res_temp = local_res_temp->ai_next) == NULL) {
- /* wrap the local and move to the next server, don't forget to
- close the current control socket. raj 2003-02-24 */
- local_res_temp = local_res;
- /* the outer while conditions will deal with the case when we
- get to the end of all the possible remote addresses. */
- remote_res_temp = remote_res_temp->ai_next;
- /* it is simplest here to just close the control sock. since
- this is not a performance critical section of code, we
- don't worry about overheads for socket allocation or
- close. raj 2003-02-24 */
- }
- close(control_sock);
- }
-
- /* we no longer need the addrinfo stuff */
- freeaddrinfo(local_res);
- freeaddrinfo(remote_res);
-
- /* so, we are either connected or not */
- if (not_connected) {
- fprintf(where, "establish control: are you sure there is a netserver listening on %s at port %s?\n",hostname,port);
- fflush(where);
- return(INVALID_SOCKET);
- }
- /* at this point, we are connected. we probably want some sort of
- version check with the remote at some point. raj 2003-02-24 */
- return(control_sock);
-}
-
-void
-establish_control(char *hostname,
- char *port,
- int remfam,
- char *localhost,
- char *localport,
- int locfam)
-
-{
-
- netlib_control = establish_control_internal(hostname,
- port,
- remfam,
- localhost,
- localport,
- locfam);
- if (netlib_control == INVALID_SOCKET) {
- fprintf(where,
- "establish_control could not establish the control connection from %s port %s address family %s to %s port %s address family %s\n",
- localhost,localport,inet_ftos(locfam),
- hostname,port,inet_ftos(remfam));
- fflush(where);
- exit(INVALID_SOCKET);
- }
-}
-
-
-
-
- /***********************************************************************/
- /* */
- /* get_id() */
- /* */
- /* Return a string to the calling routine that contains the */
- /* identifying information for the host we are running on. This */
- /* information will then either be displayed locally, or returned to */
- /* a remote caller for display there. */
- /* */
- /***********************************************************************/
-
-char *
-get_id()
-{
- static char id_string[80];
-#ifdef WIN32
-char system_name[MAX_COMPUTERNAME_LENGTH+1] ;
-DWORD name_len = MAX_COMPUTERNAME_LENGTH + 1 ;
-#else
-struct utsname system_name;
-#endif /* WIN32 */
-
-#ifdef WIN32
- SYSTEM_INFO SystemInfo;
- GetSystemInfo( &SystemInfo ) ;
- if ( !GetComputerName(system_name , &name_len) )
- strcpy(system_name , "no_name") ;
-#else
- if (uname(&system_name) <0) {
- perror("identify_local: uname");
- exit(1);
- }
-#endif /* WIN32 */
-
- snprintf(id_string, sizeof(id_string),
-#ifdef WIN32
- "%-15s%-15s%d.%d%d",
- "Windows NT",
- system_name ,
- GetVersion() & 0xFF ,
- GetVersion() & 0xFF00 ,
- SystemInfo.dwProcessorType
-
-#else
- "%-15s%-15s%-15s%-15s%-15s",
- system_name.sysname,
- system_name.nodename,
- system_name.release,
- system_name.version,
- system_name.machine
-#endif /* WIN32 */
- );
- return (id_string);
-}
-
-
- /***********************************************************************/
- /* */
- /* identify_local() */
- /* */
- /* Display identifying information about the local host to the user. */
- /* At first release, this information will be the same as that which */
- /* is returned by the uname -a command, with the exception of the */
- /* idnumber field, which seems to be a non-POSIX item, and hence */
- /* non-portable. */
- /* */
- /***********************************************************************/
-
-void
-identify_local()
-{
-
-char *local_id;
-
-local_id = get_id();
-
-fprintf(where,"Local Information \n\
-Sysname Nodename Release Version Machine\n");
-
-fprintf(where,"%s\n",
- local_id);
-
-}
-
-
- /***********************************************************************/
- /* */
- /* identify_remote() */
- /* */
- /* Display identifying information about the remote host to the user. */
- /* At first release, this information will be the same as that which */
- /* is returned by the uname -a command, with the exception of the */
- /* idnumber field, which seems to be a non-POSIX item, and hence */
- /* non-portable. A request is sent to the remote side, which will */
- /* return a string containing the utsname information in a */
- /* pre-formatted form, which is then displayed after the header. */
- /* */
- /***********************************************************************/
-
-void
-identify_remote()
-{
-
-char *remote_id="";
-
-/* send a request for node info to the remote */
-netperf_request.content.request_type = NODE_IDENTIFY;
-
-send_request();
-
-/* and now wait for the reply to come back */
-
-recv_response();
-
-if (netperf_response.content.serv_errno) {
- Set_errno(netperf_response.content.serv_errno);
- perror("identify_remote: on remote");
- exit(1);
-}
-
-fprintf(where,"Remote Information \n\
-Sysname Nodename Release Version Machine\n");
-
-fprintf(where,"%s",
- remote_id);
-}
-
-void
-cpu_start(int measure_cpu)
-{
-
- gettimeofday(&time1,
- &tz);
-
- if (measure_cpu) {
- cpu_util_init();
- measuring_cpu = 1;
- cpu_method = get_cpu_method();
- cpu_start_internal();
- }
-}
-
-
-void
-cpu_stop(int measure_cpu, float *elapsed)
-
-{
-
- int sec,
- usec;
-
- if (measure_cpu) {
- cpu_stop_internal();
- cpu_util_terminate();
- }
-
- gettimeofday(&time2,
- &tz);
-
- if (time2.tv_usec < time1.tv_usec) {
- time2.tv_usec += 1000000;
- time2.tv_sec -= 1;
- }
-
- sec = time2.tv_sec - time1.tv_sec;
- usec = time2.tv_usec - time1.tv_usec;
- lib_elapsed = (float)sec + ((float)usec/(float)1000000.0);
-
- *elapsed = lib_elapsed;
-
-}
-
-
-double
-calc_thruput_interval(double units_received,double elapsed)
-
-{
- double divisor;
-
- /* We will calculate the thruput in libfmt units/second */
- switch (libfmt) {
- case 'K':
- divisor = 1024.0;
- break;
- case 'M':
- divisor = 1024.0 * 1024.0;
- break;
- case 'G':
- divisor = 1024.0 * 1024.0 * 1024.0;
- break;
- case 'k':
- divisor = 1000.0 / 8.0;
- break;
- case 'm':
- divisor = 1000.0 * 1000.0 / 8.0;
- break;
- case 'g':
- divisor = 1000.0 * 1000.0 * 1000.0 / 8.0;
- break;
-
- default:
- divisor = 1024.0;
- }
-
- return (units_received / divisor / elapsed);
-
-}
-
-double
-calc_thruput(double units_received)
-
-{
- return(calc_thruput_interval(units_received,lib_elapsed));
-}
-
-/* these "_omni" versions are ones which understand 'x' as a unit,
- meaning transactions/s. we have a separate routine rather than
- convert the existing routine so we don't have to go and change
- _all_ the nettest_foo.c files at one time. raj 2007-06-08 */
-
-double
-calc_thruput_interval_omni(double units_received,double elapsed)
-
-{
- double divisor;
-
- /* We will calculate the thruput in libfmt units/second */
- switch (libfmt) {
- case 'K':
- divisor = 1024.0;
- break;
- case 'M':
- divisor = 1024.0 * 1024.0;
- break;
- case 'G':
- divisor = 1024.0 * 1024.0 * 1024.0;
- break;
- case 'k':
- divisor = 1000.0 / 8.0;
- break;
- case 'm':
- divisor = 1000.0 * 1000.0 / 8.0;
- break;
- case 'g':
- divisor = 1000.0 * 1000.0 * 1000.0 / 8.0;
- break;
- case 'x':
- divisor = 1.0;
- break;
-
- default:
- fprintf(where,
- "WARNING calc_throughput_internal_omni: unknown units %c\n",
- libfmt);
- fflush(where);
- divisor = 1024.0;
- }
-
- return (units_received / divisor / elapsed);
-
-}
-
-double
-calc_thruput_omni(double units_received)
-
-{
- return(calc_thruput_interval_omni(units_received,lib_elapsed));
-}
-
-
-
-
-
-float
-calc_cpu_util(float elapsed_time)
-{
- return(calc_cpu_util_internal(elapsed_time));
-}
-
-float
-calc_service_demand_internal(double unit_divisor,
- double units_sent,
- float elapsed_time,
- float cpu_utilization,
- int num_cpus)
-
-{
-
- double service_demand;
- double thruput;
-
- if (debug) {
- fprintf(where,"calc_service_demand called: units_sent = %f\n",
- units_sent);
- fprintf(where," elapsed_time = %f\n",
- elapsed_time);
- fprintf(where," cpu_util = %f\n",
- cpu_utilization);
- fprintf(where," num cpu = %d\n",
- num_cpus);
- fflush(where);
- }
-
- if (num_cpus == 0) num_cpus = lib_num_loc_cpus;
-
- if (elapsed_time == 0.0) {
- elapsed_time = lib_elapsed;
- }
- if (cpu_utilization == 0.0) {
- cpu_utilization = lib_local_cpu_util;
- }
-
- thruput = (units_sent /
- (double) unit_divisor /
- (double) elapsed_time);
-
- /* on MP systems, it is necessary to multiply the service demand by */
- /* the number of CPU's. at least, I believe that to be the case:) */
- /* raj 10/95 */
-
- /* thruput has a "per second" component. if we were using 100% ( */
- /* 100.0) of the CPU in a second, that would be 1 second, or 1 */
- /* millisecond, so we multiply cpu_utilization by 10 to go to */
- /* milliseconds, or 10,000 to go to micro seconds. With revision */
- /* 2.1, the service demand measure goes to microseconds per unit. */
- /* raj 12/95 */
- service_demand = (cpu_utilization*10000.0/thruput) *
- (float) num_cpus;
-
- if (debug) {
- fprintf(where,"calc_service_demand using: units_sent = %f\n",
- units_sent);
- fprintf(where," elapsed_time = %f\n",
- elapsed_time);
- fprintf(where," cpu_util = %f\n",
- cpu_utilization);
- fprintf(where," num cpu = %d\n",
- num_cpus);
- fprintf(where,"calc_service_demand got: thruput = %f\n",
- thruput);
- fprintf(where," servdem = %f\n",
- service_demand);
- fflush(where);
- }
- return (float)service_demand;
-}
-
-float calc_service_demand(double units_sent,
- float elapsed_time,
- float cpu_utilization,
- int num_cpus)
-
-{
-
- double unit_divisor = (double)1024.0;
-
- return(calc_service_demand_internal(unit_divisor,
- units_sent,
- elapsed_time,
- cpu_utilization,
- num_cpus));
-}
-
-float calc_service_demand_trans(double units_sent,
- float elapsed_time,
- float cpu_utilization,
- int num_cpus)
-
-{
-
- double unit_divisor = (double)1.0;
-
- return(calc_service_demand_internal(unit_divisor,
- units_sent,
- elapsed_time,
- cpu_utilization,
- num_cpus));
-}
-
-
-
-float
-calibrate_local_cpu(float local_cpu_rate)
-{
-
- lib_num_loc_cpus = get_num_cpus();
-
- lib_use_idle = 0;
-#ifdef USE_LOOPER
- cpu_util_init();
- lib_use_idle = 1;
-#endif /* USE_LOOPER */
-
- if (local_cpu_rate > 0) {
- /* The user think that he knows what the cpu rate is. We assume */
- /* that all the processors of an MP system are essentially the */
- /* same - for this reason we do not have a per processor maxrate. */
- /* if the machine has processors which are different in */
- /* performance, the CPU utilization will be skewed. raj 4/95 */
- lib_local_maxrate = local_cpu_rate;
- }
- else {
- /* if neither USE_LOOPER nor USE_PSTAT are defined, we return a */
- /* 0.0 to indicate that times or getrusage should be used. raj */
- /* 4/95 */
- lib_local_maxrate = (float)0.0;
-#if defined(USE_PROC_STAT) || defined(USE_LOOPER) || defined(USE_PSTAT) || defined(USE_KSTAT) || defined(USE_PERFSTAT) || defined(USE_SYSCTL)
- lib_local_maxrate = calibrate_idle_rate(4,10);
-#endif
- }
- return lib_local_maxrate;
-}
-
-
-float
-calibrate_remote_cpu()
-{
- float remrate;
-
- netperf_request.content.request_type = CPU_CALIBRATE;
- send_request();
- /* we know that calibration will last at least 40 seconds, so go to */
- /* sleep for that long so the 60 second select in recv_response will */
- /* not pop. raj 7/95 */
-
- /* we know that CPU calibration may last as long as 40 seconds, so
- make sure we "select" for at least that long while looking for
- the response. raj 2005-05-16 */
- recv_response_timed(40);
-
- if (netperf_response.content.serv_errno) {
- /* initially, silently ignore remote errors and pass */
- /* back a zero to the caller this should allow us to */
- /* mix rev 1.0 and rev 1.1 netperfs... */
- return((float)0.0);
- }
- else {
- /* the rate is the first word of the test_specific data */
- bcopy((char *)netperf_response.content.test_specific_data,
- (char *)&remrate,
- sizeof(remrate));
- bcopy((char *)netperf_response.content.test_specific_data + sizeof(remrate),
- (char *)&lib_num_rem_cpus,
- sizeof(lib_num_rem_cpus));
-/* remrate = (float) netperf_response.content.test_specific_data[0]; */
- return(remrate);
- }
-}
-
-#ifndef WIN32
-/* WIN32 requires that at least one of the file sets to select be non-null. */
-/* Since msec_sleep routine is only called by nettest_dlpi & nettest_unix, */
-/* let's duck this issue. */
-
-int
-msec_sleep( int msecs )
-{
- int rval ;
-
- struct timeval timeout;
-
- timeout.tv_sec = msecs / 1000;
- timeout.tv_usec = (msecs - (msecs/1000) *1000) * 1000;
- if ((rval = select(0,
- 0,
- 0,
- 0,
- &timeout))) {
- if ( SOCKET_EINTR(rval) ) {
- return(1);
- }
- perror("msec_sleep: select");
- exit(1);
- }
- return(0);
-}
-#endif /* WIN32 */
-
-#ifdef WANT_HISTOGRAM
-/* hist.c
-
- Given a time difference in microseconds, increment one of 61
- different buckets:
-
- 0 - 9 in increments of 1 usec
- 0 - 9 in increments of 10 usecs
- 0 - 9 in increments of 100 usecs
- 1 - 9 in increments of 1 msec
- 1 - 9 in increments of 10 msecs
- 1 - 9 in increments of 100 msecs
- 1 - 9 in increments of 1 sec
- 1 - 9 in increments of 10 sec
- > 100 secs
-
- This will allow any time to be recorded to within an accuracy of
- 10%, and provides a compact representation for capturing the
- distribution of a large number of time differences (e.g.
- request-response latencies).
-
- Colin Low 10/6/93
- Rick Jones 2004-06-15 extend to unit and ten usecs
-*/
-
-/* #include "sys.h" */
-
-/*#define HIST_TEST*/
-
-HIST
-HIST_new(void){
- HIST h;
- if((h = (HIST) malloc(sizeof(struct histogram_struct))) == NULL) {
- perror("HIST_new - malloc failed");
- exit(1);
- }
- HIST_clear(h);
- return h;
-}
-
-void
-HIST_clear(HIST h){
- int i;
- for(i = 0; i < 10; i++){
- h->unit_usec[i] = 0;
- h->ten_usec[i] = 0;
- h->hundred_usec[i] = 0;
- h->unit_msec[i] = 0;
- h->ten_msec[i] = 0;
- h->hundred_msec[i] = 0;
- h->unit_sec[i] = 0;
- h->ten_sec[i] = 0;
- }
- h->ridiculous = 0;
- h->total = 0;
-}
-
-void
-HIST_add(register HIST h, int time_delta){
- register int val;
- h->total++;
- val = time_delta;
- if(val <= 9) h->unit_usec[val]++;
- else {
- val = val/10;
- if(val <= 9) h->ten_usec[val]++;
- else {
- val = val/10;
- if(val <= 9) h->hundred_usec[val]++;
- else {
- val = val/10;
- if(val <= 9) h->unit_msec[val]++;
- else {
- val = val/10;
- if(val <= 9) h->ten_msec[val]++;
- else {
- val = val/10;
- if(val <= 9) h->hundred_msec[val]++;
- else {
- val = val/10;
- if(val <= 9) h->unit_sec[val]++;
- else {
- val = val/10;
- if(val <= 9) h->ten_sec[val]++;
- else h->ridiculous++;
- }
- }
- }
- }
- }
- }
- }
-}
-
-#define RB_printf printf
-
-void
-output_row(FILE *fd, char *title, int *row){
- register int i;
- RB_printf("%s", title);
- for(i = 0; i < 10; i++) RB_printf(": %4d", row[i]);
- RB_printf("\n");
-}
-
-int
-sum_row(int *row) {
- int sum = 0;
- int i;
- for (i = 0; i < 10; i++) sum += row[i];
- return(sum);
-}
-
-void
-HIST_report(HIST h){
-#ifndef OLD_HISTOGRAM
- output_row(stdout, "UNIT_USEC ", h->unit_usec);
- output_row(stdout, "TEN_USEC ", h->ten_usec);
- output_row(stdout, "HUNDRED_USEC ", h->hundred_usec);
-#else
- h->hundred_usec[0] += sum_row(h->unit_usec);
- h->hundred_usec[0] += sum_row(h->ten_usec);
- output_row(stdout, "TENTH_MSEC ", h->hundred_usec);
-#endif
- output_row(stdout, "UNIT_MSEC ", h->unit_msec);
- output_row(stdout, "TEN_MSEC ", h->ten_msec);
- output_row(stdout, "HUNDRED_MSEC ", h->hundred_msec);
- output_row(stdout, "UNIT_SEC ", h->unit_sec);
- output_row(stdout, "TEN_SEC ", h->ten_sec);
- RB_printf(">100_SECS: %d\n", h->ridiculous);
- RB_printf("HIST_TOTAL: %d\n", h->total);
-}
-
-#endif
-
-/* with the advent of sit-and-spin intervals support, we might as well
- make these things available all the time, not just for demo or
- histogram modes. raj 2006-02-06 */
-#ifdef HAVE_GETHRTIME
-
-void
-HIST_timestamp(hrtime_t *timestamp)
-{
- *timestamp = gethrtime();
-}
-
-int
-delta_micro(hrtime_t *begin, hrtime_t *end)
-{
- long nsecs;
- nsecs = (*end) - (*begin);
- return(nsecs/1000);
-}
-
-#elif defined(HAVE_GET_HRT)
-#include "hrt.h"
-
-void
-HIST_timestamp(hrt_t *timestamp)
-{
- *timestamp = get_hrt();
-}
-
-int
-delta_micro(hrt_t *begin, hrt_t *end)
-{
-
- return((int)get_hrt_delta(*end,*begin));
-
-}
-#elif defined(WIN32)
-void HIST_timestamp(LARGE_INTEGER *timestamp)
-{
- QueryPerformanceCounter(timestamp);
-}
-
-int delta_micro(LARGE_INTEGER *begin, LARGE_INTEGER *end)
-{
- LARGE_INTEGER DeltaTimestamp;
- static LARGE_INTEGER TickHz = {0,0};
-
- if (TickHz.QuadPart == 0)
- {
- QueryPerformanceFrequency(&TickHz);
- }
-
- /*+*+ Rick; this will overflow after ~2000 seconds, is that
- good enough? Spencer: Yes, that should be more than good
- enough for histogram support */
-
- DeltaTimestamp.QuadPart = (end->QuadPart - begin->QuadPart) *
- 1000000/TickHz.QuadPart;
- assert((DeltaTimestamp.HighPart == 0) &&
- ((int)DeltaTimestamp.LowPart >= 0));
-
- return (int)DeltaTimestamp.LowPart;
-}
-
-#else
-
-void
-HIST_timestamp(struct timeval *timestamp)
-{
- gettimeofday(timestamp,NULL);
-}
-
- /* return the difference (in micro seconds) between two timeval */
- /* timestamps */
-int
-delta_micro(struct timeval *begin,struct timeval *end)
-
-{
-
- int usecs, secs;
-
- if (end->tv_usec < begin->tv_usec) {
- /* borrow a second from the tv_sec */
- end->tv_usec += 1000000;
- end->tv_sec--;
- }
- usecs = end->tv_usec - begin->tv_usec;
- secs = end->tv_sec - begin->tv_sec;
-
- usecs += (secs * 1000000);
-
- return(usecs);
-
-}
-#endif /* HAVE_GETHRTIME */
-
-
-#ifdef WANT_DLPI
-
-int
-put_control(fd, len, pri, ack)
- int fd, len, pri, ack;
-{
- int error;
- int flags = 0;
- dl_error_ack_t *err_ack = (dl_error_ack_t *)control_data;
-
- control_message.len = len;
-
- if ((error = putmsg(fd, &control_message, 0, pri)) < 0 ) {
- fprintf(where,"put_control: putmsg error %d\n",error);
- fflush(where);
- return(-1);
- }
- if ((error = getmsg(fd, &control_message, 0, &flags)) < 0) {
- fprintf(where,"put_control: getsmg error %d\n",error);
- fflush(where);
- return(-1);
- }
- if (err_ack->dl_primitive != ack) {
- fprintf(where,"put_control: acknowledgement error wanted %u got %u \n",
- ack,err_ack->dl_primitive);
- if (err_ack->dl_primitive == DL_ERROR_ACK) {
- fprintf(where," dl_error_primitive: %u\n",
- err_ack->dl_error_primitive);
- fprintf(where," dl_errno: %u\n",
- err_ack->dl_errno);
- fprintf(where," dl_unix_errno %u\n",
- err_ack->dl_unix_errno);
- }
- fflush(where);
- return(-1);
- }
-
- return(0);
-}
-
-int
-dl_open(char devfile[], int ppa)
-{
- int fd;
- dl_attach_req_t *attach_req = (dl_attach_req_t *)control_data;
-
- if ((fd = open(devfile, O_RDWR)) == -1) {
- fprintf(where,"netperf: dl_open: open of %s failed, errno = %d\n",
- devfile,
- errno);
- return(-1);
- }
-
- attach_req->dl_primitive = DL_ATTACH_REQ;
- attach_req->dl_ppa = ppa;
-
- if (put_control(fd, sizeof(dl_attach_req_t), 0, DL_OK_ACK) < 0) {
- fprintf(where,
- "netperf: dl_open: could not send control message, errno = %d\n",
- errno);
- return(-1);
- }
- return(fd);
-}
-
-int
-dl_bind(int fd, int sap, int mode, char *dlsap_ptr, int *dlsap_len)
-{
- dl_bind_req_t *bind_req = (dl_bind_req_t *)control_data;
- dl_bind_ack_t *bind_ack = (dl_bind_ack_t *)control_data;
-
- bind_req->dl_primitive = DL_BIND_REQ;
- bind_req->dl_sap = sap;
- bind_req->dl_max_conind = 1;
- bind_req->dl_service_mode = mode;
- bind_req->dl_conn_mgmt = 0;
- bind_req->dl_xidtest_flg = 0;
-
- if (put_control(fd, sizeof(dl_bind_req_t), 0, DL_BIND_ACK) < 0) {
- fprintf(where,
- "netperf: dl_bind: could not send control message, errno = %d\n",
- errno);
- return(-1);
- }
-
- /* at this point, the control_data portion of the control message */
- /* structure should contain a DL_BIND_ACK, which will have a full */
- /* DLSAP in it. we want to extract this and pass it up so that */
- /* it can be passed around. */
- if (*dlsap_len >= bind_ack->dl_addr_length) {
- bcopy((char *)bind_ack+bind_ack->dl_addr_offset,
- dlsap_ptr,
- bind_ack->dl_addr_length);
- *dlsap_len = bind_ack->dl_addr_length;
- return(0);
- }
- else {
- return (-1);
- }
-}
-
-int
-dl_connect(int fd, unsigned char *remote_addr, int remote_addr_len)
-{
- dl_connect_req_t *connection_req = (dl_connect_req_t *)control_data;
- dl_connect_con_t *connection_con = (dl_connect_con_t *)control_data;
- struct pollfd pinfo;
-
- int flags = 0;
-
- /* this is here on the off chance that we really want some data */
- u_long data_area[512];
- struct strbuf data_message;
-
- int error;
-
- data_message.maxlen = 2048;
- data_message.len = 0;
- data_message.buf = (char *)data_area;
-
- connection_req->dl_primitive = DL_CONNECT_REQ;
- connection_req->dl_dest_addr_length = remote_addr_len;
- connection_req->dl_dest_addr_offset = sizeof(dl_connect_req_t);
- connection_req->dl_qos_length = 0;
- connection_req->dl_qos_offset = 0;
- bcopy (remote_addr,
- (unsigned char *)control_data + sizeof(dl_connect_req_t),
- remote_addr_len);
-
- /* well, I would call the put_control routine here, but the sequence */
- /* of connection stuff with DLPI is a bit screwey with all this */
- /* message passing - Toto, I don't think were in Berkeley anymore. */
-
- control_message.len = sizeof(dl_connect_req_t) + remote_addr_len;
- if ((error = putmsg(fd,&control_message,0,0)) !=0) {
- fprintf(where,"dl_connect: putmsg failure, errno = %d, error 0x%x \n",
- errno,error);
- fflush(where);
- return(-1);
- };
-
- pinfo.fd = fd;
- pinfo.events = POLLIN | POLLPRI;
- pinfo.revents = 0;
-
- if ((error = getmsg(fd,&control_message,&data_message,&flags)) != 0) {
- fprintf(where,"dl_connect: getmsg failure, errno = %d, error 0x%x \n",
- errno,error);
- fflush(where);
- return(-1);
- }
- while (control_data[0] == DL_TEST_CON) {
- /* i suppose we spin until we get an error, or a connection */
- /* indication */
- if((error = getmsg(fd,&control_message,&data_message,&flags)) !=0) {
- fprintf(where,"dl_connect: getmsg failure, errno = %d, error = 0x%x\n",
- errno,error);
- fflush(where);
- return(-1);
- }
- }
-
- /* we are out - it either worked or it didn't - which was it? */
- if (control_data[0] == DL_CONNECT_CON) {
- return(0);
- }
- else {
- return(-1);
- }
-}
-
-int
-dl_accept(fd, remote_addr, remote_addr_len)
- int fd;
- unsigned char *remote_addr;
- int remote_addr_len;
-{
- dl_connect_ind_t *connect_ind = (dl_connect_ind_t *)control_data;
- dl_connect_res_t *connect_res = (dl_connect_res_t *)control_data;
- int tmp_cor;
- int flags = 0;
-
- /* hang around and wait for a connection request */
- getmsg(fd,&control_message,0,&flags);
- while (control_data[0] != DL_CONNECT_IND) {
- getmsg(fd,&control_message,0,&flags);
- }
-
- /* now respond to the request. at some point, we may want to be sure */
- /* that the connection came from the correct station address, but */
- /* will assume that we do not have to worry about it just now. */
-
- tmp_cor = connect_ind->dl_correlation;
-
- connect_res->dl_primitive = DL_CONNECT_RES;
- connect_res->dl_correlation = tmp_cor;
- connect_res->dl_resp_token = 0;
- connect_res->dl_qos_length = 0;
- connect_res->dl_qos_offset = 0;
- connect_res->dl_growth = 0;
-
- return(put_control(fd, sizeof(dl_connect_res_t), 0, DL_OK_ACK));
-
-}
-
-int
-dl_set_window(fd, window)
- int fd, window;
-{
- return(0);
-}
-
-void
-dl_stats(fd)
- int fd;
-{
-}
-
-int
-dl_send_disc(fd)
- int fd;
-{
-}
-
-int
-dl_recv_disc(fd)
- int fd;
-{
-}
-#endif /* WANT_DLPI*/
-
- /* these routines for confidence intervals are courtesy of IBM. They */
- /* have been modified slightly for more general usage beyond TCP/UDP */
- /* tests. raj 11/94 I would suspect that this code carries an IBM */
- /* copyright that is much the same as that for the original HP */
- /* netperf code */
-int confidence_iterations; /* for iterations */
-
-double
- result_confid=-10.0,
- loc_cpu_confid=-10.0,
- rem_cpu_confid=-10.0,
-
- measured_sum_result=0.0,
- measured_square_sum_result=0.0,
- measured_mean_result=0.0,
- measured_var_result=0.0,
-
- measured_sum_local_cpu=0.0,
- measured_square_sum_local_cpu=0.0,
- measured_mean_local_cpu=0.0,
- measured_var_local_cpu=0.0,
-
- measured_sum_remote_cpu=0.0,
- measured_square_sum_remote_cpu=0.0,
- measured_mean_remote_cpu=0.0,
- measured_var_remote_cpu=0.0,
-
- measured_sum_local_service_demand=0.0,
- measured_square_sum_local_service_demand=0.0,
- measured_mean_local_service_demand=0.0,
- measured_var_local_service_demand=0.0,
-
- measured_sum_remote_service_demand=0.0,
- measured_square_sum_remote_service_demand=0.0,
- measured_mean_remote_service_demand=0.0,
- measured_var_remote_service_demand=0.0,
-
- measured_sum_local_time=0.0,
- measured_square_sum_local_time=0.0,
- measured_mean_local_time=0.0,
- measured_var_local_time=0.0,
-
- measured_mean_remote_time=0.0,
-
- measured_fails,
- measured_local_results,
- confidence=-10.0;
-/* interval=0.1; */
-
-/************************************************************************/
-/* */
-/* Constants for Confidence Intervals */
-/* */
-/************************************************************************/
-void
-init_stat()
-{
- measured_sum_result=0.0;
- measured_square_sum_result=0.0;
- measured_mean_result=0.0;
- measured_var_result=0.0;
-
- measured_sum_local_cpu=0.0;
- measured_square_sum_local_cpu=0.0;
- measured_mean_local_cpu=0.0;
- measured_var_local_cpu=0.0;
-
- measured_sum_remote_cpu=0.0;
- measured_square_sum_remote_cpu=0.0;
- measured_mean_remote_cpu=0.0;
- measured_var_remote_cpu=0.0;
-
- measured_sum_local_service_demand=0.0;
- measured_square_sum_local_service_demand=0.0;
- measured_mean_local_service_demand=0.0;
- measured_var_local_service_demand=0.0;
-
- measured_sum_remote_service_demand=0.0;
- measured_square_sum_remote_service_demand=0.0;
- measured_mean_remote_service_demand=0.0;
- measured_var_remote_service_demand=0.0;
-
- measured_sum_local_time=0.0;
- measured_square_sum_local_time=0.0;
- measured_mean_local_time=0.0;
- measured_var_local_time=0.0;
-
- measured_mean_remote_time=0.0;
-
- measured_fails = 0.0;
- measured_local_results=0.0,
- confidence=-10.0;
-}
-
- /* this routine does a simple table lookup for some statistical */
- /* function that I would remember if I stayed awake in my probstats */
- /* class... raj 11/94 */
-double
-confid(int level, int freedom)
-{
-double t99[35],t95[35];
-
- t95[1]=12.706;
- t95[2]= 4.303;
- t95[3]= 3.182;
- t95[4]= 2.776;
- t95[5]= 2.571;
- t95[6]= 2.447;
- t95[7]= 2.365;
- t95[8]= 2.306;
- t95[9]= 2.262;
- t95[10]= 2.228;
- t95[11]= 2.201;
- t95[12]= 2.179;
- t95[13]= 2.160;
- t95[14]= 2.145;
- t95[15]= 2.131;
- t95[16]= 2.120;
- t95[17]= 2.110;
- t95[18]= 2.101;
- t95[19]= 2.093;
- t95[20]= 2.086;
- t95[21]= 2.080;
- t95[22]= 2.074;
- t95[23]= 2.069;
- t95[24]= 2.064;
- t95[25]= 2.060;
- t95[26]= 2.056;
- t95[27]= 2.052;
- t95[28]= 2.048;
- t95[29]= 2.045;
- t95[30]= 2.042;
-
- t99[1]=63.657;
- t99[2]= 9.925;
- t99[3]= 5.841;
- t99[4]= 4.604;
- t99[5]= 4.032;
- t99[6]= 3.707;
- t99[7]= 3.499;
- t99[8]= 3.355;
- t99[9]= 3.250;
- t99[10]= 3.169;
- t99[11]= 3.106;
- t99[12]= 3.055;
- t99[13]= 3.012;
- t99[14]= 2.977;
- t99[15]= 2.947;
- t99[16]= 2.921;
- t99[17]= 2.898;
- t99[18]= 2.878;
- t99[19]= 2.861;
- t99[20]= 2.845;
- t99[21]= 2.831;
- t99[22]= 2.819;
- t99[23]= 2.807;
- t99[24]= 2.797;
- t99[25]= 2.787;
- t99[26]= 2.779;
- t99[27]= 2.771;
- t99[28]= 2.763;
- t99[29]= 2.756;
- t99[30]= 2.750;
-
- if(level==95){
- return(t95[freedom]);
- } else if(level==99){
- return(t99[freedom]);
- } else{
- return(0);
- }
-}
-
-void
-calculate_confidence(int confidence_iterations,
- float time,
- double result,
- float loc_cpu,
- float rem_cpu,
- float loc_sd,
- float rem_sd)
-{
-
- if (debug) {
- fprintf(where,
- "calculate_confidence: itr %d; time %f; res %f\n",
- confidence_iterations,
- time,
- result);
- fprintf(where,
- " lcpu %f; rcpu %f\n",
- loc_cpu,
- rem_cpu);
- fprintf(where,
- " lsdm %f; rsdm %f\n",
- loc_sd,
- rem_sd);
- fflush(where);
- }
-
- /* the test time */
- measured_sum_local_time +=
- (double) time;
- measured_square_sum_local_time +=
- (double) time*time;
- measured_mean_local_time =
- (double) measured_sum_local_time/confidence_iterations;
- measured_var_local_time =
- (double) measured_square_sum_local_time/confidence_iterations
- -measured_mean_local_time*measured_mean_local_time;
-
- /* the test result */
- measured_sum_result +=
- (double) result;
- measured_square_sum_result +=
- (double) result*result;
- measured_mean_result =
- (double) measured_sum_result/confidence_iterations;
- measured_var_result =
- (double) measured_square_sum_result/confidence_iterations
- -measured_mean_result*measured_mean_result;
-
- /* local cpu utilization */
- measured_sum_local_cpu +=
- (double) loc_cpu;
- measured_square_sum_local_cpu +=
- (double) loc_cpu*loc_cpu;
- measured_mean_local_cpu =
- (double) measured_sum_local_cpu/confidence_iterations;
- measured_var_local_cpu =
- (double) measured_square_sum_local_cpu/confidence_iterations
- -measured_mean_local_cpu*measured_mean_local_cpu;
-
- /* remote cpu util */
- measured_sum_remote_cpu +=
- (double) rem_cpu;
- measured_square_sum_remote_cpu+=
- (double) rem_cpu*rem_cpu;
- measured_mean_remote_cpu =
- (double) measured_sum_remote_cpu/confidence_iterations;
- measured_var_remote_cpu =
- (double) measured_square_sum_remote_cpu/confidence_iterations
- -measured_mean_remote_cpu*measured_mean_remote_cpu;
-
- /* local service demand */
- measured_sum_local_service_demand +=
- (double) loc_sd;
- measured_square_sum_local_service_demand+=
- (double) loc_sd*loc_sd;
- measured_mean_local_service_demand =
- (double) measured_sum_local_service_demand/confidence_iterations;
- measured_var_local_service_demand =
- (double) measured_square_sum_local_service_demand/confidence_iterations
- -measured_mean_local_service_demand*measured_mean_local_service_demand;
-
- /* remote service demand */
- measured_sum_remote_service_demand +=
- (double) rem_sd;
- measured_square_sum_remote_service_demand+=
- (double) rem_sd*rem_sd;
- measured_mean_remote_service_demand =
- (double) measured_sum_remote_service_demand/confidence_iterations;
- measured_var_remote_service_demand =
- (double) measured_square_sum_remote_service_demand/confidence_iterations
- -measured_mean_remote_service_demand*measured_mean_remote_service_demand;
-
- if(confidence_iterations>1){
- result_confid= (double) interval -
- 2.0 * confid(confidence_level,confidence_iterations-1)*
- sqrt(measured_var_result/(confidence_iterations-1.0)) /
- measured_mean_result;
-
- loc_cpu_confid= (double) interval -
- 2.0 * confid(confidence_level,confidence_iterations-1)*
- sqrt(measured_var_local_cpu/(confidence_iterations-1.0)) /
- measured_mean_local_cpu;
-
- rem_cpu_confid= (double) interval -
- 2.0 * confid(confidence_level,confidence_iterations-1)*
- sqrt(measured_var_remote_cpu/(confidence_iterations-1.0)) /
- measured_mean_remote_cpu;
-
- if(debug){
- printf("Conf_itvl %2d: results:%4.1f%% loc_cpu:%4.1f%% rem_cpu:%4.1f%%\n",
- confidence_iterations,
- (interval-result_confid)*100.0,
- (interval-loc_cpu_confid)*100.0,
- (interval-rem_cpu_confid)*100.0);
- }
-
- /* if the user has requested that we only wait for the result to
- be confident rather than the result and CPU util(s) then do
- so. raj 2007-08-08 */
- if (!result_confidence_only) {
- confidence = min(min(result_confid,loc_cpu_confid),rem_cpu_confid);
- }
- else {
- confidence = result_confid;
- }
- }
-}
-
- /* here ends the IBM code */
-
-void
-retrieve_confident_values(float *elapsed_time,
- double *thruput,
- float *local_cpu_utilization,
- float *remote_cpu_utilization,
- float *local_service_demand,
- float *remote_service_demand)
-
-{
- *elapsed_time = (float)measured_mean_local_time;
- *thruput = measured_mean_result;
- *local_cpu_utilization = (float)measured_mean_local_cpu;
- *remote_cpu_utilization = (float)measured_mean_remote_cpu;
- *local_service_demand = (float)measured_mean_local_service_demand;
- *remote_service_demand = (float)measured_mean_remote_service_demand;
-}
-
- /* display_confidence() is called when we could not achieve the */
- /* desirec confidence in the results. it will print the achieved */
- /* confidence to "where" raj 11/94 */
-void
-display_confidence()
-
-{
- fprintf(where,
- "!!! WARNING\n");
- fprintf(where,
- "!!! Desired confidence was not achieved within ");
- fprintf(where,
- "the specified iterations.\n");
- fprintf(where,
- "!!! This implies that there was variability in ");
- fprintf(where,
- "the test environment that\n");
- fprintf(where,
- "!!! must be investigated before going further.\n");
- fprintf(where,
- "!!! Confidence intervals: Throughput : %4.1f%%\n",
- 100.0 * (interval - result_confid));
- fprintf(where,
- "!!! Local CPU util : %4.1f%%\n",
- 100.0 * (interval - loc_cpu_confid));
- fprintf(where,
- "!!! Remote CPU util : %4.1f%%\n\n",
- 100.0 * (interval - rem_cpu_confid));
-}
-
diff --git a/netlib.h b/netlib.h
deleted file mode 100644
index 5b6900e..0000000
--- a/netlib.h
+++ /dev/null
@@ -1,621 +0,0 @@
-/*
- Copyright (C) 1993-2005 Hewlett-Packard Company
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#if defined(HAVE_SYS_SOCKET_H)
-# include <sys/socket.h>
-#endif
-#if defined(HAVE_NETDB_H)
-# include <netdb.h>
-#endif
-#if !defined(HAVE_GETADDRINFO) || !defined(HAVE_GETNAMEINFO)
-# include "missing/getaddrinfo.h"
-#endif
-
-#define PAD_TIME 4
-/* library routine specifc defines */
-#define MAXSPECDATA 62 /* how many ints worth of data */
- /* can tests send... */
-#define MAXTIMES 4 /* how many times may we loop */
- /* to calibrate */
-#define MAXCPUS 256 /* how many CPU's can we track */
-#define MAXMESSAGESIZE 65536
-#define MAXALIGNMENT 16384
-#define MAXOFFSET 4096
-#define DATABUFFERLEN MAXMESSAGESIZE+MAXALIGNMENT+MAXOFFSET
-
-#define DEBUG_ON 1
-#define DEBUG_OFF 2
-#define DEBUG_OK 3
-#define NODE_IDENTIFY 4
-#define CPU_CALIBRATE 5
-
-#define DO_TCP_STREAM 10
-#define TCP_STREAM_RESPONSE 11
-#define TCP_STREAM_RESULTS 12
-
-#define DO_TCP_RR 13
-#define TCP_RR_RESPONSE 14
-#define TCP_RR_RESULTS 15
-
-#define DO_UDP_STREAM 16
-#define UDP_STREAM_RESPONSE 17
-#define UDP_STREAM_RESULTS 18
-
-#define DO_UDP_RR 19
-#define UDP_RR_RESPONSE 20
-#define UDP_RR_RESULTS 21
-
-#define DO_DLPI_CO_STREAM 22
-#define DLPI_CO_STREAM_RESPONSE 23
-#define DLPI_CO_STREAM_RESULTS 24
-
-#define DO_DLPI_CO_RR 25
-#define DLPI_CO_RR_RESPONSE 26
-#define DLPI_CO_RR_RESULTS 27
-
-#define DO_DLPI_CL_STREAM 28
-#define DLPI_CL_STREAM_RESPONSE 29
-#define DLPI_CL_STREAM_RESULTS 30
-
-#define DO_DLPI_CL_RR 31
-#define DLPI_CL_RR_RESPONSE 32
-#define DLPI_CL_RR_RESULTS 33
-
-#define DO_TCP_CRR 34
-#define TCP_CRR_RESPONSE 35
-#define TCP_CRR_RESULTS 36
-
-#define DO_STREAM_STREAM 37
-#define STREAM_STREAM_RESPONSE 38
-#define STREAM_STREAM_RESULTS 39
-
-#define DO_STREAM_RR 40
-#define STREAM_RR_RESPONSE 41
-#define STREAM_RR_RESULTS 42
-
-#define DO_DG_STREAM 43
-#define DG_STREAM_RESPONSE 44
-#define DG_STREAM_RESULTS 45
-
-#define DO_DG_RR 46
-#define DG_RR_RESPONSE 47
-#define DG_RR_RESULTS 48
-
-#define DO_FORE_STREAM 49
-#define FORE_STREAM_RESPONSE 50
-#define FORE_STREAM_RESULTS 51
-
-#define DO_FORE_RR 52
-#define FORE_RR_RESPONSE 53
-#define FORE_RR_RESULTS 54
-
-#define DO_HIPPI_STREAM 55
-#define HIPPI_STREAM_RESPONSE 56
-#define HIPPI_STREAM_RESULTS 57
-
-#define DO_HIPPI_RR 52
-#define HIPPI_RR_RESPONSE 53
-#define HIPPI_RR_RESULTS 54
-
-#define DO_XTI_TCP_STREAM 55
-#define XTI_TCP_STREAM_RESPONSE 56
-#define XTI_TCP_STREAM_RESULTS 57
-
-#define DO_XTI_TCP_RR 58
-#define XTI_TCP_RR_RESPONSE 59
-#define XTI_TCP_RR_RESULTS 60
-
-#define DO_XTI_UDP_STREAM 61
-#define XTI_UDP_STREAM_RESPONSE 62
-#define XTI_UDP_STREAM_RESULTS 63
-
-#define DO_XTI_UDP_RR 64
-#define XTI_UDP_RR_RESPONSE 65
-#define XTI_UDP_RR_RESULTS 66
-
-#define DO_XTI_TCP_CRR 67
-#define XTI_TCP_CRR_RESPONSE 68
-#define XTI_TCP_CRR_RESULTS 69
-
-#define DO_TCP_TRR 70
-#define TCP_TRR_RESPONSE 71
-#define TCP_TRR_RESULTS 72
-
-#define DO_TCP_NBRR 73
-#define TCP_NBRR_RESPONSE 74
-#define TCP_NBRR_RESULTS 75
-
-#define DO_TCPIPV6_STREAM 76
-#define TCPIPV6_STREAM_RESPONSE 77
-#define TCPIPV6_STREAM_RESULTS 78
-
-#define DO_TCPIPV6_RR 79
-#define TCPIPV6_RR_RESPONSE 80
-#define TCPIPV6_RR_RESULTS 81
-
-#define DO_UDPIPV6_STREAM 82
-#define UDPIPV6_STREAM_RESPONSE 83
-#define UDPIPV6_STREAM_RESULTS 84
-
-#define DO_UDPIPV6_RR 85
-#define UDPIPV6_RR_RESPONSE 86
-#define UDPIPV6_RR_RESULTS 87
-
-#define DO_TCPIPV6_CRR 88
-#define TCPIPV6_CRR_RESPONSE 89
-#define TCPIPV6_CRR_RESULTS 90
-
-#define DO_TCPIPV6_TRR 91
-#define TCPIPV6_TRR_RESPONSE 92
-#define TCPIPV6_TRR_RESULTS 93
-
-#define DO_TCP_MAERTS 94
-#define TCP_MAERTS_RESPONSE 95
-#define TCP_MAERTS_RESULTS 96
-
-#define DO_LWPSTR_STREAM 100
-#define LWPSTR_STREAM_RESPONSE 110
-#define LWPSTR_STREAM_RESULTS 120
-
-#define DO_LWPSTR_RR 130
-#define LWPSTR_RR_RESPONSE 140
-#define LWPSTR_RR_RESULTS 150
-
-#define DO_LWPDG_STREAM 160
-#define LWPDG_STREAM_RESPONSE 170
-#define LWPDG_STREAM_RESULTS 180
-
-#define DO_LWPDG_RR 190
-#define LWPDG_RR_RESPONSE 200
-#define LWPDG_RR_RESULTS 210
-
-#define DO_TCP_CC 300
-#define TCP_CC_RESPONSE 301
-#define TCP_CC_RESULTS 302
-
-/* The DNS_RR test has been removed from netperf but we leave these
- here for historical purposes. Those wanting to do DNS_RR tests
- should use netperf4 instead. */
-#define DO_DNS_RR 400
-#define DNS_RR_RESPONSE 401
-#define DNS_RR_RESULTS 402
-
-#define DO_SCTP_STREAM 500
-#define SCTP_STREAM_RESPONSE 501
-#define SCTP_STREAM_RESULT 502
-
-#define DO_SCTP_STREAM_MANY 510
-#define SCTP_STREAM_MANY_RESPONSE 511
-#define SCTP_STREAM_MANY_RESULT 512
-
-#define DO_SCTP_RR 520
-#define SCTP_RR_RESPONSE 521
-#define SCTP_RR_RESULT 502
-
-#define DO_SCTP_RR_MANY 530
-#define SCTP_RR_MANY_RESPONSE 531
-#define SCTP_RR_MANY_RESULT 532
-
-#define DO_SDP_STREAM 540
-#define SDP_STREAM_RESPONSE 541
-#define SDP_STREAM_RESULTS 542
-
-#define DO_SDP_RR 543
-#define SDP_RR_RESPONSE 544
-#define SDP_RR_RESULTS 545
-
-#define DO_SDP_MAERTS 546
-#define SDP_MAERTS_RESPONSE 547
-#define SDP_MAERTS_RESULTS 548
-
-#define DO_SDP_CRR 549
-#define SDP_CRR_RESPONSE 550
-#define SDP_CRR_RESULTS 551
-
-#define DO_SDP_CC 552
-#define SDP_CC_RESPONSE 553
-#define SDP_CC_RESULTS 554
-
-#if HAVE_INTTYPES_H
-# include <inttypes.h>
-#else
-# if HAVE_STDINT_H
-# include <stdint.h>
-# endif
-#endif
-
-enum sock_buffer{
- SEND_BUFFER,
- RECV_BUFFER
-};
-
- /* some of the fields in these structures are going to be doubles and */
- /* such. so, we probably want to ensure that they will start on */
- /* "double" boundaries. this will break compatability to pre-2.1 */
- /* releases, but then, backwards compatability has never been a */
- /* stated goal of netperf. raj 11/95 */
-
-union netperf_request_struct {
- struct {
- int request_type;
- int dummy;
- int test_specific_data[MAXSPECDATA];
- } content;
- double dummy;
-};
-
-union netperf_response_struct {
- struct {
- int response_type;
- int serv_errno;
- int test_specific_data[MAXSPECDATA];
- } content;
- double dummy;
-};
-
-struct ring_elt {
- struct ring_elt *next; /* next element in the ring */
- char *buffer_base; /* in case we have to free it at somepoint */
- char *buffer_ptr; /* the aligned and offset pointer */
-};
-
-/* +*+ SAF Sorry about the hacks with errno; NT made me do it :(
-
- WinNT does define an errno.
- It is mostly a legacy from the XENIX days.
-
- Depending upon the version of the C run time that is linked in, it is
- either a simple variable (like UNIX code expects), but more likely it
- is the address of a procedure to return the error number. So any
- code that sets errno is likely to be overwriting the address of this
- procedure. Worse, only a tiny fraction of NT's errors get set
- through errno.
-
- So I have changed the netperf code to use a define Set_errno when
- that is it's intent. On non-windows platforms this is just an
- assignment to errno. But on NT this calls SetLastError.
-
- I also define errno (now only used on right side of assignments)
- on NT to be GetLastError.
-
- Similarly, perror is defined on NT, but it only accesses the same
- XENIX errors that errno covers. So on NT this is redefined to be
- Perror and it expands all GetLastError texts. */
-
-
-#ifdef WIN32
-/* INVALID_SOCKET == INVALID_HANDLE_VALUE == (unsigned int)(~0) */
-/* SOCKET_ERROR == -1 */
-#define ENOTSOCK WSAENOTSOCK
-#define EINTR WSAEINTR
-#define ENOBUFS WSAENOBUFS
-#define EWOULDBLOCK WSAEWOULDBLOCK
-#define EAFNOSUPPORT WSAEAFNOSUPPORT
-/* I don't use a C++ style of comment because it upsets some C
- compilers, possibly even when it is inside an ifdef WIN32... */
-/* from public\sdk\inc\crt\errno.h */
-#define ENOSPC 28
-
-#ifdef errno
-/* delete the one from stdlib.h */
-/*#define errno (*_errno()) */
-#undef errno
-#endif
-#define errno GetLastError()
-#define Set_errno(num) SetLastError((num))
-
-#define perror(text) PrintWin32Error(stderr, (text))
-#define Print_errno(stream, text) PrintWin32Error((stream), (text))
-
-extern void PrintWin32Error(FILE *stream, LPSTR text);
-
-#if !defined(NT_PERF) && !defined(USE_LOOPER)
-#define NT_PERF
-#endif
-#else
-/* Really shouldn't use manifest constants! */
-/*+*+SAF There are other examples of "== -1" and "<0" that probably */
-/*+*+SAF should be cleaned up as well. */
-#define INVALID_SOCKET -1
-#define SOCKET_ERROR -1
-
-#define SOCKET int
-#define Set_errno(num) errno = (num)
-
-#define Print_errno(stream, text) fprintf((stream), "%s errno %d\n", (text), errno)
-#endif
-
-/* Robin & Rick's kludge to try to have a timer signal EINTR by closing */
-/* the socket from another thread can also return several other errors. */
-/* Let's define a macro to hide all of this. */
-
-#ifndef WIN32
-#define SOCKET_EINTR(return_value) (errno == EINTR)
-#define SOCKET_EADDRINUSE(return_value) (errno == EADDRINUSE)
-#define SOCKET_EADDRNOTAVAIL(return_value) (errno == EADDRNOTAVAIL)
-
-#else
-
-/* not quite sure I like the extra cases for WIN32 but that is what my
- WIN32 expert sugested. I'm not sure what WSA's to put for
- EADDRINUSE */
-
-#define SOCKET_EINTR(return_value) \
- (((return_value) == SOCKET_ERROR) && \
- ((errno == EINTR) || \
- (errno == WSAECONNABORTED) || \
- (errno == WSAECONNRESET) ))
-#define SOCKET_EADDRINUSE(return_value) \
- (((return_value) == SOCKET_ERROR) && \
- ((errno == WSAEADDRINUSE) ))
-#define SOCKET_EADDRNOTAVAIL(return_value) \
- (((return_value) == SOCKET_ERROR) && \
- ((errno == WSAEADDRNOTAVAIL) ))
-#endif
-
-#ifdef HAVE_SENDFILE
-
-struct sendfile_ring_elt {
- struct sendfile_ring_elt *next; /* next element in the ring */
- int fildes; /* the file descriptor of the source
- file */
- off_t offset; /* the offset from the beginning of
- the file for this send */
- size_t length; /* the number of bytes to send -
- this is redundant with the
- send_size variable but I decided
- to include it anyway */
- struct iovec *hdtrl; /* a pointer to a header/trailer
- that we do not initially use and
- so should be set to NULL when the
- ring is setup. */
- int flags; /* the flags to pass to sendfile() -
- presently unused and should be
- set to zero when the ring is
- setup. */
-};
-
-#endif /* HAVE_SENDFILE */
-
- /* the diferent codes to denote the type of CPU utilization */
- /* methods used */
-#define CPU_UNKNOWN 0
-#define HP_IDLE_COUNTER 1
-#define PSTAT 2
-#define TIMES 3
-#define LOOPER 4
-#define GETRUSAGE 5
-#define NT_METHOD 6
-#define KSTAT 7
-#define PROC_STAT 8
-#define SYSCTL 9
-#define PERFSTAT 10
-#define KSTAT_10 11
-#define OSX 12
-
-#define BADCH ('?')
-
-#ifndef NETLIB
-#ifdef WIN32
-#ifndef _GETOPT_
-#define _GETOPT_
-
-int getopt(int argc, char **argv, char *optstring);
-
-extern char *optarg; /* returned arg to go with this option */
-extern int optind; /* index to next argv element to process */
-extern int opterr; /* should error messages be printed? */
-extern int optopt; /* */
-
-#endif /* _GETOPT_ */
-
-extern SOCKET win_kludge_socket, win_kludge_socket2;
-#endif /* WIN32 */
-
-extern int local_proc_affinity, remote_proc_affinity;
-
-/* these are to allow netperf to be run easily through those evil,
- end-to-end breaking things known as firewalls */
-extern char local_data_port[10];
-extern char remote_data_port[10];
-
-extern char *local_data_address;
-extern char *remote_data_address;
-
-extern int local_data_family;
-extern int remote_data_family;
-
-extern union netperf_request_struct netperf_request;
-extern union netperf_response_struct netperf_response;
-
-extern float lib_local_cpu_util;
-extern float lib_elapsed;
-extern float lib_local_maxrate;
-
-extern char libfmt;
-
-extern int cpu_method;
-extern int lib_num_loc_cpus;
-extern int lib_num_rem_cpus;
-extern SOCKET server_sock;
-extern int times_up;
-extern FILE *where;
-extern int loops_per_msec;
-extern float lib_local_per_cpu_util[];
-
-extern void netlib_init();
-extern int netlib_get_page_size();
-extern void install_signal_catchers();
-extern void establish_control(char hostname[],
- char port[],
- int af,
- char local_hostname[],
- char local_port[],
- int local_af);
-extern void shutdown_control();
-extern void init_stat();
-extern void send_request();
-extern void recv_response();
-extern void send_response();
-extern void recv_request();
-extern void dump_request();
-extern void dump_addrinfo(FILE *dumploc, struct addrinfo *info,
- char *host, char *port, int family);
-extern void start_timer(int time);
-extern void stop_timer();
-extern void cpu_start(int measure_cpu);
-extern void cpu_stop(int measure_cpu, float *elapsed);
-extern void calculate_confidence(int confidence_iterations,
- float time,
- double result,
- float loc_cpu,
- float rem_cpu,
- float loc_sd,
- float rem_sd);
-extern void retrieve_confident_values(float *elapsed_time,
- double *thruput,
- float *local_cpu_utilization,
- float *remote_cpu_utilization,
- float *local_service_demand,
- float *remote_service_demand);
-extern void display_confidence();
-extern void set_sock_buffer(SOCKET sd,
- enum sock_buffer which,
- int requested_size,
- int *effective_sizep);
-extern char *format_units();
-
-extern char *inet_ftos(int family);
-extern char *inet_ttos(int type);
-extern char *inet_ptos(int protocol);
-extern double ntohd(double net_double);
-extern double htond(double host_double);
-extern int inet_nton(int af, const void *src, char *dst, int cnt);
-extern void libmain();
-extern double calc_thruput(double units_received);
-extern double calc_thruput_interval(double units_received,double elapsed);
-extern double calc_thruput_omni(double units_received);
-extern double calc_thruput_interval_omni(double units_received,double elapsed);
-extern float calibrate_local_cpu(float local_cpu_rate);
-extern float calibrate_remote_cpu();
-extern void bind_to_specific_processor(int processor_affinity,int use_cpu_map);
-extern int set_nonblock (SOCKET sock);
-
-#ifndef WIN32
-
-/* WIN32 requires that at least one of the file sets to select be
- non-null. Since msec_sleep routine is only called by nettest_dlpi &
- nettest_unix, let's duck this issue. */
-
-extern int msec_sleep( int msecs );
-#endif /* WIN32 */
-extern float calc_cpu_util(float elapsed_time);
-extern float calc_service_demand(double units_sent,
- float elapsed_time,
- float cpu_utilization,
- int num_cpus);
-extern float calc_service_demand_trans(double units_sent,
- float elapsed_time,
- float cpu_utilization,
- int num_cpus);
-#if defined(__hpux)
-extern void catcher(int, siginfo_t *,void *);
-#else
-extern void catcher(int);
-#endif /* __hpux */
-extern struct ring_elt *allocate_buffer_ring();
-extern void access_buffer(char *buffer_ptr,
- int length,
- int dirty_count,
- int clean_count);
-
-#ifdef HAVE_ICSC_EXS
-extern struct ring_elt *allocate_exs_buffer_ring();
-#endif /* HAVE_ICSC_EXS */
-#ifdef HAVE_SENDFILE
-extern struct sendfile_ring_elt *alloc_sendfile_buf_ring();
-#endif /* HAVE_SENDFILE */
-#ifdef WANT_DLPI
-/* it seems that AIX in its finite wisdom has some bogus define in an
- include file which defines "rem_addr" which then screws-up this extern
- unless we change the names to protect the guilty. reported by Eric
- Jones */
-extern int dl_connect(int fd, unsigned char *remote_addr, int remote_addr_len);
-extern int dl_bind(int fd, int sap, int mode, char *dlsap_ptr, int *dlsap_len);
-extern int dl_open(char devfile[], int ppa);
-#endif /* WANT_DLPI */
-extern char format_cpu_method(int method);
-extern unsigned int convert(char *string);
-extern unsigned int convert_timespec(char *string);
-
-#ifdef WANT_INTERVALS
-extern void start_itimer(unsigned int interval_len_msec);
-#endif
- /* these are all for the confidence interval stuff */
-extern double confidence;
-
-#endif
-
-#ifdef WIN32
-#define close(x) closesocket(x)
-#define strcasecmp(a,b) _stricmp(a,b)
-#define getpid() ((int)GetCurrentProcessId())
-#endif
-
-#ifdef WIN32
-#if 0
-/* Should really use safe string functions; but not for now... */
-#include <strsafe.h>
-/* Microsoft has deprecated _snprintf; it isn't guarenteed to null terminate the result buffer. */
-/* They want us to call StringCbPrintf instead; it always null terminates the string. */
-#endif
-
-#define snprintf _snprintf
-#endif
-
-/* Define a macro to align a buffer with an offset from a power of 2
- boundary. */
-
-#ifndef WIN32
-#define ULONG_PTR unsigned long
-#endif
-
-#define ALIGN_BUFFER(BufPtr, Align, Offset) \
- (char *)(( (ULONG_PTR)(BufPtr) + \
- (ULONG_PTR) (Align) -1) & \
- ~((ULONG_PTR) (Align) - 1)) + (ULONG_PTR)(Offset)
-
- /* if your system has bcopy and bzero, include it here, otherwise, we */
- /* will try to use memcpy aand memset. fix from Bruce Barnett @ GE. */
-#if defined(hpux) || defined (__VMS)
-#define HAVE_BCOPY
-#define HAVE_BZERO
-#endif
-
-#ifdef WIN32
-#define HAVE_MIN
-#else
-#define _stdcall
-#define _cdecl
-#endif
-
-#ifndef HAVE_BCOPY
-#define bcopy(s,d,h) memcpy((d),(s),(h))
-#endif /* HAVE_BCOPY */
-
-#ifndef HAVE_BZERO
-#define bzero(p,h) memset((p),0,(h))
-#endif /* HAVE_BZERO */
-
-#ifndef HAVE_MIN
-#define min(a,b) ((a < b) ? a : b)
-#endif /* HAVE_MIN */
-
-#ifdef USE_PERFSTAT
-# include <libperfstat.h>
-#endif
diff --git a/netperf.c b/netperf.c
deleted file mode 100644
index 84717ac..0000000
--- a/netperf.c
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
-
- Copyright (C) 1993-2007 Hewlett-Packard Company
- ALL RIGHTS RESERVED.
-
- The enclosed software and documentation includes copyrighted works
- of Hewlett-Packard Co. For as long as you comply with the following
- limitations, you are hereby authorized to (i) use, reproduce, and
- modify the software and documentation, and to (ii) distribute the
- software and documentation, including modifications, for
- non-commercial purposes only.
-
- 1. The enclosed software and documentation is made available at no
- charge in order to advance the general development of
- high-performance networking products.
-
- 2. You may not delete any copyright notices contained in the
- software or documentation. All hard copies, and copies in
- source code or object code form, of the software or
- documentation (including modifications) must contain at least
- one of the copyright notices.
-
- 3. The enclosed software and documentation has not been subjected
- to testing and quality control and is not a Hewlett-Packard Co.
- product. At a future time, Hewlett-Packard Co. may or may not
- offer a version of the software and documentation as a product.
-
- 4. THE SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS".
- HEWLETT-PACKARD COMPANY DOES NOT WARRANT THAT THE USE,
- REPRODUCTION, MODIFICATION OR DISTRIBUTION OF THE SOFTWARE OR
- DOCUMENTATION WILL NOT INFRINGE A THIRD PARTY'S INTELLECTUAL
- PROPERTY RIGHTS. HP DOES NOT WARRANT THAT THE SOFTWARE OR
- DOCUMENTATION IS ERROR FREE. HP DISCLAIMS ALL WARRANTIES,
- EXPRESS AND IMPLIED, WITH REGARD TO THE SOFTWARE AND THE
- DOCUMENTATION. HP SPECIFICALLY DISCLAIMS ALL WARRANTIES OF
- MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
-
- 5. HEWLETT-PACKARD COMPANY WILL NOT IN ANY EVENT BE LIABLE FOR ANY
- DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES
- (INCLUDING LOST PROFITS) RELATED TO ANY USE, REPRODUCTION,
- MODIFICATION, OR DISTRIBUTION OF THE SOFTWARE OR DOCUMENTATION.
-
-*/
-char netperf_id[]="\
-@(#)netperf.c (c) Copyright 1993-2007 Hewlett-Packard Company. Version 2.4.3";
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-
-/* FreeBSD doesn't like socket.h before types are set. */
-#if __FreeBSD__
-# include <sys/types.h>
-#endif
-
-#ifndef WIN32
-/* this should only be temporary */
-#include <sys/socket.h>
-#endif
-
-#ifdef WIN32
-#include <winsock2.h>
-#include <windows.h>
-#endif /* WIN32 */
-
-#include "netsh.h"
-#include "netlib.h"
-#include "nettest_bsd.h"
-
-#ifdef WANT_UNIX
-#include "nettest_unix.h"
-#endif /* WANT_UNIX */
-
-#ifdef WANT_XTI
-#include "nettest_xti.h"
-#endif /* WANT_XTI */
-
-#ifdef WANT_DLPI
-#include "nettest_dlpi.h"
-#endif /* WANT_DLPI */
-
-#ifdef WANT_SDP
-#include "nettest_sdp.h"
-#endif
-
-/* The DNS tests have been removed from netperf2. Those wanting to do
- DNS_RR tests should use netperf4 instead. */
-
-#ifdef DO_DNS
-#error DNS tests have been removed from netperf. Use netperf4 instead
-#endif /* DO_DNS */
-
-#ifdef WANT_SCTP
-#include "nettest_sctp.h"
-#endif
-
- /* this file contains the main for the netperf program. all the other */
- /* routines can be found in the file netsh.c */
-
-
-int _cdecl
-main(int argc, char *argv[])
-{
-
-#ifdef WIN32
- WSADATA wsa_data ;
-
- /* Initialize the winsock lib ( version 2.2 ) */
- if ( WSAStartup(MAKEWORD(2,2), &wsa_data) == SOCKET_ERROR ){
- printf("WSAStartup() failed : %d\n", GetLastError()) ;
- return 1 ;
- }
-#endif /* WIN32 */
-
- netlib_init();
- set_defaults();
- scan_cmd_line(argc,argv);
-
- if (debug) {
- dump_globals();
- install_signal_catchers();
- }
-
- if (debug) {
- printf("remotehost is %s and port %s\n",host_name,test_port);
- fflush(stdout);
- }
-
-
- if (!no_control) {
- establish_control(host_name,test_port,address_family,
- local_host_name,local_test_port,local_address_family);
- }
-
- if (strcasecmp(test_name,"TCP_STREAM") == 0) {
- send_tcp_stream(host_name);
- }
- else if (strcasecmp(test_name,"TCP_MAERTS") == 0) {
- send_tcp_maerts(host_name);
- }
-#ifdef HAVE_ICSC_EXS
- else if (strcasecmp(test_name,"EXS_TCP_STREAM") == 0) {
- send_exs_tcp_stream(host_name);
- }
-#endif /* HAVE_ICSC_EXS */
-#ifdef HAVE_SENDFILE
- else if (strcasecmp(test_name,"TCP_SENDFILE") == 0) {
- sendfile_tcp_stream(host_name);
- }
-#endif /* HAVE_SENDFILE */
- else if (strcasecmp(test_name,"TCP_RR") == 0) {
- send_tcp_rr(host_name);
- }
- else if (strcasecmp(test_name,"TCP_CRR") == 0) {
- send_tcp_conn_rr(host_name);
- }
- else if (strcasecmp(test_name,"TCP_CC") == 0) {
- send_tcp_cc(host_name);
- }
-#ifdef DO_1644
- else if (strcasecmp(test_name,"TCP_TRR") == 0) {
- send_tcp_tran_rr(host_name);
- }
-#endif /* DO_1644 */
-#ifdef DO_NBRR
- else if (strcasecmp(test_name,"TCP_NBRR") == 0) {
- send_tcp_nbrr(host_name);
- }
-#endif /* DO_NBRR */
- else if (strcasecmp(test_name,"UDP_STREAM") == 0) {
- send_udp_stream(host_name);
- }
- else if (strcasecmp(test_name,"UDP_RR") == 0) {
- send_udp_rr(host_name);
- }
- else if (strcasecmp(test_name,"LOC_CPU") == 0) {
- loc_cpu_rate();
- }
- else if (strcasecmp(test_name,"REM_CPU") == 0) {
- rem_cpu_rate();
- }
-#ifdef WANT_DLPI
- else if (strcasecmp(test_name,"DLCO_RR") == 0) {
- send_dlpi_co_rr(host_name);
- }
- else if (strcasecmp(test_name,"DLCL_RR") == 0) {
- send_dlpi_cl_rr(host_name);
- }
- else if (strcasecmp(test_name,"DLCO_STREAM") == 0) {
- send_dlpi_co_stream(host_name);
- }
- else if (strcasecmp(test_name,"DLCL_STREAM") == 0) {
- send_dlpi_cl_stream(host_name);
- }
-#endif /* WANT_DLPI */
-#ifdef WANT_UNIX
- else if (strcasecmp(test_name,"STREAM_RR") == 0) {
- send_stream_rr(host_name);
- }
- else if (strcasecmp(test_name,"DG_RR") == 0) {
- send_dg_rr(host_name);
- }
- else if (strcasecmp(test_name,"STREAM_STREAM") == 0) {
- send_stream_stream(host_name);
- }
- else if (strcasecmp(test_name,"DG_STREAM") == 0) {
- send_dg_stream(host_name);
- }
-#endif /* WANT_UNIX */
-#ifdef WANT_XTI
- else if (strcasecmp(test_name,"XTI_TCP_STREAM") == 0) {
- send_xti_tcp_stream(host_name);
- }
- else if (strcasecmp(test_name,"XTI_TCP_RR") == 0) {
- send_xti_tcp_rr(host_name);
- }
- else if (strcasecmp(test_name,"XTI_UDP_STREAM") == 0) {
- send_xti_udp_stream(host_name);
- }
- else if (strcasecmp(test_name,"XTI_UDP_RR") == 0) {
- send_xti_udp_rr(host_name);
- }
-#endif /* WANT_XTI */
-
-#ifdef WANT_SCTP
- else if (strcasecmp(test_name, "SCTP_STREAM") == 0) {
- send_sctp_stream(host_name);
- }
- else if (strcasecmp(test_name, "SCTP_RR") == 0) {
- send_sctp_rr(host_name);
- }
- else if (strcasecmp(test_name, "SCTP_STREAM_MANY") == 0) {
- send_sctp_stream_1toMany(host_name);
- }
- else if (strcasecmp(test_name, "SCTP_RR_MANY") == 0) {
- send_sctp_stream_1toMany(host_name);
- }
-#endif
-
-#ifdef DO_DNS
- else if (strcasecmp(test_name,"DNS_RR") == 0) {
- fprintf(stderr,
- "DNS tests can now be found in netperf4.\n");
- fflush(stderr);
- exit(-1);
- }
-#endif /* DO_DNS */
-#ifdef WANT_SDP
- else if (strcasecmp(test_name,"SDP_STREAM") == 0) {
- send_sdp_stream(host_name);
- }
- else if (strcasecmp(test_name,"SDP_MAERTS") == 0) {
- send_sdp_maerts(host_name);
- }
- else if (strcasecmp(test_name,"SDP_RR") == 0) {
- send_sdp_rr(host_name);
- }
-#endif /* WANT_SDP */
- else {
- printf("The test you requested is unknown to this netperf.\n");
- printf("Please verify that you have the correct test name, \n");
- printf("and that test family has been compiled into this netperf.\n");
- exit(1);
- }
-
- if (!no_control) {
- shutdown_control();
- }
-
-#ifdef WIN32
- /* Cleanup the winsock lib */
- WSACleanup();
-#endif
-
- return(0);
-}
-
-
diff --git a/netperf_version.h b/netperf_version.h
deleted file mode 100644
index b2b9fdc..0000000
--- a/netperf_version.h
+++ /dev/null
@@ -1 +0,0 @@
-#define NETPERF_VERSION "2.4.4"
diff --git a/netserver.c b/netserver.c
deleted file mode 100644
index 02be3ce..0000000
--- a/netserver.c
+++ /dev/null
@@ -1,1022 +0,0 @@
-/*
-
- Copyright (C) 1993-2007 Hewlett-Packard Company
- ALL RIGHTS RESERVED.
-
- The enclosed software and documentation includes copyrighted works
- of Hewlett-Packard Co. For as long as you comply with the following
- limitations, you are hereby authorized to (i) use, reproduce, and
- modify the software and documentation, and to (ii) distribute the
- software and documentation, including modifications, for
- non-commercial purposes only.
-
- 1. The enclosed software and documentation is made available at no
- charge in order to advance the general development of
- high-performance networking products.
-
- 2. You may not delete any copyright notices contained in the
- software or documentation. All hard copies, and copies in
- source code or object code form, of the software or
- documentation (including modifications) must contain at least
- one of the copyright notices.
-
- 3. The enclosed software and documentation has not been subjected
- to testing and quality control and is not a Hewlett-Packard Co.
- product. At a future time, Hewlett-Packard Co. may or may not
- offer a version of the software and documentation as a product.
-
- 4. THE SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS".
- HEWLETT-PACKARD COMPANY DOES NOT WARRANT THAT THE USE,
- REPRODUCTION, MODIFICATION OR DISTRIBUTION OF THE SOFTWARE OR
- DOCUMENTATION WILL NOT INFRINGE A THIRD PARTY'S INTELLECTUAL
- PROPERTY RIGHTS. HP DOES NOT WARRANT THAT THE SOFTWARE OR
- DOCUMENTATION IS ERROR FREE. HP DISCLAIMS ALL WARRANTIES,
- EXPRESS AND IMPLIED, WITH REGARD TO THE SOFTWARE AND THE
- DOCUMENTATION. HP SPECIFICALLY DISCLAIMS ALL WARRANTIES OF
- MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
-
- 5. HEWLETT-PACKARD COMPANY WILL NOT IN ANY EVENT BE LIABLE FOR ANY
- DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES
- (INCLUDING LOST PROFITS) RELATED TO ANY USE, REPRODUCTION,
- MODIFICATION, OR DISTRIBUTION OF THE SOFTWARE OR DOCUMENTATION.
-
-*/
-
-#include "netperf_version.h"
-
-char netserver_id[]="\
-@(#)netserver.c (c) Copyright 1993-2007 Hewlett-Packard Co. Version 2.4.3";
-
- /***********************************************************************/
- /* */
- /* netserver.c */
- /* */
- /* This is the server side code for the netperf test package. It */
- /* will operate either stand-alone, or as a child of inetd. In this */
- /* way, we insure that it can be installed on systems with or without */
- /* root permissions (editing inetd.conf). Essentially, this code is */
- /* the analog to the netsh.c code. */
- /* */
- /***********************************************************************/
-
-
-/************************************************************************/
-/* */
-/* Global include files */
-/* */
-/************************************************************************/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#if HAVE_STRING_H
-# if !STDC_HEADERS && HAVE_MEMORY_H
-# include <memory.h>
-# endif
-# include <string.h>
-#endif
-#if HAVE_STRINGS_H
-# include <strings.h>
-#endif
-#if HAVE_LIMITS_H
-# include <limits.h>
-#endif
-#include <sys/types.h>
-#include <stdio.h>
-#ifndef WIN32
-#include <errno.h>
-#include <signal.h>
-#endif
-#if !defined(WIN32) && !defined(__VMS)
-#include <sys/ipc.h>
-#endif /* !defined(WIN32) && !defined(__VMS) */
-#include <fcntl.h>
-#ifdef WIN32
-#include <time.h>
-#include <winsock2.h>
-#define netperf_socklen_t socklen_t
-/* we need to find some other way to decide to include ws2 */
-/* if you are trying to compile on Windows 2000 or NT 4 you will */
-/* probably have to define DONT_IPV6 */
-#ifndef DONT_IPV6
-#include <ws2tcpip.h>
-#endif /* DONT_IPV6 */
-#include <windows.h>
-#define sleep(x) Sleep((x)*1000)
-#else
-#ifndef MPE
-#include <sys/time.h>
-#endif /* MPE */
-#include <sys/ioctl.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include <unistd.h>
-#ifndef DONT_WAIT
-#include <sys/wait.h>
-#endif /* DONT_WAIT */
-#endif /* WIN32 */
-#include <stdlib.h>
-#ifdef __VMS
-#include <tcpip$inetdef.h>
-#include <unixio.h>
-#endif /* __VMS */
-#include "netlib.h"
-#include "nettest_bsd.h"
-
-#ifdef WANT_UNIX
-#include "nettest_unix.h"
-#endif /* WANT_UNIX */
-
-#ifdef WANT_DLPI
-#include "nettest_dlpi.h"
-#endif /* WANT_DLPI */
-
-#ifdef WANT_SCTP
-#include "nettest_sctp.h"
-#endif
-
-#include "netsh.h"
-
-#ifndef DEBUG_LOG_FILE
-#ifndef WIN32
-#define DEBUG_LOG_FILE "/tmp/netperf.debug"
-#else
-#define DEBUG_LOG_FILE "c:\\temp\\netperf.debug"
-#endif /* WIN32 */
-#endif /* DEBUG_LOG_FILE */
-
- /* some global variables */
-
-FILE *afp;
-char listen_port[10];
-extern char *optarg;
-extern int optind, opterr;
-
-#ifndef WIN32
-#define SERVER_ARGS "dL:n:p:v:V46"
-#else
-#define SERVER_ARGS "dL:n:p:v:V46I:i:"
-#endif
-
-/* perhaps one day we will use this as part of only opening a debug
- log file if debug is set, of course we have to be wary of the base
- use of "where" and so probably always need "where" pointing
- "somewhere" or other. */
-void
-open_debug_file()
-{
-#ifndef WIN32
-#ifndef PATH_MAX
-#define PATH_MAX MAX_PATH
-#endif
- char FileName[PATH_MAX]; /* for opening the debug log file */
- strcpy(FileName, DEBUG_LOG_FILE);
-
- if (where != NULL) fflush(where);
-
- snprintf(&FileName[strlen(FileName)], sizeof(FileName) - strlen(FileName), "_%d", getpid());
- if ((where = fopen(FileName, "w")) == NULL) {
- perror("netserver: debug file");
- exit(1);
- }
-
- chmod(FileName,0644);
-#endif
-
-}
- /* This routine implements the "main event loop" of the netperf */
- /* server code. Code above it will have set-up the control connection */
- /* so it can just merrily go about its business, which is to */
- /* "schedule" performance tests on the server. */
-
-void
-process_requests()
-{
-
- float temp_rate;
-
- if (debug) open_debug_file();
-
-
- while (1) {
- recv_request();
-
- switch (netperf_request.content.request_type) {
-
- case DEBUG_ON:
- netperf_response.content.response_type = DEBUG_OK;
- /* dump_request already present in recv_request; redundant? */
- if (!debug) {
- debug++;
- open_debug_file();
- dump_request();
- }
- send_response();
- break;
-
- case DEBUG_OFF:
- if (debug)
- debug--;
- netperf_response.content.response_type = DEBUG_OK;
- send_response();
- /* +SAF why??? */
- if (!debug)
- {
- fclose(where);
-#if !defined(WIN32) && !defined(MPE) && !defined(__VMS)
- /* For Unix: reopen the debug write file descriptor to "/dev/null" */
- /* and redirect stdout to it. */
- fflush (stdout);
- where = fopen ("/dev/null", "w");
- if (where == NULL)
- {
- perror ("netserver: reopening debug fp for writing: /dev/null");
- exit (1);
- }
- if (close (STDOUT_FILENO) == -1)
- {
- perror ("netserver: closing stdout file descriptor");
- exit (1);
- }
- if (dup (fileno (where)) == -1)
- {
- perror ("netserver: duplicate /dev/null write file descr. to stdout");
- exit (1);
- }
-#endif /* !WIN32 !MPE !__VMS */
- }
- break;
-
- case CPU_CALIBRATE:
- netperf_response.content.response_type = CPU_CALIBRATE;
- temp_rate = calibrate_local_cpu(0.0);
- bcopy((char *)&temp_rate,
- (char *)netperf_response.content.test_specific_data,
- sizeof(temp_rate));
- bcopy((char *)&lib_num_loc_cpus,
- (char *)netperf_response.content.test_specific_data + sizeof(temp_rate),
- sizeof(lib_num_loc_cpus));
- if (debug) {
- fprintf(where,"netserver: sending CPU information:");
- fprintf(where,"rate is %g num cpu %d\n",temp_rate,lib_num_loc_cpus);
- fflush(where);
- }
-
- /* we need the cpu_start, cpu_stop in the looper case to kill the */
- /* child proceses raj 7/95 */
-
-#ifdef USE_LOOPER
- cpu_start(1);
- cpu_stop(1,&temp_rate);
-#endif /* USE_LOOPER */
-
- send_response();
- break;
-
- case DO_TCP_STREAM:
- recv_tcp_stream();
- break;
-
- case DO_TCP_MAERTS:
- recv_tcp_maerts();
- break;
-
- case DO_TCP_RR:
- recv_tcp_rr();
- break;
-
- case DO_TCP_CRR:
- recv_tcp_conn_rr();
- break;
-
- case DO_TCP_CC:
- recv_tcp_cc();
- break;
-
-#ifdef DO_1644
- case DO_TCP_TRR:
- recv_tcp_tran_rr();
- break;
-#endif /* DO_1644 */
-
-#ifdef DO_NBRR
- case DO_TCP_NBRR:
- recv_tcp_nbrr();
- break;
-#endif /* DO_NBRR */
-
- case DO_UDP_STREAM:
- recv_udp_stream();
- break;
-
- case DO_UDP_RR:
- recv_udp_rr();
- break;
-
-#ifdef WANT_DLPI
-
- case DO_DLPI_CO_RR:
- recv_dlpi_co_rr();
- break;
-
- case DO_DLPI_CL_RR:
- recv_dlpi_cl_rr();
- break;
-
- case DO_DLPI_CO_STREAM:
- recv_dlpi_co_stream();
- break;
-
- case DO_DLPI_CL_STREAM:
- recv_dlpi_cl_stream();
- break;
-
-#endif /* WANT_DLPI */
-
-#ifdef WANT_UNIX
-
- case DO_STREAM_STREAM:
- recv_stream_stream();
- break;
-
- case DO_STREAM_RR:
- recv_stream_rr();
- break;
-
- case DO_DG_STREAM:
- recv_dg_stream();
- break;
-
- case DO_DG_RR:
- recv_dg_rr();
- break;
-
-#endif /* WANT_UNIX */
-
-#ifdef WANT_XTI
- case DO_XTI_TCP_STREAM:
- recv_xti_tcp_stream();
- break;
-
- case DO_XTI_TCP_RR:
- recv_xti_tcp_rr();
- break;
-
- case DO_XTI_UDP_STREAM:
- recv_xti_udp_stream();
- break;
-
- case DO_XTI_UDP_RR:
- recv_xti_udp_rr();
- break;
-
-#endif /* WANT_XTI */
-
-#ifdef WANT_SCTP
- case DO_SCTP_STREAM:
- recv_sctp_stream();
- break;
-
- case DO_SCTP_STREAM_MANY:
- recv_sctp_stream_1toMany();
- break;
-
- case DO_SCTP_RR:
- recv_sctp_rr();
- break;
-
- case DO_SCTP_RR_MANY:
- recv_sctp_rr_1toMany();
- break;
-#endif
-
-#ifdef WANT_SDP
- case DO_SDP_STREAM:
- recv_sdp_stream();
- break;
-
- case DO_SDP_MAERTS:
- recv_sdp_maerts();
- break;
-
- case DO_SDP_RR:
- recv_sdp_rr();
- break;
-#endif
-
- default:
- fprintf(where,"unknown test number %d\n",
- netperf_request.content.request_type);
- fflush(where);
- netperf_response.content.serv_errno=998;
- send_response();
- break;
-
- }
- }
-}
-
-/*
- set_up_server()
-
- set-up the server listen socket. we only call this routine if the
- user has specified a port number on the command line or we believe we
- are not a child of inetd or its platform-specific equivalent */
-
-/*KC*/
-
-void
-set_up_server(char hostname[], char port[], int af)
-{
-
- struct addrinfo hints;
- struct addrinfo *local_res;
- struct addrinfo *local_res_temp;
-
- struct sockaddr_storage peeraddr;
- netperf_socklen_t peeraddr_len = sizeof(peeraddr);
-
- SOCKET server_control;
- int on=1;
- int count;
- int error;
- int not_listening;
-
-#if !defined(WIN32) && !defined(MPE) && !defined(__VMS)
- FILE *rd_null_fp; /* Used to redirect from "/dev/null". */
- FILE *wr_null_fp; /* Used to redirect to "/dev/null". */
-#endif /* !WIN32 !MPE !__VMS */
-
- if (debug) {
- fprintf(stderr,
- "set_up_server called with host '%s' port '%s' remfam %d\n",
- hostname,
- port,
- af);
- fflush(stderr);
- }
-
- memset(&hints,0,sizeof(hints));
- hints.ai_family = af;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = IPPROTO_TCP;
- hints.ai_flags = AI_PASSIVE;
-
- count = 0;
- do {
- error = getaddrinfo((char *)hostname,
- (char *)port,
- &hints,
- &local_res);
- count += 1;
- if (error == EAI_AGAIN) {
- if (debug) {
- fprintf(stderr,"Sleeping on getaddrinfo EAI_AGAIN\n");
- fflush(stderr);
- }
- sleep(1);
- }
- } while ((error == EAI_AGAIN) && (count <= 5));
-
- if (error) {
- fprintf(stderr,
- "set_up_server: could not resolve remote '%s' port '%s' af %d",
- hostname,
- port,
- af);
- fprintf(stderr,"\n\tgetaddrinfo returned %d %s\n",
- error,
- gai_strerror(error));
- exit(-1);
- }
-
- if (debug) {
- dump_addrinfo(stderr, local_res, hostname, port, af);
- }
-
- not_listening = 1;
- local_res_temp = local_res;
-
- while((local_res_temp != NULL) && (not_listening)) {
-
- fprintf(stderr,
- "Starting netserver at port %s\n",
- port);
-
- server_control = socket(local_res_temp->ai_family,SOCK_STREAM,0);
-
- if (server_control == INVALID_SOCKET) {
- perror("set_up_server could not allocate a socket");
- exit(-1);
- }
-
- /* happiness and joy, keep going */
- if (setsockopt(server_control,
- SOL_SOCKET,
- SO_REUSEADDR,
- (char *)&on ,
- sizeof(on)) == SOCKET_ERROR) {
- if (debug) {
- perror("warning: set_up_server could not set SO_REUSEADDR");
- }
- }
- /* still happy and joyful */
-
- if ((bind (server_control,
- local_res_temp->ai_addr,
- local_res_temp->ai_addrlen) != SOCKET_ERROR) &&
- (listen (server_control,5) != SOCKET_ERROR)) {
- not_listening = 0;
- break;
- }
- else {
- /* we consider a bind() or listen() failure a transient and try
- the next address */
- if (debug) {
- perror("warning: set_up_server failed a bind or listen call\n");
- }
- local_res_temp = local_res_temp->ai_next;
- continue;
- }
- }
-
- if (not_listening) {
- fprintf(stderr,
- "set_up_server could not establish a listen endpoint for %s port %s with family %s\n",
- host_name,
- port,
- inet_ftos(af));
- fflush(stderr);
- exit(-1);
- }
- else {
- printf("Starting netserver at hostname %s port %s and family %s\n",
- hostname,
- port,
- inet_ftos(af));
- }
-
- /*
- setpgrp();
- */
-
-#if !defined(WIN32) && !defined(MPE) && !defined(__VMS)
- /* Flush the standard I/O file descriptors before forking. */
- fflush (stdin);
- fflush (stdout);
- fflush (stderr);
- switch (fork())
- {
- case -1:
- perror("netperf server error");
- exit(1);
-
- case 0:
- /* Redirect stdin from "/dev/null". */
- rd_null_fp = fopen ("/dev/null", "r");
- if (rd_null_fp == NULL)
- {
- perror ("netserver: opening for reading: /dev/null");
- exit (1);
- }
- if (close (STDIN_FILENO) == -1)
- {
- perror ("netserver: closing stdin file descriptor");
- exit (1);
- }
- if (dup (fileno (rd_null_fp)) == -1)
- {
- perror ("netserver: duplicate /dev/null read file descr. to stdin");
- exit (1);
- }
-
- /* Redirect stdout to the debug write file descriptor. */
- if (close (STDOUT_FILENO) == -1)
- {
- perror ("netserver: closing stdout file descriptor");
- exit (1);
- }
- if (dup (fileno (where)) == -1)
- {
- perror ("netserver: duplicate the debug write file descr. to stdout");
- exit (1);
- }
-
- /* Redirect stderr to "/dev/null". */
- wr_null_fp = fopen ("/dev/null", "w");
- if (wr_null_fp == NULL)
- {
- perror ("netserver: opening for writing: /dev/null");
- exit (1);
- }
- if (close (STDERR_FILENO) == -1)
- {
- perror ("netserver: closing stderr file descriptor");
- exit (1);
- }
- if (dup (fileno (wr_null_fp)) == -1)
- {
- perror ("netserver: dupicate /dev/null write file descr. to stderr");
- exit (1);
- }
-
-#ifndef NO_SETSID
- setsid();
-#else
- setpgrp();
-#endif /* NO_SETSID */
-
- /* some OS's have SIGCLD defined as SIGCHLD */
-#ifndef SIGCLD
-#define SIGCLD SIGCHLD
-#endif /* SIGCLD */
-
- signal(SIGCLD, SIG_IGN);
-
-#endif /* !WIN32 !MPE !__VMS */
-
- for (;;)
- {
- if ((server_sock=accept(server_control,
- (struct sockaddr *)&peeraddr,
- &peeraddr_len)) == INVALID_SOCKET)
- {
- printf("server_control: accept failed errno %d\n",errno);
- exit(1);
- }
-#if defined(MPE) || defined(__VMS)
- /*
- * Since we cannot fork this process , we cant fire any threads
- * as they all share the same global data . So we better allow
- * one request at at time
- */
- process_requests() ;
-#elif WIN32
- {
- BOOL b;
- char cmdline[80];
- PROCESS_INFORMATION pi;
- STARTUPINFO si;
- int i;
-
- memset(&si, 0 , sizeof(STARTUPINFO));
- si.cb = sizeof(STARTUPINFO);
-
- /* Pass the server_sock as stdin for the new process. */
- /* Hopefully this will continue to be created with the OBJ_INHERIT attribute. */
- si.hStdInput = (HANDLE)server_sock;
- si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
- si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
- si.dwFlags = STARTF_USESTDHANDLES;
-
- /* Build cmdline for child process */
- strcpy(cmdline, program);
- if (verbosity > 1) {
- snprintf(&cmdline[strlen(cmdline)], sizeof(cmdline) - strlen(cmdline), " -v %d", verbosity);
- }
- for (i=0; i < debug; i++) {
- snprintf(&cmdline[strlen(cmdline)], sizeof(cmdline) - strlen(cmdline), " -d");
- }
- snprintf(&cmdline[strlen(cmdline)], sizeof(cmdline) - strlen(cmdline), " -I %x", (int)(UINT_PTR)server_sock);
- snprintf(&cmdline[strlen(cmdline)], sizeof(cmdline) - strlen(cmdline), " -i %x", (int)(UINT_PTR)server_control);
- snprintf(&cmdline[strlen(cmdline)], sizeof(cmdline) - strlen(cmdline), " -i %x", (int)(UINT_PTR)where);
-
- b = CreateProcess(NULL, /* Application Name */
- cmdline,
- NULL, /* Process security attributes */
- NULL, /* Thread security attributes */
- TRUE, /* Inherit handles */
- 0, /* Creation flags PROCESS_QUERY_INFORMATION, */
- NULL, /* Enviornment */
- NULL, /* Current directory */
- &si, /* StartupInfo */
- &pi);
- if (!b)
- {
- perror("CreateProcessfailure: ");
- exit(1);
- }
-
- /* We don't need the thread or process handles any more; let them */
- /* go away on their own timeframe. */
-
- CloseHandle(pi.hThread);
- CloseHandle(pi.hProcess);
-
- /* And close the server_sock since the child will own it. */
-
- close(server_sock);
- }
-#else
- signal(SIGCLD, SIG_IGN);
-
- switch (fork())
- {
- case -1:
- /* something went wrong */
- exit(1);
- case 0:
- /* we are the child process */
- close(server_control);
- process_requests();
- exit(0);
- break;
- default:
- /* we are the parent process */
- close(server_sock);
- /* we should try to "reap" some of our children. on some */
- /* systems they are being left as defunct processes. we */
- /* will call waitpid, looking for any child process, */
- /* with the WNOHANG feature. when waitpid return a zero, */
- /* we have reaped all the children there are to reap at */
- /* the moment, so it is time to move on. raj 12/94 */
-#ifndef DONT_WAIT
-#ifdef NO_SETSID
- /* Only call "waitpid()" if "setsid()" is not used. */
- while(waitpid(-1, NULL, WNOHANG) > 0) { }
-#endif /* NO_SETSID */
-#endif /* DONT_WAIT */
- break;
- }
-#endif /* !WIN32 !MPE !__VMS */
- } /*for*/
-#if !defined(WIN32) && !defined(MPE) && !defined(__VMS)
- break; /*case 0*/
-
- default:
- exit (0);
-
- }
-#endif /* !WIN32 !MPE !__VMS */
-}
-
-#ifdef WIN32
-
- /* With Win2003, WinNT's POSIX subsystem is gone and hence so is */
- /* fork. */
-
- /* But hopefully the kernel support will continue to exist for some */
- /* time. */
-
- /* We are not counting on the child address space copy_on_write */
- /* support, since it isn't exposed except through the NT native APIs */
- /* (which is not public). */
-
- /* We will try to use the InheritHandles flag in CreateProcess. It */
- /* is in the public API, though it is documented as "must be FALSE". */
-
- /* So where we would have forked, we will now create a new process. */
- /* I have added a set of command line switches to specify a list of */
- /* handles that the child should close since they shouldn't have */
- /* been inherited ("-i#"), and a single switch to specify the handle */
- /* for the server_sock ("I#"). */
-
- /* A better alternative would be to re-write NetPerf to be */
- /* multi-threaded; i.e., move all of the various NetPerf global */
- /* variables in to thread specific structures. But this is a bigger */
- /* effort than I want to tackle at this time. (And I doubt that the */
- /* HP-UX author sees value in this effort). */
-
-#endif
-
-int _cdecl
-main(int argc, char *argv[])
-{
-
- int c;
- int not_inetd = 0;
-#ifdef WIN32
- BOOL child = FALSE;
-#endif
- char arg1[BUFSIZ], arg2[BUFSIZ];
-#ifndef PATH_MAX
-#define PATH_MAX MAX_PATH
-#endif
- char FileName[PATH_MAX]; /* for opening the debug log file */
-
- struct sockaddr name;
- netperf_socklen_t namelen = sizeof(name);
-
-
-#ifdef WIN32
- WSADATA wsa_data ;
-
- /* Initialize the winsock lib ( version 2.2 ) */
- if ( WSAStartup(MAKEWORD(2,2), &wsa_data) == SOCKET_ERROR ){
- printf("WSAStartup() failed : %d\n", GetLastError()) ;
- return 1 ;
- }
-#endif /* WIN32 */
-
- /* Save away the program name */
- program = (char *)malloc(strlen(argv[0]) + 1);
- if (program == NULL) {
- printf("malloc(%d) failed!\n", strlen(argv[0]) + 1);
- return 1 ;
- }
- strcpy(program, argv[0]);
-
- netlib_init();
-
- /* Scan the command line to see if we are supposed to set-up our own */
- /* listen socket instead of relying on inetd. */
-
- /* first set a copy of initial values */
- strncpy(local_host_name,"0.0.0.0",sizeof(local_host_name));
- local_address_family = AF_UNSPEC;
- strncpy(listen_port,TEST_PORT,sizeof(listen_port));
-
- while ((c = getopt(argc, argv, SERVER_ARGS)) != EOF) {
- switch (c) {
- case '?':
- case 'h':
- print_netserver_usage();
- exit(1);
- case 'd':
- /* we want to set the debug file name sometime */
- debug++;
- break;
- case 'L':
- not_inetd = 1;
- break_args_explicit(optarg,arg1,arg2);
- if (arg1[0]) {
- strncpy(local_host_name,arg1,sizeof(local_host_name));
- }
- if (arg2[0]) {
- local_address_family = parse_address_family(arg2);
- /* if only the address family was set, we may need to set the
- local_host_name accordingly. since our defaults are IPv4
- this should only be necessary if we have IPv6 support raj
- 2005-02-07 */
-#if defined (AF_INET6)
- if (!arg1[0]) {
- strncpy(local_host_name,"::0",sizeof(local_host_name));
- }
-#endif
- }
- break;
- case 'n':
- shell_num_cpus = atoi(optarg);
- if (shell_num_cpus > MAXCPUS) {
- fprintf(stderr,
- "netserver: This version can only support %d CPUs. Please",
- MAXCPUS);
- fprintf(stderr,
- " increase MAXCPUS in netlib.h and recompile.\n");
- fflush(stderr);
- exit(1);
- }
- break;
- case 'p':
- /* we want to open a listen socket at a */
- /* specified port number */
- strncpy(listen_port,optarg,sizeof(listen_port));
- not_inetd = 1;
- break;
- case '4':
- local_address_family = AF_INET;
- break;
- case '6':
-#if defined(AF_INET6)
- local_address_family = AF_INET6;
- strncpy(local_host_name,"::0",sizeof(local_host_name));
-#else
- local_address_family = AF_UNSPEC;
-#endif
- break;
- case 'v':
- /* say how much to say */
- verbosity = atoi(optarg);
- break;
- case 'V':
- printf("Netperf version %s\n",NETPERF_VERSION);
- exit(0);
- break;
-#ifdef WIN32
-/*+*+SAF */
- case 'I':
- child = TRUE;
- /* This is the handle we expect to inherit. */
- /*+*+SAF server_sock = (HANDLE)atoi(optarg); */
- break;
- case 'i':
- /* This is a handle we should NOT inherit. */
- /*+*+SAF CloseHandle((HANDLE)atoi(optarg)); */
- break;
-#endif
-
- }
- }
-
- /* +*+SAF I need a better way to find inherited handles I should close! */
- /* +*+SAF Use DuplicateHandle to force inheritable attribute (or reset it)? */
-
-/* unlink(DEBUG_LOG_FILE); */
-
- strcpy(FileName, DEBUG_LOG_FILE);
-
-#ifndef WIN32
- snprintf(&FileName[strlen(FileName)], sizeof(FileName) - strlen(FileName), "_%d", getpid());
- if ((where = fopen(FileName, "w")) == NULL) {
- perror("netserver: debug file");
- exit(1);
- }
-#else
- {
-
- if (child) {
- snprintf(&FileName[strlen(FileName)], sizeof(FileName) - strlen(FileName), "_%x", getpid());
- }
-
- /* Hopefully, by closing stdout & stderr, the subsequent
- fopen calls will get mapped to the correct std handles. */
- fclose(stdout);
-
- if ((where = fopen(FileName, "w")) == NULL) {
- perror("netserver: fopen of debug file as new stdout failed!");
- exit(1);
- }
-
- fclose(stderr);
-
- if ((where = fopen(FileName, "w")) == NULL) {
- fprintf(stdout, "fopen of debug file as new stderr failed!\n");
- exit(1);
- }
- }
-#endif
-
-#ifndef WIN32
- chmod(DEBUG_LOG_FILE,0644);
-#endif
-
-#if WIN32
- if (child) {
- server_sock = (SOCKET)GetStdHandle(STD_INPUT_HANDLE);
- }
-#endif
-
- /* if we are not a child of an inetd or the like, then we should
- open a socket and hang listens off of it. otherwise, we should go
- straight into processing requests. the do_listen() routine will sit
- in an infinite loop accepting connections and forking child
- processes. the child processes will call process_requests */
-
- /* If fd 0 is not a socket then assume we're not being called */
- /* from inetd and start server socket on the default port. */
- /* this enhancement comes from vwelch@ncsa.uiuc.edu (Von Welch) */
- if (not_inetd) {
- /* the user specified a port number on the command line */
- set_up_server(local_host_name,listen_port,local_address_family);
- }
-#ifdef WIN32
- /* OK, with Win2003 WinNT's POSIX subsystem is gone, and hence so is */
- /* fork. But hopefully the kernel support will continue to exist */
- /* for some time. We are not counting on the address space */
- /* copy_on_write support, since it isn't exposed except through the */
- /* NT native APIs (which are not public). We will try to use the */
- /* InheritHandles flag in CreateProcess though since this is public */
- /* and is used for more than just POSIX so hopefully it won't go */
- /* away. */
- else if (TRUE) {
- if (child) {
- process_requests();
- } else {
- strncpy(listen_port,TEST_PORT,sizeof(listen_port));
- set_up_server(local_host_name,listen_port,local_address_family);
- }
- }
-#endif
-#if !defined(__VMS)
- else if (getsockname(0, &name, &namelen) == SOCKET_ERROR) {
- /* we may not be a child of inetd */
- if (errno == ENOTSOCK) {
- strncpy(listen_port,TEST_PORT,sizeof(listen_port));
- set_up_server(local_host_name,listen_port,local_address_family);
- }
- }
-#endif /* !defined(__VMS) */
- else {
- /* we are probably a child of inetd, or are being invoked via the
- VMS auxilliarly server mechanism */
-#if !defined(__VMS)
- server_sock = 0;
-#else
- if ( (server_sock = socket(TCPIP$C_AUXS, SOCK_STREAM, 0)) == INVALID_SOCKET )
- {
- perror("Failed to grab aux server socket" );
- exit(1);
- }
-
-#endif /* !defined(__VMS) */
- process_requests();
- }
-#ifdef WIN32
- /* Cleanup the winsock lib */
- WSACleanup();
-#endif
-
- return(0);
-}
diff --git a/netsh.c b/netsh.c
deleted file mode 100644
index 7659679..0000000
--- a/netsh.c
+++ /dev/null
@@ -1,1002 +0,0 @@
-#include "netperf_version.h"
-
-char netsh_id[]="\
-@(#)netsh.c (c) Copyright 1993-2007 Hewlett-Packard Company. Version 2.4.3pre";
-
-
-/****************************************************************/
-/* */
-/* Global include files */
-/* */
-/****************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <sys/types.h>
-#ifndef WIN32
-#include <unistd.h>
-#ifndef __VMS
-#include <sys/ipc.h>
-#endif /* __VMS */
-#endif /* WIN32 */
-#include <fcntl.h>
-#ifndef WIN32
-#include <errno.h>
-#include <signal.h>
-#endif /* !WIN32 */
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
- /* the following four includes should not be needed ?*/
-#ifndef WIN32
-#include <sys/time.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#else
-#include <time.h>
-#include <winsock2.h>
-#define netperf_socklen_t socklen_t
-#endif
-
-#ifndef STRINGS
-#include <string.h>
-#else /* STRINGS */
-#include <strings.h>
-#endif /* STRINGS */
-
-#ifdef WIN32
-extern int getopt(int , char **, char *) ;
-#else
-double atof(const char *);
-#endif /* WIN32 */
-
-/**********************************************************************/
-/* */
-/* Local Include Files */
-/* */
-/**********************************************************************/
-
-#define NETSH
-#include "netsh.h"
-#include "netlib.h"
-#include "nettest_bsd.h"
-
-#ifdef WANT_UNIX
-#include "nettest_unix.h"
-#ifndef WIN32
-#include "sys/socket.h"
-#endif /* !WIN32 */
-#endif /* WANT_UNIX */
-
-#ifdef WANT_XTI
-#include "nettest_xti.h"
-#endif /* WANT_XTI */
-
-#ifdef WANT_DLPI
-#include "nettest_dlpi.h"
-#endif /* WANT_DLPI */
-
-#ifdef WANT_SCTP
-#include "nettest_sctp.h"
-#endif
-
-
-/************************************************************************/
-/* */
-/* Global constants and macros */
-/* */
-/************************************************************************/
-
- /* Some of the args take optional parameters. Since we are using */
- /* getopt to parse the command line, we will tell getopt that they do */
- /* not take parms, and then look for them ourselves */
-#define GLOBAL_CMD_LINE_ARGS "A:a:b:B:CcdDf:F:H:hi:I:k:K:l:L:n:NO:o:P:p:rt:T:v:VW:w:46"
-
-/************************************************************************/
-/* */
-/* Extern variables */
-/* */
-/************************************************************************/
-
-/*
-extern int errno;
-extern char *sys_errlist[ ];
-extern int sys_nerr;
-*/
-
-/************************************************************************/
-/* */
-/* Global variables */
-/* */
-/************************************************************************/
-
-/* some names and such */
-char *program; /* program invocation name */
-char username[BUFSIZ]; /* login name of user */
-char cmd_file[BUFSIZ]; /* name of the commands file */
-
-/* stuff to say where this test is going */
-char host_name[HOSTNAMESIZE]; /* remote host name or ip addr */
-char local_host_name[HOSTNAMESIZE]; /* local hostname or ip */
-char test_name[BUFSIZ]; /* which test to run */
-char test_port[PORTBUFSIZE]; /* where is the test waiting */
-char local_test_port[PORTBUFSIZE]; /* from whence we should start */
-int address_family; /* which address family remote */
-int local_address_family; /* which address family local */
-
-/* the source of data for filling the buffers */
-char fill_file[BUFSIZ];
-
-/* output controlling variables */
-int
- debug, /* debugging level */
- print_headers, /* do/don't display headers */
- verbosity; /* verbosity level */
-
-/* When specified with -B, this will be displayed at the end of the line
- for output that does not include the test header. mostly this is
- to help identify a specific netperf result when concurrent netperfs
- are run. raj 2006-02-01 */
-char *result_brand = NULL;
-
-/* cpu variables */
-int
- local_cpu_usage, /* you guessed it */
- remote_cpu_usage; /* still right ! */
-
-float
- local_cpu_rate,
- remote_cpu_rate;
-
-int
- shell_num_cpus=1;
-
-/* the end-test conditions for the tests - either transactions, bytes, */
-/* or time. different vars used for clarity - space is cheap ;-) */
-int
- test_time, /* test ends by time */
- test_len_ticks, /* how many times will the timer go off before */
- /* the test is over? */
- test_bytes, /* test ends on byte count */
- test_trans; /* test ends on tran count */
-
-/* the alignment conditions for the tests */
-int
- local_recv_align, /* alignment for local receives */
- local_send_align, /* alignment for local sends */
- local_send_offset = 0,
- local_recv_offset = 0,
- remote_recv_align, /* alignment for remote receives */
- remote_send_align, /* alignment for remote sends */
- remote_send_offset = 0,
- remote_recv_offset = 0;
-
-#if defined(WANT_INTERVALS) || defined(WANT_DEMO)
-int
- interval_usecs,
- interval_wate,
- interval_burst;
-
-int demo_mode; /* are we actually in demo mode? */
-double demo_interval = 1000000.0; /* what is the desired interval to
- display interval results. default
- is one second in units of
- microseconds */
-double demo_units = 0.0; /* what is our current best guess as
- to how many work units must be
- done to be near the desired
- reporting interval? */
-
-double units_this_tick;
-#endif
-
-#ifdef DIRTY
-int loc_dirty_count;
-int loc_clean_count;
-int rem_dirty_count;
-int rem_clean_count;
-#endif /* DIRTY */
-
- /* some of the vairables for confidence intervals... */
-
-int confidence_level;
-int iteration_min;
-int iteration_max;
-int result_confidence_only = 0;
-
-double interval;
-
- /* stuff to control the "width" of the buffer rings for sending and */
- /* receiving data */
-int send_width;
-int recv_width;
-
-/* address family */
-int af = AF_INET;
-
-/* did someone request processor affinity? */
-int cpu_binding_requested = 0;
-
-/* are we not establishing a control connection? */
-int no_control = 0;
-
-char netserver_usage[] = "\n\
-Usage: netserver [options] \n\
-\n\
-Options:\n\
- -h Display this text\n\
- -d Increase debugging output\n\
- -L name,family Use name to pick listen address and family for family\n\
- -p portnum Listen for connect requests on portnum.\n\
- -4 Do IPv4\n\
- -6 Do IPv6\n\
- -v verbosity Specify the verbosity level\n\
- -V Display version information and exit\n\
-\n";
-
-/* netperf_usage done as two concatenated strings to make the MS
- compiler happy when compiling for x86_32. fix from Spencer
- Frink. */
-
-char netperf_usage1[] = "\n\
-Usage: netperf [global options] -- [test options] \n\
-\n\
-Global options:\n\
- -a send,recv Set the local send,recv buffer alignment\n\
- -A send,recv Set the remote send,recv buffer alignment\n\
- -B brandstr Specify a string to be emitted with brief output\n\
- -c [cpu_rate] Report local CPU usage\n\
- -C [cpu_rate] Report remote CPU usage\n\
- -d Increase debugging output\n\
- -D [secs,units] * Display interim results at least every secs seconds\n\
- using units as the initial guess for units per second\n\
- -f G|M|K|g|m|k Set the output units\n\
- -F fill_file Pre-fill buffers with data from fill_file\n\
- -h Display this text\n\
- -H name|ip,fam * Specify the target machine and/or local ip and family\n\
- -i max,min Specify the max and min number of iterations (15,1)\n\
- -I lvl[,intvl] Specify confidence level (95 or 99) (99) \n\
- and confidence interval in percentage (10)\n\
- -l testlen Specify test duration (>0 secs) (<0 bytes|trans)\n\
- -L name|ip,fam * Specify the local ip|name and address family\n\
- -o send,recv Set the local send,recv buffer offsets\n\
- -O send,recv Set the remote send,recv buffer offset\n\
- -n numcpu Set the number of processors for CPU util\n\
- -N Establish no control connection, do 'send' side only\n\
- -p port,lport* Specify netserver port number and/or local port\n\
- -P 0|1 Don't/Do display test headers\n\
- -r Allow confidence to be hit on result only\n\
- -t testname Specify test to perform\n\
- -T lcpu,rcpu Request netperf/netserver be bound to local/remote cpu\n\
- -v verbosity Specify the verbosity level\n\
- -W send,recv Set the number of send,recv buffers\n\
- -v level Set the verbosity level (default 1, min 0)\n\
- -V Display the netperf version and exit\n";
-
-char netperf_usage2[] = "\n\
-For those options taking two parms, at least one must be specified;\n\
-specifying one value without a comma will set both parms to that\n\
-value, specifying a value with a leading comma will set just the second\n\
-parm, a value with a trailing comma will set just the first. To set\n\
-each parm to unique values, specify both and separate them with a\n\
-comma.\n\
-\n"
-"* For these options taking two parms, specifying one value with no comma\n\
-will only set the first parms and will leave the second at the default\n\
-value. To set the second value it must be preceded with a comma or be a\n\
-comma-separated pair. This is to retain previous netperf behaviour.\n";
-
-
-/* This routine will return the two arguments to the calling routine. */
-/* If the second argument is not specified, and there is no comma, */
-/* then the value of the second argument will be the same as the */
-/* value of the first. If there is a comma, then the value of the */
-/* second argument will be the value of the second argument ;-) */
-void
-break_args(char *s, char *arg1, char *arg2)
-
-{
- char *ns;
- ns = strchr(s,',');
- if (ns) {
- /* there was a comma arg2 should be the second arg*/
- *ns++ = '\0';
- while ((*arg2++ = *ns++) != '\0');
- }
- else {
- /* there was not a comma, we can use ns as a temp s */
- /* and arg2 should be the same value as arg1 */
- ns = s;
- while ((*arg2++ = *ns++) != '\0');
- };
- while ((*arg1++ = *s++) != '\0');
-}
-
-/* break_args_explicit
-
- this routine is somewhat like break_args in that it will separate a
- pair of comma-separated values. however, if there is no comma,
- this version will not ass-u-me that arg2 should be the same as
- arg1. raj 2005-02-04 */
-void
-break_args_explicit(char *s, char *arg1, char *arg2)
-
-{
- char *ns;
- ns = strchr(s,',');
- if (ns) {
- /* there was a comma arg2 should be the second arg*/
- *ns++ = '\0';
- while ((*arg2++ = *ns++) != '\0');
- }
- else {
- /* there was not a comma, so we should make sure that arg2 is \0
- lest something become confused. raj 2005-02-04 */
- *arg2 = '\0';
- };
- while ((*arg1++ = *s++) != '\0');
-
-}
-
-/* given a string with possible values for setting an address family,
- convert that into one of the AF_mumble values - AF_INET, AF_INET6,
- AF_UNSPEC as apropriate. the family_string is compared in a
- case-insensitive manner */
-
-int
-parse_address_family(char family_string[])
-{
-
- char temp[10]; /* gotta love magic constants :) */
-
- strncpy(temp,family_string,10);
-
- if (debug) {
- fprintf(where,
- "Attempting to parse address family from %s derived from %s\n",
- temp,
- family_string);
- }
-#if defined(AF_INET6)
- if (strstr(temp,"6")) {
- return(AF_INET6);
- }
-#endif
- if (strstr(temp,"inet") ||
- strstr(temp,"4")) {
- return(AF_INET);
- }
- if (strstr(temp,"unspec") ||
- strstr(temp,"0")) {
- return(AF_UNSPEC);
- }
- fprintf(where,
- "WARNING! %s not recognized as an address family, using AF_UNPSEC\n",
- family_string);
- fprintf(where,
- "Are you sure netperf was configured for that address family?\n");
- fflush(where);
- return(AF_UNSPEC);
-}
-
-
-void
-set_defaults()
-{
-
- /* stuff to say where this test is going */
- strcpy(host_name,""); /* remote host name or ip addr */
- strcpy(local_host_name,""); /* we want it to be INADDR_ANY */
- strcpy(test_name,"TCP_STREAM"); /* which test to run */
- strncpy(test_port,"12865",PORTBUFSIZE); /* where is the test waiting */
- strncpy(local_test_port,"0",PORTBUFSIZE);/* INPORT_ANY as it were */
- address_family = AF_UNSPEC;
- local_address_family = AF_UNSPEC;
-
- /* output controlling variables */
- debug = 0;/* debugging level */
- print_headers = 1;/* do print test headers */
- verbosity = 1;/* verbosity level */
- /* cpu variables */
- local_cpu_usage = 0;/* measure local cpu */
- remote_cpu_usage = 0;/* what do you think ;-) */
-
- local_cpu_rate = (float)0.0;
- remote_cpu_rate = (float)0.0;
-
- /* the end-test conditions for the tests - either transactions, bytes, */
- /* or time. different vars used for clarity - space is cheap ;-) */
- test_time = 10; /* test ends by time */
- test_bytes = 0; /* test ends on byte count */
- test_trans = 0; /* test ends on tran count */
-
- /* the alignment conditions for the tests */
- local_recv_align = 8; /* alignment for local receives */
- local_send_align = 8; /* alignment for local sends */
- remote_recv_align = 8; /* alignment for remote receives*/
- remote_send_align = 8; /* alignment for remote sends */
-
-#ifdef WANT_INTERVALS
- /* rate controlling stuff */
- interval_usecs = 0;
- interval_wate = 1;
- interval_burst = 0;
-#endif /* WANT_INTERVALS */
-
-#ifdef DIRTY
- /* dirty and clean cache stuff */
- loc_dirty_count = 0;
- loc_clean_count = 0;
- rem_dirty_count = 0;
- rem_clean_count = 0;
-#endif /* DIRTY */
-
- /* some of the vairables for confidence intervals... */
-
- confidence_level = 99;
- iteration_min = 1;
- iteration_max = 1;
- interval = 0.05; /* five percent? */
-
- no_control = 0;
- strcpy(fill_file,"");
-}
-
-
-void
-print_netserver_usage()
-{
- fwrite(netserver_usage, sizeof(char), strlen(netserver_usage), stderr);
-}
-
-
-void
-print_netperf_usage()
-{
- fwrite(netperf_usage1, sizeof(char), strlen(netperf_usage1), stderr);
- fwrite(netperf_usage2, sizeof(char), strlen(netperf_usage2), stderr);
-}
-
-void
-scan_cmd_line(int argc, char *argv[])
-{
- extern int optind; /* index of first unused arg */
- extern char *optarg; /* pointer to option string */
-
- int c;
-
- char arg1[BUFSIZ], /* argument holders */
- arg2[BUFSIZ];
-
- program = (char *)malloc(strlen(argv[0]) + 1);
- if (program == NULL) {
- printf("malloc(%d) failed!\n", strlen(argv[0]) + 1);
- exit(1);
- }
- strcpy(program, argv[0]);
-
- /* Go through all the command line arguments and break them */
- /* out. For those options that take two parms, specifying only */
- /* the first will set both to that value. Specifying only the */
- /* second will leave the first untouched. To change only the */
- /* first, use the form first, (see the routine break_args.. */
-
- while ((c= getopt(argc, argv, GLOBAL_CMD_LINE_ARGS)) != EOF) {
- switch (c) {
- case '?':
- case 'h':
- print_netperf_usage();
- exit(1);
- case 'a':
- /* set local alignments */
- break_args(optarg,arg1,arg2);
- if (arg1[0]) {
- local_send_align = convert(arg1);
- }
- if (arg2[0])
- local_recv_align = convert(arg2);
- break;
- case 'A':
- /* set remote alignments */
- break_args(optarg,arg1,arg2);
- if (arg1[0]) {
- remote_send_align = convert(arg1);
- }
- if (arg2[0])
- remote_recv_align = convert(arg2);
- break;
- case 'c':
- /* measure local cpu usage please. the user */
- /* may have specified the cpu rate as an */
- /* optional parm */
- if (argv[optind] && isdigit((unsigned char)argv[optind][0])){
- /* there was an optional parm */
- local_cpu_rate = (float)atof(argv[optind]);
- optind++;
- }
- local_cpu_usage++;
- break;
- case 'C':
- /* measure remote cpu usage please */
- if (argv[optind] && isdigit((unsigned char)argv[optind][0])){
- /* there was an optional parm */
- remote_cpu_rate = (float)atof(argv[optind]);
- optind++;
- }
- remote_cpu_usage++;
- break;
- case 'd':
- debug++;
- break;
- case 'D':
-#if (defined WANT_DEMO)
- demo_mode++;
- if (argv[optind] && isdigit((unsigned char)argv[optind][0])){
- /* there was an optional parm */
- break_args_explicit(argv[optind],arg1,arg2);
- optind++;
- if (arg1[0]) {
- demo_interval = atof(arg1) * 1000000.0;
- }
- if (arg2[0]) {
- demo_units = convert(arg2);
- }
- }
-#else
- printf("Sorry, Demo Mode not configured into this netperf.\n");
- printf("please consider reconfiguring netperf with\n");
- printf("--enable-demo=yes and recompiling\n");
-#endif
- break;
- case 'f':
- /* set the thruput formatting */
- libfmt = *optarg;
- break;
- case 'F':
- /* set the fill_file variable for pre-filling buffers */
- strcpy(fill_file,optarg);
- break;
- case 'i':
- /* set the iterations min and max for confidence intervals */
- break_args(optarg,arg1,arg2);
- if (arg1[0]) {
- iteration_max = convert(arg1);
- }
- if (arg2[0] ) {
- iteration_min = convert(arg2);
- }
- /* if the iteration_max is < iteration_min make iteration_max
- equal iteration_min */
- if (iteration_max < iteration_min) iteration_max = iteration_min;
- /* limit minimum to 3 iterations */
- if (iteration_max < 3) iteration_max = 3;
- if (iteration_min < 3) iteration_min = 3;
- /* limit maximum to 30 iterations */
- if (iteration_max > 30) iteration_max = 30;
- if (iteration_min > 30) iteration_min = 30;
- break;
- case 'I':
- /* set the confidence level (95 or 99) and width */
- break_args(optarg,arg1,arg2);
- if (arg1[0]) {
- confidence_level = convert(arg1);
- }
- if((confidence_level != 95) && (confidence_level != 99)){
- printf("Only 95%% and 99%% confidence level is supported\n");
- exit(1);
- }
- if (arg2[0] ) {
- interval = (double) convert(arg2)/100;
- }
- /* make sure that iteration_min and iteration_max are at least
- at a reasonable default value. if a -i option has previously
- been parsed, these will no longer be 1, so we can check
- against 1 */
- if (iteration_min == 1) iteration_min = 3;
- if (iteration_max == 1) iteration_max = 10;
-
- break;
- case 'k':
- /* local dirty and clean counts */
-#ifdef DIRTY
- break_args(optarg,arg1,arg2);
- if (arg1[0]) {
- loc_dirty_count = convert(arg1);
- }
- if (arg2[0] ) {
- loc_clean_count = convert(arg2);
- }
-#else
- printf("I don't know how to get dirty.\n");
-#endif /* DIRTY */
- break;
- case 'K':
- /* remote dirty and clean counts */
-#ifdef DIRTY
- break_args(optarg,arg1,arg2);
- if (arg1[0]) {
- rem_dirty_count = convert(arg1);
- }
- if (arg2[0] ) {
- rem_clean_count = convert(arg2);
- }
-#else
- printf("I don't know how to get dirty.\n");
-#endif /* DIRTY */
- break;
- case 'n':
- shell_num_cpus = atoi(optarg);
- break;
- case 'N':
- no_control = 1;
- break;
- case 'o':
- /* set the local offsets */
- break_args(optarg,arg1,arg2);
- if (arg1[0])
- local_send_offset = convert(arg1);
- if (arg2[0])
- local_recv_offset = convert(arg2);
- break;
- case 'O':
- /* set the remote offsets */
- break_args(optarg,arg1,arg2);
- if (arg1[0])
- remote_send_offset = convert(arg1);
- if (arg2[0])
- remote_recv_offset = convert(arg2);
- break;
- case 'P':
- /* to print or not to print, that is */
- /* the header question */
- print_headers = convert(optarg);
- break;
- case 'r':
- /* the user wishes that we declare confidence when hit on the
- result even if not yet reached on CPU utilization. only
- meaningful if cpu util is enabled */
- result_confidence_only = 1;
- break;
- case 't':
- /* set the test name */
- strcpy(test_name,optarg);
- break;
- case 'T':
- /* We want to set the processor on which netserver or netperf */
- /* will run */
- break_args(optarg,arg1,arg2);
- if (arg1[0]) {
- local_proc_affinity = convert(arg1);
- bind_to_specific_processor(local_proc_affinity,0);
- }
- if (arg2[0]) {
- remote_proc_affinity = convert(arg2);
- }
- cpu_binding_requested = 1;
- break;
- case 'W':
- /* set the "width" of the user space data buffer ring. This will */
- /* be the number of send_size buffers malloc'd in the tests */
- break_args(optarg,arg1,arg2);
- if (arg1[0])
- send_width = convert(arg1);
- if (arg2[0])
- recv_width = convert(arg2);
- break;
- case 'l':
- /* determine test end conditions */
- /* assume a timed test */
- test_time = convert(optarg);
- test_bytes = test_trans = 0;
- if (test_time < 0) {
- test_bytes = -1 * test_time;
- test_trans = test_bytes;
- test_time = 0;
- }
- break;
- case 'v':
- /* say how much to say */
- verbosity = convert(optarg);
- break;
- case 'p':
- /* specify an alternate port number we use break_args_explicit
- here to maintain backwards compatibility with previous
- generations of netperf where having a single value did not
- set both remote _and_ local port number. raj 2005-02-04 */
- break_args_explicit(optarg,arg1,arg2);
- if (arg1[0])
- strncpy(test_port,arg1,PORTBUFSIZE);
- if (arg2[0])
- strncpy(local_test_port,arg2,PORTBUFSIZE);
- break;
- case 'H':
- /* save-off the host identifying information, use
- break_args_explicit since passing just one value should not
- set both */
- break_args_explicit(optarg,arg1,arg2);
- if (arg1[0])
- strncpy(host_name,arg1,sizeof(host_name));
- if (arg2[0])
- address_family = parse_address_family(arg2);
- break;
- case 'L':
- /* save-off the local control socket addressing information. use
- break_args_explicit since passing just one value should not
- set both */
- break_args_explicit(optarg,arg1,arg2);
- if (arg1[0])
- strncpy(local_host_name,arg1,sizeof(local_host_name));
- if (arg2[0])
- local_address_family = parse_address_family(arg2);
- break;
- case 'w':
- /* We want to send requests at a certain wate. */
- /* Remember that there are 1000000 usecs in a */
- /* second, and that the packet rate is */
- /* expressed in packets per millisecond. */
-#ifdef WANT_INTERVALS
- interval_usecs = convert_timespec(optarg);
- interval_wate = interval_usecs / 1000;
-#else
- fprintf(where,
- "Packet rate control is not compiled in.\n");
-#endif
- break;
- case 'b':
- /* we want to have a burst so many packets per */
- /* interval. */
-#ifdef WANT_INTERVALS
- interval_burst = convert(optarg);
-#else
- fprintf(where,
- "Packet burst size is not compiled in. \n");
-#endif /* WANT_INTERVALS */
- break;
- case 'B':
- result_brand = malloc(strlen(optarg)+1);
- if (NULL != result_brand) {
- strcpy(result_brand,optarg);
- }
- else {
- fprintf(where,
- "Unable to malloc space for result brand\n");
- }
- break;
- case '4':
- address_family = AF_INET;
- local_address_family = AF_INET;
- break;
- case '6':
-#if defined(AF_INET6)
- address_family = AF_INET6;
- local_address_family = AF_INET6;
-#else
- printf("This netperf was not compiled on an IPv6 capable system!\n");
- exit(-1);
-#endif
- break;
- case 'V':
- printf("Netperf version %s\n",NETPERF_VERSION);
- exit(0);
- break;
- };
- }
- /* ok, what should our default hostname and local binding info be?
- */
- if ('\0' == host_name[0]) {
- /* host_name was not set */
- switch (address_family) {
- case AF_INET:
- strcpy(host_name,"localhost");
- break;
- case AF_UNSPEC:
- /* what to do here? case it off the local_address_family I
- suppose */
- switch (local_address_family) {
- case AF_INET:
- case AF_UNSPEC:
- strcpy(host_name,"localhost");
- break;
-#if defined(AF_INET6)
- case AF_INET6:
- strcpy(host_name,"::1");
- break;
-#endif
- default:
- printf("Netperf does not understand %d as an address family\n",
- address_family);
- exit(-1);
- }
- break;
-#if defined(AF_INET6)
- case AF_INET6:
- strcpy(host_name,"::1");
- break;
-#endif
- default:
- printf("Netperf does not understand %d as an address family\n",
- address_family);
- exit(-1);
- }
- }
-
- /* now, having established the name to which the control will
- connect, from what should it come? */
- if ('\0' == local_host_name[0]) {
- switch (local_address_family) {
- case AF_INET:
- strcpy(local_host_name,"0.0.0.0");
- break;
- case AF_UNSPEC:
- switch (address_family) {
- case AF_INET:
- case AF_UNSPEC:
- strcpy(local_host_name,"0.0.0.0");
- break;
-#if defined(AF_INET6)
- case AF_INET6:
- strcpy(local_host_name,"::0");
- break;
-#endif
- default:
- printf("Netperf does not understand %d as an address family\n",
- address_family);
- exit(-1);
- }
- break;
-#if defined(AF_INET6)
- case AF_INET6:
- strcpy(local_host_name,"::0");
- break;
-#endif
- default:
- printf("Netperf does not understand %d as an address family\n",
- address_family);
- exit(-1);
- }
- }
-
- /* so, if we aren't even going to establish a control connection we
- should set certain "remote" settings to reflect this, regardless
- of what else may have been set on the command line */
- if (no_control) {
- remote_recv_align = -1;
- remote_send_align = -1;
- remote_send_offset = -1;
- remote_recv_offset = -1;
- remote_cpu_rate = (float)-1.0;
- remote_cpu_usage = 0;
- }
-
- /* parsing test-specific options used to be conditional on there
- being a "--" in the option stream. however, some of the tests
- have other initialization happening in their "scan" routines so we
- want to call them regardless. raj 2005-02-08 */
- if ((strcasecmp(test_name,"TCP_STREAM") == 0) ||
-#ifdef HAVE_ICSC_EXS
- (strcasecmp(test_name,"EXS_TCP_STREAM") == 0) ||
-#endif /* HAVE_ICSC_EXS */
-#ifdef HAVE_SENDFILE
- (strcasecmp(test_name,"TCP_SENDFILE") == 0) ||
-#endif /* HAVE_SENDFILE */
- (strcasecmp(test_name,"TCP_MAERTS") == 0) ||
- (strcasecmp(test_name,"TCP_RR") == 0) ||
- (strcasecmp(test_name,"TCP_CRR") == 0) ||
- (strcasecmp(test_name,"TCP_CC") == 0) ||
-#ifdef DO_1644
- (strcasecmp(test_name,"TCP_TRR") == 0) ||
-#endif /* DO_1644 */
-#ifdef DO_NBRR
- (strcasecmp(test_name,"TCP_TRR") == 0) ||
-#endif /* DO_NBRR */
- (strcasecmp(test_name,"UDP_STREAM") == 0) ||
- (strcasecmp(test_name,"UDP_RR") == 0))
- {
- scan_sockets_args(argc, argv);
- }
-
-#ifdef WANT_DLPI
- else if ((strcasecmp(test_name,"DLCO_RR") == 0) ||
- (strcasecmp(test_name,"DLCL_RR") == 0) ||
- (strcasecmp(test_name,"DLCO_STREAM") == 0) ||
- (strcasecmp(test_name,"DLCL_STREAM") == 0))
- {
- scan_dlpi_args(argc, argv);
- }
-#endif /* WANT_DLPI */
-
-#ifdef WANT_UNIX
- else if ((strcasecmp(test_name,"STREAM_RR") == 0) ||
- (strcasecmp(test_name,"DG_RR") == 0) ||
- (strcasecmp(test_name,"STREAM_STREAM") == 0) ||
- (strcasecmp(test_name,"DG_STREAM") == 0))
- {
- scan_unix_args(argc, argv);
- }
-#endif /* WANT_UNIX */
-
-#ifdef WANT_XTI
- else if ((strcasecmp(test_name,"XTI_TCP_RR") == 0) ||
- (strcasecmp(test_name,"XTI_TCP_STREAM") == 0) ||
- (strcasecmp(test_name,"XTI_UDP_RR") == 0) ||
- (strcasecmp(test_name,"XTI_UDP_STREAM") == 0))
- {
- scan_xti_args(argc, argv);
- }
-#endif /* WANT_XTI */
-
-#ifdef WANT_SCTP
- else if ((strcasecmp(test_name,"SCTP_STREAM") == 0) ||
- (strcasecmp(test_name,"SCTP_RR") == 0) ||
- (strcasecmp(test_name,"SCTP_STREAM_MANY") == 0) ||
- (strcasecmp(test_name,"SCTP_RR_MANY") == 0))
- {
- scan_sctp_args(argc, argv);
- }
-#endif
-
-#ifdef WANT_SDP
- else if((strcasecmp(test_name,"SDP_STREAM") == 0) ||
- (strcasecmp(test_name,"SDP_MAERTS") == 0) ||
- (strcasecmp(test_name,"SDP_RR") == 0))
- {
- scan_sdp_args(argc, argv);
- }
-#endif
-
- /* what is our default value for the output units? if the test
- name contains "RR" or "rr" or "Rr" or "rR" then the default is
- 'x' for transactions. otherwise it is 'm' for megabits
- (10^6) */
-
- if ('?' == libfmt) {
- /* we use a series of strstr's here because not everyone has
- strcasestr and I don't feel like up or downshifting text */
- if ((strstr(test_name,"RR")) ||
- (strstr(test_name,"rr")) ||
- (strstr(test_name,"Rr")) ||
- (strstr(test_name,"rR"))) {
- libfmt = 'x';
- }
- else {
- libfmt = 'm';
- }
- }
- else if ('x' == libfmt) {
- /* now, a format of 'x' makes no sense for anything other than
- an RR test. if someone has been silly enough to try to set
- that, we will reset it silently to default - namely 'm' */
- if ((strstr(test_name,"RR") == NULL) &&
- (strstr(test_name,"rr") == NULL) &&
- (strstr(test_name,"Rr") == NULL) &&
- (strstr(test_name,"rR") == NULL)) {
- libfmt = 'm';
- }
- }
-}
-
-
-void
-dump_globals()
-{
- printf("Program name: %s\n", program);
- printf("Local send alignment: %d\n",local_send_align);
- printf("Local recv alignment: %d\n",local_recv_align);
- printf("Remote send alignment: %d\n",remote_send_align);
- printf("Remote recv alignment: %d\n",remote_recv_align);
- printf("Report local CPU %d\n",local_cpu_usage);
- printf("Report remote CPU %d\n",remote_cpu_usage);
- printf("Verbosity: %d\n",verbosity);
- printf("Debug: %d\n",debug);
- printf("Port: %s\n",test_port);
- printf("Test name: %s\n",test_name);
- printf("Test bytes: %d Test time: %d Test trans: %d\n",
- test_bytes,
- test_time,
- test_trans);
- printf("Host name: %s\n",host_name);
- printf("\n");
-}
diff --git a/netsh.h b/netsh.h
deleted file mode 100644
index e99883b..0000000
--- a/netsh.h
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- Copyright (C) 1993,1995 Hewlett-Packard Company
-*/
-
-/* libraried performance include file */
-/* the define NOPERFEXTERN tels us not to re-define all the */
-
-/* defines and defaults */
-#define HOSTNAMESIZE 255
-#define PORTBUFSIZE 10
-#define DEFAULT_SIZE 32768
-#define HOST_NAME "127.0.0.1"
-#define TEST_PORT "12865"
-
-/* output controlling variables */
-#define DEBUG 0 /* debugging level */
-#define VERBOSITY 0 /* verbosity level */
-
-/* the end-test conditions for the tests - either transactions, bytes, */
-/* or time. different vars used for clarity - space is cheap ;-) */
-#define TEST_TIME 10 /* test ends by time */
-#define TEST_BYTES 0 /* test ends on byte count */
-#define TEST_TRANS 0 /* test ends on tran count */
-
-/* the alignment conditions for the tests */
-#define LOC_RECV_ALIGN 4 /* alignment for local receives */
-#define LOC_SEND_ALIGN 4 /* alignment for local sends */
-#define REM_RECV_ALIGN 4 /* alignment for remote receive */
-#define REM_SEND_ALIGN 4 /* alignment for remote sends */
-
-/* misc defines for the hell of it */
-#ifndef MAXLONG
-#define MAXLONG 4294967295UL
-#endif /* MAXLONG */
-
-#ifndef NETSH
-extern char *program; /* program invocation name */
-
-/* stuff to say where this test is going */
-extern char host_name[HOSTNAMESIZE];/* remote host name or ip addr */
-extern char local_host_name[HOSTNAMESIZE];
-extern char test_port[PORTBUFSIZE]; /* where is the test waiting */
-extern char local_test_port[PORTBUFSIZE];
-extern int address_family;
-extern int local_address_family;
-extern int parse_address_family(char family_string[]);
-extern void set_defaults();
-extern void scan_cmd_line(int argc, char *argv[]);
-extern void dump_globals();
-extern void break_args(char *s, char *arg1, char *arg2);
-extern void break_args_explicit(char *s, char *arg1, char *arg2);
-extern void print_netserver_usage();
-
-/* output controlling variables */
-extern int
- debug, /* debugging level */
- print_headers, /* do/don't print test headers */
- verbosity; /* verbosity level */
-
-/* the end-test conditions for the tests - either transactions, bytes, */
-/* or time. different vars used for clarity - space is cheap ;-) */
-extern int
- test_time, /* test ends by time */
- test_len_ticks,
- test_bytes, /* test ends on byte count */
- test_trans; /* test ends on tran count */
-
-/* the alignment conditions for the tests */
-extern int
- local_recv_align, /* alignment for local receives */
- local_send_align, /* alignment for local sends */
- remote_recv_align, /* alignment for remote receives */
- remote_send_align, /* alignment for remote sends */
- local_send_offset,
- local_recv_offset,
- remote_send_offset,
- remote_recv_offset;
-
-#if defined(WANT_INTERVALS) || defined(WANT_DEMO)
-extern int interval_usecs;
-extern int interval_wate;
-extern int interval_burst;
-
-extern int demo_mode;
-extern double demo_interval;
-extern double demo_units;
-extern double units_this_tick;
-#endif
-
-#ifdef DIRTY
-extern int rem_dirty_count;
-extern int rem_clean_count;
-extern int loc_dirty_count;
-extern int loc_clean_count;
-#endif /* DIRTY */
-
-/* stuff for confidence intervals */
-
-extern int confidence_level;
-extern int iteration_min;
-extern int iteration_max;
-extern int result_confidence_only;
-extern double interval;
-
-extern int cpu_binding_requested;
-
-/* stuff to controll the bufferspace "width" */
-extern int send_width;
-extern int recv_width;
-
-/* address family */
-extern int af;
-
-/* different options for other things */
-extern int
- local_cpu_usage,
- remote_cpu_usage;
-
-extern float
- local_cpu_rate,
- remote_cpu_rate;
-
-extern int
- shell_num_cpus;
-
-extern char
- test_name[BUFSIZ];
-
-extern char
- fill_file[BUFSIZ];
-
-extern char *
- result_brand;
-
-extern int
- no_control;
-
-#ifdef WANT_DLPI
-
-extern int
- loc_ppa,
- rem_ppa;
-
-extern int
- dlpi_sap;
-
-#endif /* WANT_DLPI */
-
-#endif
diff --git a/nettest_bsd.c b/nettest_bsd.c
deleted file mode 100644
index 27092f3..0000000
--- a/nettest_bsd.c
+++ /dev/null
@@ -1,12333 +0,0 @@
-#ifndef lint
-char nettest_id[]="\
-@(#)nettest_bsd.c (c) Copyright 1993-2004 Hewlett-Packard Co. Version 2.4.3";
-#endif /* lint */
-
-
-/****************************************************************/
-/* */
-/* nettest_bsd.c */
-/* */
-/* the BSD sockets parsing routine... */
-/* ...with the addition of Windows NT, this is now also */
-/* a Winsock test... sigh :) */
-/* */
-/* scan_sockets_args() */
-/* */
-/* the actual test routines... */
-/* */
-/* send_tcp_stream() perform a tcp stream test */
-/* recv_tcp_stream() */
-/* send_tcp_maerts() perform a tcp stream test */
-/* recv_tcp_maerts() in the other direction */
-/* send_tcp_rr() perform a tcp request/response */
-/* recv_tcp_rr() */
-/* send_tcp_conn_rr() an RR test including connect */
-/* recv_tcp_conn_rr() */
-/* send_tcp_cc() a connect/disconnect test with */
-/* recv_tcp_cc() no RR */
-/* send_udp_stream() perform a udp stream test */
-/* recv_udp_stream() */
-/* send_udp_rr() perform a udp request/response */
-/* recv_udp_rr() */
-/* loc_cpu_rate() determine the local cpu maxrate */
-/* rem_cpu_rate() find the remote cpu maxrate */
-/* */
-/****************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#if HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-#if HAVE_SYS_STAT_H
-# include <sys/stat.h>
-#endif
-#if STDC_HEADERS
-# include <stdlib.h>
-# include <stddef.h>
-#else
-# if HAVE_STDLIB_H
-# include <stdlib.h>
-# endif
-#endif
-#if HAVE_STRING_H
-# if !STDC_HEADERS && HAVE_MEMORY_H
-# include <memory.h>
-# endif
-# include <string.h>
-#endif
-#if HAVE_STRINGS_H
-# include <strings.h>
-#endif
-#if HAVE_INTTYPES_H
-# include <inttypes.h>
-#else
-# if HAVE_STDINT_H
-# include <stdint.h>
-# endif
-#endif
-#if HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-
-#include <fcntl.h>
-#ifndef WIN32
-#include <errno.h>
-#include <signal.h>
-#endif
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-#endif
-
-#ifdef NOSTDLIBH
-#include <malloc.h>
-#endif /* NOSTDLIBH */
-
-#ifndef WIN32
-#if !defined(__VMS)
-#include <sys/ipc.h>
-#endif /* !defined(__VMS) */
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#else /* WIN32 */
-#include <process.h>
-#define netperf_socklen_t socklen_t
-#include <winsock2.h>
-
-/* while it is unlikely that anyone running Windows 2000 or NT 4 is
- going to be trying to compile this, if they are they will want to
- define DONT_IPV6 in the sources file */
-#ifndef DONT_IPV6
-#include <ws2tcpip.h>
-#endif
-#include <windows.h>
-
-#define sleep(x) Sleep((x)*1000)
-
-#define __func__ __FUNCTION__
-#endif /* WIN32 */
-
-/* We don't want to use bare constants in the shutdown() call. In the
- extremely unlikely event that SHUT_WR isn't defined, we will define
- it to the value we used to be passing to shutdown() anyway. raj
- 2007-02-08 */
-#if !defined(SHUT_WR)
-#define SHUT_WR 1
-#endif
-
-#if !defined(HAVE_GETADDRINFO) || !defined(HAVE_GETNAMEINFO)
-# include "missing/getaddrinfo.h"
-#endif
-
-#include "netlib.h"
-#include "netsh.h"
-#include "nettest_bsd.h"
-
-#if defined(WANT_HISTOGRAM) || defined(WANT_DEMO)
-#include "hist.h"
-#endif /* WANT_HISTOGRAM */
-
-/* make first_burst_size unconditional so we can use it easily enough
- when calculating transaction latency for the TCP_RR test. raj
- 2007-06-08 */
-int first_burst_size=0;
-
-#if defined(HAVE_SENDFILE) && (defined(__linux) || defined(__sun__))
-#include <sys/sendfile.h>
-#endif /* HAVE_SENDFILE && (__linux || __sun__) */
-
-
-
-/* these variables are specific to the BSD sockets tests, but can
- * be used elsewhere if needed. They are externed through nettest_bsd.h
- */
-
-int
- rss_size_req = -1, /* requested remote socket send buffer size */
- rsr_size_req = -1, /* requested remote socket recv buffer size */
- rss_size, /* remote socket send buffer size */
- rsr_size, /* remote socket recv buffer size */
- lss_size_req = -1, /* requested local socket send buffer size */
- lsr_size_req = -1, /* requested local socket recv buffer size */
- lss_size, /* local socket send buffer size */
- lsr_size, /* local socket recv buffer size */
- req_size = 1, /* request size */
- rsp_size = 1, /* response size */
- send_size, /* how big are individual sends */
- recv_size; /* how big are individual receives */
-
-static int confidence_iteration;
-static char local_cpu_method;
-static char remote_cpu_method;
-
-/* these will control the width of port numbers we try to use in the */
-/* TCP_CRR and/or TCP_TRR tests. raj 3/95 */
-static int client_port_min = 5000;
-static int client_port_max = 65535;
-
- /* different options for the sockets */
-
-int
- loc_nodelay, /* don't/do use NODELAY locally */
- rem_nodelay, /* don't/do use NODELAY remotely */
-#ifdef TCP_CORK
- loc_tcpcork=0, /* don't/do use TCP_CORK locally */
- rem_tcpcork=0, /* don't/do use TCP_CORK remotely */
-#endif /* TCP_CORK */
- loc_sndavoid, /* avoid send copies locally */
- loc_rcvavoid, /* avoid recv copies locally */
- rem_sndavoid, /* avoid send copies remotely */
- rem_rcvavoid, /* avoid recv_copies remotely */
- local_connected = 0, /* local socket type, connected/non-connected */
- remote_connected = 0; /* remote socket type, connected/non-connected */
-
-#ifdef WANT_HISTOGRAM
-#ifdef HAVE_GETHRTIME
-static hrtime_t time_one;
-static hrtime_t time_two;
-#elif HAVE_GET_HRT
-#include "hrt.h"
-static hrt_t time_one;
-static hrt_t time_two;
-#elif defined(WIN32)
-static LARGE_INTEGER time_one;
-static LARGE_INTEGER time_two;
-#else
-static struct timeval time_one;
-static struct timeval time_two;
-#endif /* HAVE_GETHRTIME */
-static HIST time_hist;
-#endif /* WANT_HISTOGRAM */
-
-#ifdef WANT_INTERVALS
-int interval_count;
-#ifndef WANT_SPIN
-sigset_t signal_set;
-#define INTERVALS_INIT() \
- if (interval_burst) { \
- /* zero means that we never pause, so we never should need the \
- interval timer. we used to use it for demo mode, but we deal \
- with that with a variant on watching the clock rather than \
- waiting for a timer. raj 2006-02-06 */ \
- start_itimer(interval_wate); \
- } \
- interval_count = interval_burst; \
- /* get the signal set for the call to sigsuspend */ \
- if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &signal_set) != 0) { \
- fprintf(where, \
- "%s: unable to get sigmask errno %d\n", \
- __func__, \
- errno); \
- fflush(where); \
- exit(1); \
- }
-
-#define INTERVALS_WAIT() \
- /* in this case, the interval count is the count-down couter \
- to decide to sleep for a little bit */ \
- if ((interval_burst) && (--interval_count == 0)) { \
- /* call sigsuspend and wait for the interval timer to get us \
- out */ \
- if (debug > 1) { \
- fprintf(where,"about to suspend\n"); \
- fflush(where); \
- } \
- if (sigsuspend(&signal_set) == EFAULT) { \
- fprintf(where, \
- "%s: fault with sigsuspend.\n", \
- __func__); \
- fflush(where); \
- exit(1); \
- } \
- interval_count = interval_burst; \
- }
-#else
-/* first out timestamp */
-#ifdef HAVE_GETHRTIME
-static hrtime_t intvl_one;
-static hrtime_t intvl_two;
-static hrtime_t *intvl_one_ptr = &intvl_one;
-static hrtime_t *intvl_two_ptr = &intvl_two;
-static hrtime_t *temp_intvl_ptr = &intvl_one;
-#elif defined(WIN32)
-static LARGE_INTEGER intvl_one;
-static LARGE_INTEGER intvl_two;
-static LARGE_INTEGER *intvl_one_ptr = &intvl_one;
-static LARGE_INTEGER *intvl_two_ptr = &intvl_two;
-static LARGE_INTEGER *temp_intvl_ptr = &intvl_one;
-#else
-static struct timeval intvl_one;
-static struct timeval intvl_two;
-static struct timeval *intvl_one_ptr = &intvl_one;
-static struct timeval *intvl_two_ptr = &intvl_two;
-static struct timeval *temp_intvl_ptr = &intvl_one;
-#endif
-
-#define INTERVALS_INIT() \
- if (interval_burst) { \
- HIST_timestamp(intvl_one_ptr); \
- } \
- interval_count = interval_burst; \
-
-#define INTERVALS_WAIT() \
- /* in this case, the interval count is the count-down couter \
- to decide to sleep for a little bit */ \
- if ((interval_burst) && (--interval_count == 0)) { \
- /* call sigsuspend and wait for the interval timer to get us \
- out */ \
- if (debug > 1) { \
- fprintf(where,"about to spin suspend\n"); \
- fflush(where); \
- } \
- HIST_timestamp(intvl_two_ptr); \
- while(delta_micro(intvl_one_ptr,intvl_two_ptr) < interval_usecs) { \
- HIST_timestamp(intvl_two_ptr); \
- } \
- temp_intvl_ptr = intvl_one_ptr; \
- intvl_one_ptr = intvl_two_ptr; \
- intvl_two_ptr = temp_intvl_ptr; \
- interval_count = interval_burst; \
- }
-#endif
-#endif
-
-#ifdef WANT_DEMO
-#ifdef HAVE_GETHRTIME
-static hrtime_t demo_one;
-static hrtime_t demo_two;
-static hrtime_t *demo_one_ptr = &demo_one;
-static hrtime_t *demo_two_ptr = &demo_two;
-static hrtime_t *temp_demo_ptr = &demo_one;
-#elif defined(WIN32)
-static LARGE_INTEGER demo_one;
-static LARGE_INTEGER demo_two;
-static LARGE_INTEGER *demo_one_ptr = &demo_one;
-static LARGE_INTEGER *demo_two_ptr = &demo_two;
-static LARGE_INTEGER *temp_demo_ptr = &demo_one;
-#else
-static struct timeval demo_one;
-static struct timeval demo_two;
-static struct timeval *demo_one_ptr = &demo_one;
-static struct timeval *demo_two_ptr = &demo_two;
-static struct timeval *temp_demo_ptr = &demo_one;
-#endif
-
-/* for a _STREAM test, "a" should be lss_size and "b" should be
- rsr_size. for a _MAERTS test, "a" should be lsr_size and "b" should
- be rss_size. raj 2005-04-06 */
-#define DEMO_STREAM_SETUP(a,b) \
- if ((demo_mode) && (demo_units == 0)) { \
- /* take our default value of demo_units to be the larger of \
- twice the remote's SO_RCVBUF or twice our SO_SNDBUF */ \
- if (a > b) { \
- demo_units = 2*a; \
- } \
- else { \
- demo_units = 2*b; \
- } \
- }
-
-#define DEMO_STREAM_INTERVAL(units) \
- if (demo_mode) { \
- double actual_interval; \
- units_this_tick += units; \
- if (units_this_tick >= demo_units) { \
- /* time to possibly update demo_units and maybe output an \
- interim result */ \
- HIST_timestamp(demo_two_ptr); \
- actual_interval = delta_micro(demo_one_ptr,demo_two_ptr); \
- /* we always want to fine-tune demo_units here whether we \
- emit an interim result or not. if we are short, this \
- will lengthen demo_units. if we are long, this will \
- shorten it */ \
- demo_units = demo_units * (demo_interval / actual_interval); \
- if (actual_interval >= demo_interval) { \
- /* time to emit an interim result */ \
- fprintf(where, \
- "Interim result: %7.2f %s/s over %.2f seconds\n", \
- calc_thruput_interval(units_this_tick, \
- actual_interval/1000000.0), \
- format_units(), \
- actual_interval/1000000.0); \
- fflush(where); \
- units_this_tick = 0.0; \
- /* now get a new starting timestamp. we could be clever \
- and swap pointers - the math we do probably does not \
- take all that long, but for now this will suffice */ \
- temp_demo_ptr = demo_one_ptr; \
- demo_one_ptr = demo_two_ptr; \
- demo_two_ptr = temp_demo_ptr; \
- } \
- } \
- }
-
-#define DEMO_RR_SETUP(a) \
- if ((demo_mode) && (demo_units == 0)) { \
- /* take whatever we are given */ \
- demo_units = a; \
- }
-
-#define DEMO_RR_INTERVAL(units) \
- if (demo_mode) { \
- double actual_interval; \
- units_this_tick += units; \
- if (units_this_tick >= demo_units) { \
- /* time to possibly update demo_units and maybe output an \
- interim result */ \
- HIST_timestamp(demo_two_ptr); \
- actual_interval = delta_micro(demo_one_ptr,demo_two_ptr); \
- /* we always want to fine-tune demo_units here whether we \
- emit an interim result or not. if we are short, this \
- will lengthen demo_units. if we are long, this will \
- shorten it */ \
- demo_units = demo_units * (demo_interval / actual_interval); \
- if (actual_interval >= demo_interval) { \
- /* time to emit an interim result */ \
- fprintf(where, \
- "Interim result: %.2f %s/s over %.2f seconds\n", \
- units_this_tick / (actual_interval/1000000.0), \
- "Trans", \
- actual_interval/1000000.0); \
- units_this_tick = 0.0; \
- /* now get a new starting timestamp. we could be clever \
- and swap pointers - the math we do probably does not \
- take all that long, but for now this will suffice */ \
- temp_demo_ptr = demo_one_ptr; \
- demo_one_ptr = demo_two_ptr; \
- demo_two_ptr = temp_demo_ptr; \
- } \
- } \
- }
-#endif
-
-char sockets_usage[] = "\n\
-Usage: netperf [global options] -- [test options] \n\
-\n\
-TCP/UDP BSD Sockets Test Options:\n\
- -b number Send number requests at start of _RR tests\n\
- -C Set TCP_CORK when available\n\
- -D [L][,R] Set TCP_NODELAY locally and/or remotely (TCP_*)\n\
- -h Display this text\n\
- -H name,fam Use name (or IP) and family as target of data connection\n\
- -L name,fam Use name (or IP) and family as source of data connection\n\
- -m bytes Set the send size (TCP_STREAM, UDP_STREAM)\n\
- -M bytes Set the recv size (TCP_STREAM, UDP_STREAM)\n\
- -n Use the connected socket for UDP locally\n\
- -N Use the connected socket for UDP remotely\n\
- -p min[,max] Set the min/max port numbers for TCP_CRR, TCP_TRR\n\
- -P local[,remote] Set the local/remote port for the data socket\n\
- -r req,[rsp] Set request/response sizes (TCP_RR, UDP_RR)\n\
- -s send[,recv] Set local socket send/recv buffer sizes\n\
- -S send[,recv] Set remote socket send/recv buffer sizes\n\
- -4 Use AF_INET (eg IPv4) on both ends of the data conn\n\
- -6 Use AF_INET6 (eg IPv6) on both ends of the data conn\n\
-\n\
-For those options taking two parms, at least one must be specified;\n\
-specifying one value without a comma will set both parms to that\n\
-value, specifying a value with a leading comma will set just the second\n\
-parm, a value with a trailing comma will set just the first. To set\n\
-each parm to unique values, specify both and separate them with a\n\
-comma.\n";
-
-
-
-/* these routines convert between the AF address space and the NF
- address space since the numeric values of AF_mumble are not the
- same across the platforms. raj 2005-02-08 */
-
-int
-nf_to_af(int nf) {
- switch(nf) {
- case NF_INET:
- return AF_INET;
- break;
- case NF_UNSPEC:
- return AF_UNSPEC;
- break;
- case NF_INET6:
-#if defined(AF_INET6)
- return AF_INET6;
-#else
- return AF_UNSPEC;
-#endif
- break;
- default:
- return AF_UNSPEC;
- break;
- }
-}
-
-int
-af_to_nf(int af) {
-
- switch(af) {
- case AF_INET:
- return NF_INET;
- break;
- case AF_UNSPEC:
- return NF_UNSPEC;
- break;
-#if defined(AF_INET6)
- case AF_INET6:
- return NF_INET6;
- break;
-#endif
- default:
- return NF_UNSPEC;
- break;
- }
-}
-
-
- /* This routine is intended to retrieve interesting aspects of tcp */
- /* for the data connection. at first, it attempts to retrieve the */
- /* maximum segment size. later, it might be modified to retrieve */
- /* other information, but it must be information that can be */
- /* retrieved quickly as it is called during the timing of the test. */
- /* for that reason, a second routine may be created that can be */
- /* called outside of the timing loop */
-static
-void
-get_tcp_info(SOCKET socket, int *mss)
-{
-
-#ifdef TCP_MAXSEG
- netperf_socklen_t sock_opt_len;
-
- sock_opt_len = sizeof(netperf_socklen_t);
- if (getsockopt(socket,
- getprotobyname("tcp")->p_proto,
- TCP_MAXSEG,
- (char *)mss,
- &sock_opt_len) == SOCKET_ERROR) {
- fprintf(where,
- "netperf: get_tcp_info: getsockopt TCP_MAXSEG: errno %d\n",
- errno);
- fflush(where);
- *mss = -1;
- }
-#else
- *mss = -1;
-#endif /* TCP_MAXSEG */
-}
-
-
-/* return a pointer to a completed addrinfo chain - prefer
- data_address to controlhost and utilize the specified address
- family */
-
-struct addrinfo *
-complete_addrinfo(char *controlhost, char *data_address, char *port, int family, int type, int protocol, int flags)
-{
- struct addrinfo hints;
- struct addrinfo *res;
- struct addrinfo *temp_res;
-
-#define CHANGED_SOCK_TYPE 0x1
-#define CHANGED_PROTOCOL 0x2
-#define CHANGED_SCTP 0x4
- int change_info = 0;
- static int change_warning_displayed = 0;
-
- int count = 0;
- int error = 0;
-
- char *hostname;
-
- /* take data-address over controlhost */
- if (data_address)
- hostname = data_address;
- else
- hostname = controlhost;
-
- if (debug) {
- fprintf(where,
- "complete_addrinfo using hostname %s port %s family %s type %s prot %s flags 0x%x\n",
- hostname,
- port,
- inet_ftos(family),
- inet_ttos(type),
- inet_ptos(protocol),
- flags);
- fflush(where);
- }
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = family;
- hints.ai_socktype = type;
- hints.ai_protocol = protocol;
- hints.ai_flags = flags|AI_CANONNAME;
-
- count = 0;
- do {
- error = getaddrinfo((char *)hostname,
- (char *)port,
- &hints,
- &res);
- count += 1;
- if (error == EAI_AGAIN) {
- if (debug) {
- fprintf(where,"Sleeping on getaddrinfo EAI_AGAIN\n");
- fflush(where);
- }
- sleep(1);
- }
- /* while you see this kludge first, it is actually the second, the
- first being the one for Solaris below. The need for this kludge
- came after implementing the Solaris broken getaddrinfo kludge -
- now we see a kludge in Linux getaddrinfo where if it is given
- SOCK_STREAM and IPPROTO_SCTP it barfs with a -7
- EAI_SOCKTYPE. so, we check if the error was EAI_SOCKTYPE and if
- we were asking for IPPROTO_SCTP and if so, kludge, again... raj
- 2008-10-13 */
-#ifdef WANT_SCTP
- if (EAI_SOCKTYPE == error
-#ifdef EAI_BADHINTS
- || EAI_BADHINTS == error
-#endif
- ) {
- /* we ass-u-me this is the Linux getaddrinfo bug, clear the
- hints.ai_protocol field, and set some state "remembering"
- that we did this so the code for the Solaris kludge can do
- the fix-up for us. also flip error over to EAI_AGAIN and
- make sure we don't "count" this time around the loop. */
- hints.ai_protocol = 0;
- error = EAI_AGAIN;
- count -= 1;
- change_info |= CHANGED_SCTP;
- }
-#endif
- } while ((error == EAI_AGAIN) && (count <= 5));
-
- if (error) {
- fprintf(where,
- "complete_addrinfo: could not resolve '%s' port '%s' af %d",
- hostname,
- port,
- family);
- fprintf(where,
- "\n\tgetaddrinfo returned %d %s\n",
- error,
- gai_strerror(error));
- fflush(where);
- exit(-1);
- }
-
- /* there exists at least one platform - Solaris 10 - that does not
- seem to completely honor the ai_protocol and/or ai_socktype one
- sets in the hints parm to the getaddrinfo call. so, we need to
- walk the list of entries returned and if either of those do not
- match what we asked for, we need to go ahead and set them
- "correctly" this is based in part on some earlier SCTP-only code
- from previous revisions. raj 2006-10-09 */
-
- temp_res = res;
-
- while (temp_res) {
-
- if ((type) &&
- (temp_res->ai_socktype != type)) {
- change_info |= CHANGED_SOCK_TYPE;
- if (debug) {
- fprintf(where,
- "WARNING! Changed bogus getaddrinfo socket type %d to %d\n",
- temp_res->ai_socktype,
- type);
- fflush(where);
- }
- temp_res->ai_socktype = type;
- }
-
- if ((protocol) &&
- (temp_res->ai_protocol != protocol)) {
- change_info |= CHANGED_PROTOCOL;
- if (debug) {
- fprintf(where,
- "WARNING! Changed bogus getaddrinfo protocol %d to %d\n",
- temp_res->ai_protocol,
- protocol);
- fflush(where);
- }
- temp_res->ai_protocol = protocol;
- }
- temp_res = temp_res->ai_next;
- }
-
- if ((change_info & CHANGED_SOCK_TYPE) &&
- !(change_warning_displayed & CHANGED_SOCK_TYPE)) {
- change_warning_displayed |= CHANGED_SOCK_TYPE;
- fprintf(where,
- "WARNING! getaddrinfo returned a socket type which did not\n");
- fprintf(where,
- "match the requested type. Please contact your vendor for\n");
- fprintf(where,
- "a fix to this bug in getaddrinfo()\n");
- fflush(where);
- }
-
- /* if we dropped the protocol hint, it would be for a protocol that
- getaddrinfo() wasn't supporting yet, not for the bug that it took
- our hint and still returned zero. raj 2006-10-16 */
- if ((change_info & CHANGED_PROTOCOL) &&
- !(change_warning_displayed & CHANGED_PROTOCOL) &&
- (hints.ai_protocol != 0)) {
- change_warning_displayed |= CHANGED_PROTOCOL;
- fprintf(where,
- "WARNING! getaddrinfo returned a protocol other than the\n");
- fprintf(where,
- "requested protocol. Please contact your vendor for\n");
- fprintf(where,
- "a fix to this bug in getaddrinfo()\n");
- fflush(where);
- }
-
- if ((change_info & CHANGED_SCTP) &&
- !(change_warning_displayed & CHANGED_SCTP)) {
- change_warning_displayed |= CHANGED_SCTP;
- fprintf(where,
- "WARNING! getaddrinfo on this platform does not accept IPPROTO_SCTP!\n");
- fprintf(where,
- "Please contact your vendor for a fix to this bug in getaddrinfo().\n");
- fflush(where);
- }
-
-
- if (debug) {
- dump_addrinfo(where, res, hostname, port, family);
- }
-
- return(res);
-}
-
-void
-complete_addrinfos(struct addrinfo **remote,struct addrinfo **local, char remote_host[], int type, int protocol, int flags) {
-
- *remote = complete_addrinfo(remote_host,
- remote_data_address,
- remote_data_port,
- remote_data_family,
- type,
- protocol,
- flags);
-
- /* OK, if the user has not specified a local data endpoint address
- (test-specific -L), pick the local data endpoint address based on
- the remote data family info (test-specific -H or -4 or -6
- option). if the user has not specified remote data addressing
- info (test-specific -H, -4 -6) pick something based on the local
- control connection address (ie the global -L option). */
-
- if (NULL == local_data_address) {
- local_data_address = malloc(HOSTNAMESIZE);
- if (NULL == remote_data_address) {
- if (debug) {
- fprintf(where,
- "local_data_address not set, using local_host_name of '%s'\n",
- local_host_name);
- fflush(where);
- }
- strcpy(local_data_address,local_host_name);
- }
- else {
- if (debug) {
- fprintf(where,
- "local_data_address not set, using address family info\n");
- fflush(where);
- }
- /* by default, use 0.0.0.0 - assume IPv4 */
- strcpy(local_data_address,"0.0.0.0");
-#if defined(AF_INET6)
- if ((AF_INET6 == local_data_family) ||
- ((AF_UNSPEC == local_data_family) &&
- (AF_INET6 == remote_data_family)) ||
- ((AF_UNSPEC == local_data_family) &&
- (AF_INET6 == (*remote)->ai_family))) {
- strcpy(local_data_address,"::0");
- }
-#endif
- }
- }
-
- *local = complete_addrinfo("what to put here?",
- local_data_address,
- local_data_port,
- local_data_family,
- type,
- protocol,
- flags|AI_PASSIVE);
-
-}
-
-void
-set_hostname_and_port(char *hostname, char *portstr, int family, int port)
-{
- strcpy(hostname,"0.0.0.0");
-#if defined AF_INET6
- if (AF_INET6 == family) {
- strcpy(hostname,"::0");
- }
-#endif
-
- sprintf(portstr, "%u", port);
-
-}
-
-static unsigned short
-get_port_number(struct addrinfo *res)
-{
- switch(res->ai_family) {
- case AF_INET: {
- struct sockaddr_in *foo = (struct sockaddr_in *)res->ai_addr;
- return(ntohs(foo->sin_port));
- break;
- }
-#if defined(AF_INET6)
- case AF_INET6: {
- struct sockaddr_in6 *foo = (struct sockaddr_in6 *)res->ai_addr;
- return(ntohs(foo->sin6_port));
- break;
- }
-#endif
- default:
- fprintf(where,
- "Unexpected Address Family of %u\n",res->ai_family);
- fflush(where);
- exit(-1);
- }
-}
-
-/* this routine will set the port number of the sockaddr in the
- addrinfo to the specified value, based on the address family */
-void
-set_port_number(struct addrinfo *res, unsigned short port)
-{
- switch(res->ai_family) {
- case AF_INET: {
- struct sockaddr_in *foo = (struct sockaddr_in *)res->ai_addr;
- foo->sin_port = htons(port);
- break;
- }
-#if defined(AF_INET6)
- case AF_INET6: {
- struct sockaddr_in6 *foo = (struct sockaddr_in6 *)res->ai_addr;
- foo->sin6_port = htons(port);
- break;
- }
-#endif
- default:
- fprintf(where,
- "Unexpected Address Family of %u\n",res->ai_family);
- fflush(where);
- exit(-1);
- }
-}
-
-
-
- /* This routine will create a data (listen) socket with the
- apropriate options set and return it to the caller. this replaces
- all the duplicate code in each of the test routines and should help
- make things a little easier to understand. since this routine can be
- called by either the netperf or netserver programs, all output
- should be directed towards "where." family is generally AF_INET and
- type will be either SOCK_STREAM or SOCK_DGRAM. This routine will
- also be used by the "SCTP" tests, hence the slightly strange-looking
- SCTP stuff in the classic bsd sockets test file... vlad/raj
- 2005-03-15 */
-
-SOCKET
-create_data_socket(struct addrinfo *res)
-{
-
- SOCKET temp_socket;
- int one;
- int on = 1;
-
-
- /*set up the data socket */
- temp_socket = socket(res->ai_family,
- res->ai_socktype,
- res->ai_protocol);
-
- if (temp_socket == INVALID_SOCKET){
- fprintf(where,
- "netperf: create_data_socket: socket: errno %d fam %s type %s prot %s errmsg %s\n",
- errno,
- inet_ftos(res->ai_family),
- inet_ttos(res->ai_socktype),
- inet_ptos(res->ai_protocol),
- strerror(errno));
- fflush(where);
- exit(1);
- }
-
- if (debug) {
- fprintf(where,"create_data_socket: socket %d obtained...\n",temp_socket);
- fflush(where);
- }
-
- /* Modify the local socket size. The reason we alter the send buffer
- size here rather than when the connection is made is to take care
- of decreases in buffer size. Decreasing the window size after
- connection establishment is a TCP no-no. Also, by setting the
- buffer (window) size before the connection is established, we can
- control the TCP MSS (segment size). The MSS is never (well, should
- never be) more that 1/2 the minimum receive buffer size at each
- half of the connection. This is why we are altering the receive
- buffer size on the sending size of a unidirectional transfer. If
- the user has not requested that the socket buffers be altered, we
- will try to find-out what their values are. If we cannot touch the
- socket buffer in any way, we will set the values to -1 to indicate
- that. */
-
- /* all the oogy nitty gritty stuff moved from here into the routine
- being called below, per patches from davidm to workaround the bug
- in Linux getsockopt(). raj 2004-06-15 */
- set_sock_buffer (temp_socket, SEND_BUFFER, lss_size_req, &lss_size);
- set_sock_buffer (temp_socket, RECV_BUFFER, lsr_size_req, &lsr_size);
-
- /* now, we may wish to enable the copy avoidance features on the */
- /* local system. of course, this may not be possible... */
-
-#ifdef SO_RCV_COPYAVOID
- if (loc_rcvavoid) {
- if (setsockopt(temp_socket,
- SOL_SOCKET,
- SO_RCV_COPYAVOID,
- (const char *)&loc_rcvavoid,
- sizeof(int)) == SOCKET_ERROR) {
- fprintf(where,
- "netperf: create_data_socket: Could not enable receive copy avoidance");
- fflush(where);
- loc_rcvavoid = 0;
- }
- }
-#else
- /* it wasn't compiled in... */
- loc_rcvavoid = 0;
-#endif /* SO_RCV_COPYAVOID */
-
-#ifdef SO_SND_COPYAVOID
- if (loc_sndavoid) {
- if (setsockopt(temp_socket,
- SOL_SOCKET,
- SO_SND_COPYAVOID,
- (const char *)&loc_sndavoid,
- sizeof(int)) == SOCKET_ERROR) {
- fprintf(where,
- "netperf: create_data_socket: Could not enable send copy avoidance");
- fflush(where);
- loc_sndavoid = 0;
- }
- }
-#else
- /* it was not compiled in... */
- loc_sndavoid = 0;
-#endif
-
- /* Now, we will see about setting the TCP_NODELAY flag on the local */
- /* socket. We will only do this for those systems that actually */
- /* support the option. If it fails, note the fact, but keep going. */
- /* If the user tries to enable TCP_NODELAY on a UDP socket, this */
- /* will cause an error to be displayed */
-
- /* well..... long ago and far away that would have happened, in
- particular because we would always use IPPROTO_TCP here.
- however, now we are using res->ai_protocol, which will be
- IPPROT_UDP, and while HP-UX, and I suspect no-one else on the
- planet has a UDP_mumble option that overlaps with TCP_NODELAY,
- sure as knuth made little green programs, linux has a UDP_CORK
- option that is defined as a value of 1, which is the same a
- TCP_NODELAY under Linux. So, when asking for -D and
- "TCP_NODELAY" under Linux, we are actually setting UDP_CORK
- instead of getting an error like every other OS on the
- planet. joy and rupture. this stops a UDP_RR test cold sooo we
- have to make sure that res->ai_protocol actually makes sense for
- a _NODELAY setsockopt() or a UDP_RR test on Linux where someone
- mistakenly sets -D will hang. raj 2005-04-21 */
-
-#if defined(TCP_NODELAY) || defined(SCTP_NODELAY)
- if ((loc_nodelay) && (res->ai_protocol != IPPROTO_UDP)) {
-
- /* strictly speaking, since the if defined above is an OR, we
- should probably check against TCP_NODELAY being defined here.
- however, the likelihood of SCTP_NODELAY being defined and
- TCP_NODELAY _NOT_ being defined is, probably :), epsilon. raj
- 2005-03-15 */
-
- int option = TCP_NODELAY;
-
- /* I suspect that WANT_SCTP would suffice here since that is the
- only time we would have called getaddrinfo with a hints asking
- for SCTP, but just in case there is an SCTP implementation out
- there _without_ SCTP_NODELAY... raj 2005-03-15 */
-
-#if defined(WANT_SCTP) && defined(SCTP_NODELAY)
- if (IPPROTO_SCTP == res->ai_protocol) {
- option = SCTP_NODELAY;
- }
-#endif
-
- one = 1;
- if(setsockopt(temp_socket,
- res->ai_protocol,
- option,
- (char *)&one,
- sizeof(one)) == SOCKET_ERROR) {
- fprintf(where,
- "netperf: create_data_socket: nodelay: errno %d\n",
- errno);
- fflush(where);
- }
-
- if (debug > 1) {
- fprintf(where,
- "netperf: create_data_socket: [TCP|SCTP]_NODELAY requested...\n");
- fflush(where);
- }
- }
-#else /* TCP_NODELAY */
-
- loc_nodelay = 0;
-
-#endif /* TCP_NODELAY */
-
-#if defined(TCP_CORK)
-
- if (loc_tcpcork != 0) {
- /* the user wishes for us to set TCP_CORK on the socket */
- int one = 1;
- if (setsockopt(temp_socket,
- getprotobyname("tcp")->p_proto,
- TCP_CORK,
- (char *)&one,
- sizeof(one)) == SOCKET_ERROR) {
- perror("netperf: sendfile_tcp_stream: tcp_cork");
- exit(1);
- }
- if (debug) {
- fprintf(where,"sendfile_tcp_stream: tcp_cork...\n");
- }
- }
-
-#endif /* TCP_CORK */
-
- /* since some of the UDP tests do not do anything to cause an
- implicit bind() call, we need to be rather explicit about our
- bind() call here. even if the address and/or the port are zero
- (INADDR_ANY etc). raj 2004-07-20 */
-
- if (setsockopt(temp_socket,
- SOL_SOCKET,
- SO_REUSEADDR,
- (const char *)&on,
- sizeof(on)) < 0) {
- fprintf(where,
- "netperf: create_data_socket: SO_REUSEADDR failed %d\n",
- errno);
- fflush(where);
- }
-
- if (bind(temp_socket,
- res->ai_addr,
- res->ai_addrlen) < 0) {
- if (debug) {
- fprintf(where,
- "netperf: create_data_socket: data socket bind failed errno %d\n",
- errno);
- fprintf(where," port: %d\n",get_port_number(res));
- fflush(where);
- }
- }
-
-
- return(temp_socket);
-
-}
-
-#ifdef KLUDGE_SOCKET_OPTIONS
-
-
- /* This routine is for those BROKEN systems which do not correctly */
- /* pass socket attributes through calls such as accept(). It should */
- /* only be called for those broken systems. I *really* don't want to */
- /* have this, but even broken systems must be measured. raj 11/95 */
-void
-kludge_socket_options(int temp_socket)
-{
-
- set_sock_buffer(temp_socket, SEND_BUFFER, lss_size_req, &lss_size);
- set_sock_buffer(temp_socket, RECV_BUFFER, lsr_size_req, &lsr_size);
-
- /* now, we may wish to enable the copy avoidance features on the */
- /* local system. of course, this may not be possible... */
- /* those calls were only valid for HP-UX, and I know that HP-UX is */
- /* written correctly, and so we do not need to include those calls */
- /* in this kludgy routine. raj 11/95 */
-
-
- /* Now, we will see about setting the TCP_NODELAY flag on the local */
- /* socket. We will only do this for those systems that actually */
- /* support the option. If it fails, note the fact, but keep going. */
- /* If the user tries to enable TCP_NODELAY on a UDP socket, this */
- /* will cause an error to be displayed */
-
-#ifdef TCP_NODELAY
- if (loc_nodelay) {
- one = 1;
- if(setsockopt(temp_socket,
- getprotobyname("tcp")->p_proto,
- TCP_NODELAY,
- (char *)&one,
- sizeof(one)) == SOCKET_ERROR) {
- fprintf(where,"netperf: kludge_socket_options: nodelay: errno %d\n",
- errno);
- fflush(where);
- }
-
- if (debug > 1) {
- fprintf(where,
- "netperf: kludge_socket_options: TCP_NODELAY requested...\n");
- fflush(where);
- }
- }
-#else /* TCP_NODELAY */
-
- loc_nodelay = 0;
-
-#endif /* TCP_NODELAY */
-
- }
-
-#endif /* KLUDGE_SOCKET_OPTIONS */
-
-
-static void *
-get_address_address(struct addrinfo *info)
-{
- struct sockaddr_in *sin;
-#if defined(AF_INET6)
- struct sockaddr_in6 *sin6;
-#endif
-
- switch(info->ai_family) {
- case AF_INET:
- sin = (struct sockaddr_in *)info->ai_addr;
- return(&(sin->sin_addr));
- break;
-#if defined(AF_INET6)
- case AF_INET6:
- sin6 = (struct sockaddr_in6 *)info->ai_addr;
- return(&(sin6->sin6_addr));
- break;
-#endif
- default:
- fprintf(stderr,"we never expected to get here in get_address_address\n");
- fflush(stderr);
- exit(-1);
- }
-}
-
-#if defined(WIN32)
-/* +*+ Why isn't this in the winsock headers yet? */
-const char *
-inet_ntop(int af, const void *src, char *dst, size_t size);
-#endif
-
-/* This routine is a generic test header printer for the topmost header */
-void
-print_top_test_header(char test_name[], struct addrinfo *source, struct addrinfo *destination)
-{
-
-#if defined(AF_INET6)
- char address_buf[INET6_ADDRSTRLEN];
-#else
- char address_buf[16]; /* magic constant */
-#endif
-
- /* we want to have some additional, interesting information in */
- /* the headers. we know some of it here, but not all, so we will */
- /* only print the test title here and will print the results */
- /* titles after the test is finished */
- fprintf(where,test_name);
- address_buf[0] = '\0';
- inet_ntop(source->ai_family,get_address_address(source),address_buf,sizeof(address_buf));
- fprintf(where,
- " from %s (%s) port %u %s",
- source->ai_canonname,
- address_buf,
- get_port_number(source),
- inet_ftos(source->ai_family));
- address_buf[0] = '\0';
- inet_ntop(destination->ai_family,get_address_address(destination),address_buf,sizeof(address_buf));
- fprintf(where,
- " to %s (%s) port %u %s",
- destination->ai_canonname,
- address_buf,
- get_port_number(destination),
- inet_ftos(destination->ai_family));
-
- if (iteration_max > 1) {
- fprintf(where,
- " : +/-%3.1f%% @ %2d%% conf. %s",
- interval/0.02,
- confidence_level,
- result_confidence_only ? " on result only" : "");
- }
- if ((loc_nodelay > 0) || (rem_nodelay > 0)) {
- fprintf(where," : nodelay");
- }
- if ((loc_sndavoid > 0) ||
- (loc_rcvavoid > 0) ||
- (rem_sndavoid > 0) ||
- (rem_rcvavoid > 0)) {
- fprintf(where," : copy avoidance");
- }
-
- if (no_control) {
- fprintf(where," : no control");
- }
-
-#ifdef WANT_HISTOGRAM
- fprintf(where," : histogram");
-#endif /* WANT_HISTOGRAM */
-
-#ifdef WANT_INTERVALS
-#ifndef WANT_SPIN
- fprintf(where," : interval");
-#else
- fprintf(where," : spin interval");
-#endif
-#endif /* WANT_INTERVALS */
-
-#ifdef DIRTY
- fprintf(where," : dirty data");
-#endif /* DIRTY */
-#ifdef WANT_DEMO
- fprintf(where," : demo");
-#endif
-#ifdef WANT_FIRST_BURST
- /* a little hokey perhaps, but we really only want this to be
- emitted for tests where it actually is used, which means a
- "REQUEST/RESPONSE" test. raj 2005-11-10 */
- if (strstr(test_name,"REQUEST/RESPONSE")) {
- fprintf(where," : first burst %d",first_burst_size);
- }
-#endif
- if (cpu_binding_requested) {
- fprintf(where," : cpu bind");
- }
- fprintf(where,"\n");
-
-}
-
-
-/* This routine implements the TCP unidirectional data transfer test */
-/* (a.k.a. stream) for the sockets interface. It receives its */
-/* parameters via global variables from the shell and writes its */
-/* output to the standard output. */
-
-
-void
-send_tcp_stream(char remote_host[])
-{
-
- char *tput_title = "\
-Recv Send Send \n\
-Socket Socket Message Elapsed \n\
-Size Size Size Time Throughput \n\
-bytes bytes bytes secs. %s/sec \n\n";
-
- char *tput_fmt_0 =
- "%7.2f %s\n";
-
- char *tput_fmt_1 =
- "%6d %6d %6d %-6.2f %7.2f %s\n";
-
- char *cpu_title = "\
-Recv Send Send Utilization Service Demand\n\
-Socket Socket Message Elapsed Send Recv Send Recv\n\
-Size Size Size Time Throughput local remote local remote\n\
-bytes bytes bytes secs. %-8.8s/s %% %c %% %c us/KB us/KB\n\n";
-
- char *cpu_fmt_0 =
- "%6.3f %c %s\n";
-
- char *cpu_fmt_1 =
- "%6d %6d %6d %-6.2f %7.2f %-6.2f %-6.2f %-6.3f %-6.3f %s\n";
-
- char *ksink_fmt = "\n\
-Alignment Offset %-8.8s %-8.8s Sends %-8.8s Recvs\n\
-Local Remote Local Remote Xfered Per Per\n\
-Send Recv Send Recv Send (avg) Recv (avg)\n\
-%5d %5d %5d %5d %6.4g %6.2f %6d %6.2f %6d\n";
-
- char *ksink_fmt2 = "\n\
-Maximum\n\
-Segment\n\
-Size (bytes)\n\
-%6d\n";
-
-
- float elapsed_time;
-
- /* what we want is to have a buffer space that is at least one */
- /* send-size greater than our send window. this will insure that we */
- /* are never trying to re-use a buffer that may still be in the hands */
- /* of the transport. This buffer will be malloc'd after we have found */
- /* the size of the local senc socket buffer. We will want to deal */
- /* with alignment and offset concerns as well. */
-
- struct ring_elt *send_ring;
-
- int len;
- unsigned int nummessages = 0;
- SOCKET send_socket;
- int bytes_remaining;
- int tcp_mss = -1; /* possibly uninitialized on printf far below */
-
- /* with links like fddi, one can send > 32 bits worth of bytes */
- /* during a test... ;-) at some point, this should probably become a */
- /* 64bit integral type, but those are not entirely common yet */
-
- unsigned long long local_bytes_sent = 0;
- double bytes_sent = 0.0;
-
- float local_cpu_utilization;
- float local_service_demand;
- float remote_cpu_utilization;
- float remote_service_demand;
-
- double thruput;
-
- struct addrinfo *remote_res;
- struct addrinfo *local_res;
-
- struct tcp_stream_request_struct *tcp_stream_request;
- struct tcp_stream_response_struct *tcp_stream_response;
- struct tcp_stream_results_struct *tcp_stream_result;
-
- tcp_stream_request =
- (struct tcp_stream_request_struct *)netperf_request.content.test_specific_data;
- tcp_stream_response =
- (struct tcp_stream_response_struct *)netperf_response.content.test_specific_data;
- tcp_stream_result =
- (struct tcp_stream_results_struct *)netperf_response.content.test_specific_data;
-
-#ifdef WANT_HISTOGRAM
- if (verbosity > 1) {
- time_hist = HIST_new();
- }
-#endif /* WANT_HISTOGRAM */
- /* since we are now disconnected from the code that established the */
- /* control socket, and since we want to be able to use different */
- /* protocols and such, we are passed the name of the remote host and */
- /* must turn that into the test specific addressing information. */
-
- /* complete_addrinfos will either succede or exit the process */
- complete_addrinfos(&remote_res,
- &local_res,
- remote_host,
- SOCK_STREAM,
- IPPROTO_TCP,
- 0);
-
- if ( print_headers ) {
- print_top_test_header("TCP STREAM TEST",local_res,remote_res);
- }
-
- send_ring = NULL;
- confidence_iteration = 1;
- init_stat();
-
- /* we have a great-big while loop which controls the number of times */
- /* we run a particular test. this is for the calculation of a */
- /* confidence interval (I really should have stayed awake during */
- /* probstats :). If the user did not request confidence measurement */
- /* (no confidence is the default) then we will only go though the */
- /* loop once. the confidence stuff originates from the folks at IBM */
-
- while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
- (confidence_iteration <= iteration_min)) {
-
- /* initialize a few counters. we have to remember that we might be */
- /* going through the loop more than once. */
-
- nummessages = 0;
- bytes_sent = 0.0;
- times_up = 0;
-
- /*set up the data socket */
- send_socket = create_data_socket(local_res);
-
- if (send_socket == INVALID_SOCKET){
- perror("netperf: send_tcp_stream: tcp stream data socket");
- exit(1);
- }
-
- if (debug) {
- fprintf(where,"send_tcp_stream: send_socket obtained...\n");
- }
-
- /* at this point, we have either retrieved the socket buffer sizes, */
- /* or have tried to set them, so now, we may want to set the send */
- /* size based on that (because the user either did not use a -m */
- /* option, or used one with an argument of 0). If the socket buffer */
- /* size is not available, we will set the send size to 4KB - no */
- /* particular reason, just arbitrary... */
- if (send_size == 0) {
- if (lss_size > 0) {
- send_size = lss_size;
- }
- else {
- send_size = 4096;
- }
- }
-
- /* set-up the data buffer ring with the requested alignment and offset. */
- /* note also that we have allocated a quantity */
- /* of memory that is at least one send-size greater than our socket */
- /* buffer size. We want to be sure that there are at least two */
- /* buffers allocated - this can be a bit of a problem when the */
- /* send_size is bigger than the socket size, so we must check... the */
- /* user may have wanted to explicitly set the "width" of our send */
- /* buffers, we should respect that wish... */
- if (send_width == 0) {
- send_width = (lss_size/send_size) + 1;
- if (send_width == 1) send_width++;
- }
-
- if (send_ring == NULL) {
- /* only allocate the send ring once. this is a networking test, */
- /* not a memory allocation test. this way, we do not need a */
- /* deallocate_buffer_ring() routine, and I don't feel like */
- /* writing one anyway :) raj 11/94 */
- send_ring = allocate_buffer_ring(send_width,
- send_size,
- local_send_align,
- local_send_offset);
- }
-
- /* If the user has requested cpu utilization measurements, we must */
- /* calibrate the cpu(s). We will perform this task within the tests */
- /* themselves. If the user has specified the cpu rate, then */
- /* calibrate_local_cpu will return rather quickly as it will have */
- /* nothing to do. If local_cpu_rate is zero, then we will go through */
- /* all the "normal" calibration stuff and return the rate back. */
-
- if (local_cpu_usage) {
- local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
- }
-
- if (!no_control) {
- /* Tell the remote end to do a listen. The server alters the
- socket paramters on the other side at this point, hence the
- reason for all the values being passed in the setup
- message. If the user did not specify any of the parameters,
- they will be passed as 0, which will indicate to the remote
- that no changes beyond the system's default should be
- used. Alignment is the exception, it will default to 1, which
- will be no alignment alterations. */
-
- netperf_request.content.request_type = DO_TCP_STREAM;
- tcp_stream_request->send_buf_size = rss_size_req;
- tcp_stream_request->recv_buf_size = rsr_size_req;
- tcp_stream_request->receive_size = recv_size;
- tcp_stream_request->no_delay = rem_nodelay;
- tcp_stream_request->recv_alignment = remote_recv_align;
- tcp_stream_request->recv_offset = remote_recv_offset;
- tcp_stream_request->measure_cpu = remote_cpu_usage;
- tcp_stream_request->cpu_rate = remote_cpu_rate;
- if (test_time) {
- tcp_stream_request->test_length = test_time;
- }
- else {
- tcp_stream_request->test_length = test_bytes;
- }
- tcp_stream_request->so_rcvavoid = rem_rcvavoid;
- tcp_stream_request->so_sndavoid = rem_sndavoid;
-#ifdef DIRTY
- tcp_stream_request->dirty_count = rem_dirty_count;
- tcp_stream_request->clean_count = rem_clean_count;
-#endif /* DIRTY */
- tcp_stream_request->port = atoi(remote_data_port);
- tcp_stream_request->ipfamily = af_to_nf(remote_res->ai_family);
- if (debug > 1) {
- fprintf(where,
- "netperf: send_tcp_stream: requesting TCP stream test\n");
- }
-
- send_request();
-
- /* The response from the remote will contain all of the relevant
- socket parameters for this test type. We will put them back
- into the variables here so they can be displayed if desired.
- The remote will have calibrated CPU if necessary, and will
- have done all the needed set-up we will have calibrated the
- cpu locally before sending the request, and will grab the
- counter value right after the connect returns. The remote
- will grab the counter right after the accept call. This saves
- the hassle of extra messages being sent for the TCP
- tests. */
-
- recv_response();
-
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote listen done.\n");
- rsr_size = tcp_stream_response->recv_buf_size;
- rss_size = tcp_stream_response->send_buf_size;
- rem_nodelay = tcp_stream_response->no_delay;
- remote_cpu_usage= tcp_stream_response->measure_cpu;
- remote_cpu_rate = tcp_stream_response->cpu_rate;
-
- /* we have to make sure that the server port number is in
- network order */
- set_port_number(remote_res,
- (short)tcp_stream_response->data_port_number);
-
- rem_rcvavoid = tcp_stream_response->so_rcvavoid;
- rem_sndavoid = tcp_stream_response->so_sndavoid;
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- fprintf(where,
- "netperf: remote error %d",
- netperf_response.content.serv_errno);
- perror("");
- fflush(where);
-
- exit(1);
- }
- }
-
-#ifdef WANT_DEMO
- DEMO_STREAM_SETUP(lss_size,rsr_size)
-#endif
-
- /*Connect up to the remote port on the data socket */
- if (connect(send_socket,
- remote_res->ai_addr,
- remote_res->ai_addrlen) == INVALID_SOCKET){
- perror("netperf: send_tcp_stream: data socket connect failed");
- exit(1);
- }
-
- /* Data Socket set-up is finished. If there were problems, either */
- /* the connect would have failed, or the previous response would */
- /* have indicated a problem. I failed to see the value of the */
- /* extra message after the accept on the remote. If it failed, */
- /* we'll see it here. If it didn't, we might as well start pumping */
- /* data. */
-
- /* Set-up the test end conditions. For a stream test, they can be */
- /* either time or byte-count based. */
-
- if (test_time) {
- /* The user wanted to end the test after a period of time. */
- times_up = 0;
- bytes_remaining = 0;
- /* in previous revisions, we had the same code repeated throught */
- /* all the test suites. this was unnecessary, and meant more */
- /* work for me when I wanted to switch to POSIX signals, so I */
- /* have abstracted this out into a routine in netlib.c. if you */
- /* are experiencing signal problems, you might want to look */
- /* there. raj 11/94 */
- start_timer(test_time);
- }
- else {
- /* The tester wanted to send a number of bytes. */
- bytes_remaining = test_bytes;
- times_up = 1;
- }
-
- /* The cpu_start routine will grab the current time and possibly */
- /* value of the idle counter for later use in measuring cpu */
- /* utilization and/or service demand and thruput. */
-
- cpu_start(local_cpu_usage);
-
- /* we only start the interval timer if we are using the
- timer-timed intervals rather than the sit and spin ones. raj
- 2006-02-06 */
-#if defined(WANT_INTERVALS)
- INTERVALS_INIT();
-#endif /* WANT_INTERVALS */
-
- /* before we start, initialize a few variables */
-
-#ifdef WANT_DEMO
- if (demo_mode) {
- HIST_timestamp(demo_one_ptr);
- }
-#endif
-
-
- /* We use an "OR" to control test execution. When the test is */
- /* controlled by time, the byte count check will always return false. */
- /* When the test is controlled by byte count, the time test will */
- /* always return false. When the test is finished, the whole */
- /* expression will go false and we will stop sending data. */
-
- while ((!times_up) || (bytes_remaining > 0)) {
-
-#ifdef DIRTY
- access_buffer(send_ring->buffer_ptr,
- send_size,
- loc_dirty_count,
- loc_clean_count);
-#endif /* DIRTY */
-
-#ifdef WANT_HISTOGRAM
- if (verbosity > 1) {
- /* timestamp just before we go into send and then again just
- after we come out raj 8/94 */
- /* but lets only do this if there is going to be a histogram
- displayed */
- HIST_timestamp(&time_one);
- }
-#endif /* WANT_HISTOGRAM */
-
- if((len=send(send_socket,
- send_ring->buffer_ptr,
- send_size,
- 0)) != send_size) {
- if ((len >=0) || SOCKET_EINTR(len)) {
- /* the test was interrupted, must be the end of test */
- break;
- }
- perror("netperf: data send error");
- printf("len was %d\n",len);
- exit(1);
- }
-
- local_bytes_sent += send_size;
-
-#ifdef WANT_HISTOGRAM
- if (verbosity > 1) {
- /* timestamp the exit from the send call and update the histogram */
- HIST_timestamp(&time_two);
- HIST_add(time_hist,delta_micro(&time_one,&time_two));
- }
-#endif /* WANT_HISTOGRAM */
-
-#ifdef WANT_DEMO
- DEMO_STREAM_INTERVAL(send_size)
-#endif
-
-#if defined(WANT_INTERVALS)
- INTERVALS_WAIT();
-#endif /* WANT_INTERVALS */
-
- /* now we want to move our pointer to the next position in the */
- /* data buffer...we may also want to wrap back to the "beginning" */
- /* of the bufferspace, so we will mod the number of messages sent */
- /* by the send width, and use that to calculate the offset to add */
- /* to the base pointer. */
- nummessages++;
- send_ring = send_ring->next;
- if (bytes_remaining) {
- bytes_remaining -= send_size;
- }
- }
-
- /* The test is over. Flush the buffers to the remote end. We do a */
- /* graceful release to insure that all data has been taken by the */
- /* remote. */
-
- /* but first, if the verbosity is greater than 1, find-out what */
- /* the TCP maximum segment_size was (if possible) */
- if (verbosity > 1) {
- tcp_mss = -1;
- get_tcp_info(send_socket,&tcp_mss);
- }
-
- if (shutdown(send_socket,SHUT_WR) == SOCKET_ERROR) {
- perror("netperf: cannot shutdown tcp stream socket");
- exit(1);
- }
-
- /* hang a recv() off the socket to block until the remote has */
- /* brought all the data up into the application. it will do a */
- /* shutdown to cause a FIN to be sent our way. We will assume that */
- /* any exit from the recv() call is good... raj 4/93 */
-
- recv(send_socket, send_ring->buffer_ptr, send_size, 0);
-
- /* this call will always give us the elapsed time for the test, and */
- /* will also store-away the necessaries for cpu utilization */
-
- cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */
- /* measured and how */
- /* long did we really */
- /* run? */
-
- /* we are finished with the socket, so close it to prevent hitting */
- /* the limit on maximum open files. */
-
- close(send_socket);
-
- if (!no_control) {
- /* Get the statistics from the remote end. The remote will have
- calculated service demand and all those interesting
- things. If it wasn't supposed to care, it will return obvious
- values. */
-
- recv_response();
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote results obtained\n");
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- fprintf(where,
- "netperf: remote error %d",
- netperf_response.content.serv_errno);
- perror("");
- fflush(where);
-
- exit(1);
- }
-
- /* We now calculate what our thruput was for the test. In the
- future, we may want to include a calculation of the thruput
- measured by the remote, but it should be the case that for a
- TCP stream test, that the two numbers should be *very*
- close... We calculate bytes_sent regardless of the way the
- test length was controlled. If it was time, we needed to,
- and if it was by bytes, the user may have specified a number
- of bytes that wasn't a multiple of the send_size, so we
- really didn't send what he asked for ;-) */
-
- bytes_sent = ntohd(tcp_stream_result->bytes_received);
- }
- else {
- bytes_sent = (double)local_bytes_sent;
- }
-
- thruput = calc_thruput(bytes_sent);
-
- if (local_cpu_usage || remote_cpu_usage) {
- /* We must now do a little math for service demand and cpu */
- /* utilization for the system(s) */
- /* Of course, some of the information might be bogus because */
- /* there was no idle counter in the kernel(s). We need to make */
- /* a note of this for the user's benefit...*/
- if (local_cpu_usage) {
-
- local_cpu_utilization = calc_cpu_util(0.0);
- local_service_demand = calc_service_demand(bytes_sent,
- 0.0,
- 0.0,
- 0);
- }
- else {
- local_cpu_utilization = (float) -1.0;
- local_service_demand = (float) -1.0;
- }
-
- if (remote_cpu_usage) {
-
- remote_cpu_utilization = tcp_stream_result->cpu_util;
- remote_service_demand = calc_service_demand(bytes_sent,
- 0.0,
- remote_cpu_utilization,
- tcp_stream_result->num_cpus);
- }
- else {
- remote_cpu_utilization = (float) -1.0;
- remote_service_demand = (float) -1.0;
- }
- }
- else {
- /* we were not measuring cpu, for the confidence stuff, we */
- /* should make it -1.0 */
- local_cpu_utilization = (float) -1.0;
- local_service_demand = (float) -1.0;
- remote_cpu_utilization = (float) -1.0;
- remote_service_demand = (float) -1.0;
- }
-
- /* at this point, we want to calculate the confidence information. */
- /* if debugging is on, calculate_confidence will print-out the */
- /* parameters we pass it */
-
- calculate_confidence(confidence_iteration,
- elapsed_time,
- thruput,
- local_cpu_utilization,
- remote_cpu_utilization,
- local_service_demand,
- remote_service_demand);
-
-
- confidence_iteration++;
- }
-
- /* at this point, we have finished making all the runs that we */
- /* will be making. so, we should extract what the calcuated values */
- /* are for all the confidence stuff. we could make the values */
- /* global, but that seemed a little messy, and it did not seem worth */
- /* all the mucking with header files. so, we create a routine much */
- /* like calcualte_confidence, which just returns the mean values. */
- /* raj 11/94 */
-
- retrieve_confident_values(&elapsed_time,
- &thruput,
- &local_cpu_utilization,
- &remote_cpu_utilization,
- &local_service_demand,
- &remote_service_demand);
-
- /* We are now ready to print all the information. If the user */
- /* has specified zero-level verbosity, we will just print the */
- /* local service demand, or the remote service demand. If the */
- /* user has requested verbosity level 1, he will get the basic */
- /* "streamperf" numbers. If the user has specified a verbosity */
- /* of greater than 1, we will display a veritable plethora of */
- /* background information from outside of this block as it it */
- /* not cpu_measurement specific... */
-
- if (confidence < 0) {
- /* we did not hit confidence, but were we asked to look for it? */
- if (iteration_max > 1) {
- display_confidence();
- }
- }
-
- if (local_cpu_usage || remote_cpu_usage) {
- local_cpu_method = format_cpu_method(cpu_method);
- remote_cpu_method = format_cpu_method(tcp_stream_result->cpu_method);
-
- switch (verbosity) {
- case 0:
- if (local_cpu_usage) {
- fprintf(where,
- cpu_fmt_0,
- local_service_demand,
- local_cpu_method,
- ((print_headers) ||
- (result_brand == NULL)) ? "" : result_brand);
- }
- else {
- fprintf(where,
- cpu_fmt_0,
- remote_service_demand,
- remote_cpu_method,
- ((print_headers) ||
- (result_brand == NULL)) ? "" : result_brand);
- }
- break;
- case 1:
- case 2:
- if (print_headers) {
- fprintf(where,
- cpu_title,
- format_units(),
- local_cpu_method,
- remote_cpu_method);
- }
-
- fprintf(where,
- cpu_fmt_1, /* the format string */
- rsr_size, /* remote recvbuf size */
- lss_size, /* local sendbuf size */
- send_size, /* how large were the sends */
- elapsed_time, /* how long was the test */
- thruput, /* what was the xfer rate */
- local_cpu_utilization, /* local cpu */
- remote_cpu_utilization, /* remote cpu */
- local_service_demand, /* local service demand */
- remote_service_demand, /* remote service demand */
- ((print_headers) ||
- (result_brand == NULL)) ? "" : result_brand);
- break;
- }
- }
- else {
- /* The tester did not wish to measure service demand. */
-
- switch (verbosity) {
- case 0:
- fprintf(where,
- tput_fmt_0,
- thruput,
- ((print_headers) ||
- (result_brand == NULL)) ? "" : result_brand);
- break;
- case 1:
- case 2:
- if (print_headers) {
- fprintf(where,tput_title,format_units());
- }
- fprintf(where,
- tput_fmt_1, /* the format string */
- rsr_size, /* remote recvbuf size */
- lss_size, /* local sendbuf size */
- send_size, /* how large were the sends */
- elapsed_time, /* how long did it take */
- thruput, /* how fast did it go */
- ((print_headers) ||
- (result_brand == NULL)) ? "" : result_brand);
- break;
- }
- }
-
- /* it would be a good thing to include information about some of the */
- /* other parameters that may have been set for this test, but at the */
- /* moment, I do not wish to figure-out all the formatting, so I will */
- /* just put this comment here to help remind me that it is something */
- /* that should be done at a later time. */
-
- if (verbosity > 1) {
- /* The user wanted to know it all, so we will give it to him. */
- /* This information will include as much as we can find about */
- /* TCP statistics, the alignments of the sends and receives */
- /* and all that sort of rot... */
-
- /* this stuff needs to be worked-out in the presence of confidence */
- /* intervals and multiple iterations of the test... raj 11/94 */
-
- fprintf(where,
- ksink_fmt,
- "Bytes",
- "Bytes",
- "Bytes",
- local_send_align,
- remote_recv_align,
- local_send_offset,
- remote_recv_offset,
- bytes_sent,
- bytes_sent / (double)nummessages,
- nummessages,
- bytes_sent / (double)tcp_stream_result->recv_calls,
- tcp_stream_result->recv_calls);
- fprintf(where,
- ksink_fmt2,
- tcp_mss);
- fflush(where);
-#ifdef WANT_HISTOGRAM
- fprintf(where,"\n\nHistogram of time spent in send() call.\n");
- fflush(where);
- HIST_report(time_hist);
-#endif /* WANT_HISTOGRAM */
- }
-
-}
-
-
-
-/* This routine implements the netperf-side TCP unidirectional data
- transfer test (a.k.a. stream) for the sockets interface where the
- data flow is from the netserver to the netperf. It receives its
- parameters via global variables from the shell and writes its
- output to the standard output. */
-
-
-void
-send_tcp_maerts(char remote_host[])
-{
-
- char *tput_title = "\
-Recv Send Send \n\
-Socket Socket Message Elapsed \n\
-Size Size Size Time Throughput \n\
-bytes bytes bytes secs. %s/sec \n\n";
-
- char *tput_fmt_0 =
- "%7.2f %s\n";
-
- char *tput_fmt_1 =
- "%6d %6d %6d %-6.2f %7.2f %s \n";
-
- char *cpu_title = "\
-Recv Send Send Utilization Service Demand\n\
-Socket Socket Message Elapsed Send Recv Send Recv\n\
-Size Size Size Time Throughput local remote local remote\n\
-bytes bytes bytes secs. %-8.8s/s %% %c %% %c us/KB us/KB\n\n";
-
- char *cpu_fmt_0 =
- "%6.3f %c %s\n";
-
- char *cpu_fmt_1 =
- "%6d %6d %6d %-6.2f %7.2f %-6.2f %-6.2f %-6.3f %-6.3f %s\n";
-
- char *ksink_fmt = "\n\
-Alignment Offset %-8.8s %-8.8s Recvs %-8.8s Sends\n\
-Local Remote Local Remote Xfered Per Per\n\
-Recv Send Recv Send Recv (avg) Send (avg)\n\
-%5d %5d %5d %5d %6.4g %6.2f %6d %6.2f %6d\n";
-
- char *ksink_fmt2 = "\n\
-Maximum\n\
-Segment\n\
-Size (bytes)\n\
-%6d\n";
-
-
- float elapsed_time;
-
- /* what we want is to have a buffer space that is at least one */
- /* recv-size greater than our recv window. this will insure that we */
- /* are never trying to re-use a buffer that may still be in the hands */
- /* of the transport. This buffer will be malloc'd after we have found */
- /* the size of the local senc socket buffer. We will want to deal */
- /* with alignment and offset concerns as well. */
-
- struct ring_elt *recv_ring;
-
- int len;
- unsigned int nummessages = 0;
- SOCKET recv_socket;
- int bytes_remaining;
- int tcp_mss = -1; /* possibly uninitialized on printf far below */
-
- /* with links like fddi, one can recv > 32 bits worth of bytes */
- /* during a test... ;-) at some point, this should probably become a */
- /* 64bit integral type, but those are not entirely common yet */
- double bytes_sent = 0.0;
- unsigned long long local_bytes_recvd = 0;
-
- float local_cpu_utilization;
- float local_service_demand;
- float remote_cpu_utilization;
- float remote_service_demand;
-
- double thruput;
-
- struct addrinfo *remote_res;
- struct addrinfo *local_res;
-
- struct tcp_maerts_request_struct *tcp_maerts_request;
- struct tcp_maerts_response_struct *tcp_maerts_response;
- struct tcp_maerts_results_struct *tcp_maerts_result;
-
- tcp_maerts_request =
- (struct tcp_maerts_request_struct *)netperf_request.content.test_specific_data;
- tcp_maerts_response =
- (struct tcp_maerts_response_struct *)netperf_response.content.test_specific_data;
- tcp_maerts_result =
- (struct tcp_maerts_results_struct *)netperf_response.content.test_specific_data;
-
-#ifdef WANT_HISTOGRAM
- if (verbosity > 1) {
- time_hist = HIST_new();
- }
-#endif /* WANT_HISTOGRAM */
- /* since we are now disconnected from the code that established the */
- /* control socket, and since we want to be able to use different */
- /* protocols and such, we are passed the name of the remote host and */
- /* must turn that into the test specific addressing information. */
-
- complete_addrinfos(&remote_res,
- &local_res,
- remote_host,
- SOCK_STREAM,
- IPPROTO_TCP,
- 0);
-
- if ( print_headers ) {
- print_top_test_header("TCP MAERTS TEST",local_res,remote_res);
- }
-
- recv_ring = NULL;
- confidence_iteration = 1;
- init_stat();
-
- /* we have a great-big while loop which controls the number of times */
- /* we run a particular test. this is for the calculation of a */
- /* confidence interval (I really should have stayed awake during */
- /* probstats :). If the user did not request confidence measurement */
- /* (no confidence is the default) then we will only go though the */
- /* loop once. the confidence stuff originates from the folks at IBM */
-
- while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
- (confidence_iteration <= iteration_min)) {
-
- /* initialize a few counters. we have to remember that we might be */
- /* going through the loop more than once. */
-
- nummessages = 0;
- bytes_sent = 0.0;
- times_up = 0;
-
- /*set up the data socket */
- recv_socket = create_data_socket(local_res);
-
- if (recv_socket == INVALID_SOCKET){
- perror("netperf: send_tcp_maerts: tcp stream data socket");
- exit(1);
- }
-
- if (debug) {
- fprintf(where,"send_tcp_maerts: recv_socket obtained...\n");
- }
-
- /* at this point, we have either retrieved the socket buffer sizes, */
- /* or have tried to set them, so now, we may want to set the recv */
- /* size based on that (because the user either did not use a -m */
- /* option, or used one with an argument of 0). If the socket buffer */
- /* size is not available, we will set the recv size to 4KB - no */
- /* particular reason, just arbitrary... */
- if (recv_size == 0) {
- if (lsr_size > 0) {
- recv_size = lsr_size;
- }
- else {
- recv_size = 4096;
- }
- }
-
- /* set-up the data buffer ring with the requested alignment and offset. */
- /* note also that we have allocated a quantity */
- /* of memory that is at least one recv-size greater than our socket */
- /* buffer size. We want to be sure that there are at least two */
- /* buffers allocated - this can be a bit of a problem when the */
- /* recv_size is bigger than the socket size, so we must check... the */
- /* user may have wanted to explicitly set the "width" of our recv */
- /* buffers, we should respect that wish... */
- if (recv_width == 0) {
- recv_width = (lsr_size/recv_size) + 1;
- if (recv_width == 1) recv_width++;
- }
-
- if (recv_ring == NULL) {
- /* only allocate the recv ring once. this is a networking test, */
- /* not a memory allocation test. this way, we do not need a */
- /* deallocate_buffer_ring() routine, and I don't feel like */
- /* writing one anyway :) raj 11/94 */
- recv_ring = allocate_buffer_ring(recv_width,
- recv_size,
- local_recv_align,
- local_recv_offset);
- }
-
- /* If the user has requested cpu utilization measurements, we must */
- /* calibrate the cpu(s). We will perform this task within the tests */
- /* themselves. If the user has specified the cpu rate, then */
- /* calibrate_local_cpu will return rather quickly as it will have */
- /* nothing to do. If local_cpu_rate is zero, then we will go through */
- /* all the "normal" calibration stuff and return the rate back. */
-
- if (local_cpu_usage) {
- local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
- }
-
- if (!no_control) {
- /* Tell the remote end to do a listen. The server alters the
- socket paramters on the other side at this point, hence the
- reason for all the values being passed in the setup
- message. If the user did not specify any of the parameters,
- they will be passed as 0, which will indicate to the remote
- that no changes beyond the system's default should be
- used. Alignment is the exception, it will default to 1, which
- will be no alignment alterations. */
-
- netperf_request.content.request_type = DO_TCP_MAERTS;
- tcp_maerts_request->send_buf_size = rss_size_req;
- tcp_maerts_request->recv_buf_size = rsr_size_req;
- tcp_maerts_request->send_size = send_size;
- tcp_maerts_request->no_delay = rem_nodelay;
- tcp_maerts_request->send_alignment = remote_send_align;
- tcp_maerts_request->send_offset = remote_send_offset;
- tcp_maerts_request->measure_cpu = remote_cpu_usage;
- tcp_maerts_request->cpu_rate = remote_cpu_rate;
- if (test_time) {
- tcp_maerts_request->test_length = test_time;
- }
- else {
- tcp_maerts_request->test_length = test_bytes;
- }
- tcp_maerts_request->so_rcvavoid = rem_rcvavoid;
- tcp_maerts_request->so_sndavoid = rem_sndavoid;
-#ifdef DIRTY
- tcp_maerts_request->dirty_count = rem_dirty_count;
- tcp_maerts_request->clean_count = rem_clean_count;
-#endif /* DIRTY */
- tcp_maerts_request->port = atoi(remote_data_port);
- tcp_maerts_request->ipfamily = af_to_nf(remote_res->ai_family);
- if (debug > 1) {
- fprintf(where,
- "netperf: send_tcp_maerts: requesting TCP maerts test\n");
- }
-
- send_request();
-
- /* The response from the remote will contain all of the relevant
- socket parameters for this test type. We will put them back
- into the variables here so they can be displayed if desired.
- The remote will have calibrated CPU if necessary, and will
- have done all the needed set-up we will have calibrated the
- cpu locally before sending the request, and will grab the
- counter value right after the connect returns. The remote
- will grab the counter right after the accept call. This saves
- the hassle of extra messages being sent for the TCP
- tests. */
-
- recv_response();
-
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote listen done.\n");
- rsr_size = tcp_maerts_response->recv_buf_size;
- rss_size = tcp_maerts_response->send_buf_size;
- rem_nodelay = tcp_maerts_response->no_delay;
- remote_cpu_usage= tcp_maerts_response->measure_cpu;
- remote_cpu_rate = tcp_maerts_response->cpu_rate;
- send_size = tcp_maerts_response->send_size;
-
- /* we have to make sure that the server port number is in
- network order */
- set_port_number(remote_res,
- (short)tcp_maerts_response->data_port_number);
- rem_rcvavoid = tcp_maerts_response->so_rcvavoid;
- rem_sndavoid = tcp_maerts_response->so_sndavoid;
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- fprintf(where,
- "netperf: remote error %d",
- netperf_response.content.serv_errno);
- perror("");
- fflush(where);
-
- exit(1);
- }
- }
-
-#ifdef WANT_DEMO
- DEMO_STREAM_SETUP(lsr_size,rss_size)
-#endif
-
- /*Connect up to the remote port on the data socket */
- if (connect(recv_socket,
- remote_res->ai_addr,
- remote_res->ai_addrlen) == INVALID_SOCKET){
- perror("netperf: send_tcp_maerts: data socket connect failed");
- exit(1);
- }
-
- /* Data Socket set-up is finished. If there were problems, either */
- /* the connect would have failed, or the previous response would */
- /* have indicated a problem. I failed to see the value of the */
- /* extra message after the accept on the remote. If it failed, */
- /* we'll see it here. If it didn't, we might as well start pumping */
- /* data. */
-
- /* Set-up the test end conditions. For a maerts test, they can be */
- /* either time or byte-count based. */
-
- if (test_time) {
- /* The user wanted to end the test after a period of time. */
- times_up = 0;
- bytes_remaining = 0;
- /* in previous revisions, we had the same code repeated throught */
- /* all the test suites. this was unnecessary, and meant more */
- /* work for me when I wanted to switch to POSIX signals, so I */
- /* have abstracted this out into a routine in netlib.c. if you */
- /* are experiencing signal problems, you might want to look */
- /* there. raj 11/94 */
- if (!no_control) {
- /* this is a netperf to netserver test, netserver will close
- to tell us the test is over, so use PAD_TIME to avoid
- causing the netserver fits. */
- start_timer(test_time + PAD_TIME);
- }
- else {
- /* this is a netperf to data source test, no PAD_TIME */
- start_timer(test_time);
- }
- }
- else {
- /* The tester wanted to recv a number of bytes. we don't do that
- in a TCP_MAERTS test. sorry. raj 2002-06-21 */
- printf("netperf: send_tcp_maerts: test must be timed\n");
- exit(1);
- }
-
- /* The cpu_start routine will grab the current time and possibly */
- /* value of the idle counter for later use in measuring cpu */
- /* utilization and/or service demand and thruput. */
-
- cpu_start(local_cpu_usage);
-
-#ifdef WANT_INTERVALS
- INTERVALS_INIT();
-#endif /* WANT_INTERVALS */
-
- /* before we start, initialize a few variables */
-
-#ifdef WANT_DEMO
- if (demo_mode) {
- HIST_timestamp(demo_one_ptr);
- }
-#endif
-
- /* the test will continue until we either get a zero-byte recv()
- on the socket or our failsafe timer expires. most of the time
- we trust that we get a zero-byte recieve from the socket. raj
- 2002-06-21 */
-
-#ifdef WANT_HISTOGRAM
- if (verbosity > 1) {
- /* timestamp just before we go into recv and then again just
- after we come out raj 8/94 */
- /* but only if we are actually going to display a histogram. raj
- 2006-02-07 */
- HIST_timestamp(&time_one);
- }
-#endif /* WANT_HISTOGRAM */
-
- while ((!times_up) && (len=recv(recv_socket,
- recv_ring->buffer_ptr,
- recv_size,
- 0)) > 0 ) {
-
-#ifdef WANT_HISTOGRAM
- if (verbosity > 1) {
- /* timestamp the exit from the recv call and update the histogram */
- HIST_timestamp(&time_two);
- HIST_add(time_hist,delta_micro(&time_one,&time_two));
- }
-#endif /* WANT_HISTOGRAM */
-
-#ifdef DIRTY
- access_buffer(recv_ring->buffer_ptr,
- recv_size,
- loc_dirty_count,
- loc_clean_count);
-#endif /* DIRTY */
-
-#ifdef WANT_DEMO
- DEMO_STREAM_INTERVAL(len);
-#endif
-
-#ifdef WANT_INTERVALS
- INTERVALS_WAIT();
-#endif /* WANT_INTERVALS */
-
- /* now we want to move our pointer to the next position in the */
- /* data buffer...we may also want to wrap back to the "beginning" */
- /* of the bufferspace, so we will mod the number of messages sent */
- /* by the recv width, and use that to calculate the offset to add */
- /* to the base pointer. */
- nummessages++;
- recv_ring = recv_ring->next;
- if (bytes_remaining) {
- bytes_remaining -= len;
- }
-
- local_bytes_recvd += len;
-
-#ifdef WANT_HISTOGRAM
- if (verbosity > 1) {
- /* make sure we timestamp just before we go into recv */
- /* raj 2004-06-15 */
- HIST_timestamp(&time_one);
- }
-#endif /* WANT_HISTOGRAM */
-
- }
-
- /* an EINTR is to be expected when this is a no_control test */
- if (((len < 0) || SOCKET_EINTR(len)) && (!no_control)) {
- perror("send_tcp_maerts: data recv error");
- printf("len was %d\n",len);
- exit(1);
- }
-
- /* if we get here, it must mean we had a recv return of 0 before
- the watchdog timer expired, or the watchdog timer expired and
- this was a no_control test */
-
- /* The test is over. Flush the buffers to the remote end. We do a
- graceful release to tell the remote we have all the data. */
-
- /* but first, if the verbosity is greater than 1, find-out what */
- /* the TCP maximum segment_size was (if possible) */
- if (verbosity > 1) {
- tcp_mss = -1;
- get_tcp_info(recv_socket,&tcp_mss);
- }
-
- if (shutdown(recv_socket,SHUT_WR) == SOCKET_ERROR) {
- perror("netperf: cannot shutdown tcp maerts socket");
- exit(1);
- }
-
- stop_timer();
-
- /* this call will always give us the local elapsed time for the
- test, and will also store-away the necessaries for cpu
- utilization */
-
- cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */
- /* measured and how */
- /* long did we really */
- /* run? */
-
- /* we are finished with the socket, so close it to prevent hitting */
- /* the limit on maximum open files. */
-
- close(recv_socket);
-
- if (!no_control) {
- /* Get the statistics from the remote end. The remote will have
- calculated service demand and all those interesting
- things. If it wasn't supposed to care, it will return obvious
- values. */
-
- recv_response();
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote results obtained\n");
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- fprintf(where,
- "netperf: remote error %d",
- netperf_response.content.serv_errno);
- perror("");
- fflush(where);
-
- exit(1);
- }
-
- /* We now calculate what our thruput was for the test. In the
- future, we may want to include a calculation of the thruput
- measured by the remote, but it should be the case that for a
- TCP maerts test, that the two numbers should be *very*
- close... We calculate bytes_sent regardless of the way the
- test length was controlled. If it was time, we needed to,
- and if it was by bytes, the user may have specified a number
- of bytes that wasn't a multiple of the recv_size, so we
- really didn't recv what he asked for ;-) */
-
- bytes_sent = ntohd(tcp_maerts_result->bytes_sent);
- }
- else {
- bytes_sent = (double)local_bytes_recvd;
- }
-
-
- thruput = calc_thruput(bytes_sent);
-
- if (local_cpu_usage || remote_cpu_usage) {
- /* We must now do a little math for service demand and cpu */
- /* utilization for the system(s) */
- /* Of course, some of the information might be bogus because */
- /* there was no idle counter in the kernel(s). We need to make */
- /* a note of this for the user's benefit...*/
- if (local_cpu_usage) {
-
- local_cpu_utilization = calc_cpu_util(0.0);
- local_service_demand = calc_service_demand(bytes_sent,
- 0.0,
- 0.0,
- 0);
- }
- else {
- local_cpu_utilization = (float) -1.0;
- local_service_demand = (float) -1.0;
- }
-
- if (remote_cpu_usage) {
-
- remote_cpu_utilization = tcp_maerts_result->cpu_util;
- remote_service_demand = calc_service_demand(bytes_sent,
- 0.0,
- remote_cpu_utilization,
- tcp_maerts_result->num_cpus);
- }
- else {
- remote_cpu_utilization = (float) -1.0;
- remote_service_demand = (float) -1.0;
- }
- }
- else {
- /* we were not measuring cpu, for the confidence stuff, we */
- /* should make it -1.0 */
- local_cpu_utilization = (float) -1.0;
- local_service_demand = (float) -1.0;
- remote_cpu_utilization = (float) -1.0;
- remote_service_demand = (float) -1.0;
- }
-
- /* at this point, we want to calculate the confidence information. */
- /* if debugging is on, calculate_confidence will print-out the */
- /* parameters we pass it */
-
- calculate_confidence(confidence_iteration,
- elapsed_time,
- thruput,
- local_cpu_utilization,
- remote_cpu_utilization,
- local_service_demand,
- remote_service_demand);
-
-
- confidence_iteration++;
- }
-
- /* at this point, we have finished making all the runs that we */
- /* will be making. so, we should extract what the calcuated values */
- /* are for all the confidence stuff. we could make the values */
- /* global, but that seemed a little messy, and it did not seem worth */
- /* all the mucking with header files. so, we create a routine much */
- /* like calcualte_confidence, which just returns the mean values. */
- /* raj 11/94 */
-
- retrieve_confident_values(&elapsed_time,
- &thruput,
- &local_cpu_utilization,
- &remote_cpu_utilization,
- &local_service_demand,
- &remote_service_demand);
-
- /* We are now ready to print all the information. If the user */
- /* has specified zero-level verbosity, we will just print the */
- /* local service demand, or the remote service demand. If the */
- /* user has requested verbosity level 1, he will get the basic */
- /* "streamperf" numbers. If the user has specified a verbosity */
- /* of greater than 1, we will display a veritable plethora of */
- /* background information from outside of this block as it it */
- /* not cpu_measurement specific... */
-
- if (confidence < 0) {
- /* we did not hit confidence, but were we asked to look for it? */
- if (iteration_max > 1) {
- display_confidence();
- }
- }
-
- if (local_cpu_usage || remote_cpu_usage) {
- local_cpu_method = format_cpu_method(cpu_method);
- remote_cpu_method = format_cpu_method(tcp_maerts_result->cpu_method);
-
- switch (verbosity) {
- case 0:
- if (local_cpu_usage) {
- fprintf(where,
- cpu_fmt_0,
- local_service_demand,
- local_cpu_method,
- ((print_headers) ||
- (result_brand == NULL)) ? "" : result_brand);
- }
- else {
- fprintf(where,
- cpu_fmt_0,
- remote_service_demand,
- remote_cpu_method,
- ((print_headers) ||
- (result_brand == NULL)) ? "" : result_brand);
- }
- break;
- case 1:
- case 2:
- if (print_headers) {
- fprintf(where,
- cpu_title,
- format_units(),
- local_cpu_method,
- remote_cpu_method);
- }
-
- fprintf(where,
- cpu_fmt_1, /* the format string */
- rsr_size, /* remote recvbuf size */
- lss_size, /* local sendbuf size */
- send_size, /* how large were the recvs */
- elapsed_time, /* how long was the test */
- thruput, /* what was the xfer rate */
- local_cpu_utilization, /* local cpu */
- remote_cpu_utilization, /* remote cpu */
- local_service_demand, /* local service demand */
- remote_service_demand, /* remote service demand */
- ((print_headers) ||
- (result_brand == NULL)) ? "" : result_brand);
- break;
- }
- }
- else {
- /* The tester did not wish to measure service demand. */
-
- switch (verbosity) {
- case 0:
- fprintf(where,
- tput_fmt_0,
- thruput,
- ((print_headers) ||
- (result_brand == NULL)) ? "" : result_brand);
- break;
- case 1:
- case 2:
- if (print_headers) {
- fprintf(where,tput_title,format_units());
- }
- fprintf(where,
- tput_fmt_1, /* the format string */
- lsr_size, /* local recvbuf size */
- rss_size, /* remot sendbuf size */
- send_size, /* how large were the recvs */
- elapsed_time, /* how long did it take */
- thruput, /* how fast did it go */
- ((print_headers) ||
- (result_brand == NULL)) ? "" : result_brand);
- break;
- }
- }
-
- /* it would be a good thing to include information about some of the */
- /* other parameters that may have been set for this test, but at the */
- /* moment, I do not wish to figure-out all the formatting, so I will */
- /* just put this comment here to help remind me that it is something */
- /* that should be done at a later time. */
-
- if (verbosity > 1) {
- /* The user wanted to know it all, so we will give it to him. */
- /* This information will include as much as we can find about */
- /* TCP statistics, the alignments of the sends and receives */
- /* and all that sort of rot... */
-
- /* this stuff needs to be worked-out in the presence of confidence */
- /* intervals and multiple iterations of the test... raj 11/94 */
-
- fprintf(where,
- ksink_fmt,
- "Bytes",
- "Bytes",
- "Bytes",
- local_recv_align,
- remote_recv_align,
- local_recv_offset,
- remote_recv_offset,
- bytes_sent,
- bytes_sent / (double)nummessages,
- nummessages,
- bytes_sent / (double)tcp_maerts_result->send_calls,
- tcp_maerts_result->send_calls);
- fprintf(where,
- ksink_fmt2,
- tcp_mss);
- fflush(where);
-#ifdef WANT_HISTOGRAM
- fprintf(where,"\n\nHistogram of time spent in recv() call.\n");
- fflush(where);
- HIST_report(time_hist);
-#endif /* WANT_HISTOGRAM */
- }
-
-}
-
-
-
-#ifdef HAVE_ICSC_EXS
-
-#include <sys/exs.h>
-
-
-/* This routine implements the TCP unidirectional data transfer test */
-/* (a.k.a. stream) for the sockets interface. It receives its */
-/* parameters via global variables from the shell and writes its */
-/* output to the standard output. */
-
-void
-send_exs_tcp_stream(char remote_host[])
-{
-
- char *tput_title = "\
-Recv Send Send \n\
-Socket Socket Message Elapsed \n\
-Size Size Size Time Throughput \n\
-bytes bytes bytes secs. %s/sec \n\n";
-
- char *tput_fmt_0 =
- "%7.2f\n";
-
- char *tput_fmt_1 =
- "%6d %6d %6d %-6.2f %7.2f \n";
-
- char *cpu_title = "\
-Recv Send Send Utilization Service Demand\n\
-Socket Socket Message Elapsed Send Recv Send Recv\n\
-Size Size Size Time Throughput local remote local remote\n\
-bytes bytes bytes secs. %-8.8s/s %% %c %% %c us/KB us/KB\n\n";
-
- char *cpu_fmt_0 =
- "%6.3f %c\n";
-
- char *cpu_fmt_1 =
- "%6d %6d %6d %-6.2f %7.2f %-6.2f %-6.2f %-6.3f %-6.3f\n";
-
- char *ksink_fmt = "\n\
-Alignment Offset %-8.8s %-8.8s Sends %-8.8s Recvs\n\
-Local Remote Local Remote Xfered Per Per\n\
-Send Recv Send Recv Send (avg) Recv (avg)\n\
-%5d %5d %5d %5d %6.4g %6.2f %6d %6.2f %6d\n";
-
- char *ksink_fmt2 = "\n\
-Maximum\n\
-Segment\n\
-Size (bytes)\n\
-%6d\n";
-
-
- float elapsed_time;
-
- /* what we want is to have a buffer space that is at least one */
- /* send-size greater than our send window. this will insure that we */
- /* are never trying to re-use a buffer that may still be in the hands */
- /* of the transport. This buffer will be malloc'd after we have found */
- /* the size of the local senc socket buffer. We will want to deal */
- /* with alignment and offset concerns as well. */
-
- struct ring_elt *send_ring;
-
- int len;
- unsigned int nummessages = 0;
- SOCKET send_socket;
- int bytes_remaining;
- int tcp_mss = -1; /* possibly uninitialized on printf far below */
-
- exs_mhandle_t exs_mhandle;
- exs_qhandle_t exs_qhandle;
-#define NETPERF_EXS_PENDING 16
- int exs_aio_pending;
- int exs_aio_eagain;
- int exs_aio_dequeued;
- int exs_aio_dequeuecnt;
- int exs_evtcnt;
-#define NETPERF_EXS_QSIZE 128
- exs_event_t exs_evtvec[NETPERF_EXS_QSIZE];
-
- /* with links like fddi, one can send > 32 bits worth of bytes */
- /* during a test... ;-) at some point, this should probably become a */
- /* 64bit integral type, but those are not entirely common yet */
-
- double bytes_sent = 0.0;
-
- float local_cpu_utilization;
- float local_service_demand;
- float remote_cpu_utilization;
- float remote_service_demand;
-
- double thruput;
-
- struct addrinfo *remote_res;
- struct addrinfo *local_res;
-
- struct tcp_stream_request_struct *tcp_stream_request;
- struct tcp_stream_response_struct *tcp_stream_response;
- struct tcp_stream_results_struct *tcp_stream_result;
-
- tcp_stream_request =
- (struct tcp_stream_request_struct *)netperf_request.content.test_specific_data;
- tcp_stream_response =
- (struct tcp_stream_response_struct *)netperf_response.content.test_specific_data;
- tcp_stream_result =
- (struct tcp_stream_results_struct *)netperf_response.content.test_specific_data;
-
-#if 0 /* def WANT_HISTOGRAM */
- time_hist = HIST_new();
-#endif /* WANT_HISTOGRAM */
- /* since we are now disconnected from the code that established the */
- /* control socket, and since we want to be able to use different */
- /* protocols and such, we are passed the name of the remote host and */
- /* must turn that into the test specific addressing information. */
-
- /* complete_addrinfos will either succede or exit the process */
- complete_addrinfos(&remote_res,
- &local_res,
- remote_host,
- SOCK_STREAM,
- IPPROTO_TCP,
- 0);
-
- if ( print_headers ) {
- print_top_test_header("EXS TCP STREAM TEST",local_res,remote_res);
- }
-
- send_ring = NULL;
- confidence_iteration = 1;
- init_stat();
-
- /* initialize EXS API and create event queue */
- if (exs_init (EXS_VERSION) == -1) {
- perror ("netperf: send_exs_tcp_stream: exs_init failed");
- exit (1);
- }
-
- if ((exs_qhandle = exs_qcreate (NETPERF_EXS_QSIZE)) == EXS_QHANDLE_INVALID) {
- perror ("netperf: send_exs_tcp_stream: exs_qcreate failed");
- exit (1);
- }
- if (debug) {
- fprintf (where, "send_exs_tcp_stream: qhandle=%d\n", exs_qhandle);
- }
-
- /* we have a great-big while loop which controls the number of times */
- /* we run a particular test. this is for the calculation of a */
- /* confidence interval (I really should have stayed awake during */
- /* probstats :). If the user did not request confidence measurement */
- /* (no confidence is the default) then we will only go though the */
- /* loop once. the confidence stuff originates from the folks at IBM */
-
- while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
- (confidence_iteration <= iteration_min)) {
-
- /* initialize a few counters. we have to remember that we might be */
- /* going through the loop more than once. */
-
- nummessages = 0;
- bytes_sent = 0.0;
- times_up = 0;
-
- /*set up the data socket */
- send_socket = create_data_socket(local_res);
-
- if (send_socket == INVALID_SOCKET){
- perror("netperf: send_tcp_stream: tcp stream data socket");
- exit(1);
- }
-
- if (debug) {
- fprintf(where,"send_tcp_stream: send_socket obtained...\n");
- }
-
- /* at this point, we have either retrieved the socket buffer sizes, */
- /* or have tried to set them, so now, we may want to set the send */
- /* size based on that (because the user either did not use a -m */
- /* option, or used one with an argument of 0). If the socket buffer */
- /* size is not available, we will set the send size to 4KB - no */
- /* particular reason, just arbitrary... */
- if (send_size == 0) {
- if (lss_size > 0) {
- send_size = lss_size;
- }
- else {
- send_size = 4096;
- }
- }
-
- /* set-up the data buffer ring with the requested alignment and offset. */
- /* note also that we have allocated a quantity */
- /* of memory that is at least one send-size greater than our socket */
- /* buffer size. We want to be sure that there are at least two */
- /* buffers allocated - this can be a bit of a problem when the */
- /* send_size is bigger than the socket size, so we must check... the */
- /* user may have wanted to explicitly set the "width" of our send */
- /* buffers, we should respect that wish... */
- if (send_width == 0) {
- send_width = (lss_size/send_size) + 1;
- if (send_width == 1) send_width++;
- }
-
- if (send_ring == NULL) {
- /* only allocate the send ring once. this is a networking test, */
- /* not a memory allocation test. this way, we do not need a */
- /* deallocate_buffer_ring() routine, and I don't feel like */
- /* writing one anyway :) raj 11/94 */
- send_ring = allocate_exs_buffer_ring(send_width,
- send_size,
- local_send_align,
- local_send_offset,
- &exs_mhandle);
- }
-
- /* If the user has requested cpu utilization measurements, we must */
- /* calibrate the cpu(s). We will perform this task within the tests */
- /* themselves. If the user has specified the cpu rate, then */
- /* calibrate_local_cpu will return rather quickly as it will have */
- /* nothing to do. If local_cpu_rate is zero, then we will go through */
- /* all the "normal" calibration stuff and return the rate back. */
-
- if (local_cpu_usage) {
- local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
- }
-
- /* Tell the remote end to do a listen. The server alters the socket */
- /* paramters on the other side at this point, hence the reason for */
- /* all the values being passed in the setup message. If the user did */
- /* not specify any of the parameters, they will be passed as 0, which */
- /* will indicate to the remote that no changes beyond the system's */
- /* default should be used. Alignment is the exception, it will */
- /* default to 1, which will be no alignment alterations. */
-
- netperf_request.content.request_type = DO_TCP_STREAM;
- tcp_stream_request->send_buf_size = rss_size_req;
- tcp_stream_request->recv_buf_size = rsr_size_req;
- tcp_stream_request->receive_size = recv_size;
- tcp_stream_request->no_delay = rem_nodelay;
- tcp_stream_request->recv_alignment = remote_recv_align;
- tcp_stream_request->recv_offset = remote_recv_offset;
- tcp_stream_request->measure_cpu = remote_cpu_usage;
- tcp_stream_request->cpu_rate = remote_cpu_rate;
- if (test_time) {
- tcp_stream_request->test_length = test_time;
- }
- else {
- tcp_stream_request->test_length = test_bytes;
- }
- tcp_stream_request->so_rcvavoid = rem_rcvavoid;
- tcp_stream_request->so_sndavoid = rem_sndavoid;
-#ifdef DIRTY
- tcp_stream_request->dirty_count = rem_dirty_count;
- tcp_stream_request->clean_count = rem_clean_count;
-#endif /* DIRTY */
- tcp_stream_request->port = atoi(remote_data_port);
- tcp_stream_request->ipfamily = af_to_nf(remote_res->ai_family);
- if (debug > 1) {
- fprintf(where,
- "netperf: send_tcp_stream: requesting TCP stream test\n");
- }
-
- send_request();
-
- /* The response from the remote will contain all of the relevant */
- /* socket parameters for this test type. We will put them back into */
- /* the variables here so they can be displayed if desired. The */
- /* remote will have calibrated CPU if necessary, and will have done */
- /* all the needed set-up we will have calibrated the cpu locally */
- /* before sending the request, and will grab the counter value right*/
- /* after the connect returns. The remote will grab the counter right*/
- /* after the accept call. This saves the hassle of extra messages */
- /* being sent for the TCP tests. */
-
- recv_response();
-
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote listen done.\n");
- rsr_size = tcp_stream_response->recv_buf_size;
- rss_size = tcp_stream_response->send_buf_size;
- rem_nodelay = tcp_stream_response->no_delay;
- remote_cpu_usage= tcp_stream_response->measure_cpu;
- remote_cpu_rate = tcp_stream_response->cpu_rate;
-
- /* we have to make sure that the server port number is in */
- /* network order */
- set_port_number(remote_res,(short)tcp_stream_response->data_port_number);
-
- rem_rcvavoid = tcp_stream_response->so_rcvavoid;
- rem_sndavoid = tcp_stream_response->so_sndavoid;
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- fprintf(where,
- "netperf: remote error %d",
- netperf_response.content.serv_errno);
- perror("");
- fflush(where);
-
- exit(1);
- }
-
-#if 0 /* def WANT_DEMO */
- DEMO_STREAM_SETUP(lss_size,rsr_size)
-#endif
-
- /*Connect up to the remote port on the data socket */
- if (connect(send_socket,
- remote_res->ai_addr,
- remote_res->ai_addrlen) == INVALID_SOCKET){
- perror("netperf: send_tcp_stream: data socket connect failed");
- exit(1);
- }
-
- /* Data Socket set-up is finished. If there were problems, either */
- /* the connect would have failed, or the previous response would */
- /* have indicated a problem. I failed to see the value of the */
- /* extra message after the accept on the remote. If it failed, */
- /* we'll see it here. If it didn't, we might as well start pumping */
- /* data. */
-
- /* Set-up the test end conditions. For a stream test, they can be */
- /* either time or byte-count based. */
-
- if (test_time) {
- /* The user wanted to end the test after a period of time. */
- times_up = 0;
- bytes_remaining = 0;
- /* in previous revisions, we had the same code repeated throught */
- /* all the test suites. this was unnecessary, and meant more */
- /* work for me when I wanted to switch to POSIX signals, so I */
- /* have abstracted this out into a routine in netlib.c. if you */
- /* are experiencing signal problems, you might want to look */
- /* there. raj 11/94 */
- start_timer(test_time);
- }
- else {
- /* The tester wanted to send a number of bytes. */
- bytes_remaining = test_bytes;
- times_up = 1;
- }
-
- /* The cpu_start routine will grab the current time and possibly */
- /* value of the idle counter for later use in measuring cpu */
- /* utilization and/or service demand and thruput. */
-
- cpu_start(local_cpu_usage);
-
-#if 0 /* def WANT_INTERVALS */
- INTERVALS_INIT();
-#endif /* WANT_INTERVALS */
-
- /* before we start, initialize a few variables */
-
-#if 0 /* def WANT_DEMO */
- if (demo_mode) {
- HIST_timestamp(demo_one_ptr);
- }
-#endif
-
-
- /* We use an "OR" to control test execution. When the test is */
- /* controlled by time, the byte count check will always return false. */
- /* When the test is controlled by byte count, the time test will */
- /* always return false. When the test is finished, the whole */
- /* expression will go false and we will stop sending data. */
-
- exs_aio_pending = 0;
- exs_aio_eagain = 0;
- exs_aio_dequeuecnt = 0;
-
- while ((!times_up) || (bytes_remaining > 0)) {
-
-#ifdef DIRTY
- access_buffer(send_ring->buffer_ptr,
- send_size,
- loc_dirty_count,
- loc_clean_count);
-#endif /* DIRTY */
-
-#if 0 /* def WANT_HISTOGRAM */
- /* timestamp just before we go into send and then again just after */
- /* we come out raj 8/94 */
- HIST_timestamp(&time_one);
-#endif /* WANT_HISTOGRAM */
-
-
- /* post up to NETPERF_EXS_PENDING I/Os */
- while ((exs_aio_pending < NETPERF_EXS_PENDING) &&
- (exs_send (send_socket, send_ring->buffer_ptr, send_size,
- 0, exs_qhandle, (exs_ahandle_t)-1, exs_mhandle) == 0)) {
- exs_aio_pending++;
-
- /* now we want to move our pointer to the next
- position in the data buffer...we may also want to
- wrap back to the "beginning" of the bufferspace, so
- we will mod the number of messages sent by the send
- width, and use that to calculate the offset to add
- to the base pointer. */
-
- nummessages++;
- send_ring = send_ring->next;
- if (bytes_remaining) {
- bytes_remaining -= send_size;
- }
- }
-
- /* check exs_send result */
- if (exs_aio_pending < NETPERF_EXS_PENDING) {
- /* standard flow control case */
- if (errno == EAGAIN)
- exs_aio_eagain++;
- /* case of times_up */
- else if (errno == EINTR)
- break;
- /* strange, let's stop */
- else {
- perror ("netperf: exs_send error");
- exit (1);
- }
- }
-
- /* dequeue events with "threshold" on 1/2 posted */
- exs_aio_dequeued =
- exs_qdequeue (exs_qhandle, exs_evtvec,
- -(exs_aio_pending>>1), NULL);
- exs_aio_dequeuecnt++;
-
- /* check exs_dequeue result */
- if (exs_aio_dequeued < 0) {
- /* case of times_up */
- if (errno == EINTR)
- break;
- /* strange, let's stop */
- else {
- perror ("netperf: exs_send error");
- exit (1);
- }
- }
- /* update number of pending I/Os */
- else {
- exs_aio_pending -= exs_aio_dequeued;
- }
-
-
-#if 0 /* def WANT_HISTOGRAM */
- /* timestamp the exit from the send call and update the histogram */
- HIST_timestamp(&time_two);
- HIST_add(time_hist,delta_micro(&time_one,&time_two));
-#endif /* WANT_HISTOGRAM */
-
-#if 0 /* def WANT_DEMO */
- DEMO_STREAM_INTERVAL(send_size);
-#endif
-
-#if 0 /* def WANT_INTERVALS */
- INTERVALS_WAIT();
-#endif /* WANT_INTERVALS */
-
- }
-
- /* Collect the last completion events */
- exs_aio_dequeued =
- exs_qdequeue (exs_qhandle, exs_evtvec, -exs_aio_pending, NULL);
- exs_aio_dequeuecnt++;
- /* check exs_dequeue result and update number of pending I/Os */
- if (exs_aio_dequeued < 0) {
- perror ("netperf: exs_send error");
- exit (1);
- }
- exs_aio_pending -= exs_aio_dequeued;
-
- /* Display some async I/O debug info */
- if (debug) {
- fprintf (where, "send_exs_tcp_stream: "
- "aio sent=%d eagain=%d dequeue=%d pending=%d\n",
- nummessages, exs_aio_eagain, exs_aio_dequeuecnt, exs_aio_pending);
- }
-
- /* The test is over. Flush the buffers to the remote end. We do a */
- /* graceful release to insure that all data has been taken by the */
- /* remote. */
-
- /* but first, if the verbosity is greater than 1, find-out what */
- /* the TCP maximum segment_size was (if possible) */
- if (verbosity > 1) {
- tcp_mss = -1;
- get_tcp_info(send_socket,&tcp_mss);
- }
-
- if (shutdown(send_socket,SHUT_WR) == SOCKET_ERROR) {
- perror("netperf: cannot shutdown tcp stream socket");
- exit(1);
- }
-
- /* hang a recv() off the socket to block until the remote has */
- /* brought all the data up into the application. it will do a */
- /* shutdown to cause a FIN to be sent our way. We will assume that */
- /* any exit from the recv() call is good... raj 4/93 */
-
- recv(send_socket, send_ring->buffer_ptr, send_size, 0);
-
- /* this call will always give us the elapsed time for the test, and */
- /* will also store-away the necessaries for cpu utilization */
-
- cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */
- /* measured and how */
- /* long did we really */
- /* run? */
-
- /* we are finished with the socket, so close it to prevent hitting */
- /* the limit on maximum open files. */
-
- close(send_socket);
-
- /* Get the statistics from the remote end. The remote will have */
- /* calculated service demand and all those interesting things. If it */
- /* wasn't supposed to care, it will return obvious values. */
-
- recv_response();
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote results obtained\n");
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- fprintf(where,
- "netperf: remote error %d",
- netperf_response.content.serv_errno);
- perror("");
- fflush(where);
-
- exit(1);
- }
-
- /* We now calculate what our thruput was for the test. In the future, */
- /* we may want to include a calculation of the thruput measured by */
- /* the remote, but it should be the case that for a TCP stream test, */
- /* that the two numbers should be *very* close... We calculate */
- /* bytes_sent regardless of the way the test length was controlled. */
- /* If it was time, we needed to, and if it was by bytes, the user may */
- /* have specified a number of bytes that wasn't a multiple of the */
- /* send_size, so we really didn't send what he asked for ;-) */
-
- bytes_sent = ntohd(tcp_stream_result->bytes_received);
-
- thruput = calc_thruput(bytes_sent);
-
- if (local_cpu_usage || remote_cpu_usage) {
- /* We must now do a little math for service demand and cpu */
- /* utilization for the system(s) */
- /* Of course, some of the information might be bogus because */
- /* there was no idle counter in the kernel(s). We need to make */
- /* a note of this for the user's benefit...*/
- if (local_cpu_usage) {
-
- local_cpu_utilization = calc_cpu_util(0.0);
- local_service_demand = calc_service_demand(bytes_sent,
- 0.0,
- 0.0,
- 0);
- }
- else {
- local_cpu_utilization = (float) -1.0;
- local_service_demand = (float) -1.0;
- }
-
- if (remote_cpu_usage) {
-
- remote_cpu_utilization = tcp_stream_result->cpu_util;
- remote_service_demand = calc_service_demand(bytes_sent,
- 0.0,
- remote_cpu_utilization,
- tcp_stream_result->num_cpus);
- }
- else {
- remote_cpu_utilization = (float) -1.0;
- remote_service_demand = (float) -1.0;
- }
- }
- else {
- /* we were not measuring cpu, for the confidence stuff, we */
- /* should make it -1.0 */
- local_cpu_utilization = (float) -1.0;
- local_service_demand = (float) -1.0;
- remote_cpu_utilization = (float) -1.0;
- remote_service_demand = (float) -1.0;
- }
-
- /* at this point, we want to calculate the confidence information. */
- /* if debugging is on, calculate_confidence will print-out the */
- /* parameters we pass it */
-
- calculate_confidence(confidence_iteration,
- elapsed_time,
- thruput,
- local_cpu_utilization,
- remote_cpu_utilization,
- local_service_demand,
- remote_service_demand);
-
-
- confidence_iteration++;
- }
-
- /* at this point, we have finished making all the runs that we */
- /* will be making. so, we should extract what the calcuated values */
- /* are for all the confidence stuff. we could make the values */
- /* global, but that seemed a little messy, and it did not seem worth */
- /* all the mucking with header files. so, we create a routine much */
- /* like calcualte_confidence, which just returns the mean values. */
- /* raj 11/94 */
-
- retrieve_confident_values(&elapsed_time,
- &thruput,
- &local_cpu_utilization,
- &remote_cpu_utilization,
- &local_service_demand,
- &remote_service_demand);
-
- /* We are now ready to print all the information. If the user */
- /* has specified zero-level verbosity, we will just print the */
- /* local service demand, or the remote service demand. If the */
- /* user has requested verbosity level 1, he will get the basic */
- /* "streamperf" numbers. If the user has specified a verbosity */
- /* of greater than 1, we will display a veritable plethora of */
- /* background information from outside of this block as it it */
- /* not cpu_measurement specific... */
-
- if (confidence < 0) {
- /* we did not hit confidence, but were we asked to look for it? */
- if (iteration_max > 1) {
- display_confidence();
- }
- }
-
- if (local_cpu_usage || remote_cpu_usage) {
- local_cpu_method = format_cpu_method(cpu_method);
- remote_cpu_method = format_cpu_method(tcp_stream_result->cpu_method);
-
- switch (verbosity) {
- case 0:
- if (local_cpu_usage) {
- fprintf(where,
- cpu_fmt_0,
- local_service_demand,
- local_cpu_method);
- }
- else {
- fprintf(where,
- cpu_fmt_0,
- remote_service_demand,
- remote_cpu_method);
- }
- break;
- case 1:
- case 2:
- if (print_headers) {
- fprintf(where,
- cpu_title,
- format_units(),
- local_cpu_method,
- remote_cpu_method);
- }
-
- fprintf(where,
- cpu_fmt_1, /* the format string */
- rsr_size, /* remote recvbuf size */
- lss_size, /* local sendbuf size */
- send_size, /* how large were the sends */
- elapsed_time, /* how long was the test */
- thruput, /* what was the xfer rate */
- local_cpu_utilization, /* local cpu */
- remote_cpu_utilization, /* remote cpu */
- local_service_demand, /* local service demand */
- remote_service_demand); /* remote service demand */
- break;
- }
- }
- else {
- /* The tester did not wish to measure service demand. */
-
- switch (verbosity) {
- case 0:
- fprintf(where,
- tput_fmt_0,
- thruput);
- break;
- case 1:
- case 2:
- if (print_headers) {
- fprintf(where,tput_title,format_units());
- }
- fprintf(where,
- tput_fmt_1, /* the format string */
- rsr_size, /* remote recvbuf size */
- lss_size, /* local sendbuf size */
- send_size, /* how large were the sends */
- elapsed_time, /* how long did it take */
- thruput);/* how fast did it go */
- break;
- }
- }
-
- /* it would be a good thing to include information about some of the */
- /* other parameters that may have been set for this test, but at the */
- /* moment, I do not wish to figure-out all the formatting, so I will */
- /* just put this comment here to help remind me that it is something */
- /* that should be done at a later time. */
-
- if (verbosity > 1) {
- /* The user wanted to know it all, so we will give it to him. */
- /* This information will include as much as we can find about */
- /* TCP statistics, the alignments of the sends and receives */
- /* and all that sort of rot... */
-
- /* this stuff needs to be worked-out in the presence of confidence */
- /* intervals and multiple iterations of the test... raj 11/94 */
-
- fprintf(where,
- ksink_fmt,
- "Bytes",
- "Bytes",
- "Bytes",
- local_send_align,
- remote_recv_align,
- local_send_offset,
- remote_recv_offset,
- bytes_sent,
- bytes_sent / (double)nummessages,
- nummessages,
- bytes_sent / (double)tcp_stream_result->recv_calls,
- tcp_stream_result->recv_calls);
- fprintf(where,
- ksink_fmt2,
- tcp_mss);
- fflush(where);
-#if 0 /* def WANT_HISTOGRAM */
- fprintf(where,"\n\nHistogram of time spent in send() call.\n");
- fflush(where);
- HIST_report(time_hist);
-#endif /* WANT_HISTOGRAM */
- }
-
-}
-
-#endif /* HAVE_ICSC_EXS */
-
-
-
-#if defined(HAVE_SENDFILE)
-
-#if defined(QUICK_SENDPATH)
-
-/*
- * a temporary stub for the sendpath() system call
- * which is defined & implemented in the kernel
- * but which has no libc stub.
- */
-#include <sys/types.h>
-#include <sys/scall_define.h>
-#include <sys/uio.h>
-
-ssize_t
-sendpath(int s, char *path, off_t offset, size_t nbytes,
- const struct iovec *hdtrl, int flags)
- {
- return syscall(SYS_sendpath, s, path, offset, nbytes, hdtrl, flags);
- }
-#endif /* QUICK_SENDPATH */
-
-/* This routine implements the TCP unidirectional data transfer test
- (a.k.a. stream) for the sockets interface using the sendfile()
- system call - TCP_SENDFILE. It receives its parameters via global
- variables from the shell and writes its output to the standard
- output. Basically, this is the same test as the send_tcp_stream()
- logic and we even tell the remote to do a TCP_STREAM test since for
- all it knows, nothig is different. */
-
-void
-sendfile_tcp_stream(remote_host)
- char remote_host[];
-{
-
- char *tput_title = "\
-Recv Send Send \n\
-Socket Socket Message Elapsed \n\
-Size Size Size Time Throughput \n\
-bytes bytes bytes secs. %s/sec \n\n";
-
- char *tput_fmt_0 =
- "%7.2f\n";
-
- char *tput_fmt_1 =
- "%6d %6d %6d %-6.2f %7.2f \n";
-
- char *cpu_title = "\
-Recv Send Send Utilization Service Demand\n\
-Socket Socket Message Elapsed Send Recv Send Recv\n\
-Size Size Size Time Throughput local remote local remote\n\
-bytes bytes bytes secs. %-8.8s/s %% %c %% %c us/KB us/KB\n\n";
-
- char *cpu_fmt_0 =
- "%6.3f %c\n";
- char *cpu_fmt_1 =
- "%6d %6d %6d %-6.2f %7.2f %-6.2f %-6.2f %-6.3f %-6.3f\n";
-
- char *ksink_fmt = "\n\
-Alignment Offset %-8.8s %-8.8s Sends %-8.8s Recvs\n\
-Local Remote Local Remote Xfered Per Per\n\
-Send Recv Send Recv Send (avg) Recv (avg)\n\
-%5d %5d %5d %5d %6.4g %6.2f %6d %6.2f %6d\n";
-
-char *ksink_fmt2 = "\n\
-Maximum\n\
-Segment\n\
-Size (bytes)\n\
-%6d\n";
-
- float elapsed_time;
-
- /* what we want is to have a buffer space that is at least one */
- /* send-size greater than our send window. this will insure that we */
- /* are never trying to re-use a buffer that may still be in the hands */
- /* of the transport. This buffer will be malloc'd after we have found */
- /* the size of the local senc socket buffer. We will want to deal */
- /* with alignment and offset concerns as well. */
-
- struct sendfile_ring_elt *send_ring;
-
- int len;
- unsigned int nummessages = 0;
- SOCKET send_socket;
- int bytes_remaining;
- int tcp_mss = -1; /* possibly uninitialized on printf far below */
-
- /* with links like fddi, one can send > 32 bits worth of bytes */
- /* during a test... ;-) at some point, this should probably become a */
- /* 64bit integral type, but those are not entirely common yet */
- double bytes_sent = 0.0;
-
- float local_cpu_utilization;
- float local_service_demand;
- float remote_cpu_utilization;
- float remote_service_demand;
-
- double thruput;
-
- struct addrinfo *remote_res;
- struct addrinfo *local_res;
- struct sockaddr_in server;
-
-#if defined(__linux) || defined(__sun__)
- off_t scratch_offset; /* the linux sendfile() call will update
- the offset variable, which is
- something we do _not_ want to happen
- to the value in the send_ring! so, we
- have to use a scratch variable. */
-#endif /* __linux || defined(__sun__) */
-#if defined (USE_OSX)
- off_t scratch_len; /* Darwin 9.x need a value-result parameter */
-#endif
-#if defined (__sun__)
- size_t scratch_len; /* the sun sendfilev() needs a place to
- tell us how many bytes were written,
- even though it also returns the value */
- sendfilevec_t sv;
-#endif /* __sun__ */
-
- struct tcp_stream_request_struct *tcp_stream_request;
- struct tcp_stream_response_struct *tcp_stream_response;
- struct tcp_stream_results_struct *tcp_stream_result;
-
- tcp_stream_request =
- (struct tcp_stream_request_struct *)netperf_request.content.test_specific_data;
- tcp_stream_response =
- (struct tcp_stream_response_struct *)netperf_response.content.test_specific_data;
- tcp_stream_result =
- (struct tcp_stream_results_struct *)netperf_response.content.test_specific_data;
-
-#ifdef WANT_HISTOGRAM
- if (verbosity > 1) {
- time_hist = HIST_new();
- }
-#endif /* WANT_HISTOGRAM */
-
- /* since we are now disconnected from the code that established the */
- /* control socket, and since we want to be able to use different */
- /* protocols and such, we are passed the name of the remote host and */
- /* must turn that into the test specific addressing information. */
-
- bzero((char *)&server,
- sizeof(server));
-
- complete_addrinfos(&remote_res,
- &local_res,
- remote_host,
- SOCK_STREAM,
- IPPROTO_TCP,
- 0);
-
- if ( print_headers ) {
- /* we want to have some additional, interesting information in */
- /* the headers. we know some of it here, but not all, so we will */
- /* only print the test title here and will print the results */
- /* titles after the test is finished */
-#ifdef QUICK_SENDPATH
- print_top_test_header("TCP SENDPATH TEST",local_res,remote_res);
-#else
- print_top_test_header("TCP SENDFILE TEST",local_res,remote_res);
-#endif /* QUICK_SENDPATH */
- }
- send_ring = NULL;
- confidence_iteration = 1;
- init_stat();
-
- /* we have a great-big while loop which controls the number of times */
- /* we run a particular test. this is for the calculation of a */
- /* confidence interval (I really should have stayed awake during */
- /* probstats :). If the user did not request confidence measurement */
- /* (no confidence is the default) then we will only go though the */
- /* loop once. the confidence stuff originates from the folks at IBM */
-
- while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
- (confidence_iteration <= iteration_min)) {
-
- /* initialize a few counters. we have to remember that we might be */
- /* going through the loop more than once. */
-
- nummessages = 0;
- bytes_sent = 0.0;
- times_up = 0;
-
- /* set up the data socket */
- send_socket = create_data_socket(local_res);
-
- if (send_socket == INVALID_SOCKET){
- perror("netperf: sendfile_tcp_stream: tcp stream data socket");
- exit(1);
- }
-
- if (debug) {
- fprintf(where,"sendfile_tcp_stream: send_socket obtained...\n");
- }
-
-#if defined(TCP_CORK)
- /* should this even be here?!? */
- if (loc_tcpcork != 0) {
- /* the user wishes for us to set TCP_CORK on the socket */
- int one = 1;
- if (setsockopt(send_socket,
- getprotobyname("tcp")->p_proto,
- TCP_CORK,
- (char *)&one,
- sizeof(one)) == SOCKET_ERROR) {
- perror("netperf: sendfile_tcp_stream: tcp_cork");
- exit(1);
- }
- if (debug) {
- fprintf(where,"sendfile_tcp_stream: tcp_cork...\n");
- }
- }
-
-#endif /* TCP_CORK */
-
- /* at this point, we have either retrieved the socket buffer sizes, */
- /* or have tried to set them, so now, we may want to set the send */
- /* size based on that (because the user either did not use a -m */
- /* option, or used one with an argument of 0). If the socket buffer */
- /* size is not available, we will set the send size to 4KB - no */
- /* particular reason, just arbitrary... */
-
- /*check for file size/ min file size here? create file here/ back out???*/
-
- if (send_size == 0) {
- if (lss_size > 0) {
- send_size = lss_size;
- }
- else {
- send_size = 4096;
- }
- }
-
- /* set-up the data buffer ring with the requested alignment and
- offset. note also that we have allocated a quantity of memory
- that is at least one send-size greater than our socket buffer
- size. We want to be sure that there are at least two buffers
- allocated - this can be a bit of a problem when the send_size
- is bigger than the socket size, so we must check... the user
- may have wanted to explicitly set the "width" of our send
- buffers, we should respect that wish... */
-
- /*sendring -> an offset index that will shift the starting point of the*/
- /*section of the file sent throughout the file*/
-
- if (send_width == 0) {
- send_width = (lss_size/send_size) + 1;
- if (send_width == 1) send_width++;
- }
-
- if (send_ring == NULL) {
-
- /* only allocate the send ring once. this is a networking test,
- not a memory allocation test. this way, we do not need a
- deallocate_buffer_ring() routine, and I don't feel like
- writing one anyway :) raj 11/94 */
-
- send_ring = alloc_sendfile_buf_ring(send_width,
- send_size,
- local_send_align,
- local_send_offset);
- }
-
- /* If the user has requested cpu utilization measurements, we must
- calibrate the cpu(s). We will perform this task within the
- tests themselves. If the user has specified the cpu rate, then
- calibrate_local_cpu will return rather quickly as it will have
- nothing to do. If local_cpu_rate is zero, then we will go
- through all the "normal" calibration stuff and return the rate
- back. */
-
- if (local_cpu_usage) {
- local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
- }
-
- /* Tell the remote end to do a listen. The server alters the
- socket paramters on the other side at this point, hence the
- reason for all the values being passed in the setup
- message. If the user did not specify any of the parameters,
- they will be passed as 0, which will indicate to the remote
- that no changes beyond the system's default should be
- used. Alignment is the exception, it will default to 1, which
- will be no alignment alterations. */
-
- netperf_request.content.request_type = DO_TCP_STREAM;
- tcp_stream_request->send_buf_size = rss_size_req;
- tcp_stream_request->recv_buf_size = rsr_size_req;
- tcp_stream_request->receive_size = recv_size;
- tcp_stream_request->no_delay = rem_nodelay;
- tcp_stream_request->recv_alignment = remote_recv_align;
- tcp_stream_request->recv_offset = remote_recv_offset;
- tcp_stream_request->measure_cpu = remote_cpu_usage;
- tcp_stream_request->cpu_rate = remote_cpu_rate;
-
- if (test_time) {
- tcp_stream_request->test_length = test_time;
- }
- else {
- tcp_stream_request->test_length = test_bytes;
- }
-
- tcp_stream_request->so_rcvavoid = rem_rcvavoid;
- tcp_stream_request->so_sndavoid = rem_sndavoid;
-
-#ifdef DIRTY
- tcp_stream_request->dirty_count = rem_dirty_count;
- tcp_stream_request->clean_count = rem_clean_count;
-#endif /* DIRTY */
- tcp_stream_request->port = atoi(remote_data_port);
- tcp_stream_request->ipfamily = af_to_nf(remote_res->ai_family);
-
- if (debug > 1) {
- fprintf(where,
- "netperf: send_tcp_stream: requesting TCP stream test\n");
- }
-
- send_request();
-
- /* The response from the remote will contain all of the relevant
- socket parameters for this test type. We will put them back
- into the variables here so they can be displayed if desired.
- The remote will have calibrated CPU if necessary, and will have
- done all the needed set-up we will have calibrated the cpu
- locally before sending the request, and will grab the counter
- value right after the connect returns. The remote will grab the
- counter right after the accept call. This saves the hassle of
- extra messages being sent for the TCP tests. */
-
- recv_response();
-
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote listen done.\n");
- rsr_size = tcp_stream_response->recv_buf_size;
- rss_size = tcp_stream_response->send_buf_size;
- rem_nodelay = tcp_stream_response->no_delay;
- remote_cpu_usage= tcp_stream_response->measure_cpu;
- remote_cpu_rate = tcp_stream_response->cpu_rate;
-
- /* we have to make sure that the server port number is in */
- /* network order */
- set_port_number(remote_res,(short)tcp_stream_response->data_port_number);
- rem_rcvavoid = tcp_stream_response->so_rcvavoid;
- rem_sndavoid = tcp_stream_response->so_sndavoid;
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- fprintf(where,
- "netperf: remote error %d",
- netperf_response.content.serv_errno);
- perror("");
- fflush(where);
-
- exit(1);
- }
-
-#ifdef WANT_DEMO
- DEMO_STREAM_SETUP(lss_size,rsr_size)
-#endif
-
- /*Connect up to the remote port on the data socket */
- if (connect(send_socket,
- remote_res->ai_addr,
- remote_res->ai_addrlen) == INVALID_SOCKET){
- perror("netperf: send_tcp_stream: data socket connect failed");
- printf(" port: %d\n",ntohs(server.sin_port));
- exit(1);
- }
-
- /* Data Socket set-up is finished. If there were problems, either
- the connect would have failed, or the previous response would
- have indicated a problem. I failed to see the value of the
- extra message after the accept on the remote. If it failed,
- we'll see it here. If it didn't, we might as well start pumping
- data. */
-
- /* Set-up the test end conditions. For a stream test, they can be */
- /* either time or byte-count based. */
-
- if (test_time) {
- /* The user wanted to end the test after a period of time. */
- times_up = 0;
- bytes_remaining = 0;
-
- /* in previous revisions, we had the same code repeated throught
- all the test suites. this was unnecessary, and meant more
- work for me when I wanted to switch to POSIX signals, so I
- have abstracted this out into a routine in netlib.c. if you
- are experiencing signal problems, you might want to look
- there. raj 11/94 */
-
- start_timer(test_time);
- }
- else {
- /* The tester wanted to send a number of bytes. */
- bytes_remaining = test_bytes;
- times_up = 1;
- }
-
- /* The cpu_start routine will grab the current time and possibly */
- /* value of the idle counter for later use in measuring cpu */
- /* utilization and/or service demand and thruput. */
-
- cpu_start(local_cpu_usage);
-
-#ifdef WANT_INTERVALS
- INTERVALS_INIT();
-#endif /* WANT_INTERVALS */
-
-
- /* before we start, initialize a few variables */
-
-#ifdef WANT_DEMO
- if (demo_mode) {
- HIST_timestamp(demo_one_ptr);
- }
-#endif
-
- /* We use an "OR" to control test execution. When the test is
- controlled by time, the byte count check will always return
- false. When the test is controlled by byte count, the time test
- will always return false. When the test is finished, the whole
- expression will go false and we will stop sending data. */
-
- while ((!times_up) || (bytes_remaining > 0)) {
-
- /* the sendfile_tcp_stream test does not support making the buffers
- dirty. 08/2000 */
-
-#ifdef WANT_HISTOGRAM
- if (verbosity > 1) {
- /* timestamp just before we go into sendfile() and then again
- just after we come out raj 08/2000 */
- /* but only if we are actually going to display a histogram */
- HIST_timestamp(&time_one);
- }
-#endif /* WANT_HISTOGRAM */
-
- /* you can look at netlib.h for a description of the fields we
- are passing to sendfile(). 08/2000 */
-#ifdef QUICK_SENDPATH
- if ((len=sendpath(send_socket,
- fill_file,
- send_ring->offset,
- send_ring->length,
- send_ring->hdtrl,
- send_ring->flags)) != send_size)
-#elif defined(__linux)
- scratch_offset = send_ring->offset;
- if ((len=sendfile(send_socket,
- send_ring->fildes,
- &scratch_offset, /* modified after the call! */
- send_ring->length)) != send_size)
-#elif defined (__sun__)
- /* We must call with SFV_NOWAIT and a large file size (>= 16MB) to
- get zero-copy, as well as compiling with -D_LARGEFILE_SOURCE
- -D_FILE_OFFSET_BITS=64 */
- sv.sfv_fd = send_ring->fildes;
- sv.sfv_flag = SFV_NOWAIT;
- sv.sfv_off = send_ring->offset;
- sv.sfv_len = send_ring->length;
- if ((len = sendfilev(send_socket, &sv, 1, &scratch_len)) != send_size)
-#elif defined(__FreeBSD__)
- /* so close to HP-UX and yet so far away... :) */
- if ((sendfile(send_ring->fildes,
- send_socket,
- send_ring->offset,
- send_ring->length,
- NULL,
- (off_t *)&len,
- send_ring->flags) != 0) ||
- (len != send_size))
-#elif defined(USE_OSX)
- scratch_len = send_ring->length;
- if ((sendfile(send_ring->fildes,
- send_socket,
- send_ring->offset,
- (off_t *)&scratch_len,
- NULL,
- send_ring->flags) != 0) ||
- (scratch_len != send_size))
-#else /* original sendile HP-UX */
- if ((len=sendfile(send_socket,
- send_ring->fildes,
- send_ring->offset,
- send_ring->length,
- send_ring->hdtrl,
- send_ring->flags)) != send_size)
-#endif /* QUICK_SENDPATH */
- {
- /* the test was interrupted, must be the end of test. the
- send_tcp_stream code has some WIN32 ifdefs that we do not
- need here. */
- if ((len >=0) || SOCKET_EINTR(len)) {
- break;
- }
- perror("netperf: data send error: sendfile");
- fprintf(stderr,
- "len was %d send_size was %d\n",
- len,
- send_size);
- fflush(stderr);
- exit(1);
- }
-
- /* offset += len;*/
-
-#ifdef WANT_HISTOGRAM
- if (verbosity > 1) {
- /* timestamp the exit from the send call and update the
- histogram */
-
- HIST_timestamp(&time_two);
- HIST_add(time_hist,delta_micro(&time_one,&time_two));
- }
-#endif /* WANT_HISTOGRAM */
-
-#ifdef WANT_DEMO
- DEMO_STREAM_INTERVAL(send_size);
-#endif
-
-#ifdef WANT_INTERVALS
- INTERVALS_WAIT();
-#endif /* WANT_INTERVALS */
-
- /* now we want to move our pointer to the next position in the */
- /* data buffer...we may also want to wrap back to the "beginning" */
- /* of the bufferspace, so we will mod the number of messages sent */
- /* by the send width, and use that to calculate the offset to add */
- /* to the base pointer. */
-
- nummessages++;
- send_ring = send_ring->next;
- if (bytes_remaining) {
- bytes_remaining -= send_size;
- }
- }
-
- /* The test is over. Flush the buffers to the remote end. We do a
- graceful release to insure that all data has been taken by the
- remote. */
-
- /* but first, if the verbosity is greater than 1, find-out what */
- /* the TCP maximum segment_size was (if possible) */
- if (verbosity > 1) {
- tcp_mss = -1;
- get_tcp_info(send_socket,&tcp_mss);
- }
-
- if (shutdown(send_socket,SHUT_WR) == SOCKET_ERROR) {
- perror("netperf: cannot shutdown tcp stream socket");
- exit(1);
- }
-
- /* hang a recv() off the socket to block until the remote has */
- /* brought all the data up into the application. it will do a */
- /* shutdown to cause a FIN to be sent our way. We will assume that */
- /* any exit from the recv() call is good... raj 4/93 */
-
- /* since we are using sendfile() instead of send, we have no
- scratch buffer from the send_ring to use for the
- receive. however, since we "know" that the recv should be
- returning zero bytes (not that we are making the checks we
- should) we can pass the address of the flags field. raj 08/2000
- */
-
- recv(send_socket,
- &(send_ring->flags),
- sizeof(send_ring->flags),
- 0);
-
- /* this call will always give us the elapsed time for the test, and */
- /* will also store-away the necessaries for cpu utilization */
-
- cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */
- /* measured and how */
- /* long did we really */
- /* run? */
-
- /* we are finished with the socket, so close it to prevent hitting */
- /* the limit on maximum open files. */
-
- close(send_socket);
-
- /* Get the statistics from the remote end. The remote will have */
- /* calculated service demand and all those interesting things. If it */
- /* wasn't supposed to care, it will return obvious values. */
-
- recv_response();
-
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote results obtained\n");
- }
-
- else {
- Set_errno(netperf_response.content.serv_errno);
- fprintf(where,
- "netperf: remote error %d",
- netperf_response.content.serv_errno);
- perror("");
- fflush(where);
-
- exit(1);
- }
-
- /* We now calculate what our thruput was for the test. In the future, */
- /* we may want to include a calculation of the thruput measured by */
- /* the remote, but it should be the case that for a TCP stream test, */
- /* that the two numbers should be *very* close... We calculate */
- /* bytes_sent regardless of the way the test length was controlled. */
- /* If it was time, we needed to, and if it was by bytes, the user may */
- /* have specified a number of bytes that wasn't a multiple of the */
- /* send_size, so we really didn't send what he asked for ;-) */
-
- bytes_sent = ntohd(tcp_stream_result->bytes_received);
-
- thruput = calc_thruput(bytes_sent);
-
- if (local_cpu_usage || remote_cpu_usage) {
-
- /* We must now do a little math for service demand and cpu */
- /* utilization for the system(s) */
- /* Of course, some of the information might be bogus because */
- /* there was no idle counter in the kernel(s). We need to make */
- /* a note of this for the user's benefit...*/
- if (local_cpu_usage) {
-
- local_cpu_utilization = calc_cpu_util(0.0);
- local_service_demand = calc_service_demand(bytes_sent,
- 0.0,
- 0.0,
- 0);
- }
- else {
- local_cpu_utilization = (float) -1.0;
- local_service_demand = (float) -1.0;
- }
-
- if (remote_cpu_usage) {
-
- remote_cpu_utilization = tcp_stream_result->cpu_util;
- remote_service_demand = calc_service_demand(bytes_sent,
- 0.0,
- remote_cpu_utilization,
- tcp_stream_result->num_cpus);
- }
- else {
- remote_cpu_utilization = (float) -1.0;
- remote_service_demand = (float) -1.0;
- }
- }
- else {
- /* we were not measuring cpu, for the confidence stuff, we */
- /* should make it -1.0 */
- local_cpu_utilization = (float) -1.0;
- local_service_demand = (float) -1.0;
- remote_cpu_utilization = (float) -1.0;
- remote_service_demand = (float) -1.0;
- }
-
- /* at this point, we want to calculate the confidence information. */
- /* if debugging is on, calculate_confidence will print-out the */
- /* parameters we pass it */
-
- calculate_confidence(confidence_iteration,
- elapsed_time,
- thruput,
- local_cpu_utilization,
- remote_cpu_utilization,
- local_service_demand,
- remote_service_demand);
-
- confidence_iteration++;
- }
-
- /* at this point, we have finished making all the runs that we */
- /* will be making. so, we should extract what the calcuated values */
- /* are for all the confidence stuff. we could make the values */
- /* global, but that seemed a little messy, and it did not seem worth */
- /* all the mucking with header files. so, we create a routine much */
- /* like calcualte_confidence, which just returns the mean values. */
- /* raj 11/94 */
-
- retrieve_confident_values(&elapsed_time,
- &thruput,
- &local_cpu_utilization,
- &remote_cpu_utilization,
- &local_service_demand,
- &remote_service_demand);
-
- /* We are now ready to print all the information. If the user */
- /* has specified zero-level verbosity, we will just print the */
- /* local service demand, or the remote service demand. If the */
- /* user has requested verbosity level 1, he will get the basic */
- /* "streamperf" numbers. If the user has specified a verbosity */
- /* of greater than 1, we will display a veritable plethora of */
- /* background information from outside of this block as it it */
- /* not cpu_measurement specific... */
-
- if (confidence < 0) {
- /* we did not hit confidence, but were we asked to look for it? */
- if (iteration_max > 1) {
- display_confidence();
- }
- }
-
- if (local_cpu_usage || remote_cpu_usage) {
- local_cpu_method = format_cpu_method(cpu_method);
- remote_cpu_method = format_cpu_method(tcp_stream_result->cpu_method);
-
- switch (verbosity) {
- case 0:
-
- if (local_cpu_usage) {
- fprintf(where,
- cpu_fmt_0,
- local_service_demand,
- local_cpu_method);
- }
-
- else {
- fprintf(where,
- cpu_fmt_0,
- remote_service_demand,
- remote_cpu_method);
- }
-
- break;
-
- case 1:
- case 2:
- if (print_headers) {
- fprintf(where,
- cpu_title,
- format_units(),
- local_cpu_method,
- remote_cpu_method);
- }
-
- fprintf(where,
- cpu_fmt_1, /* the format string */
- rsr_size, /* remote recvbuf size */
- lss_size, /* local sendbuf size */
- send_size, /* how large were the sends */
- elapsed_time, /* how long was the test */
- thruput, /* what was the xfer rate */
- local_cpu_utilization, /* local cpu */
- remote_cpu_utilization, /* remote cpu */
- local_service_demand, /* local service demand */
- remote_service_demand); /* remote service demand */
- break;
- }
-
- }
-
- else {
- /* The tester did not wish to measure service demand. */
-
- switch (verbosity) {
-
- case 0:
-
- fprintf(where,
- tput_fmt_0,
- thruput);
- break;
-
- case 1:
- case 2:
-
- if (print_headers) {
- fprintf(where,tput_title,format_units());
- }
-
- fprintf(where,
- tput_fmt_1, /* the format string */
- rsr_size, /* remote recvbuf size */
- lss_size, /* local sendbuf size */
- send_size, /* how large were the sends */
- elapsed_time, /* how long did it take */
- thruput);/* how fast did it go */
- break;
- }
- }
-
- /* it would be a good thing to include information about some of the */
- /* other parameters that may have been set for this test, but at the */
- /* moment, I do not wish to figure-out all the formatting, so I will */
- /* just put this comment here to help remind me that it is something */
- /* that should be done at a later time. */
-
- if (verbosity > 1) {
-
- /* The user wanted to know it all, so we will give it to him. */
- /* This information will include as much as we can find about */
- /* TCP statistics, the alignments of the sends and receives */
- /* and all that sort of rot... */
-
- /* this stuff needs to be worked-out in the presence of confidence */
- /* intervals and multiple iterations of the test... raj 11/94 */
-
- fprintf(where,
- ksink_fmt,
- "Bytes",
- "Bytes",
- "Bytes",
- local_send_align,
- remote_recv_align,
- local_send_offset,
- remote_recv_offset,
- bytes_sent,
- bytes_sent / (double)nummessages,
- nummessages,
- bytes_sent / (double)tcp_stream_result->recv_calls,
- tcp_stream_result->recv_calls);
-
- fprintf(where,
- ksink_fmt2,
- tcp_mss);
-
- fflush(where);
-
-#ifdef WANT_HISTOGRAM
-
- fprintf(where,"\n\nHistogram of time spent in send() call.\n");
- fflush(where);
- HIST_report(time_hist);
-#endif /* WANT_HISTOGRAM */
- }
-}
-
-#endif /* HAVE_SENDFILE */
-
-/* This is the server-side routine for the tcp stream test. It is */
-/* implemented as one routine. I could break things-out somewhat, but */
-/* didn't feel it was necessary. */
-
-void
-recv_tcp_stream()
-{
-
- struct sockaddr_storage myaddr_in, peeraddr_in;
- SOCKET s_listen,s_data;
- netperf_socklen_t addrlen;
- int len;
- unsigned int receive_calls;
- float elapsed_time;
- double bytes_received;
-
- struct ring_elt *recv_ring;
-
- struct addrinfo *local_res;
- char local_name[BUFSIZ];
- char port_buffer[PORTBUFSIZE];
-
-#ifdef DO_SELECT
- fd_set readfds;
- struct timeval timeout;
-#endif /* DO_SELECT */
-
- struct tcp_stream_request_struct *tcp_stream_request;
- struct tcp_stream_response_struct *tcp_stream_response;
- struct tcp_stream_results_struct *tcp_stream_results;
-
-#ifdef DO_SELECT
- FD_ZERO(&readfds);
- timeout.tv_sec = 1;
- timeout.tv_usec = 0;
-#endif /* DO_SELECT */
-
- tcp_stream_request =
- (struct tcp_stream_request_struct *)netperf_request.content.test_specific_data;
- tcp_stream_response =
- (struct tcp_stream_response_struct *)netperf_response.content.test_specific_data;
- tcp_stream_results =
- (struct tcp_stream_results_struct *)netperf_response.content.test_specific_data;
-
- if (debug) {
- fprintf(where,"netserver: recv_tcp_stream: entered...\n");
- fflush(where);
- }
-
- /* We want to set-up the listen socket with all the desired */
- /* parameters and then let the initiator know that all is ready. If */
- /* socket size defaults are to be used, then the initiator will have */
- /* sent us 0's. If the socket sizes cannot be changed, then we will */
- /* send-back what they are. If that information cannot be determined, */
- /* then we send-back -1's for the sizes. If things go wrong for any */
- /* reason, we will drop back ten yards and punt. */
-
- /* If anything goes wrong, we want the remote to know about it. It */
- /* would be best if the error that the remote reports to the user is */
- /* the actual error we encountered, rather than some bogus unexpected */
- /* response type message. */
-
- if (debug) {
- fprintf(where,"recv_tcp_stream: setting the response type...\n");
- fflush(where);
- }
-
- netperf_response.content.response_type = TCP_STREAM_RESPONSE;
-
- if (debug) {
- fprintf(where,"recv_tcp_stream: the response type is set...\n");
- fflush(where);
- }
-
- /* We now alter the message_ptr variable to be at the desired */
- /* alignment with the desired offset. */
-
- if (debug) {
- fprintf(where,"recv_tcp_stream: requested alignment of %d\n",
- tcp_stream_request->recv_alignment);
- fflush(where);
- }
-
- /* create_data_socket expects to find some things in the global */
- /* variables, so set the globals based on the values in the request. */
- /* once the socket has been created, we will set the response values */
- /* based on the updated value of those globals. raj 7/94 */
- lss_size_req = tcp_stream_request->send_buf_size;
- lsr_size_req = tcp_stream_request->recv_buf_size;
- loc_nodelay = tcp_stream_request->no_delay;
- loc_rcvavoid = tcp_stream_request->so_rcvavoid;
- loc_sndavoid = tcp_stream_request->so_sndavoid;
-
- set_hostname_and_port(local_name,
- port_buffer,
- nf_to_af(tcp_stream_request->ipfamily),
- tcp_stream_request->port);
-
- local_res = complete_addrinfo(local_name,
- local_name,
- port_buffer,
- nf_to_af(tcp_stream_request->ipfamily),
- SOCK_STREAM,
- IPPROTO_TCP,
- 0);
-
- s_listen = create_data_socket(local_res);
-
- if (s_listen == INVALID_SOCKET) {
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
-
-#ifdef WIN32
- /* The test timer can fire during operations on the listening socket,
- so to make the start_timer below work we have to move
- it to close s_listen while we are blocked on accept. */
- win_kludge_socket2 = s_listen;
-#endif
-
- /* what sort of sizes did we end-up with? */
- if (tcp_stream_request->receive_size == 0) {
- if (lsr_size > 0) {
- recv_size = lsr_size;
- }
- else {
- recv_size = 4096;
- }
- }
- else {
- recv_size = tcp_stream_request->receive_size;
- }
-
- /* we want to set-up our recv_ring in a manner analagous to what we */
- /* do on the sending side. this is more for the sake of symmetry */
- /* than for the needs of say copy avoidance, but it might also be */
- /* more realistic - this way one could conceivably go with a */
- /* double-buffering scheme when taking the data an putting it into */
- /* the filesystem or something like that. raj 7/94 */
-
- if (recv_width == 0) {
- recv_width = (lsr_size/recv_size) + 1;
- if (recv_width == 1) recv_width++;
- }
-
- recv_ring = allocate_buffer_ring(recv_width,
- recv_size,
- tcp_stream_request->recv_alignment,
- tcp_stream_request->recv_offset);
-
- if (debug) {
- fprintf(where,"recv_tcp_stream: receive alignment and offset set...\n");
- fflush(where);
- }
-
- /* Now, let's set-up the socket to listen for connections */
- if (listen(s_listen, 5) == SOCKET_ERROR) {
- netperf_response.content.serv_errno = errno;
- close(s_listen);
- send_response();
-
- exit(1);
- }
-
-
- /* now get the port number assigned by the system */
- addrlen = sizeof(myaddr_in);
- if (getsockname(s_listen,
- (struct sockaddr *)&myaddr_in,
- &addrlen) == SOCKET_ERROR){
- netperf_response.content.serv_errno = errno;
- close(s_listen);
- send_response();
-
- exit(1);
- }
-
- /* Now myaddr_in contains the port and the internet address this is */
- /* returned to the sender also implicitly telling the sender that the */
- /* socket buffer sizing has been done. */
-
- tcp_stream_response->data_port_number =
- (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port);
- netperf_response.content.serv_errno = 0;
-
- /* But wait, there's more. If the initiator wanted cpu measurements, */
- /* then we must call the calibrate routine, which will return the max */
- /* rate back to the initiator. If the CPU was not to be measured, or */
- /* something went wrong with the calibration, we will return a -1 to */
- /* the initiator. */
-
- tcp_stream_response->cpu_rate = (float)0.0; /* assume no cpu */
- if (tcp_stream_request->measure_cpu) {
- tcp_stream_response->measure_cpu = 1;
- tcp_stream_response->cpu_rate =
- calibrate_local_cpu(tcp_stream_request->cpu_rate);
- }
- else {
- tcp_stream_response->measure_cpu = 0;
- }
-
- /* before we send the response back to the initiator, pull some of */
- /* the socket parms from the globals */
- tcp_stream_response->send_buf_size = lss_size;
- tcp_stream_response->recv_buf_size = lsr_size;
- tcp_stream_response->no_delay = loc_nodelay;
- tcp_stream_response->so_rcvavoid = loc_rcvavoid;
- tcp_stream_response->so_sndavoid = loc_sndavoid;
- tcp_stream_response->receive_size = recv_size;
-
- send_response();
-
- addrlen = sizeof(peeraddr_in);
-
- if ((s_data=accept(s_listen,
- (struct sockaddr *)&peeraddr_in,
- &addrlen)) == INVALID_SOCKET) {
- /* Let's just punt. The remote will be given some information */
- close(s_listen);
- exit(1);
- }
-
-#ifdef KLUDGE_SOCKET_OPTIONS
- /* this is for those systems which *INCORRECTLY* fail to pass */
- /* attributes across an accept() call. Including this goes against */
- /* my better judgement :( raj 11/95 */
-
- kludge_socket_options(s_data);
-
-#endif /* KLUDGE_SOCKET_OPTIONS */
-
- /* Now it's time to start receiving data on the connection. We will */
- /* first grab the apropriate counters and then start grabbing. */
-
- cpu_start(tcp_stream_request->measure_cpu);
-
- /* The loop will exit when the sender does a shutdown, which will */
- /* return a length of zero */
-
- /* there used to be an #ifdef DIRTY call to access_buffer() here,
- but we have switched from accessing the buffer before the recv()
- call to accessing the buffer after the recv() call. The
- accessing before was, IIRC, related to having dirty data when
- doing page-flipping copy avoidance. */
-
- bytes_received = 0;
- receive_calls = 0;
-
- while ((len = recv(s_data, recv_ring->buffer_ptr, recv_size, 0)) != 0) {
- if (len == SOCKET_ERROR )
- {
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
- bytes_received += len;
- receive_calls++;
-
-#ifdef DIRTY
- /* we access the buffer after the recv() call now, rather than before */
- access_buffer(recv_ring->buffer_ptr,
- recv_size,
- tcp_stream_request->dirty_count,
- tcp_stream_request->clean_count);
-#endif /* DIRTY */
-
-
- /* move to the next buffer in the recv_ring */
- recv_ring = recv_ring->next;
-
-#ifdef PAUSE
- sleep(1);
-#endif /* PAUSE */
-
-#ifdef DO_SELECT
- FD_SET(s_data,&readfds);
- select(s_data+1,&readfds,NULL,NULL,&timeout);
-#endif /* DO_SELECT */
-
- }
-
- /* perform a shutdown to signal the sender that */
- /* we have received all the data sent. raj 4/93 */
-
- if (shutdown(s_data,SHUT_WR) == SOCKET_ERROR) {
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
-
- cpu_stop(tcp_stream_request->measure_cpu,&elapsed_time);
-
- /* send the results to the sender */
-
- if (debug) {
- fprintf(where,
- "recv_tcp_stream: got %g bytes\n",
- bytes_received);
- fprintf(where,
- "recv_tcp_stream: got %d recvs\n",
- receive_calls);
- fflush(where);
- }
-
- tcp_stream_results->bytes_received = htond(bytes_received);
- tcp_stream_results->elapsed_time = elapsed_time;
- tcp_stream_results->recv_calls = receive_calls;
-
- tcp_stream_results->cpu_method = cpu_method;
- tcp_stream_results->num_cpus = lib_num_loc_cpus;
-
- if (tcp_stream_request->measure_cpu) {
- tcp_stream_results->cpu_util = calc_cpu_util(0.0);
- };
-
- if (debug) {
- fprintf(where,
- "recv_tcp_stream: test complete, sending results.\n");
- fprintf(where,
- " bytes_received %g receive_calls %d\n",
- bytes_received,
- receive_calls);
- fprintf(where,
- " len %d\n",
- len);
- fflush(where);
- }
-
- send_response();
-
- /* we are now done with the sockets */
- close(s_data);
- close(s_listen);
-
- }
-
-/* This is the server-side routine for the tcp maerts test. It is
- implemented as one routine. I could break things-out somewhat, but
- didn't feel it was necessary. */
-
-void
-recv_tcp_maerts()
-{
-
- struct sockaddr_storage myaddr_in, peeraddr_in;
- struct addrinfo *local_res;
- char local_name[BUFSIZ];
- char port_buffer[PORTBUFSIZE];
-
- SOCKET s_listen,s_data;
- netperf_socklen_t addrlen;
- int len;
- unsigned int send_calls;
- float elapsed_time;
- double bytes_sent = 0.0 ;
-
- struct ring_elt *send_ring;
-
- struct tcp_maerts_request_struct *tcp_maerts_request;
- struct tcp_maerts_response_struct *tcp_maerts_response;
- struct tcp_maerts_results_struct *tcp_maerts_results;
-
- tcp_maerts_request =
- (struct tcp_maerts_request_struct *)netperf_request.content.test_specific_data;
- tcp_maerts_response =
- (struct tcp_maerts_response_struct *)netperf_response.content.test_specific_data;
- tcp_maerts_results =
- (struct tcp_maerts_results_struct *)netperf_response.content.test_specific_data;
-
- if (debug) {
- fprintf(where,"netserver: recv_tcp_maerts: entered...\n");
- fflush(where);
- }
-
- /* We want to set-up the listen socket with all the desired
- parameters and then let the initiator know that all is ready. If
- socket size defaults are to be used, then the initiator will have
- sent us 0's. If the socket sizes cannot be changed, then we will
- send-back what they are. If that information cannot be
- determined, then we send-back -1's for the sizes. If things go
- wrong for any reason, we will drop back ten yards and punt. */
-
- /* If anything goes wrong, we want the remote to know about it. It
- would be best if the error that the remote reports to the user is
- the actual error we encountered, rather than some bogus
- unexpected response type message. */
-
- if (debug) {
- fprintf(where,"recv_tcp_maerts: setting the response type...\n");
- fflush(where);
- }
-
- netperf_response.content.response_type = TCP_MAERTS_RESPONSE;
-
- if (debug) {
- fprintf(where,"recv_tcp_maerts: the response type is set...\n");
- fflush(where);
- }
-
- /* We now alter the message_ptr variable to be at the desired */
- /* alignment with the desired offset. */
-
- if (debug) {
- fprintf(where,"recv_tcp_maerts: requested alignment of %d\n",
- tcp_maerts_request->send_alignment);
- fflush(where);
- }
-
- /* Grab a socket to listen on, and then listen on it. */
-
- if (debug) {
- fprintf(where,"recv_tcp_maerts: grabbing a socket...\n");
- fflush(where);
- }
-
- /* create_data_socket expects to find some things in the global */
- /* variables, so set the globals based on the values in the request. */
- /* once the socket has been created, we will set the response values */
- /* based on the updated value of those globals. raj 7/94 */
- lss_size_req = tcp_maerts_request->send_buf_size;
- lsr_size_req = tcp_maerts_request->recv_buf_size;
- loc_nodelay = tcp_maerts_request->no_delay;
- loc_rcvavoid = tcp_maerts_request->so_rcvavoid;
- loc_sndavoid = tcp_maerts_request->so_sndavoid;
-
- set_hostname_and_port(local_name,
- port_buffer,
- nf_to_af(tcp_maerts_request->ipfamily),
- tcp_maerts_request->port);
-
- local_res = complete_addrinfo(local_name,
- local_name,
- port_buffer,
- nf_to_af(tcp_maerts_request->ipfamily),
- SOCK_STREAM,
- IPPROTO_TCP,
- 0);
-
- s_listen = create_data_socket(local_res);
-
- if (s_listen == INVALID_SOCKET) {
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
-
-#ifdef WIN32
- /* The test timer can fire during operations on the listening socket,
- so to make the start_timer below work we have to move
- it to close s_listen while we are blocked on accept. */
- win_kludge_socket2 = s_listen;
-#endif
-
-
- /* what sort of sizes did we end-up with? */
- if (tcp_maerts_request->send_size == 0) {
- if (lss_size > 0) {
- send_size = lss_size;
- }
- else {
- send_size = 4096;
- }
- }
- else {
- send_size = tcp_maerts_request->send_size;
- }
-
- /* we want to set-up our recv_ring in a manner analagous to what we */
- /* do on the recving side. this is more for the sake of symmetry */
- /* than for the needs of say copy avoidance, but it might also be */
- /* more realistic - this way one could conceivably go with a */
- /* double-buffering scheme when taking the data an putting it into */
- /* the filesystem or something like that. raj 7/94 */
-
- if (send_width == 0) {
- send_width = (lsr_size/send_size) + 1;
- if (send_width == 1) send_width++;
- }
-
- send_ring = allocate_buffer_ring(send_width,
- send_size,
- tcp_maerts_request->send_alignment,
- tcp_maerts_request->send_offset);
-
- if (debug) {
- fprintf(where,"recv_tcp_maerts: receive alignment and offset set...\n");
- fflush(where);
- }
-
- /* Now, let's set-up the socket to listen for connections */
- if (listen(s_listen, 5) == SOCKET_ERROR) {
- netperf_response.content.serv_errno = errno;
- close(s_listen);
- send_response();
-
- exit(1);
- }
-
-
- /* now get the port number assigned by the system */
- addrlen = sizeof(myaddr_in);
- if (getsockname(s_listen,
- (struct sockaddr *)&myaddr_in,
- &addrlen) == SOCKET_ERROR){
- netperf_response.content.serv_errno = errno;
- close(s_listen);
- send_response();
-
- exit(1);
- }
-
- /* Now myaddr_in contains the port and the internet address this is */
- /* returned to the sender also implicitly telling the sender that the */
- /* socket buffer sizing has been done. */
-
- tcp_maerts_response->data_port_number =
- (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port);
- netperf_response.content.serv_errno = 0;
-
- /* But wait, there's more. If the initiator wanted cpu measurements, */
- /* then we must call the calibrate routine, which will return the max */
- /* rate back to the initiator. If the CPU was not to be measured, or */
- /* something went wrong with the calibration, we will return a -1 to */
- /* the initiator. */
-
- tcp_maerts_response->cpu_rate = (float)0.0; /* assume no cpu */
- if (tcp_maerts_request->measure_cpu) {
- tcp_maerts_response->measure_cpu = 1;
- tcp_maerts_response->cpu_rate =
- calibrate_local_cpu(tcp_maerts_request->cpu_rate);
- }
- else {
- tcp_maerts_response->measure_cpu = 0;
- }
-
- /* before we send the response back to the initiator, pull some of */
- /* the socket parms from the globals */
- tcp_maerts_response->send_buf_size = lss_size;
- tcp_maerts_response->recv_buf_size = lsr_size;
- tcp_maerts_response->no_delay = loc_nodelay;
- tcp_maerts_response->so_rcvavoid = loc_rcvavoid;
- tcp_maerts_response->so_sndavoid = loc_sndavoid;
- tcp_maerts_response->send_size = send_size;
-
- send_response();
-
- addrlen = sizeof(peeraddr_in);
-
- /* we will start the timer before the accept() to be somewhat
- analagous to the starting of the timer before the connect() call
- in the TCP_STREAM test. raj 2002-06-21 */
-
- start_timer(tcp_maerts_request->test_length);
-
- /* Now it's time to start receiving data on the connection. We will
- first grab the apropriate counters and then start grabbing. */
-
- cpu_start(tcp_maerts_request->measure_cpu);
-
-
- if ((s_data=accept(s_listen,
- (struct sockaddr *)&peeraddr_in,
- &addrlen)) == INVALID_SOCKET) {
- /* Let's just punt. The remote will be given some information */
- close(s_listen);
- exit(1);
- }
-
-#ifdef KLUDGE_SOCKET_OPTIONS
-
- /* this is for those systems which *INCORRECTLY* fail to pass
- attributes across an accept() call. Including this goes against
- my better judgement :( raj 11/95 */
-
- kludge_socket_options(s_data);
-
-#endif /* KLUDGE_SOCKET_OPTIONS */
-
- /* The loop will exit when the sender does a shutdown, which will */
- /* return a length of zero */
-
- bytes_sent = 0.0;
- send_calls = 0;
-
- len = 0; /* nt-lint; len is not initialized (printf far below) if
- times_up initially true.*/
- times_up = 0; /* must remember to initialize this little beauty */
- while (!times_up) {
-
-#ifdef DIRTY
- /* we want to dirty some number of consecutive integers in the buffer */
- /* we are about to send. we may also want to bring some number of */
- /* them cleanly into the cache. The clean ones will follow any dirty */
- /* ones into the cache. */
-
- access_buffer(send_ring->buffer_ptr,
- send_size,
- tcp_maerts_request->dirty_count,
- tcp_maerts_request->clean_count);
-
-#endif /* DIRTY */
-
- if((len=send(s_data,
- send_ring->buffer_ptr,
- send_size,
- 0)) != send_size) {
- if ((len >=0) || SOCKET_EINTR(len)) {
- /* the test was interrupted, must be the end of test */
- break;
- }
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
-
- bytes_sent += len;
- send_calls++;
-
- /* more to the next buffer in the send_ring */
- send_ring = send_ring->next;
-
- }
-
- /* perform a shutdown to signal the sender that */
- /* we have received all the data sent. raj 4/93 */
-
- if (shutdown(s_data,SHUT_WR) == SOCKET_ERROR) {
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
-
- /* hang a recv() off the socket to block until the remote has
- brought all the data up into the application. it will do a
- shutdown to cause a FIN to be sent our way. We will assume that
- any exit from the recv() call is good... raj 4/93 */
-
- recv(s_data, send_ring->buffer_ptr, send_size, 0);
-
-
- cpu_stop(tcp_maerts_request->measure_cpu,&elapsed_time);
-
- /* send the results to the sender */
-
- if (debug) {
- fprintf(where,
- "recv_tcp_maerts: got %g bytes\n",
- bytes_sent);
- fprintf(where,
- "recv_tcp_maerts: got %d sends\n",
- send_calls);
- fflush(where);
- }
-
- tcp_maerts_results->bytes_sent = htond(bytes_sent);
- tcp_maerts_results->elapsed_time = elapsed_time;
- tcp_maerts_results->send_calls = send_calls;
-
- if (tcp_maerts_request->measure_cpu) {
- tcp_maerts_results->cpu_util = calc_cpu_util(0.0);
- };
-
- if (debug) {
- fprintf(where,
- "recv_tcp_maerts: test complete, sending results.\n");
- fprintf(where,
- " bytes_sent %g send_calls %d\n",
- bytes_sent,
- send_calls);
- fprintf(where,
- " len %d\n",
- len);
- fflush(where);
- }
-
- tcp_maerts_results->cpu_method = cpu_method;
- tcp_maerts_results->num_cpus = lib_num_loc_cpus;
- send_response();
-
- /* we are now done with the sockets */
- close(s_data);
- close(s_listen);
-
- }
-
-
- /* this routine implements the sending (netperf) side of the TCP_RR */
- /* test. */
-
-void
-send_tcp_rr(char remote_host[])
-{
-
- char *tput_title = "\
-Local /Remote\n\
-Socket Size Request Resp. Elapsed Trans.\n\
-Send Recv Size Size Time Rate \n\
-bytes Bytes bytes bytes secs. per sec \n\n";
-
- char *tput_title_band = "\
-Local /Remote\n\
-Socket Size Request Resp. Elapsed \n\
-Send Recv Size Size Time Throughput \n\
-bytes Bytes bytes bytes secs. %s/sec \n\n";
-
- char *tput_fmt_0 =
- "%7.2f %s\n";
-
- char *tput_fmt_1_line_1 = "\
-%-6d %-6d %-6d %-6d %-6.2f %7.2f %s\n";
- char *tput_fmt_1_line_2 = "\
-%-6d %-6d\n";
-
- char *cpu_title = "\
-Local /Remote\n\
-Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\
-Send Recv Size Size Time Rate local remote local remote\n\
-bytes bytes bytes bytes secs. per sec %% %c %% %c us/Tr us/Tr\n\n";
-
- char *cpu_title_tput = "\
-Local /Remote\n\
-Socket Size Request Resp. Elapsed Tput CPU CPU S.dem S.dem\n\
-Send Recv Size Size Time %-8.8s local remote local remote\n\
-bytes bytes bytes bytes secs. per sec %% %c %% %c us/Tr us/Tr\n\n";
-
- char *cpu_fmt_0 =
- "%6.3f %c %s\n";
-
- char *cpu_fmt_1_line_1 = "\
-%-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f %s\n";
-
- char *cpu_fmt_1_line_2 = "\
-%-6d %-6d\n";
-
- char *ksink_fmt = "\
-Alignment Offset RoundTrip Trans Throughput\n\
-Local Remote Local Remote Latency Rate %-8.8s/s\n\
-Send Recv Send Recv usec/Tran per sec Outbound Inbound\n\
-%5d %5d %5d %5d %-6.3f %-6.3f %-6.3f %-6.3f\n";
-
-
- int timed_out = 0;
- float elapsed_time;
-
- int len;
- char *temp_message_ptr;
- int nummessages;
- SOCKET send_socket;
- int trans_remaining;
- double bytes_xferd;
-
- struct ring_elt *send_ring;
- struct ring_elt *recv_ring;
-
- int rsp_bytes_left;
- int rsp_bytes_recvd;
-
- float local_cpu_utilization;
- float local_service_demand;
- float remote_cpu_utilization;
- float remote_service_demand;
- double thruput;
-
- struct addrinfo *local_res;
- struct addrinfo *remote_res;
-
- struct tcp_rr_request_struct *tcp_rr_request;
- struct tcp_rr_response_struct *tcp_rr_response;
- struct tcp_rr_results_struct *tcp_rr_result;
-
-#ifdef WANT_FIRST_BURST
-#define REQUEST_CWND_INITIAL 2
- /* "in the beginning..." the WANT_FIRST_BURST stuff was like both
- Unix and the state of New Jersey - both were simple an unspoiled.
- then it was realized that some stacks are quite picky about
- initial congestion windows and a non-trivial initial burst of
- requests would not be individual segments even with TCP_NODELAY
- set. so, we have to start tracking a poor-man's congestion window
- up here in window space because we want to try to make something
- happen that frankly, we cannot guarantee with the specification
- of TCP. ain't that grand?-) raj 2006-01-30 */
- int requests_outstanding = 0;
- int request_cwnd = REQUEST_CWND_INITIAL; /* we ass-u-me that having
- three requests
- outstanding at the
- beginning of the test
- is ok with TCP stacks
- of interest. the first
- two will come from our
- first_burst loop, and
- the third from our
- regularly scheduled
- send */
-#endif
-
- tcp_rr_request =
- (struct tcp_rr_request_struct *)netperf_request.content.test_specific_data;
- tcp_rr_response=
- (struct tcp_rr_response_struct *)netperf_response.content.test_specific_data;
- tcp_rr_result =
- (struct tcp_rr_results_struct *)netperf_response.content.test_specific_data;
-
-#ifdef WANT_HISTOGRAM
- if (verbosity > 1) {
- time_hist = HIST_new();
- }
-#endif /* WANT_HISTOGRAM */
-
- /* since we are now disconnected from the code that established the */
- /* control socket, and since we want to be able to use different */
- /* protocols and such, we are passed the name of the remote host and */
- /* must turn that into the test specific addressing information. */
-
- complete_addrinfos(&remote_res,
- &local_res,
- remote_host,
- SOCK_STREAM,
- IPPROTO_TCP,
- 0);
-
- if ( print_headers ) {
- print_top_test_header("TCP REQUEST/RESPONSE TEST",local_res,remote_res);
- }
-
- /* initialize a few counters */
-
- send_ring = NULL;
- recv_ring = NULL;
- confidence_iteration = 1;
- init_stat();
-
- /* we have a great-big while loop which controls the number of times */
- /* we run a particular test. this is for the calculation of a */
- /* confidence interval (I really should have stayed awake during */
- /* probstats :). If the user did not request confidence measurement */
- /* (no confidence is the default) then we will only go though the */
- /* loop once. the confidence stuff originates from the folks at IBM */
-
- while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
- (confidence_iteration <= iteration_min)) {
-
- /* initialize a few counters. we have to remember that we might be */
- /* going through the loop more than once. */
-
- nummessages = 0;
- bytes_xferd = 0.0;
- times_up = 0;
- timed_out = 0;
- trans_remaining = 0;
-
-#ifdef WANT_FIRST_BURST
- /* we have to remember to reset the number of transactions
- outstanding and the "congestion window for each new
- iteration. raj 2006-01-31 */
- requests_outstanding = 0;
- request_cwnd = REQUEST_CWND_INITIAL;
-#endif
-
-
- /* set-up the data buffers with the requested alignment and offset. */
- /* since this is a request/response test, default the send_width and */
- /* recv_width to 1 and not two raj 7/94 */
-
- if (send_width == 0) send_width = 1;
- if (recv_width == 0) recv_width = 1;
-
- if (send_ring == NULL) {
- send_ring = allocate_buffer_ring(send_width,
- req_size,
- local_send_align,
- local_send_offset);
- }
-
- if (recv_ring == NULL) {
- recv_ring = allocate_buffer_ring(recv_width,
- rsp_size,
- local_recv_align,
- local_recv_offset);
- }
-
- /*set up the data socket */
- send_socket = create_data_socket(local_res);
-
- if (send_socket == INVALID_SOCKET){
- perror("netperf: send_tcp_rr: tcp stream data socket");
- exit(1);
- }
-
- if (debug) {
- fprintf(where,"send_tcp_rr: send_socket obtained...\n");
- }
-
- /* If the user has requested cpu utilization measurements, we must */
- /* calibrate the cpu(s). We will perform this task within the tests */
- /* themselves. If the user has specified the cpu rate, then */
- /* calibrate_local_cpu will return rather quickly as it will have */
- /* nothing to do. If local_cpu_rate is zero, then we will go through */
- /* all the "normal" calibration stuff and return the rate back.*/
-
- if (local_cpu_usage) {
- local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
- }
-
- if (!no_control) {
- /* Tell the remote end to do a listen. The server alters the
- socket paramters on the other side at this point, hence the
- reason for all the values being passed in the setup
- message. If the user did not specify any of the parameters,
- they will be passed as 0, which will indicate to the remote
- that no changes beyond the system's default should be
- used. Alignment is the exception, it will default to 8, which
- will be no alignment alterations. */
-
- netperf_request.content.request_type = DO_TCP_RR;
- tcp_rr_request->recv_buf_size = rsr_size_req;
- tcp_rr_request->send_buf_size = rss_size_req;
- tcp_rr_request->recv_alignment = remote_recv_align;
- tcp_rr_request->recv_offset = remote_recv_offset;
- tcp_rr_request->send_alignment = remote_send_align;
- tcp_rr_request->send_offset = remote_send_offset;
- tcp_rr_request->request_size = req_size;
- tcp_rr_request->response_size = rsp_size;
- tcp_rr_request->no_delay = rem_nodelay;
- tcp_rr_request->measure_cpu = remote_cpu_usage;
- tcp_rr_request->cpu_rate = remote_cpu_rate;
- tcp_rr_request->so_rcvavoid = rem_rcvavoid;
- tcp_rr_request->so_sndavoid = rem_sndavoid;
- if (test_time) {
- tcp_rr_request->test_length = test_time;
- }
- else {
- tcp_rr_request->test_length = test_trans * -1;
- }
- tcp_rr_request->port = atoi(remote_data_port);
- tcp_rr_request->ipfamily = af_to_nf(remote_res->ai_family);
-
- if (debug > 1) {
- fprintf(where,"netperf: send_tcp_rr: requesting TCP rr test\n");
- }
-
- send_request();
-
- /* The response from the remote will contain all of the relevant
- socket parameters for this test type. We will put them back
- into the variables here so they can be displayed if desired.
- The remote will have calibrated CPU if necessary, and will
- have done all the needed set-up we will have calibrated the
- cpu locally before sending the request, and will grab the
- counter value right after the connect returns. The remote
- will grab the counter right after the accept call. This saves
- the hassle of extra messages being sent for the TCP
- tests. */
-
- recv_response();
-
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote listen done.\n");
- rsr_size = tcp_rr_response->recv_buf_size;
- rss_size = tcp_rr_response->send_buf_size;
- rem_nodelay = tcp_rr_response->no_delay;
- remote_cpu_usage = tcp_rr_response->measure_cpu;
- remote_cpu_rate = tcp_rr_response->cpu_rate;
- /* make sure that port numbers are in network order */
- set_port_number(remote_res,(short)tcp_rr_response->data_port_number);
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- fprintf(where,
- "netperf: remote error %d",
- netperf_response.content.serv_errno);
- perror("");
- fflush(where);
-
- exit(1);
- }
- }
-
-#ifdef WANT_DEMO
- DEMO_RR_SETUP(1000)
-#endif
-
- /*Connect up to the remote port on the data socket */
- if (connect(send_socket,
- remote_res->ai_addr,
- remote_res->ai_addrlen) == INVALID_SOCKET){
- perror("netperf: data socket connect failed");
-
- exit(1);
- }
-
- /* Data Socket set-up is finished. If there were problems, either the */
- /* connect would have failed, or the previous response would have */
- /* indicated a problem. I failed to see the value of the extra */
- /* message after the accept on the remote. If it failed, we'll see it */
- /* here. If it didn't, we might as well start pumping data. */
-
- /* Set-up the test end conditions. For a request/response test, they */
- /* can be either time or transaction based. */
-
- if (test_time) {
- /* The user wanted to end the test after a period of time. */
- times_up = 0;
- trans_remaining = 0;
- start_timer(test_time);
- }
- else {
- /* The tester wanted to send a number of bytes. */
- trans_remaining = test_bytes;
- times_up = 1;
- }
-
- /* The cpu_start routine will grab the current time and possibly */
- /* value of the idle counter for later use in measuring cpu */
- /* utilization and/or service demand and thruput. */
-
- cpu_start(local_cpu_usage);
-
-#ifdef WANT_INTERVALS
- INTERVALS_INIT();
-#endif /* WANT_INTERVALS */
-
- /* We use an "OR" to control test execution. When the test is */
- /* controlled by time, the byte count check will always return false. */
- /* When the test is controlled by byte count, the time test will */
- /* always return false. When the test is finished, the whole */
- /* expression will go false and we will stop sending data. I think I */
- /* just arbitrarily decrement trans_remaining for the timed test, but */
- /* will not do that just yet... One other question is whether or not */
- /* the send buffer and the receive buffer should be the same buffer. */
-
-#ifdef WANT_DEMO
- if (demo_mode) {
- HIST_timestamp(demo_one_ptr);
- }
-#endif
-
- while ((!times_up) || (trans_remaining > 0)) {
- /* send the request. we assume that if we use a blocking socket, */
- /* the request will be sent at one shot. */
-
-#ifdef WANT_FIRST_BURST
- /* we can inject no more than request_cwnd, which will grow with
- time, and no more than first_burst_size. we don't use <= to
- account for the "regularly scheduled" send call. of course
- that makes it more a "max_outstanding_ than a
- "first_burst_size" but for now we won't fix the names. also,
- I suspect the extra check against < first_burst_size is
- redundant since later I expect to make sure that request_cwnd
- can never get larger than first_burst_size, but just at the
- moment I'm feeling like a belt and suspenders kind of
- programmer. raj 2006-01-30 */
- while ((first_burst_size > 0) &&
- (requests_outstanding < request_cwnd) &&
- (requests_outstanding < first_burst_size)) {
- if (debug) {
- fprintf(where,
- "injecting, req_outstndng %d req_cwnd %d burst %d\n",
- requests_outstanding,
- request_cwnd,
- first_burst_size);
- }
- if ((len = send(send_socket,
- send_ring->buffer_ptr,
- req_size,
- 0)) != req_size) {
- /* we should never hit the end of the test in the first burst */
- perror("send_tcp_rr: initial burst data send error");
- exit(-1);
- }
- requests_outstanding += 1;
- }
-
-#endif /* WANT_FIRST_BURST */
-
-#ifdef WANT_HISTOGRAM
- if (verbosity > 1) {
- /* timestamp just before our call to send, and then again just
- after the receive raj 8/94 */
- /* but only if we are actually going to display one. raj
- 2007-02-07 */
-
- HIST_timestamp(&time_one);
- }
-#endif /* WANT_HISTOGRAM */
-
- if ((len = send(send_socket,
- send_ring->buffer_ptr,
- req_size,
- 0)) != req_size) {
- if (SOCKET_EINTR(len) || (errno == 0)) {
- /* we hit the end of a */
- /* timed test. */
- timed_out = 1;
- break;
- }
- perror("send_tcp_rr: data send error");
- exit(1);
- }
- send_ring = send_ring->next;
-
-#ifdef WANT_FIRST_BURST
- requests_outstanding += 1;
-#endif
-
- /* receive the response */
- rsp_bytes_left = rsp_size;
- temp_message_ptr = recv_ring->buffer_ptr;
- while(rsp_bytes_left > 0) {
- if((rsp_bytes_recvd=recv(send_socket,
- temp_message_ptr,
- rsp_bytes_left,
- 0)) == SOCKET_ERROR) {
- if ( SOCKET_EINTR(rsp_bytes_recvd) ) {
- /* We hit the end of a timed test. */
- timed_out = 1;
- break;
- }
- perror("send_tcp_rr: data recv error");
- exit(1);
- }
- rsp_bytes_left -= rsp_bytes_recvd;
- temp_message_ptr += rsp_bytes_recvd;
- }
- recv_ring = recv_ring->next;
-
-#ifdef WANT_FIRST_BURST
- /* so, since we've gotten a response back, update the
- bookkeeping accordingly. there is one less request
- outstanding and we can put one more out there than before. */
- requests_outstanding -= 1;
- if (request_cwnd < first_burst_size) {
- request_cwnd += 1;
- if (debug) {
- fprintf(where,
- "incr req_cwnd to %d first_burst %d reqs_outstndng %d\n",
- request_cwnd,
- first_burst_size,
- requests_outstanding);
- }
- }
-#endif
- if (timed_out) {
- /* we may have been in a nested while loop - we need */
- /* another call to break. */
- break;
- }
-
-#ifdef WANT_HISTOGRAM
- if (verbosity > 1) {
- HIST_timestamp(&time_two);
- HIST_add(time_hist,delta_micro(&time_one,&time_two));
- }
-#endif /* WANT_HISTOGRAM */
-
-#ifdef WANT_DEMO
- DEMO_RR_INTERVAL(1);
-#endif
-
-#ifdef WANT_INTERVALS
- INTERVALS_WAIT();
-#endif /* WANT_INTERVALS */
-
- nummessages++;
- if (trans_remaining) {
- trans_remaining--;
- }
-
- if (debug > 3) {
- if ((nummessages % 100) == 0) {
- fprintf(where,
- "Transaction %d completed\n",
- nummessages);
- fflush(where);
- }
- }
- }
-
- /* At this point we used to call shutdown on the data socket to be
- sure all the data was delivered, but this was not germane in a
- request/response test, and it was causing the tests to "hang"
- when they were being controlled by time. So, I have replaced
- this shutdown call with a call to close that can be found later
- in the procedure. */
-
- /* this call will always give us the elapsed time for the test,
- and will also store-away the necessaries for cpu utilization */
-
- cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */
- /* measured? how long */
- /* did we really run? */
-
- if (!no_control) {
- /* Get the statistics from the remote end. The remote will have
- calculated CPU utilization. If it wasn't supposed to care, it
- will return obvious values. */
-
- recv_response();
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote results obtained\n");
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- fprintf(where,"netperf: remote error %d",
- netperf_response.content.serv_errno);
- perror("");
- fflush(where);
- exit(1);
- }
- }
-
- /* We now calculate what our "throughput" was for the test. */
-
- bytes_xferd = (req_size * nummessages) + (rsp_size * nummessages);
- thruput = nummessages/elapsed_time;
-
- if (local_cpu_usage || remote_cpu_usage) {
- /* We must now do a little math for service demand and cpu
- utilization for the system(s) Of course, some of the
- information might be bogus because there was no idle counter in
- the kernel(s). We need to make a note of this for the user's
- benefit... */
- if (local_cpu_usage) {
- local_cpu_utilization = calc_cpu_util(0.0);
- /* since calc_service demand is doing ms/Kunit we will
- multiply the number of transaction by 1024 to get "good"
- numbers */
- local_service_demand = calc_service_demand((double) nummessages*1024,
- 0.0,
- 0.0,
- 0);
- }
- else {
- local_cpu_utilization = (float) -1.0;
- local_service_demand = (float) -1.0;
- }
-
- if (remote_cpu_usage) {
- remote_cpu_utilization = tcp_rr_result->cpu_util;
- /* since calc_service demand is doing ms/Kunit we will
- multiply the number of transaction by 1024 to get "good"
- numbers */
- remote_service_demand = calc_service_demand((double) nummessages*1024,
- 0.0,
- remote_cpu_utilization,
- tcp_rr_result->num_cpus);
- }
- else {
- remote_cpu_utilization = (float) -1.0;
- remote_service_demand = (float) -1.0;
- }
-
- }
- else {
- /* we were not measuring cpu, for the confidence stuff, we */
- /* should make it -1.0 */
- local_cpu_utilization = (float) -1.0;
- local_service_demand = (float) -1.0;
- remote_cpu_utilization = (float) -1.0;
- remote_service_demand = (float) -1.0;
- }
-
- /* at this point, we want to calculate the confidence information.
- if debugging is on, calculate_confidence will print-out the
- parameters we pass it */
-
- calculate_confidence(confidence_iteration,
- elapsed_time,
- thruput,
- local_cpu_utilization,
- remote_cpu_utilization,
- local_service_demand,
- remote_service_demand);
-
-
- confidence_iteration++;
-
- /* we are now done with the socket, so close it */
- close(send_socket);
-
- }
-
- retrieve_confident_values(&elapsed_time,
- &thruput,
- &local_cpu_utilization,
- &remote_cpu_utilization,
- &local_service_demand,
- &remote_service_demand);
-
- /* We are now ready to print all the information. If the user has
- specified zero-level verbosity, we will just print the local
- service demand, or the remote service demand. If the user has
- requested verbosity level 1, he will get the basic "streamperf"
- numbers. If the user has specified a verbosity of greater than 1,
- we will display a veritable plethora of background information
- from outside of this block as it it not cpu_measurement
- specific... */
-
- if (confidence < 0) {
- /* we did not hit confidence, but were we asked to look for it? */
- if (iteration_max > 1) {
- display_confidence();
- }
- }
-
- if (local_cpu_usage || remote_cpu_usage) {
- local_cpu_method = format_cpu_method(cpu_method);
- remote_cpu_method = format_cpu_method(tcp_rr_result->cpu_method);
-
- switch (verbosity) {
- case 0:
- if (local_cpu_usage) {
- fprintf(where,
- cpu_fmt_0,
- local_service_demand,
- local_cpu_method,
- ((print_headers) ||
- (result_brand == NULL)) ? "" : result_brand);
- }
- else {
- fprintf(where,
- cpu_fmt_0,
- remote_service_demand,
- remote_cpu_method,
- ((print_headers) ||
- (result_brand == NULL)) ? "" : result_brand);
- }
- break;
- case 1:
- case 2:
- if (print_headers) {
- if ('x' == libfmt) {
- fprintf(where,
- cpu_title,
- local_cpu_method,
- remote_cpu_method);
- }
- else {
- fprintf(where,
- cpu_title_tput,
- format_units(),
- local_cpu_method,
- remote_cpu_method);
- }
- }
-
- fprintf(where,
- cpu_fmt_1_line_1, /* the format string */
- lss_size, /* local sendbuf size */
- lsr_size,
- req_size, /* how large were the requests */
- rsp_size, /* guess */
- elapsed_time, /* how long was the test */
- ('x' == libfmt) ? thruput :
- calc_thruput_interval_omni(thruput * (req_size+rsp_size),
- 1.0),
- local_cpu_utilization, /* local cpu */
- remote_cpu_utilization, /* remote cpu */
- local_service_demand, /* local service demand */
- remote_service_demand, /* remote service demand */
- ((print_headers) ||
- (result_brand == NULL)) ? "" : result_brand);
- fprintf(where,
- cpu_fmt_1_line_2,
- rss_size,
- rsr_size);
- break;
- }
- }
- else {
- /* The tester did not wish to measure service demand. */
-
- switch (verbosity) {
- case 0:
- fprintf(where,
- tput_fmt_0,
- ('x' == libfmt) ? thruput :
- calc_thruput_interval_omni(thruput * (req_size+rsp_size),
- 1.0),
- ((print_headers) ||
- (result_brand == NULL)) ? "" : result_brand);
- break;
- case 1:
- case 2:
- if (print_headers) {
- fprintf(where,
- ('x' == libfmt) ? tput_title : tput_title_band,
- format_units());
- }
-
- fprintf(where,
- tput_fmt_1_line_1, /* the format string */
- lss_size,
- lsr_size,
- req_size, /* how large were the requests */
- rsp_size, /* how large were the responses */
- elapsed_time, /* how long did it take */
- /* are we trans or do we need to convert to bytes then
- bits? at this point, thruput is in our "confident"
- transactions per second. we can convert to a
- bidirectional bitrate by multiplying that by the sum
- of the req_size and rsp_size. we pass that to
- calc_thruput_interval_omni with an elapsed time of
- 1.0 s to get it converted to [kmg]bits/s or
- [KMG]Bytes/s */
- ('x' == libfmt) ? thruput :
- calc_thruput_interval_omni(thruput * (req_size+rsp_size),
- 1.0),
- ((print_headers) ||
- (result_brand == NULL)) ? "" : result_brand);
- fprintf(where,
- tput_fmt_1_line_2,
- rss_size, /* remote recvbuf size */
- rsr_size);
-
- break;
- }
- }
-
- /* it would be a good thing to include information about some of the */
- /* other parameters that may have been set for this test, but at the */
- /* moment, I do not wish to figure-out all the formatting, so I will */
- /* just put this comment here to help remind me that it is something */
- /* that should be done at a later time. */
-
- /* how to handle the verbose information in the presence of */
- /* confidence intervals is yet to be determined... raj 11/94 */
- if (verbosity > 1) {
- /* The user wanted to know it all, so we will give it to him. */
- /* This information will include as much as we can find about */
- /* TCP statistics, the alignments of the sends and receives */
- /* and all that sort of rot... */
-
- /* normally, you might think that if we were messing about with
- the value of libfmt we would need to put it back again, but
- since this is basically the last thing we are going to do with
- it, it does not matter. so there :) raj 2007-06-08 */
- /* if the user was asking for transactions, then we report
- megabits per sedcond for the unidirectional throughput,
- otherwise we use the desired units. */
- if ('x' == libfmt) {
- libfmt = 'm';
- }
-
- fprintf(where,
- ksink_fmt,
- format_units(),
- local_send_align,
- remote_recv_offset,
- local_send_offset,
- remote_recv_offset,
- /* if the user has enable burst mode, we have to remember
- to account for that in the number of transactions
- outstanding at any one time. otherwise we will
- underreport the latency of individual
- transactions. learned from saf by raj 2007-06-08 */
- (((double)1.0/thruput)*(double)1000000.0) *
- (double) (1+first_burst_size),
- thruput,
- calc_thruput_interval_omni(thruput * (double)req_size,1.0),
- calc_thruput_interval_omni(thruput * (double)rsp_size,1.0));
-
-#ifdef WANT_HISTOGRAM
- fprintf(where,"\nHistogram of request/response times\n");
- fflush(where);
- HIST_report(time_hist);
-#endif /* WANT_HISTOGRAM */
-
- }
-
-}
-
-void
-send_udp_stream(char remote_host[])
-{
- /**********************************************************************/
- /* */
- /* UDP Unidirectional Send Test */
- /* */
- /**********************************************************************/
-
-#define UDP_LENGTH_MAX 0XFFFF - 28
-
- char *tput_title = "\
-Socket Message Elapsed Messages \n\
-Size Size Time Okay Errors Throughput\n\
-bytes bytes secs # # %s/sec\n\n";
-
- char *tput_fmt_0 =
- "%7.2f\n";
-
- char *tput_fmt_1 = "\
-%6d %6d %-7.2f %7d %6d %7.2f\n\
-%6d %-7.2f %7d %7.2f\n\n";
-
-
- char *cpu_title = "\
-Socket Message Elapsed Messages CPU Service\n\
-Size Size Time Okay Errors Throughput Util Demand\n\
-bytes bytes secs # # %s/sec %% %c%c us/KB\n\n";
-
- char *cpu_fmt_0 =
- "%6.2f %c\n";
-
- char *cpu_fmt_1 = "\
-%6d %6d %-7.2f %7d %6d %7.1f %-6.2f %-6.3f\n\
-%6d %-7.2f %7d %7.1f %-6.2f %-6.3f\n\n";
-
- unsigned int messages_recvd;
- unsigned int messages_sent;
- unsigned int failed_sends;
-
- float elapsed_time,
- local_cpu_utilization,
- remote_cpu_utilization;
-
- float local_service_demand, remote_service_demand;
- double local_thruput, remote_thruput;
- double bytes_sent;
- double bytes_recvd;
-
-
- int len;
- struct ring_elt *send_ring;
- SOCKET data_socket;
-
- unsigned int sum_messages_sent;
- unsigned int sum_messages_recvd;
- unsigned int sum_failed_sends;
- double sum_local_thruput;
-
- struct addrinfo *local_res;
- struct addrinfo *remote_res;
-
- struct udp_stream_request_struct *udp_stream_request;
- struct udp_stream_response_struct *udp_stream_response;
- struct udp_stream_results_struct *udp_stream_results;
-
- udp_stream_request =
- (struct udp_stream_request_struct *)netperf_request.content.test_specific_data;
- udp_stream_response =
- (struct udp_stream_response_struct *)netperf_response.content.test_specific_data;
- udp_stream_results =
- (struct udp_stream_results_struct *)netperf_response.content.test_specific_data;
-
-#ifdef WANT_HISTOGRAM
- if (verbosity > 1) {
- time_hist = HIST_new();
- }
-#endif /* WANT_HISTOGRAM */
-
- /* since we are now disconnected from the code that established the */
- /* control socket, and since we want to be able to use different */
- /* protocols and such, we are passed the name of the remote host and */
- /* must turn that into the test specific addressing information. */
-
- complete_addrinfos(&remote_res,
- &local_res,
- remote_host,
- SOCK_DGRAM,
- IPPROTO_UDP,
- 0);
-
- if ( print_headers ) {
- print_top_test_header("UDP UNIDIRECTIONAL SEND TEST",local_res,remote_res);
- }
-
- send_ring = NULL;
- confidence_iteration = 1;
- init_stat();
- sum_messages_sent = 0;
- sum_messages_recvd = 0;
- sum_failed_sends = 0;
- sum_local_thruput = 0.0;
-
- /* we have a great-big while loop which controls the number of times */
- /* we run a particular test. this is for the calculation of a */
- /* confidence interval (I really should have stayed awake during */
- /* probstats :). If the user did not request confidence measurement */
- /* (no confidence is the default) then we will only go though the */
- /* loop once. the confidence stuff originates from the folks at IBM */
-
- while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
- (confidence_iteration <= iteration_min)) {
-
- /* initialize a few counters. we have to remember that we might be */
- /* going through the loop more than once. */
- messages_sent = 0;
- messages_recvd = 0;
- failed_sends = 0;
- times_up = 0;
-
- /*set up the data socket */
- data_socket = create_data_socket(local_res);
-
- if (data_socket == INVALID_SOCKET){
- perror("udp_send: data socket");
- exit(1);
- }
-
- /* now, we want to see if we need to set the send_size */
- if (send_size == 0) {
- if (lss_size > 0) {
- send_size = (lss_size < UDP_LENGTH_MAX ? lss_size : UDP_LENGTH_MAX);
- }
- else {
- send_size = 4096;
- }
- }
-
-
- /* set-up the data buffer with the requested alignment and offset, */
- /* most of the numbers here are just a hack to pick something nice */
- /* and big in an attempt to never try to send a buffer a second time */
- /* before it leaves the node...unless the user set the width */
- /* explicitly. */
- if (send_width == 0) send_width = 32;
-
- if (send_ring == NULL ) {
- send_ring = allocate_buffer_ring(send_width,
- send_size,
- local_send_align,
- local_send_offset);
- }
-
-
- /* if the user supplied a cpu rate, this call will complete rather */
- /* quickly, otherwise, the cpu rate will be retured to us for */
- /* possible display. The Library will keep it's own copy of this data */
- /* for use elsewhere. We will only display it. (Does that make it */
- /* "opaque" to us?) */
-
- if (local_cpu_usage)
- local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
-
- if (!no_control) {
- /* Tell the remote end to set up the data connection. The server
- sends back the port number and alters the socket parameters
- there. Of course this is a datagram service so no connection
- is actually set up, the server just sets up the socket and
- binds it. */
-
- netperf_request.content.request_type = DO_UDP_STREAM;
- udp_stream_request->recv_buf_size = rsr_size_req;
- udp_stream_request->message_size = send_size;
- udp_stream_request->recv_connected = remote_connected;
- udp_stream_request->recv_alignment = remote_recv_align;
- udp_stream_request->recv_offset = remote_recv_offset;
- udp_stream_request->measure_cpu = remote_cpu_usage;
- udp_stream_request->cpu_rate = remote_cpu_rate;
- udp_stream_request->test_length = test_time;
- udp_stream_request->so_rcvavoid = rem_rcvavoid;
- udp_stream_request->so_sndavoid = rem_sndavoid;
- udp_stream_request->port = atoi(remote_data_port);
- udp_stream_request->ipfamily = af_to_nf(remote_res->ai_family);
-
- send_request();
-
- recv_response();
-
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"send_udp_stream: remote data connection done.\n");
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- perror("send_udp_stream: error on remote");
- exit(1);
- }
-
- /* Place the port number returned by the remote into the sockaddr */
- /* structure so our sends can be sent to the correct place. Also get */
- /* some of the returned socket buffer information for user display. */
-
- /* make sure that port numbers are in the proper order */
- set_port_number(remote_res,(short)udp_stream_response->data_port_number);
-
- rsr_size = udp_stream_response->recv_buf_size;
- rss_size = udp_stream_response->send_buf_size;
- remote_cpu_rate = udp_stream_response->cpu_rate;
- }
-
-#ifdef WANT_DEMO
- DEMO_STREAM_SETUP(lss_size,rsr_size)
-#endif
-
- /* We "connect" up to the remote post to allow is to use the send */
- /* call instead of the sendto call. Presumeably, this is a little */
- /* simpler, and a little more efficient. I think that it also means */
- /* that we can be informed of certain things, but am not sure */
- /* yet...also, this is the way I would expect a client to behave */
- /* when talking to a server */
- if (local_connected) {
- if (connect(data_socket,
- remote_res->ai_addr,
- remote_res->ai_addrlen) == INVALID_SOCKET){
- perror("send_udp_stream: data socket connect failed");
- exit(1);
- } else if (debug) {
- fprintf(where,"send_udp_stream: connected data socket.\n");
- fflush(where);
- }
- }
-
- /* set up the timer to call us after test_time. one of these days, */
- /* it might be nice to figure-out a nice reliable way to have the */
- /* test controlled by a byte count as well, but since UDP is not */
- /* reliable, that could prove difficult. so, in the meantime, we */
- /* only allow a UDP_STREAM test to be a timed test. */
-
- if (test_time) {
- times_up = 0;
- start_timer(test_time);
- }
- else {
- fprintf(where,"Sorry, UDP_STREAM tests must be timed.\n");
- fflush(where);
- }
-
- /* Get the start count for the idle counter and the start time */
-
- cpu_start(local_cpu_usage);
-
-#ifdef WANT_INTERVALS
- INTERVALS_INIT();
-#endif /* WANT_INTERVALS */
-
-#ifdef WANT_DEMO
- if (demo_mode) {
- HIST_timestamp(demo_one_ptr);
- }
-#endif
-
- /* Send datagrams like there was no tomorrow. at somepoint it might */
- /* be nice to set this up so that a quantity of bytes could be sent, */
- /* but we still need some sort of end of test trigger on the receive */
- /* side. that could be a select with a one second timeout, but then */
- /* if there is a test where none of the data arrives for awile and */
- /* then starts again, we would end the test too soon. something to */
- /* think about... */
- while (!times_up) {
-
-#ifdef DIRTY
- /* we want to dirty some number of consecutive integers in the buffer */
- /* we are about to send. we may also want to bring some number of */
- /* them cleanly into the cache. The clean ones will follow any dirty */
- /* ones into the cache. */
-
- access_buffer(send_ring->buffer_ptr,
- send_size,
- loc_dirty_count,
- loc_clean_count);
-#endif /* DIRTY */
-
-#ifdef WANT_HISTOGRAM
- if (verbosity > 1) {
- HIST_timestamp(&time_one);
- }
-#endif /* WANT_HISTOGRAM */
-
- if (local_connected) {
- len = send(data_socket,
- send_ring->buffer_ptr,
- send_size,
- 0);
- } else {
- len = sendto(data_socket,
- send_ring->buffer_ptr,
- send_size,
- 0,
- remote_res->ai_addr,
- remote_res->ai_addrlen);
- }
-
- if (len != send_size) {
- if ((len >= 0) ||
- SOCKET_EINTR(len))
- break;
- if (errno == ENOBUFS) {
- failed_sends++;
- continue;
- }
- perror("udp_send: data send error");
- exit(1);
- }
- messages_sent++;
-
- /* now we want to move our pointer to the next position in the */
- /* data buffer... */
-
- send_ring = send_ring->next;
-
-
-#ifdef WANT_HISTOGRAM
- if (verbosity > 1) {
- /* get the second timestamp */
- HIST_timestamp(&time_two);
- HIST_add(time_hist,delta_micro(&time_one,&time_two));
- }
-#endif /* WANT_HISTOGRAM */
-
-#ifdef WANT_DEMO
- DEMO_STREAM_INTERVAL(send_size)
-#endif
-
-#ifdef WANT_INTERVALS
- INTERVALS_WAIT();
-#endif /* WANT_INTERVALS */
-
- }
-
- /* This is a timed test, so the remote will be returning to us after */
- /* a time. We should not need to send any "strange" messages to tell */
- /* the remote that the test is completed, unless we decide to add a */
- /* number of messages to the test. */
-
- /* the test is over, so get stats and stuff */
- cpu_stop(local_cpu_usage,
- &elapsed_time);
-
- if (!no_control) {
- /* Get the statistics from the remote end */
- recv_response();
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"send_udp_stream: remote results obtained\n");
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- perror("send_udp_stream: error on remote");
- exit(1);
- }
- messages_recvd = udp_stream_results->messages_recvd;
- bytes_recvd = (double) send_size * (double) messages_recvd;
- }
- else {
- /* since there was no control connection, we've no idea what was
- actually received. raj 2007-02-08 */
- messages_recvd = -1;
- bytes_recvd = -1.0;
- }
-
- bytes_sent = (double) send_size * (double) messages_sent;
- local_thruput = calc_thruput(bytes_sent);
-
-
- /* we asume that the remote ran for as long as we did */
-
- remote_thruput = calc_thruput(bytes_recvd);
-
- /* print the results for this socket and message size */
-
- if (local_cpu_usage || remote_cpu_usage) {
- /* We must now do a little math for service demand and cpu */
- /* utilization for the system(s) We pass zeros for the local */
- /* cpu utilization and elapsed time to tell the routine to use */
- /* the libraries own values for those. */
- if (local_cpu_usage) {
- local_cpu_utilization = calc_cpu_util(0.0);
- /* shouldn't this really be based on bytes_recvd, since that is */
- /* the effective throughput of the test? I think that it should, */
- /* so will make the change raj 11/94 */
- local_service_demand = calc_service_demand(bytes_recvd,
- 0.0,
- 0.0,
- 0);
- }
- else {
- local_cpu_utilization = (float) -1.0;
- local_service_demand = (float) -1.0;
- }
-
- /* The local calculations could use variables being kept by */
- /* the local netlib routines. The remote calcuations need to */
- /* have a few things passed to them. */
- if (remote_cpu_usage) {
- remote_cpu_utilization = udp_stream_results->cpu_util;
- remote_service_demand = calc_service_demand(bytes_recvd,
- 0.0,
- remote_cpu_utilization,
- udp_stream_results->num_cpus);
- }
- else {
- remote_cpu_utilization = (float) -1.0;
- remote_service_demand = (float) -1.0;
- }
- }
- else {
- /* we were not measuring cpu, for the confidence stuff, we */
- /* should make it -1.0 */
- local_cpu_utilization = (float) -1.0;
- local_service_demand = (float) -1.0;
- remote_cpu_utilization = (float) -1.0;
- remote_service_demand = (float) -1.0;
- }
-
- /* at this point, we want to calculate the confidence information. */
- /* if debugging is on, calculate_confidence will print-out the */
- /* parameters we pass it */
-
- calculate_confidence(confidence_iteration,
- elapsed_time,
- remote_thruput,
- local_cpu_utilization,
- remote_cpu_utilization,
- local_service_demand,
- remote_service_demand);
-
- /* since the routine calculate_confidence is rather generic, and */
- /* we have a few other parms of interest, we will do a little work */
- /* here to caclulate their average. */
- sum_messages_sent += messages_sent;
- sum_messages_recvd += messages_recvd;
- sum_failed_sends += failed_sends;
- sum_local_thruput += local_thruput;
-
- confidence_iteration++;
-
- /* this datapoint is done, so we don't need the socket any longer */
- close(data_socket);
-
- }
-
- /* we should reach this point once the test is finished */
-
- retrieve_confident_values(&elapsed_time,
- &remote_thruput,
- &local_cpu_utilization,
- &remote_cpu_utilization,
- &local_service_demand,
- &remote_service_demand);
-
- /* some of the interesting values aren't covered by the generic */
- /* confidence routine */
- messages_sent = sum_messages_sent / (confidence_iteration -1);
- messages_recvd = sum_messages_recvd / (confidence_iteration -1);
- failed_sends = sum_failed_sends / (confidence_iteration -1);
- local_thruput = sum_local_thruput / (confidence_iteration -1);
-
- /* We are now ready to print all the information. If the user */
- /* has specified zero-level verbosity, we will just print the */
- /* local service demand, or the remote service demand. If the */
- /* user has requested verbosity level 1, he will get the basic */
- /* "streamperf" numbers. If the user has specified a verbosity */
- /* of greater than 1, we will display a veritable plethora of */
- /* background information from outside of this block as it it */
- /* not cpu_measurement specific... */
-
-
- if (confidence < 0) {
- /* we did not hit confidence, but were we asked to look for it? */
- if (iteration_max > 1) {
- display_confidence();
- }
- }
-
- if (local_cpu_usage || remote_cpu_usage) {
- local_cpu_method = format_cpu_method(cpu_method);
- remote_cpu_method = format_cpu_method(udp_stream_results->cpu_method);
-
- switch (verbosity) {
- case 0:
- if (local_cpu_usage) {
- fprintf(where,
- cpu_fmt_0,
- local_service_demand,
- local_cpu_method);
- }
- else {
- fprintf(where,
- cpu_fmt_0,
- remote_service_demand,
- local_cpu_method);
- }
- break;
- case 1:
- case 2:
- if (print_headers) {
- fprintf(where,
- cpu_title,
- format_units(),
- local_cpu_method,
- remote_cpu_method);
- }
-
- fprintf(where,
- cpu_fmt_1, /* the format string */
- lss_size, /* local sendbuf size */
- send_size, /* how large were the sends */
- elapsed_time, /* how long was the test */
- messages_sent,
- failed_sends,
- local_thruput, /* what was the xfer rate */
- local_cpu_utilization, /* local cpu */
- local_service_demand, /* local service demand */
- rsr_size,
- elapsed_time,
- messages_recvd,
- remote_thruput,
- remote_cpu_utilization, /* remote cpu */
- remote_service_demand); /* remote service demand */
- break;
- }
- }
- else {
- /* The tester did not wish to measure service demand. */
- switch (verbosity) {
- case 0:
- fprintf(where,
- tput_fmt_0,
- local_thruput);
- break;
- case 1:
- case 2:
- if (print_headers) {
- fprintf(where,tput_title,format_units());
- }
- fprintf(where,
- tput_fmt_1, /* the format string */
- lss_size, /* local sendbuf size */
- send_size, /* how large were the sends */
- elapsed_time, /* how long did it take */
- messages_sent,
- failed_sends,
- local_thruput,
- rsr_size, /* remote recvbuf size */
- elapsed_time,
- messages_recvd,
- remote_thruput);
- break;
- }
- }
-
- fflush(where);
-#ifdef WANT_HISTOGRAM
- if (verbosity > 1) {
- fprintf(where,"\nHistogram of time spent in send() call\n");
- fflush(where);
- HIST_report(time_hist);
- }
-#endif /* WANT_HISTOGRAM */
-
-}
-
-
- /* this routine implements the receive side (netserver) of the */
- /* UDP_STREAM performance test. */
-
-void
-recv_udp_stream()
-{
- struct ring_elt *recv_ring;
- struct addrinfo *local_res;
- char local_name[BUFSIZ];
- char port_buffer[PORTBUFSIZE];
-
- struct sockaddr_storage myaddr_in;
- SOCKET s_data;
- netperf_socklen_t addrlen;
- struct sockaddr_storage remote_addr;
- netperf_socklen_t remote_addrlen;
-
- int len = 0;
- unsigned int bytes_received = 0;
- float elapsed_time;
-
- int message_size;
- unsigned int messages_recvd = 0;
-
- struct udp_stream_request_struct *udp_stream_request;
- struct udp_stream_response_struct *udp_stream_response;
- struct udp_stream_results_struct *udp_stream_results;
-
- udp_stream_request =
- (struct udp_stream_request_struct *)netperf_request.content.test_specific_data;
- udp_stream_response =
- (struct udp_stream_response_struct *)netperf_response.content.test_specific_data;
- udp_stream_results =
- (struct udp_stream_results_struct *)netperf_response.content.test_specific_data;
-
- if (debug) {
- fprintf(where,"netserver: recv_udp_stream: entered...\n");
- fflush(where);
- }
-
- /* We want to set-up the listen socket with all the desired */
- /* parameters and then let the initiator know that all is ready. If */
- /* socket size defaults are to be used, then the initiator will have */
- /* sent us 0's. If the socket sizes cannot be changed, then we will */
- /* send-back what they are. If that information cannot be determined, */
- /* then we send-back -1's for the sizes. If things go wrong for any */
- /* reason, we will drop back ten yards and punt. */
-
- /* If anything goes wrong, we want the remote to know about it. It */
- /* would be best if the error that the remote reports to the user is */
- /* the actual error we encountered, rather than some bogus unexpected */
- /* response type message. */
-
- if (debug > 1) {
- fprintf(where,"recv_udp_stream: setting the response type...\n");
- fflush(where);
- }
-
- netperf_response.content.response_type = UDP_STREAM_RESPONSE;
-
- if (debug > 2) {
- fprintf(where,"recv_udp_stream: the response type is set...\n");
- fflush(where);
- }
-
- /* We now alter the message_ptr variable to be at the desired */
- /* alignment with the desired offset. */
-
- if (debug > 1) {
- fprintf(where,"recv_udp_stream: requested alignment of %d\n",
- udp_stream_request->recv_alignment);
- fflush(where);
- }
-
- if (recv_width == 0) recv_width = 1;
-
- recv_ring = allocate_buffer_ring(recv_width,
- udp_stream_request->message_size,
- udp_stream_request->recv_alignment,
- udp_stream_request->recv_offset);
-
- if (debug > 1) {
- fprintf(where,"recv_udp_stream: receive alignment and offset set...\n");
- fflush(where);
- }
-
- /* Grab a socket to listen on, and then listen on it. */
-
- if (debug > 1) {
- fprintf(where,"recv_udp_stream: grabbing a socket...\n");
- fflush(where);
- }
-
- /* create_data_socket expects to find some things in the global */
- /* variables, so set the globals based on the values in the request. */
- /* once the socket has been created, we will set the response values */
- /* based on the updated value of those globals. raj 7/94 */
- lsr_size_req = udp_stream_request->recv_buf_size;
- loc_rcvavoid = udp_stream_request->so_rcvavoid;
- loc_sndavoid = udp_stream_request->so_sndavoid;
- local_connected = udp_stream_request->recv_connected;
-
- set_hostname_and_port(local_name,
- port_buffer,
- nf_to_af(udp_stream_request->ipfamily),
- udp_stream_request->port);
-
- local_res = complete_addrinfo(local_name,
- local_name,
- port_buffer,
- nf_to_af(udp_stream_request->ipfamily),
- SOCK_DGRAM,
- IPPROTO_UDP,
- 0);
-
- s_data = create_data_socket(local_res);
-
- if (s_data == INVALID_SOCKET) {
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
-
- udp_stream_response->test_length = udp_stream_request->test_length;
-
- /* now get the port number assigned by the system */
- addrlen = sizeof(myaddr_in);
- if (getsockname(s_data,
- (struct sockaddr *)&myaddr_in,
- &addrlen) == SOCKET_ERROR){
- netperf_response.content.serv_errno = errno;
- close(s_data);
- send_response();
-
- exit(1);
- }
-
- /* Now myaddr_in contains the port and the internet address this is */
- /* returned to the sender also implicitly telling the sender that the */
- /* socket buffer sizing has been done. */
-
- udp_stream_response->data_port_number =
- (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port);
- netperf_response.content.serv_errno = 0;
-
- /* But wait, there's more. If the initiator wanted cpu measurements, */
- /* then we must call the calibrate routine, which will return the max */
- /* rate back to the initiator. If the CPU was not to be measured, or */
- /* something went wrong with the calibration, we will return a -1 to */
- /* the initiator. */
-
- udp_stream_response->cpu_rate = (float)0.0; /* assume no cpu */
- udp_stream_response->measure_cpu = 0;
- if (udp_stream_request->measure_cpu) {
- /* We will pass the rate into the calibration routine. If the */
- /* user did not specify one, it will be 0.0, and we will do a */
- /* "real" calibration. Otherwise, all it will really do is */
- /* store it away... */
- udp_stream_response->measure_cpu = 1;
- udp_stream_response->cpu_rate =
- calibrate_local_cpu(udp_stream_request->cpu_rate);
- }
-
- message_size = udp_stream_request->message_size;
- test_time = udp_stream_request->test_length;
-
- /* before we send the response back to the initiator, pull some of */
- /* the socket parms from the globals */
- udp_stream_response->send_buf_size = lss_size;
- udp_stream_response->recv_buf_size = lsr_size;
- udp_stream_response->so_rcvavoid = loc_rcvavoid;
- udp_stream_response->so_sndavoid = loc_sndavoid;
-
- send_response();
-
- /* Now it's time to start receiving data on the connection. We will */
- /* first grab the apropriate counters and then start grabbing. */
-
- cpu_start(udp_stream_request->measure_cpu);
-
-#ifdef WIN32
- /* this is used so the timer thread can close the socket out from */
- /* under us, which to date is the easiest/cleanest/least */
- /* Windows-specific way I can find to force the winsock calls to */
- /* return WSAEINTR with the test is over. anything that will run on */
- /* 95 and NT and is closer to what netperf expects from Unix signals */
- /* and such would be appreciated raj 1/96 */
- win_kludge_socket = s_data;
-#endif /* WIN32 */
-
- /* The loop will exit when the timer pops, or if we happen to recv a */
- /* message of less than send_size bytes... */
-
- times_up = 0;
-
- start_timer(test_time + PAD_TIME);
-
- if (debug) {
- fprintf(where,"recv_udp_stream: about to enter inner sanctum.\n");
- fflush(where);
- }
-
- /* We "connect" up to the remote post to allow us to use the recv */
- /* call instead of the recvfrom call. Presumeably, this is a little */
- /* simpler, and a little more efficient. */
-
- if (local_connected) {
-
- /* Receive the first message using recvfrom to find the remote address */
- remote_addrlen = sizeof(remote_addr);
- len = recvfrom(s_data, recv_ring->buffer_ptr,
- message_size, 0,
- (struct sockaddr*)&remote_addr, &remote_addrlen);
- if (len != message_size) {
- if ((len == SOCKET_ERROR) && !SOCKET_EINTR(len)) {
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
- }
- messages_recvd++;
- recv_ring = recv_ring->next;
-
-
- /* Now connect with the remote socket address */
- if (connect(s_data,
- (struct sockaddr*)&remote_addr,
- remote_addrlen )== INVALID_SOCKET) {
- netperf_response.content.serv_errno = errno;
- close(s_data);
- send_response();
- exit(1);
- }
-
- if (debug) {
- fprintf(where,"recv_udp_stream: connected data socket\n");
- fflush(where);
- }
- }
-
- while (!times_up) {
- if(local_connected) {
- len = recv(s_data,
- recv_ring->buffer_ptr,
- message_size,
- 0);
- } else {
- len = recvfrom(s_data,
- recv_ring->buffer_ptr,
- message_size,
- 0,0,0);
- }
-
- if (len != message_size) {
- if ((len == SOCKET_ERROR) && !SOCKET_EINTR(len)) {
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
- break;
- }
- messages_recvd++;
- recv_ring = recv_ring->next;
- }
-
- if (debug) {
- fprintf(where,"recv_udp_stream: got %d messages.\n",messages_recvd);
- fflush(where);
- }
-
-
- /* The loop now exits due timer or < send_size bytes received. in */
- /* reality, we only really support a timed UDP_STREAM test. raj */
- /* 12/95 */
-
- cpu_stop(udp_stream_request->measure_cpu,&elapsed_time);
-
- if (times_up) {
- /* we ended on a timer, subtract the PAD_TIME */
- elapsed_time -= (float)PAD_TIME;
- }
- else {
- stop_timer();
- }
-
- if (debug) {
- fprintf(where,"recv_udp_stream: test ended in %f seconds.\n",elapsed_time);
- fflush(where);
- }
-
-
- /* We will count the "off" message that got us out of the loop */
- bytes_received = (messages_recvd * message_size) + len;
-
- /* send the results to the sender */
-
- if (debug) {
- fprintf(where,
- "recv_udp_stream: got %d bytes\n",
- bytes_received);
- fflush(where);
- }
-
- netperf_response.content.response_type = UDP_STREAM_RESULTS;
- udp_stream_results->bytes_received = htonl(bytes_received);
- udp_stream_results->messages_recvd = messages_recvd;
- udp_stream_results->elapsed_time = elapsed_time;
- udp_stream_results->cpu_method = cpu_method;
- udp_stream_results->num_cpus = lib_num_loc_cpus;
- if (udp_stream_request->measure_cpu) {
- udp_stream_results->cpu_util = calc_cpu_util(elapsed_time);
- }
- else {
- udp_stream_results->cpu_util = (float) -1.0;
- }
-
- if (debug > 1) {
- fprintf(where,
- "recv_udp_stream: test complete, sending results.\n");
- fflush(where);
- }
-
- send_response();
-
- close(s_data);
-
-}
-
-void
-send_udp_rr(char remote_host[])
-{
-
- char *tput_title = "\
-Local /Remote\n\
-Socket Size Request Resp. Elapsed Trans.\n\
-Send Recv Size Size Time Rate \n\
-bytes Bytes bytes bytes secs. per sec \n\n";
-
- char *tput_fmt_0 =
- "%7.2f\n";
-
- char *tput_fmt_1_line_1 = "\
-%-6d %-6d %-6d %-6d %-6.2f %7.2f \n";
- char *tput_fmt_1_line_2 = "\
-%-6d %-6d\n";
-
- char *cpu_title = "\
-Local /Remote\n\
-Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\
-Send Recv Size Size Time Rate local remote local remote\n\
-bytes bytes bytes bytes secs. per sec %% %c %% %c us/Tr us/Tr\n\n";
-
- char *cpu_fmt_0 =
- "%6.3f %c\n";
-
- char *cpu_fmt_1_line_1 = "\
-%-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f\n";
-
- char *cpu_fmt_1_line_2 = "\
-%-6d %-6d\n";
-
- float elapsed_time;
-
- struct ring_elt *send_ring;
- struct ring_elt *recv_ring;
-
- int len;
- int nummessages;
- SOCKET send_socket;
- int trans_remaining;
- int bytes_xferd;
-
- int rsp_bytes_recvd;
-
- float local_cpu_utilization;
- float local_service_demand;
- float remote_cpu_utilization;
- float remote_service_demand;
- double thruput;
-
- struct addrinfo *local_res;
- struct addrinfo *remote_res;
-
- struct udp_rr_request_struct *udp_rr_request;
- struct udp_rr_response_struct *udp_rr_response;
- struct udp_rr_results_struct *udp_rr_result;
-
- udp_rr_request =
- (struct udp_rr_request_struct *)netperf_request.content.test_specific_data;
- udp_rr_response =
- (struct udp_rr_response_struct *)netperf_response.content.test_specific_data;
- udp_rr_result =
- (struct udp_rr_results_struct *)netperf_response.content.test_specific_data;
-
-#ifdef WANT_HISTOGRAM
- if (verbosity > 1) {
- time_hist = HIST_new();
- }
-#endif
-
- /* since we are now disconnected from the code that established the */
- /* control socket, and since we want to be able to use different */
- /* protocols and such, we are passed the name of the remote host and */
- /* must turn that into the test specific addressing information. */
-
- complete_addrinfos(&remote_res,
- &local_res,
- remote_host,
- SOCK_DGRAM,
- IPPROTO_UDP,
- 0);
-
- if ( print_headers ) {
- print_top_test_header("UDP REQUEST/RESPONSE TEST",local_res,remote_res);
- }
-
- /* initialize a few counters */
-
- send_ring = NULL;
- recv_ring = NULL;
- nummessages = 0;
- bytes_xferd = 0;
- times_up = 0;
- confidence_iteration = 1;
- init_stat();
-
- /* we have a great-big while loop which controls the number of times */
- /* we run a particular test. this is for the calculation of a */
- /* confidence interval (I really should have stayed awake during */
- /* probstats :). If the user did not request confidence measurement */
- /* (no confidence is the default) then we will only go though the */
- /* loop once. the confidence stuff originates from the folks at IBM */
-
- while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
- (confidence_iteration <= iteration_min)) {
-
- nummessages = 0;
- bytes_xferd = 0;
- times_up = 0;
- trans_remaining = 0;
-
- /* set-up the data buffers with the requested alignment and offset */
-
- if (send_width == 0) send_width = 1;
- if (recv_width == 0) recv_width = 1;
-
- if (send_ring == NULL) {
- send_ring = allocate_buffer_ring(send_width,
- req_size,
- local_send_align,
- local_send_offset);
- }
-
- if (recv_ring == NULL) {
- recv_ring = allocate_buffer_ring(recv_width,
- rsp_size,
- local_recv_align,
- local_recv_offset);
- }
-
- /*set up the data socket */
- send_socket = create_data_socket(local_res);
-
- if (send_socket == INVALID_SOCKET){
- perror("netperf: send_udp_rr: udp rr data socket");
- exit(1);
- }
-
- if (debug) {
- fprintf(where,"send_udp_rr: send_socket obtained...\n");
- }
-
- /* If the user has requested cpu utilization measurements, we must */
- /* calibrate the cpu(s). We will perform this task within the tests */
- /* themselves. If the user has specified the cpu rate, then */
- /* calibrate_local_cpu will return rather quickly as it will have */
- /* nothing to do. If local_cpu_rate is zero, then we will go through */
- /* all the "normal" calibration stuff and return the rate back. If */
- /* there is no idle counter in the kernel idle loop, the */
- /* local_cpu_rate will be set to -1. */
-
- if (local_cpu_usage) {
- local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
- }
-
- if (!no_control) {
- /* Tell the remote end to do a listen. The server alters the
- socket paramters on the other side at this point, hence the
- reason for all the values being passed in the setup
- message. If the user did not specify any of the parameters,
- they will be passed as 0, which will indicate to the remote
- that no changes beyond the system's default should be
- used. Alignment is the exception, it will default to 8, which
- will be no alignment alterations. */
-
- netperf_request.content.request_type = DO_UDP_RR;
- udp_rr_request->recv_buf_size = rsr_size_req;
- udp_rr_request->send_buf_size = rss_size_req;
- udp_rr_request->recv_alignment = remote_recv_align;
- udp_rr_request->recv_offset = remote_recv_offset;
- udp_rr_request->send_alignment = remote_send_align;
- udp_rr_request->send_offset = remote_send_offset;
- udp_rr_request->request_size = req_size;
- udp_rr_request->response_size = rsp_size;
- udp_rr_request->measure_cpu = remote_cpu_usage;
- udp_rr_request->cpu_rate = remote_cpu_rate;
- udp_rr_request->so_rcvavoid = rem_rcvavoid;
- udp_rr_request->so_sndavoid = rem_sndavoid;
- if (test_time) {
- udp_rr_request->test_length = test_time;
- }
- else {
- udp_rr_request->test_length = test_trans * -1;
- }
- udp_rr_request->port = atoi(remote_data_port);
- udp_rr_request->ipfamily = af_to_nf(remote_res->ai_family);
-
- if (debug > 1) {
- fprintf(where,"netperf: send_udp_rr: requesting UDP r/r test\n");
- }
-
- send_request();
-
- /* The response from the remote will contain all of the relevant
- socket parameters for this test type. We will put them back
- into the variables here so they can be displayed if desired.
- The remote will have calibrated CPU if necessary, and will
- have done all the needed set-up we will have calibrated the
- cpu locally before sending the request, and will grab the
- counter value right after the connect returns. The remote
- will grab the counter right after the accept call. This saves
- the hassle of extra messages being sent for the UDP
- tests. */
-
- recv_response();
-
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote listen done.\n");
- rsr_size = udp_rr_response->recv_buf_size;
- rss_size = udp_rr_response->send_buf_size;
- remote_cpu_usage = udp_rr_response->measure_cpu;
- remote_cpu_rate = udp_rr_response->cpu_rate;
- /* port numbers in proper order */
- set_port_number(remote_res,(short)udp_rr_response->data_port_number);
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- fprintf(where,
- "netperf: remote error %d",
- netperf_response.content.serv_errno);
- perror("");
- fflush(where);
- exit(1);
- }
- }
-
-#ifdef WANT_DEMO
- DEMO_RR_SETUP(100)
-#endif
-
- /* Connect up to the remote port on the data socket. This will set */
- /* the default destination address on this socket. With UDP, this */
- /* does make a performance difference as we may not have to do as */
- /* many routing lookups, however, I expect that a client would */
- /* behave this way. raj 1/94 */
-
- if ( connect(send_socket,
- remote_res->ai_addr,
- remote_res->ai_addrlen) == INVALID_SOCKET ) {
- perror("netperf: data socket connect failed");
- exit(1);
- }
-
- /* Data Socket set-up is finished. If there were problems, either the */
- /* connect would have failed, or the previous response would have */
- /* indicated a problem. I failed to see the value of the extra */
- /* message after the accept on the remote. If it failed, we'll see it */
- /* here. If it didn't, we might as well start pumping data. */
-
- /* Set-up the test end conditions. For a request/response test, they */
- /* can be either time or transaction based. */
-
- if (test_time) {
- /* The user wanted to end the test after a period of time. */
- times_up = 0;
- trans_remaining = 0;
- start_timer(test_time);
- }
- else {
- /* The tester wanted to send a number of bytes. */
- trans_remaining = test_bytes;
- times_up = 1;
- }
-
- /* The cpu_start routine will grab the current time and possibly */
- /* value of the idle counter for later use in measuring cpu */
- /* utilization and/or service demand and thruput. */
-
- cpu_start(local_cpu_usage);
-
-#ifdef WANT_DEMO
- if (demo_mode) {
- HIST_timestamp(demo_one_ptr);
- }
-#endif
-
-#ifdef WANT_INTERVALS
- INTERVALS_INIT();
-#endif /* WANT_INTERVALS */
-
- /* We use an "OR" to control test execution. When the test is */
- /* controlled by time, the byte count check will always return */
- /* false. When the test is controlled by byte count, the time test */
- /* will always return false. When the test is finished, the whole */
- /* expression will go false and we will stop sending data. I think */
- /* I just arbitrarily decrement trans_remaining for the timed */
- /* test, but will not do that just yet... One other question is */
- /* whether or not the send buffer and the receive buffer should be */
- /* the same buffer. */
-
-#ifdef WANT_FIRST_BURST
- {
- int i;
- for (i = 0; i < first_burst_size; i++) {
- if((len=send(send_socket,
- send_ring->buffer_ptr,
- req_size,
- 0)) != req_size) {
- /* we should never hit the end of the test in the first burst */
- perror("send_udp_rr: initial burst data send error");
- exit(-1);
- }
- }
- }
-#endif /* WANT_FIRST_BURST */
-
- while ((!times_up) || (trans_remaining > 0)) {
- /* send the request */
-#ifdef WANT_HISTOGRAM
- if (verbosity > 1) {
- HIST_timestamp(&time_one);
- }
-#endif
- if((len=send(send_socket,
- send_ring->buffer_ptr,
- req_size,
- 0)) != req_size) {
- if (SOCKET_EINTR(len)) {
- /* We likely hit */
- /* test-end time. */
- break;
- }
- perror("send_udp_rr: data send error");
- exit(1);
- }
- send_ring = send_ring->next;
-
- /* receive the response. with UDP we will get it all, or nothing */
-
- if((rsp_bytes_recvd=recv(send_socket,
- recv_ring->buffer_ptr,
- rsp_size,
- 0)) != rsp_size) {
- if (SOCKET_EINTR(rsp_bytes_recvd))
- {
- /* Again, we have likely hit test-end time */
- break;
- }
- perror("send_udp_rr: data recv error");
- exit(1);
- }
- recv_ring = recv_ring->next;
-
-#ifdef WANT_HISTOGRAM
- if (verbosity > 1) {
- HIST_timestamp(&time_two);
- HIST_add(time_hist,delta_micro(&time_one,&time_two));
- }
-
-#endif
-
- /* at this point, we may wish to sleep for some period of */
- /* time, so we see how long that last transaction just took, */
- /* and sleep for the difference of that and the interval. We */
- /* will not sleep if the time would be less than a */
- /* millisecond. */
-
-#ifdef WANT_DEMO
- DEMO_RR_INTERVAL(1);
-#endif
-
-#ifdef WANT_INTERVALS
- INTERVALS_WAIT();
-#endif /* WANT_INTERVALS */
-
- nummessages++;
- if (trans_remaining) {
- trans_remaining--;
- }
-
- if (debug > 3) {
- if ((nummessages % 100) == 0) {
- fprintf(where,"Transaction %d completed\n",nummessages);
- fflush(where);
- }
- }
-
- }
-
- /* for some strange reason, I used to call shutdown on the UDP */
- /* data socket here. I'm not sure why, because it would not have */
- /* any effect... raj 11/94 */
-
- /* this call will always give us the elapsed time for the test, and */
- /* will also store-away the necessaries for cpu utilization */
-
- cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */
- /* measured? how long */
- /* did we really run? */
-
- if (!no_control) {
- /* Get the statistics from the remote end. The remote will have
- calculated service demand and all those interesting
- things. If it wasn't supposed to care, it will return obvious
- values. */
-
- recv_response();
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote results obtained\n");
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- fprintf(where,
- "netperf: remote error %d",
- netperf_response.content.serv_errno);
- perror("");
- fflush(where);
- exit(1);
- }
- }
-
- /* We now calculate what our thruput was for the test. In the */
- /* future, we may want to include a calculation of the thruput */
- /* measured by the remote, but it should be the case that for a */
- /* UDP rr test, that the two numbers should be *very* close... */
- /* We calculate bytes_sent regardless of the way the test length */
- /* was controlled. */
-
- bytes_xferd = (req_size * nummessages) + (rsp_size * nummessages);
- thruput = nummessages / elapsed_time;
-
- if (local_cpu_usage || remote_cpu_usage) {
-
- /* We must now do a little math for service demand and cpu */
- /* utilization for the system(s) Of course, some of the */
- /* information might be bogus because there was no idle counter */
- /* in the kernel(s). We need to make a note of this for the */
- /* user's benefit by placing a code for the metod used in the */
- /* test banner */
-
- if (local_cpu_usage) {
- local_cpu_utilization = calc_cpu_util(0.0);
-
- /* since calc_service demand is doing ms/Kunit we will */
- /* multiply the number of transaction by 1024 to get */
- /* "good" numbers */
-
- local_service_demand = calc_service_demand((double) nummessages*1024,
- 0.0,
- 0.0,
- 0);
- }
- else {
- local_cpu_utilization = (float) -1.0;
- local_service_demand = (float) -1.0;
- }
-
- if (remote_cpu_usage) {
- remote_cpu_utilization = udp_rr_result->cpu_util;
-
- /* since calc_service demand is doing ms/Kunit we will */
- /* multiply the number of transaction by 1024 to get */
- /* "good" numbers */
-
- remote_service_demand = calc_service_demand((double) nummessages*1024,
- 0.0,
- remote_cpu_utilization,
- udp_rr_result->num_cpus);
- }
- else {
- remote_cpu_utilization = (float) -1.0;
- remote_service_demand = (float) -1.0;
- }
- }
- else {
- /* we were not measuring cpu, for the confidence stuff, we */
- /* should make it -1.0 */
- local_cpu_utilization = (float) -1.0;
- local_service_demand = (float) -1.0;
- remote_cpu_utilization = (float) -1.0;
- remote_service_demand = (float) -1.0;
- }
-
- /* at this point, we want to calculate the confidence information. */
- /* if debugging is on, calculate_confidence will print-out the */
- /* parameters we pass it */
-
- calculate_confidence(confidence_iteration,
- elapsed_time,
- thruput,
- local_cpu_utilization,
- remote_cpu_utilization,
- local_service_demand,
- remote_service_demand);
-
-
- confidence_iteration++;
-
- /* we are done with the socket */
- close(send_socket);
- }
-
- /* at this point, we have made all the iterations we are going to */
- /* make. */
- retrieve_confident_values(&elapsed_time,
- &thruput,
- &local_cpu_utilization,
- &remote_cpu_utilization,
- &local_service_demand,
- &remote_service_demand);
-
- /* We are now ready to print all the information. If the user */
- /* has specified zero-level verbosity, we will just print the */
- /* local service demand, or the remote service demand. If the */
- /* user has requested verbosity level 1, he will get the basic */
- /* "streamperf" numbers. If the user has specified a verbosity */
- /* of greater than 1, we will display a veritable plethora of */
- /* background information from outside of this block as it it */
- /* not cpu_measurement specific... */
-
- if (confidence < 0) {
- /* we did not hit confidence, but were we asked to look for it? */
- if (iteration_max > 1) {
- display_confidence();
- }
- }
-
- if (local_cpu_usage || remote_cpu_usage) {
- local_cpu_method = format_cpu_method(cpu_method);
- remote_cpu_method = format_cpu_method(udp_rr_result->cpu_method);
-
- switch (verbosity) {
- case 0:
- if (local_cpu_usage) {
- fprintf(where,
- cpu_fmt_0,
- local_service_demand,
- local_cpu_method);
- }
- else {
- fprintf(where,
- cpu_fmt_0,
- remote_service_demand,
- remote_cpu_method);
- }
- break;
- case 1:
- case 2:
- if (print_headers) {
- fprintf(where,
- cpu_title,
- local_cpu_method,
- remote_cpu_method);
- }
-
- fprintf(where,
- cpu_fmt_1_line_1, /* the format string */
- lss_size, /* local sendbuf size */
- lsr_size,
- req_size, /* how large were the requests */
- rsp_size, /* guess */
- elapsed_time, /* how long was the test */
- nummessages/elapsed_time,
- local_cpu_utilization, /* local cpu */
- remote_cpu_utilization, /* remote cpu */
- local_service_demand, /* local service demand */
- remote_service_demand); /* remote service demand */
- fprintf(where,
- cpu_fmt_1_line_2,
- rss_size,
- rsr_size);
- break;
- }
- }
- else {
- /* The tester did not wish to measure service demand. */
- switch (verbosity) {
- case 0:
- fprintf(where,
- tput_fmt_0,
- nummessages/elapsed_time);
- break;
- case 1:
- case 2:
- if (print_headers) {
- fprintf(where,tput_title,format_units());
- }
-
- fprintf(where,
- tput_fmt_1_line_1, /* the format string */
- lss_size,
- lsr_size,
- req_size, /* how large were the requests */
- rsp_size, /* how large were the responses */
- elapsed_time, /* how long did it take */
- nummessages/elapsed_time);
- fprintf(where,
- tput_fmt_1_line_2,
- rss_size, /* remote recvbuf size */
- rsr_size);
-
- break;
- }
- }
- fflush(where);
-
- /* it would be a good thing to include information about some of the */
- /* other parameters that may have been set for this test, but at the */
- /* moment, I do not wish to figure-out all the formatting, so I will */
- /* just put this comment here to help remind me that it is something */
- /* that should be done at a later time. */
-
- /* how to handle the verbose information in the presence of */
- /* confidence intervals is yet to be determined... raj 11/94 */
-
- if (verbosity > 1) {
- /* The user wanted to know it all, so we will give it to him. */
- /* This information will include as much as we can find about */
- /* UDP statistics, the alignments of the sends and receives */
- /* and all that sort of rot... */
-
-#ifdef WANT_HISTOGRAM
- fprintf(where,"\nHistogram of request/reponse times.\n");
- fflush(where);
- HIST_report(time_hist);
-#endif /* WANT_HISTOGRAM */
- }
-}
-
- /* this routine implements the receive side (netserver) of a UDP_RR */
- /* test. */
-void
-recv_udp_rr()
-{
-
- struct ring_elt *recv_ring;
- struct ring_elt *send_ring;
-
- struct addrinfo *local_res;
- char local_name[BUFSIZ];
- char port_buffer[PORTBUFSIZE];
-
- struct sockaddr_storage myaddr_in;
- struct sockaddr_storage peeraddr;
- SOCKET s_data;
- netperf_socklen_t addrlen;
- int trans_received;
- int trans_remaining;
- int request_bytes_recvd;
- int response_bytes_sent;
- float elapsed_time;
-
- struct udp_rr_request_struct *udp_rr_request;
- struct udp_rr_response_struct *udp_rr_response;
- struct udp_rr_results_struct *udp_rr_results;
-
- udp_rr_request =
- (struct udp_rr_request_struct *)netperf_request.content.test_specific_data;
- udp_rr_response =
- (struct udp_rr_response_struct *)netperf_response.content.test_specific_data;
- udp_rr_results =
- (struct udp_rr_results_struct *)netperf_response.content.test_specific_data;
-
- if (debug) {
- fprintf(where,"netserver: recv_udp_rr: entered...\n");
- fflush(where);
- }
-
- /* We want to set-up the listen socket with all the desired */
- /* parameters and then let the initiator know that all is ready. If */
- /* socket size defaults are to be used, then the initiator will have */
- /* sent us 0's. If the socket sizes cannot be changed, then we will */
- /* send-back what they are. If that information cannot be determined, */
- /* then we send-back -1's for the sizes. If things go wrong for any */
- /* reason, we will drop back ten yards and punt. */
-
- /* If anything goes wrong, we want the remote to know about it. It */
- /* would be best if the error that the remote reports to the user is */
- /* the actual error we encountered, rather than some bogus unexpected */
- /* response type message. */
-
- if (debug) {
- fprintf(where,"recv_udp_rr: setting the response type...\n");
- fflush(where);
- }
-
- netperf_response.content.response_type = UDP_RR_RESPONSE;
-
- if (debug) {
- fprintf(where,"recv_udp_rr: the response type is set...\n");
- fflush(where);
- }
-
- /* We now alter the message_ptr variables to be at the desired */
- /* alignments with the desired offsets. */
-
- if (debug) {
- fprintf(where,"recv_udp_rr: requested recv alignment of %d offset %d\n",
- udp_rr_request->recv_alignment,
- udp_rr_request->recv_offset);
- fprintf(where,"recv_udp_rr: requested send alignment of %d offset %d\n",
- udp_rr_request->send_alignment,
- udp_rr_request->send_offset);
- fflush(where);
- }
-
- if (send_width == 0) send_width = 1;
- if (recv_width == 0) recv_width = 1;
-
- recv_ring = allocate_buffer_ring(recv_width,
- udp_rr_request->request_size,
- udp_rr_request->recv_alignment,
- udp_rr_request->recv_offset);
-
- send_ring = allocate_buffer_ring(send_width,
- udp_rr_request->response_size,
- udp_rr_request->send_alignment,
- udp_rr_request->send_offset);
-
- if (debug) {
- fprintf(where,"recv_udp_rr: receive alignment and offset set...\n");
- fflush(where);
- }
-
- /* Grab a socket to listen on, and then listen on it. */
-
- if (debug) {
- fprintf(where,"recv_udp_rr: grabbing a socket...\n");
- fflush(where);
- }
-
-
- /* create_data_socket expects to find some things in the global */
- /* variables, so set the globals based on the values in the request. */
- /* once the socket has been created, we will set the response values */
- /* based on the updated value of those globals. raj 7/94 */
- lss_size_req = udp_rr_request->send_buf_size;
- lsr_size_req = udp_rr_request->recv_buf_size;
- loc_rcvavoid = udp_rr_request->so_rcvavoid;
- loc_sndavoid = udp_rr_request->so_sndavoid;
-
- set_hostname_and_port(local_name,
- port_buffer,
- nf_to_af(udp_rr_request->ipfamily),
- udp_rr_request->port);
-
- local_res = complete_addrinfo(local_name,
- local_name,
- port_buffer,
- nf_to_af(udp_rr_request->ipfamily),
- SOCK_DGRAM,
- IPPROTO_UDP,
- 0);
-
- s_data = create_data_socket(local_res);
-
- if (s_data == INVALID_SOCKET) {
- netperf_response.content.serv_errno = errno;
- send_response();
-
- exit(1);
- }
-
- /* now get the port number assigned by the system */
- addrlen = sizeof(myaddr_in);
- if (getsockname(s_data,
- (struct sockaddr *)&myaddr_in,
- &addrlen) == SOCKET_ERROR){
- netperf_response.content.serv_errno = errno;
- close(s_data);
- send_response();
-
- exit(1);
- }
-
- /* Now myaddr_in contains the port and the internet address this is */
- /* returned to the sender also implicitly telling the sender that the */
- /* socket buffer sizing has been done. */
-
- udp_rr_response->data_port_number =
- (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port);
- netperf_response.content.serv_errno = 0;
-
- if (debug) {
- fprintf(where,
- "recv port number %d\n",
- ((struct sockaddr_in *)&myaddr_in)->sin_port);
- fflush(where);
- }
-
- /* But wait, there's more. If the initiator wanted cpu measurements, */
- /* then we must call the calibrate routine, which will return the max */
- /* rate back to the initiator. If the CPU was not to be measured, or */
- /* something went wrong with the calibration, we will return a 0.0 to */
- /* the initiator. */
-
- udp_rr_response->cpu_rate = (float)0.0; /* assume no cpu */
- udp_rr_response->measure_cpu = 0;
- if (udp_rr_request->measure_cpu) {
- udp_rr_response->measure_cpu = 1;
- udp_rr_response->cpu_rate = calibrate_local_cpu(udp_rr_request->cpu_rate);
- }
-
- /* before we send the response back to the initiator, pull some of */
- /* the socket parms from the globals */
- udp_rr_response->send_buf_size = lss_size;
- udp_rr_response->recv_buf_size = lsr_size;
- udp_rr_response->so_rcvavoid = loc_rcvavoid;
- udp_rr_response->so_sndavoid = loc_sndavoid;
-
- send_response();
-
-
- /* Now it's time to start receiving data on the connection. We will */
- /* first grab the apropriate counters and then start grabbing. */
-
- cpu_start(udp_rr_request->measure_cpu);
-
-#ifdef WIN32
- /* this is used so the timer thread can close the socket out from */
- /* under us, which to date is the easiest/cleanest/least */
- /* Windows-specific way I can find to force the winsock calls to */
- /* return WSAEINTR with the test is over. anything that will run on */
- /* 95 and NT and is closer to what netperf expects from Unix signals */
- /* and such would be appreciated raj 1/96 */
- win_kludge_socket = s_data;
-#endif /* WIN32 */
-
- if (udp_rr_request->test_length > 0) {
- times_up = 0;
- trans_remaining = 0;
- start_timer(udp_rr_request->test_length + PAD_TIME);
- }
- else {
- times_up = 1;
- trans_remaining = udp_rr_request->test_length * -1;
- }
-
- addrlen = sizeof(peeraddr);
- bzero((char *)&peeraddr, addrlen);
-
- trans_received = 0;
-
- while ((!times_up) || (trans_remaining > 0)) {
-
- /* receive the request from the other side */
- if ((request_bytes_recvd = recvfrom(s_data,
- recv_ring->buffer_ptr,
- udp_rr_request->request_size,
- 0,
- (struct sockaddr *)&peeraddr,
- &addrlen)) != udp_rr_request->request_size) {
- if ( SOCKET_EINTR(request_bytes_recvd) )
- {
- /* we must have hit the end of test time. */
- break;
- }
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
- recv_ring = recv_ring->next;
-
- /* Now, send the response to the remote */
- if ((response_bytes_sent = sendto(s_data,
- send_ring->buffer_ptr,
- udp_rr_request->response_size,
- 0,
- (struct sockaddr *)&peeraddr,
- addrlen)) !=
- udp_rr_request->response_size) {
- if ( SOCKET_EINTR(response_bytes_sent) )
- {
- /* we have hit end of test time. */
- break;
- }
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
- send_ring = send_ring->next;
-
- trans_received++;
- if (trans_remaining) {
- trans_remaining--;
- }
-
- if (debug) {
- fprintf(where,
- "recv_udp_rr: Transaction %d complete.\n",
- trans_received);
- fflush(where);
- }
-
- }
-
-
- /* The loop now exits due to timeout or transaction count being */
- /* reached */
-
- cpu_stop(udp_rr_request->measure_cpu,&elapsed_time);
-
- if (times_up) {
- /* we ended the test by time, which was at least 2 seconds */
- /* longer than we wanted to run. so, we want to subtract */
- /* PAD_TIME from the elapsed_time. */
- elapsed_time -= PAD_TIME;
- }
- /* send the results to the sender */
-
- if (debug) {
- fprintf(where,
- "recv_udp_rr: got %d transactions\n",
- trans_received);
- fflush(where);
- }
-
- udp_rr_results->bytes_received = (trans_received *
- (udp_rr_request->request_size +
- udp_rr_request->response_size));
- udp_rr_results->trans_received = trans_received;
- udp_rr_results->elapsed_time = elapsed_time;
- udp_rr_results->cpu_method = cpu_method;
- udp_rr_results->num_cpus = lib_num_loc_cpus;
- if (udp_rr_request->measure_cpu) {
- udp_rr_results->cpu_util = calc_cpu_util(elapsed_time);
- }
-
- if (debug) {
- fprintf(where,
- "recv_udp_rr: test complete, sending results.\n");
- fflush(where);
- }
-
- send_response();
-
- /* we are done with the socket now */
- close(s_data);
-
- }
-
-
- /* this routine implements the receive (netserver) side of a TCP_RR */
- /* test */
-void
-recv_tcp_rr()
-{
-
- struct ring_elt *send_ring;
- struct ring_elt *recv_ring;
-
- struct addrinfo *local_res;
- char local_name[BUFSIZ];
- char port_buffer[PORTBUFSIZE];
-
- struct sockaddr_storage myaddr_in,
- peeraddr_in;
- SOCKET s_listen,s_data;
- netperf_socklen_t addrlen;
- char *temp_message_ptr;
- int trans_received;
- int trans_remaining;
- int bytes_sent;
- int request_bytes_recvd;
- int request_bytes_remaining;
- int timed_out = 0;
- int sock_closed = 0;
- float elapsed_time;
-
- struct tcp_rr_request_struct *tcp_rr_request;
- struct tcp_rr_response_struct *tcp_rr_response;
- struct tcp_rr_results_struct *tcp_rr_results;
-
- tcp_rr_request =
- (struct tcp_rr_request_struct *)netperf_request.content.test_specific_data;
- tcp_rr_response =
- (struct tcp_rr_response_struct *)netperf_response.content.test_specific_data;
- tcp_rr_results =
- (struct tcp_rr_results_struct *)netperf_response.content.test_specific_data;
-
- if (debug) {
- fprintf(where,"netserver: recv_tcp_rr: entered...\n");
- fflush(where);
- }
-
- /* We want to set-up the listen socket with all the desired */
- /* parameters and then let the initiator know that all is ready. If */
- /* socket size defaults are to be used, then the initiator will have */
- /* sent us 0's. If the socket sizes cannot be changed, then we will */
- /* send-back what they are. If that information cannot be determined, */
- /* then we send-back -1's for the sizes. If things go wrong for any */
- /* reason, we will drop back ten yards and punt. */
-
- /* If anything goes wrong, we want the remote to know about it. It */
- /* would be best if the error that the remote reports to the user is */
- /* the actual error we encountered, rather than some bogus unexpected */
- /* response type message. */
-
- if (debug) {
- fprintf(where,"recv_tcp_rr: setting the response type...\n");
- fflush(where);
- }
-
- netperf_response.content.response_type = TCP_RR_RESPONSE;
-
- if (debug) {
- fprintf(where,"recv_tcp_rr: the response type is set...\n");
- fflush(where);
- }
-
- /* allocate the recv and send rings with the requested alignments */
- /* and offsets. raj 7/94 */
- if (debug) {
- fprintf(where,"recv_tcp_rr: requested recv alignment of %d offset %d\n",
- tcp_rr_request->recv_alignment,
- tcp_rr_request->recv_offset);
- fprintf(where,"recv_tcp_rr: requested send alignment of %d offset %d\n",
- tcp_rr_request->send_alignment,
- tcp_rr_request->send_offset);
- fflush(where);
- }
-
- /* at some point, these need to come to us from the remote system */
- if (send_width == 0) send_width = 1;
- if (recv_width == 0) recv_width = 1;
-
- send_ring = allocate_buffer_ring(send_width,
- tcp_rr_request->response_size,
- tcp_rr_request->send_alignment,
- tcp_rr_request->send_offset);
-
- recv_ring = allocate_buffer_ring(recv_width,
- tcp_rr_request->request_size,
- tcp_rr_request->recv_alignment,
- tcp_rr_request->recv_offset);
-
-
- /* Grab a socket to listen on, and then listen on it. */
-
- if (debug) {
- fprintf(where,"recv_tcp_rr: grabbing a socket...\n");
- fflush(where);
- }
-
- /* create_data_socket expects to find some things in the global */
- /* variables, so set the globals based on the values in the request. */
- /* once the socket has been created, we will set the response values */
- /* based on the updated value of those globals. raj 7/94 */
- lss_size_req = tcp_rr_request->send_buf_size;
- lsr_size_req = tcp_rr_request->recv_buf_size;
- loc_nodelay = tcp_rr_request->no_delay;
- loc_rcvavoid = tcp_rr_request->so_rcvavoid;
- loc_sndavoid = tcp_rr_request->so_sndavoid;
-
- set_hostname_and_port(local_name,
- port_buffer,
- nf_to_af(tcp_rr_request->ipfamily),
- tcp_rr_request->port);
-
- local_res = complete_addrinfo(local_name,
- local_name,
- port_buffer,
- nf_to_af(tcp_rr_request->ipfamily),
- SOCK_STREAM,
- IPPROTO_TCP,
- 0);
-
- s_listen = create_data_socket(local_res);
-
- if (s_listen == INVALID_SOCKET) {
- netperf_response.content.serv_errno = errno;
- send_response();
-
- exit(1);
- }
-
-
-#ifdef WIN32
- /* The test timer can fire during operations on the listening socket,
- so to make the start_timer below work we have to move
- it to close s_listen while we are blocked on accept. */
- win_kludge_socket2 = s_listen;
-#endif
-
-
- /* Now, let's set-up the socket to listen for connections */
- if (listen(s_listen, 5) == SOCKET_ERROR) {
- netperf_response.content.serv_errno = errno;
- close(s_listen);
- send_response();
-
- exit(1);
- }
-
-
- /* now get the port number assigned by the system */
- addrlen = sizeof(myaddr_in);
- if (getsockname(s_listen,
- (struct sockaddr *)&myaddr_in,
- &addrlen) == SOCKET_ERROR) {
- netperf_response.content.serv_errno = errno;
- close(s_listen);
- send_response();
-
- exit(1);
- }
-
- /* Now myaddr_in contains the port and the internet address this is */
- /* returned to the sender also implicitly telling the sender that the */
- /* socket buffer sizing has been done. */
-
- tcp_rr_response->data_port_number =
- (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port);
- netperf_response.content.serv_errno = 0;
-
- /* But wait, there's more. If the initiator wanted cpu measurements, */
- /* then we must call the calibrate routine, which will return the max */
- /* rate back to the initiator. If the CPU was not to be measured, or */
- /* something went wrong with the calibration, we will return a 0.0 to */
- /* the initiator. */
-
- tcp_rr_response->cpu_rate = (float)0.0; /* assume no cpu */
- tcp_rr_response->measure_cpu = 0;
-
- if (tcp_rr_request->measure_cpu) {
- tcp_rr_response->measure_cpu = 1;
- tcp_rr_response->cpu_rate = calibrate_local_cpu(tcp_rr_request->cpu_rate);
- }
-
-
- /* before we send the response back to the initiator, pull some of */
- /* the socket parms from the globals */
- tcp_rr_response->send_buf_size = lss_size;
- tcp_rr_response->recv_buf_size = lsr_size;
- tcp_rr_response->no_delay = loc_nodelay;
- tcp_rr_response->so_rcvavoid = loc_rcvavoid;
- tcp_rr_response->so_sndavoid = loc_sndavoid;
- tcp_rr_response->test_length = tcp_rr_request->test_length;
- send_response();
-
- addrlen = sizeof(peeraddr_in);
-
- if ((s_data = accept(s_listen,
- (struct sockaddr *)&peeraddr_in,
- &addrlen)) == INVALID_SOCKET) {
- /* Let's just punt. The remote will be given some information */
- close(s_listen);
-
- exit(1);
- }
-
-#ifdef KLUDGE_SOCKET_OPTIONS
- /* this is for those systems which *INCORRECTLY* fail to pass */
- /* attributes across an accept() call. Including this goes against */
- /* my better judgement :( raj 11/95 */
-
- kludge_socket_options(s_data);
-
-#endif /* KLUDGE_SOCKET_OPTIONS */
-
-#ifdef WIN32
- /* this is used so the timer thread can close the socket out from */
- /* under us, which to date is the easiest/cleanest/least */
- /* Windows-specific way I can find to force the winsock calls to */
- /* return WSAEINTR with the test is over. anything that will run on */
- /* 95 and NT and is closer to what netperf expects from Unix signals */
- /* and such would be appreciated raj 1/96 */
- win_kludge_socket = s_data;
-#endif /* WIN32 */
-
- if (debug) {
- fprintf(where,"recv_tcp_rr: accept completes on the data connection.\n");
- fflush(where);
- }
-
- /* Now it's time to start receiving data on the connection. We will */
- /* first grab the apropriate counters and then start grabbing. */
-
- cpu_start(tcp_rr_request->measure_cpu);
-
- /* The loop will exit when we hit the end of the test time, or when */
- /* we have exchanged the requested number of transactions. */
-
- if (tcp_rr_request->test_length > 0) {
- times_up = 0;
- trans_remaining = 0;
- start_timer(tcp_rr_request->test_length + PAD_TIME);
- }
- else {
- times_up = 1;
- trans_remaining = tcp_rr_request->test_length * -1;
- }
-
- trans_received = 0;
-
- while ((!times_up) || (trans_remaining > 0)) {
- temp_message_ptr = recv_ring->buffer_ptr;
- request_bytes_remaining = tcp_rr_request->request_size;
- while(request_bytes_remaining > 0) {
- if((request_bytes_recvd=recv(s_data,
- temp_message_ptr,
- request_bytes_remaining,
- 0)) == SOCKET_ERROR) {
- if (SOCKET_EINTR(request_bytes_recvd))
- {
- timed_out = 1;
- break;
- }
-
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
- else if( request_bytes_recvd == 0 ) {
- if (debug) {
- fprintf(where,"zero is my hero\n");
- fflush(where);
- }
- sock_closed = 1;
- break;
- }
- else {
- request_bytes_remaining -= request_bytes_recvd;
- temp_message_ptr += request_bytes_recvd;
- }
- }
-
- recv_ring = recv_ring->next;
-
- if ((timed_out) || (sock_closed)) {
- /* we hit the end of the test based on time - or the socket
- closed on us along the way. bail out of here now... */
- if (debug) {
- fprintf(where,"yo5\n");
- fflush(where);
- }
- break;
- }
-
- /* Now, send the response to the remote */
- if((bytes_sent=send(s_data,
- send_ring->buffer_ptr,
- tcp_rr_request->response_size,
- 0)) == SOCKET_ERROR) {
- if (SOCKET_EINTR(bytes_sent)) {
- /* the test timer has popped */
- timed_out = 1;
- fprintf(where,"yo6\n");
- fflush(where);
- break;
- }
- netperf_response.content.serv_errno = 992;
- send_response();
- exit(1);
- }
-
- send_ring = send_ring->next;
-
- trans_received++;
- if (trans_remaining) {
- trans_remaining--;
- }
- }
-
-
- /* The loop now exits due to timeout or transaction count being */
- /* reached */
-
- cpu_stop(tcp_rr_request->measure_cpu,&elapsed_time);
-
- stop_timer();
-
- if (timed_out) {
- /* we ended the test by time, which was at least 2 seconds */
- /* longer than we wanted to run. so, we want to subtract */
- /* PAD_TIME from the elapsed_time. */
- elapsed_time -= PAD_TIME;
- }
-
- /* send the results to the sender */
-
- if (debug) {
- fprintf(where,
- "recv_tcp_rr: got %d transactions\n",
- trans_received);
- fflush(where);
- }
-
- tcp_rr_results->bytes_received = (trans_received *
- (tcp_rr_request->request_size +
- tcp_rr_request->response_size));
- tcp_rr_results->trans_received = trans_received;
- tcp_rr_results->elapsed_time = elapsed_time;
- tcp_rr_results->cpu_method = cpu_method;
- tcp_rr_results->num_cpus = lib_num_loc_cpus;
- if (tcp_rr_request->measure_cpu) {
- tcp_rr_results->cpu_util = calc_cpu_util(elapsed_time);
- }
-
- if (debug) {
- fprintf(where,
- "recv_tcp_rr: test complete, sending results.\n");
- fflush(where);
- }
-
- /* we are now done with the sockets */
- close(s_data);
- close(s_listen);
-
- send_response();
-
-}
-
-
-void
-loc_cpu_rate()
-{
-#if defined(USE_LOOPER)
- float dummy;
-#endif
-
- /* a rather simple little test - it merely calibrates the local cpu */
- /* and prints the results. There are no headers to allow someone to */
- /* find a rate and use it in other tests automagically by setting a */
- /* variable equal to the output of this test. We ignore any rates */
- /* that may have been specified. In fact, we ignore all of the */
- /* command line args! */
-
- fprintf(where,
- "%g",
- calibrate_local_cpu(0.0));
-
- if (verbosity > 1)
- fprintf(where,
- "\nThere %s %d local %s\n",
- (lib_num_loc_cpus > 1) ? "are" : "is",
- lib_num_loc_cpus,
- (lib_num_loc_cpus > 1) ? "cpus" : "cpu");
-
- /* we need the cpu_start, cpu_stop in the looper case to kill the */
- /* child proceses raj 4/95 */
-
-#ifdef USE_LOOPER
- cpu_start(1);
- cpu_stop(1,&dummy);
-#endif /* USE_LOOPER */
-
-}
-
-void
-rem_cpu_rate()
-{
- /* this test is much like the local variant, except that it works for */
- /* the remote system, so in this case, we do pay attention to the */
- /* value of the '-H' command line argument. */
-
- fprintf(where,
- "%g",
- calibrate_remote_cpu());
-
- if (verbosity > 1)
- fprintf(where,
- "\nThere %s %d remote %s\n",
- (lib_num_rem_cpus > 1) ? "are" : "is",
- lib_num_rem_cpus,
- (lib_num_rem_cpus > 1) ? "cpus" : "cpu");
-
-}
-
-
- /* this test is intended to test the performance of establishing a
- connection, exchanging a request/response pair, and repeating. it
- is expected that this would be a good starting-point for
- comparision of T/TCP with classic TCP for transactional workloads.
- it will also look (can look) much like the communication pattern
- of http for www access. */
-
-void
-send_tcp_conn_rr(char remote_host[])
-{
-
- char *tput_title = "\
-Local /Remote\n\
-Socket Size Request Resp. Elapsed Trans.\n\
-Send Recv Size Size Time Rate \n\
-bytes Bytes bytes bytes secs. per sec \n\n";
-
- char *tput_fmt_0 =
- "%7.2f\n";
-
- char *tput_fmt_1_line_1 = "\
-%-6d %-6d %-6d %-6d %-6.2f %7.2f \n";
- char *tput_fmt_1_line_2 = "\
-%-6d %-6d\n";
-
- char *cpu_title = "\
-Local /Remote\n\
-Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\
-Send Recv Size Size Time Rate local remote local remote\n\
-bytes bytes bytes bytes secs. per sec %% %% us/Tr us/Tr\n\n";
-
- char *cpu_fmt_0 =
- "%6.3f\n";
-
- char *cpu_fmt_1_line_1 = "\
-%-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f\n";
-
- char *cpu_fmt_1_line_2 = "\
-%-6d %-6d\n";
-
- char *ksink_fmt = "\n\
-Alignment Offset\n\
-Local Remote Local Remote\n\
-Send Recv Send Recv\n\
-%5d %5d %5d %5d\n";
-
-
- int timed_out = 0;
- float elapsed_time;
-
- int len;
- struct ring_elt *send_ring;
- struct ring_elt *recv_ring;
- char *temp_message_ptr;
- int nummessages;
- SOCKET send_socket;
- int trans_remaining;
- double bytes_xferd;
- int rsp_bytes_left;
- int rsp_bytes_recvd;
-
- float local_cpu_utilization;
- float local_service_demand;
- float remote_cpu_utilization;
- float remote_service_demand;
- double thruput;
-
- struct addrinfo *local_res;
- struct addrinfo *remote_res;
-
- int myport;
- int ret;
-
- struct tcp_conn_rr_request_struct *tcp_conn_rr_request;
- struct tcp_conn_rr_response_struct *tcp_conn_rr_response;
- struct tcp_conn_rr_results_struct *tcp_conn_rr_result;
-
- tcp_conn_rr_request =
- (struct tcp_conn_rr_request_struct *)netperf_request.content.test_specific_data;
- tcp_conn_rr_response =
- (struct tcp_conn_rr_response_struct *)netperf_response.content.test_specific_data;
- tcp_conn_rr_result =
- (struct tcp_conn_rr_results_struct *)netperf_response.content.test_specific_data;
-
-
-#ifdef WANT_HISTOGRAM
- if (verbosity > 1) {
- time_hist = HIST_new();
- }
-#endif /* WANT_HISTOGRAM */
-
- /* since we are now disconnected from the code that established the */
- /* control socket, and since we want to be able to use different */
- /* protocols and such, we are passed the name of the remote host and */
- /* must turn that into the test specific addressing information. */
-
- complete_addrinfos(&remote_res,
- &local_res,
- remote_host,
- SOCK_STREAM,
- IPPROTO_TCP,
- 0);
-
- if ( print_headers ) {
- print_top_test_header("TCP Connect/Request/Response TEST",local_res,remote_res);
- }
-
- /* initialize a few counters */
-
- nummessages = 0;
- bytes_xferd = 0.0;
- times_up = 0;
-
- /* set-up the data buffers with the requested alignment and offset */
- if (send_width == 0) send_width = 1;
- if (recv_width == 0) recv_width = 1;
-
- send_ring = allocate_buffer_ring(send_width,
- req_size,
- local_send_align,
- local_send_offset);
-
- recv_ring = allocate_buffer_ring(recv_width,
- rsp_size,
- local_recv_align,
- local_recv_offset);
-
-
- if (debug) {
- fprintf(where,"send_tcp_conn_rr: send_socket obtained...\n");
- }
-
- /* If the user has requested cpu utilization measurements, we must */
- /* calibrate the cpu(s). We will perform this task within the tests */
- /* themselves. If the user has specified the cpu rate, then */
- /* calibrate_local_cpu will return rather quickly as it will have */
- /* nothing to do. If local_cpu_rate is zero, then we will go through */
- /* all the "normal" calibration stuff and return the rate back.*/
-
- if (local_cpu_usage) {
- local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
- }
-
- if (!no_control) {
-
- /* Tell the remote end to do a listen. The server alters the
- socket paramters on the other side at this point, hence the
- reason for all the values being passed in the setup message. If
- the user did not specify any of the parameters, they will be
- passed as 0, which will indicate to the remote that no changes
- beyond the system's default should be used. Alignment is the
- exception, it will default to 8, which will be no alignment
- alterations. */
-
- netperf_request.content.request_type = DO_TCP_CRR;
- tcp_conn_rr_request->recv_buf_size = rsr_size_req;
- tcp_conn_rr_request->send_buf_size = rss_size_req;
- tcp_conn_rr_request->recv_alignment = remote_recv_align;
- tcp_conn_rr_request->recv_offset = remote_recv_offset;
- tcp_conn_rr_request->send_alignment = remote_send_align;
- tcp_conn_rr_request->send_offset = remote_send_offset;
- tcp_conn_rr_request->request_size = req_size;
- tcp_conn_rr_request->response_size = rsp_size;
- tcp_conn_rr_request->no_delay = rem_nodelay;
- tcp_conn_rr_request->measure_cpu = remote_cpu_usage;
- tcp_conn_rr_request->cpu_rate = remote_cpu_rate;
- tcp_conn_rr_request->so_rcvavoid = rem_rcvavoid;
- tcp_conn_rr_request->so_sndavoid = rem_sndavoid;
- if (test_time) {
- tcp_conn_rr_request->test_length = test_time;
- }
- else {
- tcp_conn_rr_request->test_length = test_trans * -1;
- }
- tcp_conn_rr_request->port = atoi(remote_data_port);
- tcp_conn_rr_request->ipfamily = af_to_nf(remote_res->ai_family);
-
- if (debug > 1) {
- fprintf(where,"netperf: send_tcp_conn_rr: requesting TCP crr test\n");
- }
-
- send_request();
-
- /* The response from the remote will contain all of the relevant
- socket parameters for this test type. We will put them back
- into the variables here so they can be displayed if desired.
- The remote will have calibrated CPU if necessary, and will have
- done all the needed set-up we will have calibrated the cpu
- locally before sending the request, and will grab the counter
- value right after the connect returns. The remote will grab the
- counter right after the accept call. This saves the hassle of
- extra messages being sent for the TCP tests. */
-
- recv_response();
-
- if (!netperf_response.content.serv_errno) {
- rsr_size = tcp_conn_rr_response->recv_buf_size;
- rss_size = tcp_conn_rr_response->send_buf_size;
- rem_nodelay = tcp_conn_rr_response->no_delay;
- remote_cpu_usage = tcp_conn_rr_response->measure_cpu;
- remote_cpu_rate = tcp_conn_rr_response->cpu_rate;
- /* make sure that port numbers are in network order */
- set_port_number(remote_res,
- (unsigned short)tcp_conn_rr_response->data_port_number);
-
- if (debug) {
- fprintf(where,"remote listen done.\n");
- fprintf(where,"remote port is %u\n",get_port_number(remote_res));
- fflush(where);
- }
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- fprintf(where,
- "netperf: remote error %d",
- netperf_response.content.serv_errno);
- perror("");
- fflush(where);
- exit(1);
- }
- }
-#ifdef WANT_DEMO
- DEMO_RR_SETUP(100)
-#endif
-
- /* pick a nice random spot between client_port_min and */
- /* client_port_max for our initial port number */
- srand(getpid());
- if (client_port_max - client_port_min) {
- myport = client_port_min +
- (rand() % (client_port_max - client_port_min));
- }
- else {
- myport = client_port_min;
- }
- /* there will be a ++ before the first call to bind, so subtract one */
- myport--;
- /* Set-up the test end conditions. For a request/response test, they */
- /* can be either time or transaction based. */
-
- if (test_time) {
- /* The user wanted to end the test after a period of time. */
- times_up = 0;
- trans_remaining = 0;
- start_timer(test_time);
- }
- else {
- /* The tester wanted to send a number of bytes. */
- trans_remaining = test_bytes;
- times_up = 1;
- }
-
- /* The cpu_start routine will grab the current time and possibly */
- /* value of the idle counter for later use in measuring cpu */
- /* utilization and/or service demand and thruput. */
-
-
- cpu_start(local_cpu_usage);
-
-#ifdef WANT_DEMO
- if (demo_mode) {
- HIST_timestamp(demo_one_ptr);
- }
-#endif
-
- /* We use an "OR" to control test execution. When the test is */
- /* controlled by time, the byte count check will always return false. */
- /* When the test is controlled by byte count, the time test will */
- /* always return false. When the test is finished, the whole */
- /* expression will go false and we will stop sending data. I think I */
- /* just arbitrarily decrement trans_remaining for the timed test, but */
- /* will not do that just yet... One other question is whether or not */
- /* the send buffer and the receive buffer should be the same buffer. */
-
- while ((!times_up) || (trans_remaining > 0)) {
-
-#ifdef WANT_HISTOGRAM
- if (verbosity > 1) {
- /* timestamp just before our call to create the socket, and then */
- /* again just after the receive raj 3/95 */
- HIST_timestamp(&time_one);
- }
-#endif /* WANT_HISTOGRAM */
-
-newport:
- /* pick a new port number */
- myport++;
-
- /* wrap the port number when we get to client_port_max. NOTE, some */
- /* broken TCP's might treat the port number as a signed 16 bit */
- /* quantity. we aren't interested in testing such broken */
- /* implementations :) so we won't make sure that it is below 32767 */
- /* raj 8/94 */
- if (myport >= client_port_max) {
- myport = client_port_min;
- }
-
- /* we do not want to use the port number that the server is */
- /* sitting at - this would cause us to fail in a loopback test. we */
- /* could just rely on the failure of the bind to get us past this, */
- /* but I'm guessing that in this one case at least, it is much */
- /* faster, given that we *know* that port number is already in use */
- /* (or rather would be in a loopback test) */
-
- if (myport == get_port_number(remote_res)) myport++;
-
- if (debug) {
- if ((nummessages % 100) == 0) {
- printf("port %d\n",myport);
- }
- }
-
- /* set up the data socket */
- set_port_number(local_res, (unsigned short)myport);
- send_socket = create_data_socket(local_res);
-
- if (send_socket == INVALID_SOCKET) {
- perror("netperf: send_tcp_conn_rr: tcp stream data socket");
- exit(1);
- }
-
-
- /* we used to call bind here, but that is now taken-care-of by the
- create_data_socket routine. */
-
- /* Connect up to the remote port on the data socket */
- if ((ret = connect(send_socket,
- remote_res->ai_addr,
- remote_res->ai_addrlen)) == INVALID_SOCKET){
- if (SOCKET_EINTR(ret))
- {
- /* we hit the end of a */
- /* timed test. */
- timed_out = 1;
- break;
- }
- if ((SOCKET_EADDRINUSE(ret)) || SOCKET_EADDRNOTAVAIL(ret)) {
- /* likely something our explicit bind() would have caught in
- the past, so go get another port, via create_data_socket.
- yes, this is a bit more overhead than before, but the
- condition should be rather rare. raj 2005-02-08 */
- close(send_socket);
- goto newport;
- }
- perror("netperf: data socket connect failed");
- printf("\tattempted to connect on socket %d to port %d",
- send_socket,
- get_port_number(remote_res));
- printf(" from port %d \n",get_port_number(local_res));
- exit(1);
- }
-
-
- /* send the request */
- if((len=send(send_socket,
- send_ring->buffer_ptr,
- req_size,
- 0)) != req_size) {
- if (SOCKET_EINTR(len))
- {
- /* we hit the end of a */
- /* timed test. */
- timed_out = 1;
- break;
- }
- perror("send_tcp_conn_rr: data send error");
- exit(1);
- }
- send_ring = send_ring->next;
-
- /* receive the response */
- rsp_bytes_left = rsp_size;
- temp_message_ptr = recv_ring->buffer_ptr;
-
-
- do {
- rsp_bytes_recvd = recv(send_socket,
- temp_message_ptr,
- rsp_bytes_left,
- 0);
- if (rsp_bytes_recvd > 0) {
- rsp_bytes_left -= rsp_bytes_recvd;
- temp_message_ptr += rsp_bytes_recvd;
- }
- else {
- break;
- }
- } while (rsp_bytes_left);
-
-
- /* OK, we are out of the loop - now what? */
- if (rsp_bytes_recvd < 0) {
- /* did the timer hit, or was there an error? */
- if (SOCKET_EINTR(rsp_bytes_recvd))
- {
- /* We hit the end of a timed test. */
- timed_out = 1;
- break;
- }
- perror("send_tcp_conn_rr: data recv error");
- exit(1);
- }
-
- /* if this is a no_control test, we initiate connection close,
- otherwise the remote netserver does it to remain just like
- previous behaviour. raj 2007-27-08 */
- if (!no_control) {
- shutdown(send_socket,SHUT_WR);
- }
-
- /* we are expecting to get either a return of zero indicating
- connection close, or an error. */
- rsp_bytes_recvd = recv(send_socket,
- temp_message_ptr,
- 1,
- 0);
-
- /* our exit from the while loop should generally be when */
- /* tmp_bytes_recvd is equal to zero, which implies the connection */
- /* has been closed by the server side. By waiting until we get the */
- /* zero return we can avoid race conditions that stick us with the */
- /* TIME_WAIT connection and not the server. raj 8/96 */
-
- if (rsp_bytes_recvd == 0) {
- /* connection close, call close. we assume that the requisite */
- /* number of bytes have been received */
- recv_ring = recv_ring->next;
-
-#ifdef WANT_HISTOGRAM
- if (verbosity > 1) {
- HIST_timestamp(&time_two);
- HIST_add(time_hist,delta_micro(&time_one,&time_two));
- }
-#endif /* WANT_HISTOGRAM */
-
-#ifdef WANT_DEMO
- DEMO_RR_INTERVAL(1)
-#endif
-
- nummessages++;
- if (trans_remaining) {
- trans_remaining--;
- }
-
- if (debug > 3) {
- fprintf(where,
- "Transaction %d completed on local port %d\n",
- nummessages,
- get_port_number(local_res));
- fflush(where);
- }
-
- close(send_socket);
-
- }
- else {
- /* it was less than zero - an error occured */
- if (SOCKET_EINTR(rsp_bytes_recvd))
- {
- /* We hit the end of a timed test. */
- timed_out = 1;
- break;
- }
- perror("send_tcp_conn_rr: data recv error");
- exit(1);
- }
-
- }
-
-
- /* this call will always give us the elapsed time for the test, and */
- /* will also store-away the necessaries for cpu utilization */
-
- cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being measured? */
- /* how long did we really run? */
-
- if (!no_control) {
- /* Get the statistics from the remote end. The remote will have
- calculated service demand and all those interesting things. If
- it wasn't supposed to care, it will return obvious values. */
-
- recv_response();
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote results obtained\n");
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- fprintf(where,
- "netperf: remote error %d",
- netperf_response.content.serv_errno);
- perror("");
- fflush(where);
-
- exit(1);
- }
- }
-
- /* We now calculate what our thruput was for the test. In the future, */
- /* we may want to include a calculation of the thruput measured by */
- /* the remote, but it should be the case that for a TCP stream test, */
- /* that the two numbers should be *very* close... We calculate */
- /* bytes_sent regardless of the way the test length was controlled. */
- /* If it was time, we needed to, and if it was by bytes, the user may */
- /* have specified a number of bytes that wasn't a multiple of the */
- /* send_size, so we really didn't send what he asked for ;-) We use */
- /* Kbytes/s as the units of thruput for a TCP stream test, where K = */
- /* 1024. A future enhancement *might* be to choose from a couple of */
- /* unit selections. */
-
- bytes_xferd = (req_size * nummessages) + (rsp_size * nummessages);
- thruput = calc_thruput(bytes_xferd);
-
- if (local_cpu_usage || remote_cpu_usage) {
- /* We must now do a little math for service demand and cpu */
- /* utilization for the system(s) */
- /* Of course, some of the information might be bogus because */
- /* there was no idle counter in the kernel(s). We need to make */
- /* a note of this for the user's benefit...*/
- if (local_cpu_usage) {
- if (local_cpu_rate == 0.0) {
- fprintf(where,
- "WARNING WARNING WARNING WARNING WARNING WARNING WARNING!\n");
- fprintf(where,
- "Local CPU usage numbers based on process information only!\n");
- fflush(where);
- }
- local_cpu_utilization = calc_cpu_util(0.0);
- /* since calc_service demand is doing ms/Kunit we will */
- /* multiply the number of transaction by 1024 to get */
- /* "good" numbers */
- local_service_demand = calc_service_demand((double) nummessages*1024,
- 0.0,
- 0.0,
- 0);
- }
- else {
- local_cpu_utilization = (float) -1.0;
- local_service_demand = (float) -1.0;
- }
-
- if (remote_cpu_usage) {
- if (remote_cpu_rate == 0.0) {
- fprintf(where,
- "DANGER DANGER DANGER DANGER DANGER DANGER DANGER!\n");
- fprintf(where,
- "Remote CPU usage numbers based on process information only!\n");
- fflush(where);
- }
- remote_cpu_utilization = tcp_conn_rr_result->cpu_util;
- /* since calc_service demand is doing ms/Kunit we will */
- /* multiply the number of transaction by 1024 to get */
- /* "good" numbers */
- remote_service_demand = calc_service_demand((double) nummessages*1024,
- 0.0,
- remote_cpu_utilization,
- tcp_conn_rr_result->num_cpus);
- }
- else {
- remote_cpu_utilization = (float) -1.0;
- remote_service_demand = (float) -1.0;
- }
-
- /* We are now ready to print all the information. If the user */
- /* has specified zero-level verbosity, we will just print the */
- /* local service demand, or the remote service demand. If the */
- /* user has requested verbosity level 1, he will get the basic */
- /* "streamperf" numbers. If the user has specified a verbosity */
- /* of greater than 1, we will display a veritable plethora of */
- /* background information from outside of this block as it it */
- /* not cpu_measurement specific... */
-
- switch (verbosity) {
- case 0:
- if (local_cpu_usage) {
- fprintf(where,
- cpu_fmt_0,
- local_service_demand);
- }
- else {
- fprintf(where,
- cpu_fmt_0,
- remote_service_demand);
- }
- break;
- case 1:
- case 2:
-
- if (print_headers) {
- fprintf(where,
- cpu_title,
- local_cpu_method,
- remote_cpu_method);
- }
-
- fprintf(where,
- cpu_fmt_1_line_1, /* the format string */
- lss_size, /* local sendbuf size */
- lsr_size,
- req_size, /* how large were the requests */
- rsp_size, /* guess */
- elapsed_time, /* how long was the test */
- nummessages/elapsed_time,
- local_cpu_utilization, /* local cpu */
- remote_cpu_utilization, /* remote cpu */
- local_service_demand, /* local service demand */
- remote_service_demand); /* remote service demand */
- fprintf(where,
- cpu_fmt_1_line_2,
- rss_size,
- rsr_size);
- break;
- }
- }
- else {
- /* The tester did not wish to measure service demand. */
- switch (verbosity) {
- case 0:
- fprintf(where,
- tput_fmt_0,
- nummessages/elapsed_time);
- break;
- case 1:
- case 2:
- if (print_headers) {
- fprintf(where,tput_title,format_units());
- }
-
- fprintf(where,
- tput_fmt_1_line_1, /* the format string */
- lss_size,
- lsr_size,
- req_size, /* how large were the requests */
- rsp_size, /* how large were the responses */
- elapsed_time, /* how long did it take */
- nummessages/elapsed_time);
- fprintf(where,
- tput_fmt_1_line_2,
- rss_size, /* remote recvbuf size */
- rsr_size);
-
- break;
- }
- }
-
- /* it would be a good thing to include information about some of the */
- /* other parameters that may have been set for this test, but at the */
- /* moment, I do not wish to figure-out all the formatting, so I will */
- /* just put this comment here to help remind me that it is something */
- /* that should be done at a later time. */
-
- if (verbosity > 1) {
- /* The user wanted to know it all, so we will give it to him. */
- /* This information will include as much as we can find about */
- /* TCP statistics, the alignments of the sends and receives */
- /* and all that sort of rot... */
-
- fprintf(where,
- ksink_fmt,
- local_send_align,
- remote_recv_offset,
- local_send_offset,
- remote_recv_offset);
-
-#ifdef WANT_HISTOGRAM
- fprintf(where,"\nHistogram of request/response times\n");
- fflush(where);
- HIST_report(time_hist);
-#endif /* WANT_HISTOGRAM */
-
- }
-
-}
-
-
-void
-recv_tcp_conn_rr()
-{
-
- char *message;
- struct addrinfo *local_res;
- char local_name[BUFSIZ];
- char port_buffer[PORTBUFSIZE];
-
- struct sockaddr_storage myaddr_in, peeraddr_in;
- SOCKET s_listen,s_data;
- netperf_socklen_t addrlen;
- char *recv_message_ptr;
- char *send_message_ptr;
- char *temp_message_ptr;
- int trans_received;
- int trans_remaining;
- int bytes_sent;
- int request_bytes_recvd;
- int request_bytes_remaining;
- int timed_out = 0;
- float elapsed_time;
-
- struct tcp_conn_rr_request_struct *tcp_conn_rr_request;
- struct tcp_conn_rr_response_struct *tcp_conn_rr_response;
- struct tcp_conn_rr_results_struct *tcp_conn_rr_results;
-
- tcp_conn_rr_request =
- (struct tcp_conn_rr_request_struct *)netperf_request.content.test_specific_data;
- tcp_conn_rr_response =
- (struct tcp_conn_rr_response_struct *)netperf_response.content.test_specific_data;
- tcp_conn_rr_results =
- (struct tcp_conn_rr_results_struct *)netperf_response.content.test_specific_data;
-
- if (debug) {
- fprintf(where,"netserver: recv_tcp_conn_rr: entered...\n");
- fflush(where);
- }
-
- /* We want to set-up the listen socket with all the desired */
- /* parameters and then let the initiator know that all is ready. If */
- /* socket size defaults are to be used, then the initiator will have */
- /* sent us 0's. If the socket sizes cannot be changed, then we will */
- /* send-back what they are. If that information cannot be determined, */
- /* then we send-back -1's for the sizes. If things go wrong for any */
- /* reason, we will drop back ten yards and punt. */
-
- /* If anything goes wrong, we want the remote to know about it. It */
- /* would be best if the error that the remote reports to the user is */
- /* the actual error we encountered, rather than some bogus unexpected */
- /* response type message. */
-
- if (debug) {
- fprintf(where,"recv_tcp_conn_rr: setting the response type...\n");
- fflush(where);
- }
-
- netperf_response.content.response_type = TCP_CRR_RESPONSE;
-
- if (debug) {
- fprintf(where,"recv_tcp_conn_rr: the response type is set...\n");
- fflush(where);
- }
-
- /* set-up the data buffer with the requested alignment and offset */
- message = (char *)malloc(DATABUFFERLEN);
- if (message == NULL) {
- printf("malloc(%d) failed!\n", DATABUFFERLEN);
- exit(1);
- }
-
- /* We now alter the message_ptr variables to be at the desired */
- /* alignments with the desired offsets. */
-
- if (debug) {
- fprintf(where,
- "recv_tcp_conn_rr: requested recv alignment of %d offset %d\n",
- tcp_conn_rr_request->recv_alignment,
- tcp_conn_rr_request->recv_offset);
- fprintf(where,
- "recv_tcp_conn_rr: requested send alignment of %d offset %d\n",
- tcp_conn_rr_request->send_alignment,
- tcp_conn_rr_request->send_offset);
- fflush(where);
- }
-
- recv_message_ptr = ALIGN_BUFFER(message, tcp_conn_rr_request->recv_alignment, tcp_conn_rr_request->recv_offset);
-
- send_message_ptr = ALIGN_BUFFER(message, tcp_conn_rr_request->send_alignment, tcp_conn_rr_request->send_offset);
-
- if (debug) {
- fprintf(where,"recv_tcp_conn_rr: receive alignment and offset set...\n");
- fflush(where);
- }
-
- /* Grab a socket to listen on, and then listen on it. */
-
- if (debug) {
- fprintf(where,"recv_tcp_conn_rr: grabbing a socket...\n");
- fflush(where);
- }
-
- /* create_data_socket expects to find some things in the global */
- /* variables, so set the globals based on the values in the request. */
- /* once the socket has been created, we will set the response values */
- /* based on the updated value of those globals. raj 7/94 */
- lss_size_req = tcp_conn_rr_request->send_buf_size;
- lsr_size_req = tcp_conn_rr_request->recv_buf_size;
- loc_nodelay = tcp_conn_rr_request->no_delay;
- loc_rcvavoid = tcp_conn_rr_request->so_rcvavoid;
- loc_sndavoid = tcp_conn_rr_request->so_sndavoid;
-
- set_hostname_and_port(local_name,
- port_buffer,
- nf_to_af(tcp_conn_rr_request->ipfamily),
- tcp_conn_rr_request->port);
-
- local_res = complete_addrinfo(local_name,
- local_name,
- port_buffer,
- nf_to_af(tcp_conn_rr_request->ipfamily),
- SOCK_STREAM,
- IPPROTO_TCP,
- 0);
-
- s_listen = create_data_socket(local_res);
-
- if (s_listen == INVALID_SOCKET) {
- netperf_response.content.serv_errno = errno;
- send_response();
- if (debug) {
- fprintf(where,"could not create data socket\n");
- fflush(where);
- }
- exit(1);
- }
-
-#ifdef WIN32
- /* The test timer can fire during operations on the listening socket,
- so to make the start_timer below work we have to move
- it to close s_listen while we are blocked on accept. */
- win_kludge_socket2 = s_listen;
-#endif
-
-
- /* Now, let's set-up the socket to listen for connections */
- if (listen(s_listen, 5) == SOCKET_ERROR) {
- netperf_response.content.serv_errno = errno;
- close(s_listen);
- send_response();
- if (debug) {
- fprintf(where,"could not listen\n");
- fflush(where);
- }
- exit(1);
- }
-
- /* now get the port number assigned by the system */
- addrlen = sizeof(myaddr_in);
- if (getsockname(s_listen,
- (struct sockaddr *)&myaddr_in,
- &addrlen) == SOCKET_ERROR){
- netperf_response.content.serv_errno = errno;
- close(s_listen);
- send_response();
- if (debug) {
- fprintf(where,"could not getsockname\n");
- fflush(where);
- }
- exit(1);
- }
-
- /* Now myaddr_in contains the port and the internet address this is */
- /* returned to the sender also implicitly telling the sender that the */
- /* socket buffer sizing has been done. */
-
- tcp_conn_rr_response->data_port_number =
- (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port);
- if (debug) {
- fprintf(where,"telling the remote to call me at %d\n",
- tcp_conn_rr_response->data_port_number);
- fflush(where);
- }
- netperf_response.content.serv_errno = 0;
-
- /* But wait, there's more. If the initiator wanted cpu measurements, */
- /* then we must call the calibrate routine, which will return the max */
- /* rate back to the initiator. If the CPU was not to be measured, or */
- /* something went wrong with the calibration, we will return a 0.0 to */
- /* the initiator. */
-
- tcp_conn_rr_response->cpu_rate = (float)0.0; /* assume no cpu */
- if (tcp_conn_rr_request->measure_cpu) {
- tcp_conn_rr_response->measure_cpu = 1;
- tcp_conn_rr_response->cpu_rate =
- calibrate_local_cpu(tcp_conn_rr_request->cpu_rate);
- }
-
-
-
- /* before we send the response back to the initiator, pull some of */
- /* the socket parms from the globals */
- tcp_conn_rr_response->send_buf_size = lss_size;
- tcp_conn_rr_response->recv_buf_size = lsr_size;
- tcp_conn_rr_response->no_delay = loc_nodelay;
- tcp_conn_rr_response->so_rcvavoid = loc_rcvavoid;
- tcp_conn_rr_response->so_sndavoid = loc_sndavoid;
-
- send_response();
-
- addrlen = sizeof(peeraddr_in);
-
- /* Now it's time to start receiving data on the connection. We will */
- /* first grab the apropriate counters and then start grabbing. */
-
- cpu_start(tcp_conn_rr_request->measure_cpu);
-
- /* The loop will exit when the sender does a shutdown, which will */
- /* return a length of zero */
-
- if (tcp_conn_rr_request->test_length > 0) {
- times_up = 0;
- trans_remaining = 0;
- start_timer(tcp_conn_rr_request->test_length + PAD_TIME);
- }
- else {
- times_up = 1;
- trans_remaining = tcp_conn_rr_request->test_length * -1;
- }
-
- trans_received = 0;
-
- while ((!times_up) || (trans_remaining > 0)) {
-
- /* accept a connection from the remote */
-#ifdef WIN32
- /* The test timer will probably fire during this accept,
- so to make the start_timer above work we have to move
- it to close s_listen while we are blocked on accept. */
- win_kludge_socket = s_listen;
-#endif
- if ((s_data=accept(s_listen,
- (struct sockaddr *)&peeraddr_in,
- &addrlen)) == INVALID_SOCKET) {
- if (errno == EINTR) {
- /* the timer popped */
- timed_out = 1;
- break;
- }
- fprintf(where,"recv_tcp_conn_rr: accept: errno = %d\n",errno);
- fflush(where);
- close(s_listen);
-
- exit(1);
- }
-
- if (debug) {
- fprintf(where,"recv_tcp_conn_rr: accepted data connection.\n");
- fflush(where);
- }
-
-#ifdef WIN32
- /* this is used so the timer thread can close the socket out from */
- /* under us, which to date is the easiest/cleanest/least */
- /* Windows-specific way I can find to force the winsock calls to */
- /* return WSAEINTR with the test is over. anything that will run on */
- /* 95 and NT and is closer to what netperf expects from Unix signals */
- /* and such would be appreciated raj 1/96 */
- win_kludge_socket = s_data;
-#endif /* WIN32 */
-
-#ifdef KLUDGE_SOCKET_OPTIONS
- /* this is for those systems which *INCORRECTLY* fail to pass */
- /* attributes across an accept() call. Including this goes against */
- /* my better judgement :( raj 11/95 */
-
- kludge_socket_options(s_data);
-
-#endif /* KLUDGE_SOCKET_OPTIONS */
-
- temp_message_ptr = recv_message_ptr;
- request_bytes_remaining = tcp_conn_rr_request->request_size;
-
- /* receive the request from the other side */
- while (!times_up && (request_bytes_remaining > 0)) {
- if((request_bytes_recvd=recv(s_data,
- temp_message_ptr,
- request_bytes_remaining,
- 0)) == SOCKET_ERROR) {
- if (SOCKET_EINTR(request_bytes_recvd))
- {
- /* the timer popped */
- timed_out = 1;
- break;
- }
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
- else {
- request_bytes_remaining -= request_bytes_recvd;
- temp_message_ptr += request_bytes_recvd;
- }
- }
-
- if (timed_out) {
- /* we hit the end of the test based on time - lets */
- /* bail out of here now... */
- fprintf(where,"yo5\n");
- fflush(where);
- break;
- }
-
- /* Now, send the response to the remote */
- if((bytes_sent=send(s_data,
- send_message_ptr,
- tcp_conn_rr_request->response_size,
- 0)) == SOCKET_ERROR) {
- if (errno == EINTR) {
- /* the test timer has popped */
- timed_out = 1;
- fprintf(where,"yo6\n");
- fflush(where);
- break;
- }
- netperf_response.content.serv_errno = 99;
- send_response();
- exit(1);
- }
-
- trans_received++;
- if (trans_remaining) {
- trans_remaining--;
- }
-
- if (debug) {
- fprintf(where,
- "recv_tcp_conn_rr: Transaction %d complete\n",
- trans_received);
- fflush(where);
- }
-
- /* close the connection. the server will likely do a graceful */
- /* close of the connection, insuring that all data has arrived at */
- /* the client. for this it will call shutdown(), and then recv() and */
- /* then close(). I'm reasonably confident that this is the */
- /* appropriate sequence of calls - I would like to hear of */
- /* examples in web servers to the contrary. raj 10/95*/
-#ifdef TCP_CRR_SHUTDOWN
- shutdown(s_data,SHUT_WR);
- recv(s_data,
- recv_message_ptr,
- 1,
- 0);
- close(s_data);
-#else
- close(s_data);
-#endif /* TCP_CRR_SHUTDOWN */
-
- }
-
-
- /* The loop now exits due to timeout or transaction count being */
- /* reached */
-
- cpu_stop(tcp_conn_rr_request->measure_cpu,&elapsed_time);
-
- if (timed_out) {
- /* we ended the test by time, which was at least 2 seconds */
- /* longer than we wanted to run. so, we want to subtract */
- /* PAD_TIME from the elapsed_time. */
- elapsed_time -= PAD_TIME;
- }
- /* send the results to the sender */
-
- if (debug) {
- fprintf(where,
- "recv_tcp_conn_rr: got %d transactions\n",
- trans_received);
- fflush(where);
- }
-
- tcp_conn_rr_results->bytes_received = (trans_received *
- (tcp_conn_rr_request->request_size +
- tcp_conn_rr_request->response_size));
- tcp_conn_rr_results->trans_received = trans_received;
- tcp_conn_rr_results->elapsed_time = elapsed_time;
- if (tcp_conn_rr_request->measure_cpu) {
- tcp_conn_rr_results->cpu_util = calc_cpu_util(elapsed_time);
- }
-
- if (debug) {
- fprintf(where,
- "recv_tcp_conn_rr: test complete, sending results.\n");
- fflush(where);
- }
-
- send_response();
-
-}
-
-
-#ifdef DO_1644
-
- /* this test is intended to test the performance of establishing a */
- /* connection, exchanging a request/response pair, and repeating. it */
- /* is expected that this would be a good starting-point for */
- /* comparision of T/TCP with classic TCP for transactional workloads. */
- /* it will also look (can look) much like the communication pattern */
- /* of http for www access. */
-
-int
-send_tcp_tran_rr(char remote_host[])
-{
-
- char *tput_title = "\
-Local /Remote\n\
-Socket Size Request Resp. Elapsed Trans.\n\
-Send Recv Size Size Time Rate \n\
-bytes Bytes bytes bytes secs. per sec \n\n";
-
- char *tput_fmt_0 =
- "%7.2f\n";
-
- char *tput_fmt_1_line_1 = "\
-%-6d %-6d %-6d %-6d %-6.2f %7.2f \n";
- char *tput_fmt_1_line_2 = "\
-%-6d %-6d\n";
-
- char *cpu_title = "\
-Local /Remote\n\
-Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\
-Send Recv Size Size Time Rate local remote local remote\n\
-bytes bytes bytes bytes secs. per sec %% %% us/Tr us/Tr\n\n";
-
- char *cpu_fmt_0 =
- "%6.3f\n";
-
- char *cpu_fmt_1_line_1 = "\
-%-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f\n";
-
- char *cpu_fmt_1_line_2 = "\
-%-6d %-6d\n";
-
- char *ksink_fmt = "\n\
-Alignment Offset\n\
-Local Remote Local Remote\n\
-Send Recv Send Recv\n\
-%5d %5d %5d %5d\n";
-
-
- int one = 1;
- int timed_out = 0;
- float elapsed_time;
-
- int len;
- struct ring_elt *send_ring;
- struct ring_elt *recv_ring;
- char *temp_message_ptr;
- int nummessages;
- SOCKET send_socket;
- int trans_remaining;
- double bytes_xferd;
- int sock_opt_len = sizeof(int);
- int rsp_bytes_left;
- int rsp_bytes_recvd;
-
- float local_cpu_utilization;
- float local_service_demand;
- float remote_cpu_utilization;
- float remote_service_demand;
- double thruput;
-
- struct hostent *hp;
- struct sockaddr_in server;
- struct sockaddr_in *myaddr;
- unsigned int addr;
- int myport;
-
- struct tcp_tran_rr_request_struct *tcp_tran_rr_request;
- struct tcp_tran_rr_response_struct *tcp_tran_rr_response;
- struct tcp_tran_rr_results_struct *tcp_tran_rr_result;
-
- tcp_tran_rr_request =
- (struct tcp_tran_rr_request_struct *)netperf_request.content.test_specific_data;
- tcp_tran_rr_response =
- (struct tcp_tran_rr_response_struct *)netperf_response.content.test_specific_data;
- tcp_tran_rr_result =
- (struct tcp_tran_rr_results_struct *)netperf_response.content.test_specific_data;
-
-
-#ifdef WANT_HISTOGRAM
- if (verbosity > 1) {
- time_hist = HIST_new();
- }
-#endif /* WANT_HISTOGRAM */
-
- /* since we are now disconnected from the code that established the */
- /* control socket, and since we want to be able to use different */
- /* protocols and such, we are passed the name of the remote host and */
- /* must turn that into the test specific addressing information. */
-
- myaddr = (struct sockaddr_storage *)malloc(sizeof(struct sockaddr_storage));
- if (myaddr == NULL) {
- printf("malloc(%d) failed!\n", sizeof(struct sockaddr_storage));
- exit(1);
- }
-
- bzero((char *)&server,
- sizeof(server));
- bzero((char *)myaddr,
- sizeof(struct sockaddr_storage));
- myaddr->sin_family = AF_INET;
-
- complete_addrinfos(&remote_res,
- &local_res,
- remote_host,
- SOCK_STREAM,
- IPPROTO_TCP,
- 0);
-
- if ( print_headers ) {
- print_top_test_header("TCP Transactional/Request/Response TEST",local_res,remote_res);
- }
-
- /* initialize a few counters */
-
- nummessages = 0;
- bytes_xferd = 0.0;
- times_up = 0;
-
- /* set-up the data buffers with the requested alignment and offset */
- if (send_width == 0) send_width = 1;
- if (recv_width == 0) recv_width = 1;
-
- send_ring = allocate_buffer_ring(send_width,
- req_size,
- local_send_align,
- local_send_offset);
-
- recv_ring = allocate_buffer_ring(recv_width,
- rsp_size,
- local_recv_align,
- local_recv_offset);
-
-
- if (debug) {
- fprintf(where,"send_tcp_tran_rr: send_socket obtained...\n");
- }
-
- /* If the user has requested cpu utilization measurements, we must */
- /* calibrate the cpu(s). We will perform this task within the tests */
- /* themselves. If the user has specified the cpu rate, then */
- /* calibrate_local_cpu will return rather quickly as it will have */
- /* nothing to do. If local_cpu_rate is zero, then we will go through */
- /* all the "normal" calibration stuff and return the rate back.*/
-
- if (local_cpu_usage) {
- local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
- }
-
- /* Tell the remote end to do a listen. The server alters the socket */
- /* paramters on the other side at this point, hence the reason for */
- /* all the values being passed in the setup message. If the user did */
- /* not specify any of the parameters, they will be passed as 0, which */
- /* will indicate to the remote that no changes beyond the system's */
- /* default should be used. Alignment is the exception, it will */
- /* default to 8, which will be no alignment alterations. */
-
- netperf_request.content.request_type = DO_TCP_TRR;
- tcp_tran_rr_request->recv_buf_size = rsr_size_req;
- tcp_tran_rr_request->send_buf_size = rss_size_req;
- tcp_tran_rr_request->recv_alignment = remote_recv_align;
- tcp_tran_rr_request->recv_offset = remote_recv_offset;
- tcp_tran_rr_request->send_alignment = remote_send_align;
- tcp_tran_rr_request->send_offset = remote_send_offset;
- tcp_tran_rr_request->request_size = req_size;
- tcp_tran_rr_request->response_size = rsp_size;
- tcp_tran_rr_request->no_delay = rem_nodelay;
- tcp_tran_rr_request->measure_cpu = remote_cpu_usage;
- tcp_tran_rr_request->cpu_rate = remote_cpu_rate;
- tcp_tran_rr_request->so_rcvavoid = rem_rcvavoid;
- tcp_tran_rr_request->so_sndavoid = rem_sndavoid;
- if (test_time) {
- tcp_tran_rr_request->test_length = test_time;
- }
- else {
- tcp_tran_rr_request->test_length = test_trans * -1;
- }
- tcp_tran_rr_request->port = atoi(remote_data_port);
- tcp_tran_rr_request->ipfamily = af_to_nf(remote_res->ai_family);
-
- if (debug > 1) {
- fprintf(where,"netperf: send_tcp_tran_rr: requesting TCP_TRR test\n");
- }
-
- send_request();
-
- /* The response from the remote will contain all of the relevant */
- /* socket parameters for this test type. We will put them back into */
- /* the variables here so they can be displayed if desired. The */
- /* remote will have calibrated CPU if necessary, and will have done */
- /* all the needed set-up we will have calibrated the cpu locally */
- /* before sending the request, and will grab the counter value right */
- /* after the connect returns. The remote will grab the counter right */
- /* after the accept call. This saves the hassle of extra messages */
- /* being sent for the TCP tests. */
-
- recv_response();
-
- if (!netperf_response.content.serv_errno) {
- rsr_size = tcp_tran_rr_response->recv_buf_size;
- rss_size = tcp_tran_rr_response->send_buf_size;
- rem_nodelay = tcp_tran_rr_response->no_delay;
- remote_cpu_usage= tcp_tran_rr_response->measure_cpu;
- remote_cpu_rate = tcp_tran_rr_response->cpu_rate;
- /* make sure that port numbers are in network order */
- server.sin_port = tcp_tran_rr_response->data_port_number;
- server.sin_port = htons(server.sin_port);
- if (debug) {
- fprintf(where,"remote listen done.\n");
- fprintf(where,"remote port is %d\n",ntohs(server.sin_port));
- fflush(where);
- }
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- fprintf(where,
- "netperf: remote error %d",
- netperf_response.content.serv_errno);
- perror("");
- fflush(where);
- exit(1);
- }
-
- /* pick a nice random spot between client_port_min and */
- /* client_port_max for our initial port number. if they are the */
- /* same, then just set to _min */
- if (client_port_max - client_port_min) {
- srand(getpid());
- myport = client_port_min +
- (rand() % (client_port_max - client_port_min));
- }
- else {
- myport = client_port_min;
- }
-
- /* there will be a ++ before the first call to bind, so subtract one */
- myport--;
- myaddr->sin_port = htons((unsigned short)myport);
-
- /* Set-up the test end conditions. For a request/response test, they */
- /* can be either time or transaction based. */
-
- if (test_time) {
- /* The user wanted to end the test after a period of time. */
- times_up = 0;
- trans_remaining = 0;
- start_timer(test_time);
- }
- else {
- /* The tester wanted to send a number of bytes. */
- trans_remaining = test_bytes;
- times_up = 1;
- }
-
- /* The cpu_start routine will grab the current time and possibly */
- /* value of the idle counter for later use in measuring cpu */
- /* utilization and/or service demand and thruput. */
-
- cpu_start(local_cpu_usage);
-
- /* We use an "OR" to control test execution. When the test is */
- /* controlled by time, the byte count check will always return false. */
- /* When the test is controlled by byte count, the time test will */
- /* always return false. When the test is finished, the whole */
- /* expression will go false and we will stop sending data. I think I */
- /* just arbitrarily decrement trans_remaining for the timed test, but */
- /* will not do that just yet... One other question is whether or not */
- /* the send buffer and the receive buffer should be the same buffer. */
-
- while ((!times_up) || (trans_remaining > 0)) {
-
-#ifdef WANT_HISTOGRAM
- if (verbosity > 1) {
- /* timestamp just before our call to create the socket, and then */
- /* again just after the receive raj 3/95 */
- HIST_timestamp(&time_one);
- }
-#endif /* WANT_HISTOGRAM */
-
- /* set up the data socket - is this really necessary or can I just */
- /* re-use the same socket and move this cal out of the while loop. */
- /* it does introcudea *boatload* of system calls. I guess that it */
- /* all depends on "reality of programming." keeping it this way is */
- /* a bit more conservative I imagine - raj 3/95 */
- send_socket = create_data_socket(local_res);
-
- if (send_socket == INVALID_SOCKET) {
- perror("netperf: send_tcp_tran_rr: tcp stream data socket");
- exit(1);
- }
-
- /* we set SO_REUSEADDR on the premis that no unreserved port */
- /* number on the local system is going to be already connected to */
- /* the remote netserver's port number. One thing that I might */
- /* try later is to have the remote actually allocate a couple of */
- /* port numbers and cycle through those as well. depends on if we */
- /* can get through all the unreserved port numbers in less than */
- /* the length of the TIME_WAIT state raj 8/94 */
- one = 1;
- if(setsockopt(send_socket, SOL_SOCKET, SO_REUSEADDR,
- (char *)&one, sock_opt_len) == SOCKET_ERROR) {
- perror("netperf: send_tcp_tran_rr: so_reuseaddr");
- exit(1);
- }
-
-newport:
- /* pick a new port number */
- myport = ntohs(myaddr->sin_port);
- myport++;
-
- /* we do not want to use the port number that the server is */
- /* sitting at - this would cause us to fail in a loopback test. we */
- /* could just rely on the failure of the bind to get us past this, */
- /* but I'm guessing that in this one case at least, it is much */
- /* faster, given that we *know* that port number is already in use */
- /* (or rather would be in a loopback test) */
-
- if (myport == ntohs(server.sin_port)) myport++;
-
- /* wrap the port number when we get to 65535. NOTE, some broken */
- /* TCP's might treat the port number as a signed 16 bit quantity. */
- /* we aren't interested in testing such broken implementations :) */
- /* raj 8/94 */
- if (myport >= client_port_max) {
- myport = client_port_min;
- }
- myaddr->sin_port = htons((unsigned short)myport);
-
- if (debug) {
- if ((nummessages % 100) == 0) {
- printf("port %d\n",myport);
- }
- }
-
- /* we want to bind our socket to a particular port number. */
- if (bind(send_socket,
- (struct sockaddr *)myaddr,
- sizeof(struct sockaddr_storage)) == SOCKET_ERROR) {
- /* if the bind failed, someone else must have that port number */
- /* - perhaps in the listen state. since we can't use it, skip to */
- /* the next port number. we may have to do this again later, but */
- /* that's just too bad :) */
- if (debug > 1) {
- fprintf(where,
- "send_tcp_tran_rr: tried to bind to port %d errno %d\n",
- ntohs(myaddr->sin_port),
- errno);
- fflush(where);
- }
- /* yes, goto's are supposed to be evil, but they do have their */
- /* uses from time to time. the real world doesn't always have */
- /* to code to ge tthe A in CS 101 :) raj 3/95 */
- goto newport;
- }
-
- /* Connect up to the remote port on the data socket. Since this is */
- /* a test for RFC_1644-style transactional TCP, we can use the */
- /* sendto() call instead of calling connect and then send() */
-
- /* send the request */
- if((len=sendto(send_socket,
- send_ring->buffer_ptr,
- req_size,
- MSG_EOF,
- (struct sockaddr *)&server,
- sizeof(server))) != req_size) {
- if (SOCKET_EINTR(len))
- {
- /* we hit the end of a */
- /* timed test. */
- timed_out = 1;
- break;
- }
- perror("send_tcp_tran_rr: data send error");
- exit(1);
- }
- send_ring = send_ring->next;
-
- /* receive the response */
- rsp_bytes_left = rsp_size;
- temp_message_ptr = recv_ring->buffer_ptr;
- while(rsp_bytes_left > 0) {
- if((rsp_bytes_recvd=recv(send_socket,
- temp_message_ptr,
- rsp_bytes_left,
- 0)) == SOCKET_ERROR) {
- if (SOCKET_EINTR(rsp_bytes_recvd))
- {
- /* We hit the end of a timed test. */
- timed_out = 1;
- break;
- }
- perror("send_tcp_tran_rr: data recv error");
- exit(1);
- }
- rsp_bytes_left -= rsp_bytes_recvd;
- temp_message_ptr += rsp_bytes_recvd;
- }
- recv_ring = recv_ring->next;
-
- if (timed_out) {
- /* we may have been in a nested while loop - we need */
- /* another call to break. */
- break;
- }
-
- close(send_socket);
-
-#ifdef WANT_HISTOGRAM
- if (verbosity > 1) {
- HIST_timestamp(&time_two);
- HIST_add(time_hist,delta_micro(&time_one,&time_two));
- }
-#endif /* WANT_HISTOGRAM */
-
- nummessages++;
- if (trans_remaining) {
- trans_remaining--;
- }
-
- if (debug > 3) {
- fprintf(where,
- "Transaction %d completed on local port %d\n",
- nummessages,
- ntohs(myaddr->sin_port));
- fflush(where);
- }
-
-
- }
-
- /* this call will always give us the elapsed time for the test, and */
- /* will also store-away the necessaries for cpu utilization */
-
- cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being measured? */
- /* how long did we really run? */
-
- /* Get the statistics from the remote end. The remote will have */
- /* calculated service demand and all those interesting things. If it */
- /* wasn't supposed to care, it will return obvious values. */
-
- recv_response();
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote results obtained\n");
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- fprintf(where,
- "netperf: remote error %d",
- netperf_response.content.serv_errno);
- perror("");
- fflush(where);
- exit(1);
- }
-
- /* We now calculate what our thruput was for the test. In the future, */
- /* we may want to include a calculation of the thruput measured by */
- /* the remote, but it should be the case that for a TCP stream test, */
- /* that the two numbers should be *very* close... We calculate */
- /* bytes_sent regardless of the way the test length was controlled. */
- /* If it was time, we needed to, and if it was by bytes, the user may */
- /* have specified a number of bytes that wasn't a multiple of the */
- /* send_size, so we really didn't send what he asked for ;-) We use */
- /* Kbytes/s as the units of thruput for a TCP stream test, where K = */
- /* 1024. A future enhancement *might* be to choose from a couple of */
- /* unit selections. */
-
- bytes_xferd = (req_size * nummessages) + (rsp_size * nummessages);
- thruput = calc_thruput(bytes_xferd);
-
- if (local_cpu_usage || remote_cpu_usage) {
- /* We must now do a little math for service demand and cpu */
- /* utilization for the system(s) */
- /* Of course, some of the information might be bogus because */
- /* there was no idle counter in the kernel(s). We need to make */
- /* a note of this for the user's benefit...*/
- if (local_cpu_usage) {
- if (local_cpu_rate == 0.0) {
- fprintf(where,"WARNING WARNING WARNING WARNING WARNING WARNING WARNING!\n");
- fprintf(where,"Local CPU usage numbers based on process information only!\n");
- fflush(where);
- }
- local_cpu_utilization = calc_cpu_util(0.0);
- /* since calc_service demand is doing ms/Kunit we will */
- /* multiply the number of transaction by 1024 to get */
- /* "good" numbers */
- local_service_demand = calc_service_demand((double) nummessages*1024,
- 0.0,
- 0.0,
- 0);
- }
- else {
- local_cpu_utilization = (float) -1.0;
- local_service_demand = (float) -1.0;
- }
-
- if (remote_cpu_usage) {
- if (remote_cpu_rate == 0.0) {
- fprintf(where,"DANGER DANGER DANGER DANGER DANGER DANGER DANGER!\n");
- fprintf(where,"Remote CPU usage numbers based on process information only!\n");
- fflush(where);
- }
- remote_cpu_utilization = tcp_tran_rr_result->cpu_util;
- /* since calc_service demand is doing ms/Kunit we will */
- /* multiply the number of transaction by 1024 to get */
- /* "good" numbers */
- remote_service_demand = calc_service_demand((double) nummessages*1024,
- 0.0,
- remote_cpu_utilization,
- tcp_tran_rr_result->num_cpus);
- }
- else {
- remote_cpu_utilization = (float) -1.0;
- remote_service_demand = (float) -1.0;
- }
-
- /* We are now ready to print all the information. If the user */
- /* has specified zero-level verbosity, we will just print the */
- /* local service demand, or the remote service demand. If the */
- /* user has requested verbosity level 1, he will get the basic */
- /* "streamperf" numbers. If the user has specified a verbosity */
- /* of greater than 1, we will display a veritable plethora of */
- /* background information from outside of this block as it it */
- /* not cpu_measurement specific... */
-
- switch (verbosity) {
- case 0:
- if (local_cpu_usage) {
- fprintf(where,
- cpu_fmt_0,
- local_service_demand);
- }
- else {
- fprintf(where,
- cpu_fmt_0,
- remote_service_demand);
- }
- break;
- case 1:
- case 2:
-
- if (print_headers) {
- fprintf(where,
- cpu_title,
- local_cpu_method,
- remote_cpu_method);
- }
-
- fprintf(where,
- cpu_fmt_1_line_1, /* the format string */
- lss_size, /* local sendbuf size */
- lsr_size,
- req_size, /* how large were the requests */
- rsp_size, /* guess */
- elapsed_time, /* how long was the test */
- nummessages/elapsed_time,
- local_cpu_utilization, /* local cpu */
- remote_cpu_utilization, /* remote cpu */
- local_service_demand, /* local service demand */
- remote_service_demand); /* remote service demand */
- fprintf(where,
- cpu_fmt_1_line_2,
- rss_size,
- rsr_size);
- break;
- }
- }
- else {
- /* The tester did not wish to measure service demand. */
- switch (verbosity) {
- case 0:
- fprintf(where,
- tput_fmt_0,
- nummessages/elapsed_time);
- break;
- case 1:
- case 2:
- if (print_headers) {
- fprintf(where,tput_title,format_units());
- }
-
- fprintf(where,
- tput_fmt_1_line_1, /* the format string */
- lss_size,
- lsr_size,
- req_size, /* how large were the requests */
- rsp_size, /* how large were the responses */
- elapsed_time, /* how long did it take */
- nummessages/elapsed_time);
- fprintf(where,
- tput_fmt_1_line_2,
- rss_size, /* remote recvbuf size */
- rsr_size);
-
- break;
- }
- }
-
- /* it would be a good thing to include information about some of the */
- /* other parameters that may have been set for this test, but at the */
- /* moment, I do not wish to figure-out all the formatting, so I will */
- /* just put this comment here to help remind me that it is something */
- /* that should be done at a later time. */
-
- if (verbosity > 1) {
- /* The user wanted to know it all, so we will give it to him. */
- /* This information will include as much as we can find about */
- /* TCP statistics, the alignments of the sends and receives */
- /* and all that sort of rot... */
-
- fprintf(where,
- ksink_fmt,
- local_send_align,
- remote_recv_offset,
- local_send_offset,
- remote_recv_offset);
-
-#ifdef WANT_HISTOGRAM
- fprintf(where,"\nHistogram of request/response times\n");
- fflush(where);
- HIST_report(time_hist);
-#endif /* WANT_HISTOGRAM */
-
- }
-
-}
-
-
-int
-recv_tcp_tran_rr()
-{
-
- char *message;
- struct sockaddr_in myaddr_in,
- peeraddr_in;
- SOCKET s_listen,s_data;
- netperf_socklen_t addrlen;
- int NoPush = 1;
-
- char *recv_message_ptr;
- char *send_message_ptr;
- char *temp_message_ptr;
- int trans_received;
- int trans_remaining;
- int bytes_sent;
- int request_bytes_recvd;
- int request_bytes_remaining;
- int timed_out = 0;
- float elapsed_time;
-
- struct tcp_tran_rr_request_struct *tcp_tran_rr_request;
- struct tcp_tran_rr_response_struct *tcp_tran_rr_response;
- struct tcp_tran_rr_results_struct *tcp_tran_rr_results;
-
- tcp_tran_rr_request =
- (struct tcp_tran_rr_request_struct *)netperf_request.content.test_specific_data;
- tcp_tran_rr_response =
- (struct tcp_tran_rr_response_struct *)netperf_response.content.test_specific_data;
- tcp_tran_rr_results =
- (struct tcp_tran_rr_results_struct *)netperf_response.content.test_specific_data;
-
- if (debug) {
- fprintf(where,"netserver: recv_tcp_tran_rr: entered...\n");
- fflush(where);
- }
-
- /* We want to set-up the listen socket with all the desired */
- /* parameters and then let the initiator know that all is ready. If */
- /* socket size defaults are to be used, then the initiator will have */
- /* sent us 0's. If the socket sizes cannot be changed, then we will */
- /* send-back what they are. If that information cannot be determined, */
- /* then we send-back -1's for the sizes. If things go wrong for any */
- /* reason, we will drop back ten yards and punt. */
-
- /* If anything goes wrong, we want the remote to know about it. It */
- /* would be best if the error that the remote reports to the user is */
- /* the actual error we encountered, rather than some bogus unexpected */
- /* response type message. */
-
- if (debug) {
- fprintf(where,"recv_tcp_tran_rr: setting the response type...\n");
- fflush(where);
- }
-
- netperf_response.content.response_type = TCP_TRR_RESPONSE;
-
- if (debug) {
- fprintf(where,"recv_tcp_tran_rr: the response type is set...\n");
- fflush(where);
- }
-
- /* set-up the data buffer with the requested alignment and offset */
- message = (char *)malloc(DATABUFFERLEN);
- if (message == NULL) {
- printf("malloc(%d) failed!\n", DATABUFFERLEN);
- exit(1);
- }
-
- /* We now alter the message_ptr variables to be at the desired */
- /* alignments with the desired offsets. */
-
- if (debug) {
- fprintf(where,
- "recv_tcp_tran_rr: requested recv alignment of %d offset %d\n",
- tcp_tran_rr_request->recv_alignment,
- tcp_tran_rr_request->recv_offset);
- fprintf(where,
- "recv_tcp_tran_rr: requested send alignment of %d offset %d\n",
- tcp_tran_rr_request->send_alignment,
- tcp_tran_rr_request->send_offset);
- fflush(where);
- }
-
- recv_message_ptr = ALIGN_BUFFER(message, tcp_tran_rr_request->recv_alignment, tcp_tran_rr_request->recv_offset);
-
- send_message_ptr = ALIGN_BUFFER(message, tcp_tran_rr_request->send_alignment, tcp_tran_rr_request->send_offset);
-
- if (debug) {
- fprintf(where,"recv_tcp_tran_rr: receive alignment and offset set...\n");
- fflush(where);
- }
-
- /* Let's clear-out our sockaddr for the sake of cleanlines. Then we */
- /* can put in OUR values !-) At some point, we may want to nail this */
- /* socket to a particular network-level address, but for now, */
- /* INADDR_ANY should be just fine. */
-
- bzero((char *)&myaddr_in,
- sizeof(myaddr_in));
- myaddr_in.sin_family = AF_INET;
- myaddr_in.sin_addr.s_addr = INADDR_ANY;
- myaddr_in.sin_port = htons((unsigned short)tcp_tran_rr_request->port);
-
- /* Grab a socket to listen on, and then listen on it. */
-
- if (debug) {
- fprintf(where,"recv_tcp_tran_rr: grabbing a socket...\n");
- fflush(where);
- }
-
- /* create_data_socket expects to find some things in the global */
- /* variables, so set the globals based on the values in the request. */
- /* once the socket has been created, we will set the response values */
- /* based on the updated value of those globals. raj 7/94 */
- lss_size_req = tcp_tran_rr_request->send_buf_size;
- lsr_size_req = tcp_tran_rr_request->recv_buf_size;
- loc_nodelay = tcp_tran_rr_request->no_delay;
- loc_rcvavoid = tcp_tran_rr_request->so_rcvavoid;
- loc_sndavoid = tcp_tran_rr_request->so_sndavoid;
-
- set_hostname_and_port(local_name,
- port_buffer,
- nf_to_af(tcp_tran_rr_request->ipfamily),
- tcp_tran_rr_request->port);
-
- local_res = complete_addrinfo(local_name,
- local_name,
- port_buffer,
- nf_to_af(tcp_tran_rr_request->ipfamily),
- SOCK_STREAM,
- IPPROTO_TCP,
- 0);
-
- s_listen = create_data_socket(local_res);
-
- if (s_listen == INVALID_SOCKET) {
- netperf_response.content.serv_errno = errno;
- send_response();
- if (debug) {
- fprintf(where,"could not create data socket\n");
- fflush(where);
- }
- exit(1);
- }
-
-#ifdef WIN32
- /* The test timer can fire during operations on the listening socket,
- so to make the start_timer below work we have to move
- it to close s_listen while we are blocked on accept. */
- win_kludge_socket2 = s_listen;
-#endif
-
-
- /* Let's get an address assigned to this socket so we can tell the */
- /* initiator how to reach the data socket. There may be a desire to */
- /* nail this socket to a specific IP address in a multi-homed, */
- /* multi-connection situation, but for now, we'll ignore the issue */
- /* and concentrate on single connection testing. */
-
- if (bind(s_listen,
- (struct sockaddr *)&myaddr_in,
- sizeof(myaddr_in)) == SOCKET_ERROR) {
- netperf_response.content.serv_errno = errno;
- close(s_listen);
- send_response();
- if (debug) {
- fprintf(where,"could not bind\n");
- fflush(where);
- }
- exit(1);
- }
-
- /* we want to disable the implicit PUSH on all sends. at some point, */
- /* this might want to be a parm to the test raj 3/95 */
- if (setsockopt(s_listen,
- IPPROTO_TCP,
- TCP_NOPUSH,
- (const char *)&NoPush,
- sizeof(int)) == SOCKET_ERROR) {
- fprintf(where,
- "recv_tcp_tran_rr: could not set TCP_NOPUSH errno %d\n",
- errno);
- fflush(where);
- netperf_response.content.serv_errno = errno;
- close(s_listen);
- send_response();
- }
-
- /* Now, let's set-up the socket to listen for connections */
- if (listen(s_listen, 5) == SOCKET_ERROR) {
- netperf_response.content.serv_errno = errno;
- close(s_listen);
- send_response();
- if (debug) {
- fprintf(where,"could not listen\n");
- fflush(where);
- }
- exit(1);
- }
-
- /* now get the port number assigned by the system */
- addrlen = sizeof(myaddr_in);
- if (getsockname(s_listen,
- (struct sockaddr *)&myaddr_in,
- &addrlen) == SOCKET_ERROR){
- netperf_response.content.serv_errno = errno;
- close(s_listen);
- send_response();
- if (debug) {
- fprintf(where,"could not geetsockname\n");
- fflush(where);
- }
- exit(1);
- }
-
- /* Now myaddr_in contains the port and the internet address this is */
- /* returned to the sender also implicitly telling the sender that the */
- /* socket buffer sizing has been done. */
-
- tcp_tran_rr_response->data_port_number = (int) ntohs(myaddr_in.sin_port);
- if (debug) {
- fprintf(where,"telling the remote to call me at %d\n",
- tcp_tran_rr_response->data_port_number);
- fflush(where);
- }
- netperf_response.content.serv_errno = 0;
-
- /* But wait, there's more. If the initiator wanted cpu measurements, */
- /* then we must call the calibrate routine, which will return the max */
- /* rate back to the initiator. If the CPU was not to be measured, or */
- /* something went wrong with the calibration, we will return a 0.0 to */
- /* the initiator. */
-
- tcp_tran_rr_response->cpu_rate = 0.0; /* assume no cpu */
- if (tcp_tran_rr_request->measure_cpu) {
- tcp_tran_rr_response->measure_cpu = 1;
- tcp_tran_rr_response->cpu_rate =
- calibrate_local_cpu(tcp_tran_rr_request->cpu_rate);
- }
-
-
-
- /* before we send the response back to the initiator, pull some of */
- /* the socket parms from the globals */
- tcp_tran_rr_response->send_buf_size = lss_size;
- tcp_tran_rr_response->recv_buf_size = lsr_size;
- tcp_tran_rr_response->no_delay = loc_nodelay;
- tcp_tran_rr_response->so_rcvavoid = loc_rcvavoid;
- tcp_tran_rr_response->so_sndavoid = loc_sndavoid;
-
- send_response();
-
- addrlen = sizeof(peeraddr_in);
-
- /* Now it's time to start receiving data on the connection. We will */
- /* first grab the apropriate counters and then start grabbing. */
-
- cpu_start(tcp_tran_rr_request->measure_cpu);
-
- /* The loop will exit when the sender does a shutdown, which will */
- /* return a length of zero */
-
- if (tcp_tran_rr_request->test_length > 0) {
- times_up = 0;
- trans_remaining = 0;
- start_timer(tcp_tran_rr_request->test_length + PAD_TIME);
- }
- else {
- times_up = 1;
- trans_remaining = tcp_tran_rr_request->test_length * -1;
- }
-
- trans_received = 0;
-
- while ((!times_up) || (trans_remaining > 0)) {
-
- /* accept a connection from the remote */
- if ((s_data=accept(s_listen,
- (struct sockaddr *)&peeraddr_in,
- &addrlen)) == INVALID_SOCKET) {
- if (errno == EINTR) {
- /* the timer popped */
- timed_out = 1;
- break;
- }
- fprintf(where,"recv_tcp_tran_rr: accept: errno = %d\n",errno);
- fflush(where);
- close(s_listen);
-
- exit(1);
- }
-
- if (debug) {
- fprintf(where,"recv_tcp_tran_rr: accepted data connection.\n");
- fflush(where);
- }
-
-#ifdef WIN32
- /* this is used so the timer thread can close the socket out from */
- /* under us, which to date is the easiest/cleanest/least */
- /* Windows-specific way I can find to force the winsock calls to */
- /* return WSAEINTR with the test is over. anything that will run on */
- /* 95 and NT and is closer to what netperf expects from Unix signals */
- /* and such would be appreciated raj 1/96 */
- win_kludge_socket = s_data;
-#endif /* WIN32 */
-
-#ifdef KLUDGE_SOCKET_OPTIONS
- /* this is for those systems which *INCORRECTLY* fail to pass */
- /* attributes across an accept() call. Including this goes against */
- /* my better judgement :( raj 11/95 */
-
- kludge_socket_options(s_data);
-
-#endif /* KLUDGE_SOCKET_OPTIONS */
-
- temp_message_ptr = recv_message_ptr;
- request_bytes_remaining = tcp_tran_rr_request->request_size;
-
- /* receive the request from the other side. we can just receive */
- /* until we get zero bytes, but that would be a slight structure */
- /* change in the code, with minimal perfomance effects. If */
- /* however, I has variable-length messages, I would want to do */
- /* this to avoid needing "double reads" - one for the message */
- /* length, and one for the rest of the message raj 3/95 */
- while(request_bytes_remaining > 0) {
- if((request_bytes_recvd=recv(s_data,
- temp_message_ptr,
- request_bytes_remaining,
- 0)) == SOCKET_ERROR) {
- if ( SOCKET_EINTR(request_bytes_recvd) )
- {
- /* the timer popped */
- timed_out = 1;
- break;
- }
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
- else {
- request_bytes_remaining -= request_bytes_recvd;
- temp_message_ptr += request_bytes_recvd;
- }
- }
-
- if (timed_out) {
- /* we hit the end of the test based on time - lets */
- /* bail out of here now... */
- fprintf(where,"yo5\n");
- fflush(where);
- break;
- }
-
- /* Now, send the response to the remote we can use sendto here to */
- /* help remind people that this is an rfc 1644 style of test */
- if((bytes_sent=sendto(s_data,
- send_message_ptr,
- tcp_tran_rr_request->response_size,
- MSG_EOF,
- (struct sockaddr *)&peeraddr_in,
- sizeof(struct sockaddr_storage))) == SOCKET_ERROR) {
- if (SOCKET_EINTR(bytes_sent)) {
- /* the test timer has popped */
- timed_out = 1;
- fprintf(where,"yo6\n");
- fflush(where);
- break;
- }
- netperf_response.content.serv_errno = 99;
- send_response();
- exit(1);
- }
-
- trans_received++;
- if (trans_remaining) {
- trans_remaining--;
- }
-
- if (debug) {
- fprintf(where,
- "recv_tcp_tran_rr: Transaction %d complete\n",
- trans_received);
- fflush(where);
- }
-
- /* close the connection. since we have disable PUSH on sends, the */
- /* FIN should be tacked-onto our last send instead of being */
- /* standalone */
- close(s_data);
-
- }
-
-
- /* The loop now exits due to timeout or transaction count being */
- /* reached */
-
- cpu_stop(tcp_tran_rr_request->measure_cpu,&elapsed_time);
-
- if (timed_out) {
- /* we ended the test by time, which was at least 2 seconds */
- /* longer than we wanted to run. so, we want to subtract */
- /* PAD_TIME from the elapsed_time. */
- elapsed_time -= PAD_TIME;
- }
- /* send the results to the sender */
-
- if (debug) {
- fprintf(where,
- "recv_tcp_tran_rr: got %d transactions\n",
- trans_received);
- fflush(where);
- }
-
- tcp_tran_rr_results->bytes_received = (trans_received *
- (tcp_tran_rr_request->request_size +
- tcp_tran_rr_request->response_size));
- tcp_tran_rr_results->trans_received = trans_received;
- tcp_tran_rr_results->elapsed_time = elapsed_time;
- if (tcp_tran_rr_request->measure_cpu) {
- tcp_tran_rr_results->cpu_util = calc_cpu_util(elapsed_time);
- }
-
- if (debug) {
- fprintf(where,
- "recv_tcp_tran_rr: test complete, sending results.\n");
- fflush(where);
- }
-
- send_response();
-
-}
-#endif /* DO_1644 */
-
-#ifdef DO_NBRR
- /* this routine implements the sending (netperf) side of the TCP_RR */
- /* test using POSIX-style non-blocking sockets. */
-
-void
-send_tcp_nbrr(char remote_host[])
-{
-
- char *tput_title = "\
-Local /Remote\n\
-Socket Size Request Resp. Elapsed Trans.\n\
-Send Recv Size Size Time Rate \n\
-bytes Bytes bytes bytes secs. per sec \n\n";
-
- char *tput_fmt_0 =
- "%7.2f\n";
-
- char *tput_fmt_1_line_1 = "\
-%-6d %-6d %-6d %-6d %-6.2f %7.2f \n";
- char *tput_fmt_1_line_2 = "\
-%-6d %-6d\n";
-
- char *cpu_title = "\
-Local /Remote\n\
-Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\
-Send Recv Size Size Time Rate local remote local remote\n\
-bytes bytes bytes bytes secs. per sec %% %c %% %c us/Tr us/Tr\n\n";
-
- char *cpu_fmt_0 =
- "%6.3f %c\n";
-
- char *cpu_fmt_1_line_1 = "\
-%-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f\n";
-
- char *cpu_fmt_1_line_2 = "\
-%-6d %-6d\n";
-
- char *ksink_fmt = "\
-Alignment Offset\n\
-Local Remote Local Remote\n\
-Send Recv Send Recv\n\
-%5d %5d %5d %5d\n";
-
-
- int timed_out = 0;
- float elapsed_time;
-
- int len;
- char *temp_message_ptr;
- int nummessages;
- SOCKET send_socket;
- int trans_remaining;
- double bytes_xferd;
-
- struct ring_elt *send_ring;
- struct ring_elt *recv_ring;
-
- int rsp_bytes_left;
- int rsp_bytes_recvd;
-
- float local_cpu_utilization;
- float local_service_demand;
- float remote_cpu_utilization;
- float remote_service_demand;
- double thruput;
-
- struct hostent *hp;
- struct sockaddr_storage server;
- unsigned int addr;
-
- struct tcp_rr_request_struct *tcp_rr_request;
- struct tcp_rr_response_struct *tcp_rr_response;
- struct tcp_rr_results_struct *tcp_rr_result;
-
- struct addrinfo *remote_res;
- struct addrinfo *local_res;
-
- tcp_rr_request =
- (struct tcp_rr_request_struct *)netperf_request.content.test_specific_data;
- tcp_rr_response=
- (struct tcp_rr_response_struct *)netperf_response.content.test_specific_data;
- tcp_rr_result =
- (struct tcp_rr_results_struct *)netperf_response.content.test_specific_data;
-
-#ifdef WANT_HISTOGRAM
- if (verbosity > 1) {
- time_hist = HIST_new();
- }
-#endif /* WANT_HISTOGRAM */
-
- /* since we are now disconnected from the code that established the */
- /* control socket, and since we want to be able to use different */
- /* protocols and such, we are passed the name of the remote host and */
- /* must turn that into the test specific addressing information. */
-
- bzero((char *)&server,
- sizeof(server));
-
- complete_addrinfos(&remote_res,
- &local_res,
- remote_host,
- SOCK_STREAM,
- IPPROTO_TCP,
- 0);
-
- if ( print_headers ) {
- print_top_test_header("TCP Non-Blocking REQUEST/RESPONSE TEST",local_res,remote_res);
- }
-
- /* initialize a few counters */
-
- send_ring = NULL;
- recv_ring = NULL;
- confidence_iteration = 1;
- init_stat();
-
- /* we have a great-big while loop which controls the number of times */
- /* we run a particular test. this is for the calculation of a */
- /* confidence interval (I really should have stayed awake during */
- /* probstats :). If the user did not request confidence measurement */
- /* (no confidence is the default) then we will only go though the */
- /* loop once. the confidence stuff originates from the folks at IBM */
-
- while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
- (confidence_iteration <= iteration_min)) {
-
- /* initialize a few counters. we have to remember that we might be */
- /* going through the loop more than once. */
-
- nummessages = 0;
- bytes_xferd = 0.0;
- times_up = 0;
- timed_out = 0;
- trans_remaining = 0;
-
- /* set-up the data buffers with the requested alignment and offset. */
- /* since this is a request/response test, default the send_width and */
- /* recv_width to 1 and not two raj 7/94 */
-
- if (send_width == 0) send_width = 1;
- if (recv_width == 0) recv_width = 1;
-
- if (send_ring == NULL) {
- send_ring = allocate_buffer_ring(send_width,
- req_size,
- local_send_align,
- local_send_offset);
- }
-
- if (recv_ring == NULL) {
- recv_ring = allocate_buffer_ring(recv_width,
- rsp_size,
- local_recv_align,
- local_recv_offset);
- }
-
- /*set up the data socket */
- send_socket = create_data_socket(local_res);
-
- if (send_socket == INVALID_SOCKET){
- perror("netperf: send_tcp_nbrr: tcp stream data socket");
- exit(1);
- }
-
- if (debug) {
- fprintf(where,"send_tcp_nbrr: send_socket obtained...\n");
- }
-
- /* If the user has requested cpu utilization measurements, we must */
- /* calibrate the cpu(s). We will perform this task within the tests */
- /* themselves. If the user has specified the cpu rate, then */
- /* calibrate_local_cpu will return rather quickly as it will have */
- /* nothing to do. If local_cpu_rate is zero, then we will go through */
- /* all the "normal" calibration stuff and return the rate back.*/
-
- if (local_cpu_usage) {
- local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
- }
-
- /* Tell the remote end to do a listen. The server alters the socket */
- /* paramters on the other side at this point, hence the reason for */
- /* all the values being passed in the setup message. If the user did */
- /* not specify any of the parameters, they will be passed as 0, which */
- /* will indicate to the remote that no changes beyond the system's */
- /* default should be used. Alignment is the exception, it will */
- /* default to 8, which will be no alignment alterations. */
-
- netperf_request.content.request_type = DO_TCP_NBRR;
- tcp_rr_request->recv_buf_size = rsr_size_req;
- tcp_rr_request->send_buf_size = rss_size_req;
- tcp_rr_request->recv_alignment = remote_recv_align;
- tcp_rr_request->recv_offset = remote_recv_offset;
- tcp_rr_request->send_alignment = remote_send_align;
- tcp_rr_request->send_offset = remote_send_offset;
- tcp_rr_request->request_size = req_size;
- tcp_rr_request->response_size = rsp_size;
- tcp_rr_request->no_delay = rem_nodelay;
- tcp_rr_request->measure_cpu = remote_cpu_usage;
- tcp_rr_request->cpu_rate = remote_cpu_rate;
- tcp_rr_request->so_rcvavoid = rem_rcvavoid;
- tcp_rr_request->so_sndavoid = rem_sndavoid;
- if (test_time) {
- tcp_rr_request->test_length = test_time;
- }
- else {
- tcp_rr_request->test_length = test_trans * -1;
- }
-
- if (debug > 1) {
- fprintf(where,"netperf: send_tcp_nbrr: requesting TCP rr test\n");
- }
-
- send_request();
-
- /* The response from the remote will contain all of the relevant */
- /* socket parameters for this test type. We will put them back into */
- /* the variables here so they can be displayed if desired. The */
- /* remote will have calibrated CPU if necessary, and will have done */
- /* all the needed set-up we will have calibrated the cpu locally */
- /* before sending the request, and will grab the counter value right*/
- /* after the connect returns. The remote will grab the counter right*/
- /* after the accept call. This saves the hassle of extra messages */
- /* being sent for the TCP tests. */
-
- recv_response();
-
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote listen done.\n");
- rsr_size = tcp_rr_response->recv_buf_size;
- rss_size = tcp_rr_response->send_buf_size;
- rem_nodelay = tcp_rr_response->no_delay;
- remote_cpu_usage = tcp_rr_response->measure_cpu;
- remote_cpu_rate = tcp_rr_response->cpu_rate;
- /* make sure that port numbers are in network order */
- server.sin_port = (unsigned short)tcp_rr_response->data_port_number;
- server.sin_port = htons(server.sin_port);
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- fprintf(where,
- "netperf: remote error %d",
- netperf_response.content.serv_errno);
- perror("");
- fflush(where);
- exit(1);
- }
-
- /*Connect up to the remote port on the data socket */
- if (connect(send_socket,
- remote_res->ai_addr,
- remote_res->ai_addrlen) == INVALID_SOCKET){
- perror("netperf: data socket connect failed");
-
- exit(1);
- }
-
- /* now that we are connected, mark the socket as non-blocking */
- if (!set_nonblock(send_socket)) {
- perror("netperf: set_nonblock");
- exit(1);
- }
-
- /* Data Socket set-up is finished. If there were problems, either the */
- /* connect would have failed, or the previous response would have */
- /* indicated a problem. I failed to see the value of the extra */
- /* message after the accept on the remote. If it failed, we'll see it */
- /* here. If it didn't, we might as well start pumping data. */
-
- /* Set-up the test end conditions. For a request/response test, they */
- /* can be either time or transaction based. */
-
- if (test_time) {
- /* The user wanted to end the test after a period of time. */
- times_up = 0;
- trans_remaining = 0;
- start_timer(test_time);
- }
- else {
- /* The tester wanted to send a number of bytes. */
- trans_remaining = test_bytes;
- times_up = 1;
- }
-
- /* The cpu_start routine will grab the current time and possibly */
- /* value of the idle counter for later use in measuring cpu */
- /* utilization and/or service demand and thruput. */
-
- cpu_start(local_cpu_usage);
-
-#ifdef WANT_INTERVALS
- INTERVALS_INIT();
-#endif /* WANT_INTERVALS */
-
- /* We use an "OR" to control test execution. When the test is */
- /* controlled by time, the byte count check will always return false. */
- /* When the test is controlled by byte count, the time test will */
- /* always return false. When the test is finished, the whole */
- /* expression will go false and we will stop sending data. I think I */
- /* just arbitrarily decrement trans_remaining for the timed test, but */
- /* will not do that just yet... One other question is whether or not */
- /* the send buffer and the receive buffer should be the same buffer. */
-
- while ((!times_up) || (trans_remaining > 0)) {
- /* send the request. we assume that if we use a blocking socket, */
- /* the request will be sent at one shot. */
-
-#ifdef WANT_HISTOGRAM
- if (verbosity > 1) {
- /* timestamp just before our call to send, and then again just */
- /* after the receive raj 8/94 */
- HIST_timestamp(&time_one);
- }
-#endif /* WANT_HISTOGRAM */
-
- /* even though this is a non-blocking socket, we will assume for */
- /* the time being that we will be able to send an entire request */
- /* without getting an EAGAIN */
- if((len=send(send_socket,
- send_ring->buffer_ptr,
- req_size,
- 0)) != req_size) {
- if (SOCKET_EINTR(len)) {
- /* we hit the end of a */
- /* timed test. */
- timed_out = 1;
- break;
- }
- perror("send_tcp_nbrr: data send error");
- exit(1);
- }
- send_ring = send_ring->next;
-
- /* receive the response. since we are using non-blocking I/O, we */
- /* will "spin" on the recvs */
- rsp_bytes_left = rsp_size;
- temp_message_ptr = recv_ring->buffer_ptr;
- while(rsp_bytes_left > 0) {
- if((rsp_bytes_recvd=recv(send_socket,
- temp_message_ptr,
- rsp_bytes_left,
- 0)) == SOCKET_ERROR) {
- if (SOCKET_EINTR(rsp_bytes_recvd))
- {
- /* We hit the end of a timed test. */
- timed_out = 1;
- break;
- }
-#ifndef WIN32 // But what does WinNT indicate in this situation...
- else if (errno == EAGAIN) {
- Set_errno(0);
- continue;
- }
-#endif
- else {
- perror("send_tcp_nbrr: data recv error");
- exit(1);
- }
- }
- rsp_bytes_left -= rsp_bytes_recvd;
- temp_message_ptr += rsp_bytes_recvd;
- }
- recv_ring = recv_ring->next;
-
- if (timed_out) {
- /* we may have been in a nested while loop - we need */
- /* another call to break. */
- break;
- }
-
-#ifdef WANT_HISTOGRAM
- if (verbosity > 1) {
- HIST_timestamp(&time_two);
- HIST_add(time_hist,delta_micro(&time_one,&time_two));
- }
-#endif /* WANT_HISTOGRAM */
-#ifdef WANT_INTERVALS
- INTERVALS_WAIT();
-#endif /* WANT_INTERVALS */
-
- nummessages++;
- if (trans_remaining) {
- trans_remaining--;
- }
-
- if (debug > 3) {
- if ((nummessages % 100) == 0) {
- fprintf(where,
- "Transaction %d completed\n",
- nummessages);
- fflush(where);
- }
- }
- }
-
- /* At this point we used to call shutdown on the data socket to be */
- /* sure all the data was delivered, but this was not germane in a */
- /* request/response test, and it was causing the tests to "hang" when */
- /* they were being controlled by time. So, I have replaced this */
- /* shutdown call with a call to close that can be found later in the */
- /* procedure. */
-
- /* this call will always give us the elapsed time for the test, and */
- /* will also store-away the necessaries for cpu utilization */
-
- cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */
- /* measured? how long */
- /* did we really run? */
-
- /* Get the statistics from the remote end. The remote will have */
- /* calculated service demand and all those interesting things. If it */
- /* wasn't supposed to care, it will return obvious values. */
-
- recv_response();
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote results obtained\n");
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- fprintf(where,
- "netperf: remote error %d",
- netperf_response.content.serv_errno);
- perror("");
- fflush(where);
-
- exit(1);
- }
-
- /* We now calculate what our thruput was for the test. */
-
- bytes_xferd = (req_size * nummessages) + (rsp_size * nummessages);
- thruput = nummessages/elapsed_time;
-
- if (local_cpu_usage || remote_cpu_usage) {
- /* We must now do a little math for service demand and cpu */
- /* utilization for the system(s) */
- /* Of course, some of the information might be bogus because */
- /* there was no idle counter in the kernel(s). We need to make */
- /* a note of this for the user's benefit...*/
- if (local_cpu_usage) {
- local_cpu_utilization = calc_cpu_util(0.0);
- /* since calc_service demand is doing ms/Kunit we will */
- /* multiply the number of transaction by 1024 to get */
- /* "good" numbers */
- local_service_demand = calc_service_demand((double) nummessages*1024,
- 0.0,
- 0.0,
- 0);
- }
- else {
- local_cpu_utilization = (float) -1.0;
- local_service_demand = (float) -1.0;
- }
-
- if (remote_cpu_usage) {
- remote_cpu_utilization = tcp_rr_result->cpu_util;
- /* since calc_service demand is doing ms/Kunit we will */
- /* multiply the number of transaction by 1024 to get */
- /* "good" numbers */
- remote_service_demand = calc_service_demand((double) nummessages*1024,
- 0.0,
- remote_cpu_utilization,
- tcp_rr_result->num_cpus);
- }
- else {
- remote_cpu_utilization = (float) -1.0;
- remote_service_demand = (float) -1.0;
- }
-
- }
- else {
- /* we were not measuring cpu, for the confidence stuff, we */
- /* should make it -1.0 */
- local_cpu_utilization = (float) -1.0;
- local_service_demand = (float) -1.0;
- remote_cpu_utilization = (float) -1.0;
- remote_service_demand = (float) -1.0;
- }
-
- /* at this point, we want to calculate the confidence information. */
- /* if debugging is on, calculate_confidence will print-out the */
- /* parameters we pass it */
-
- calculate_confidence(confidence_iteration,
- elapsed_time,
- thruput,
- local_cpu_utilization,
- remote_cpu_utilization,
- local_service_demand,
- remote_service_demand);
-
-
- confidence_iteration++;
-
- /* we are now done with the socket, so close it */
- close(send_socket);
-
- }
-
- retrieve_confident_values(&elapsed_time,
- &thruput,
- &local_cpu_utilization,
- &remote_cpu_utilization,
- &local_service_demand,
- &remote_service_demand);
-
- /* We are now ready to print all the information. If the user */
- /* has specified zero-level verbosity, we will just print the */
- /* local service demand, or the remote service demand. If the */
- /* user has requested verbosity level 1, he will get the basic */
- /* "streamperf" numbers. If the user has specified a verbosity */
- /* of greater than 1, we will display a veritable plethora of */
- /* background information from outside of this block as it it */
- /* not cpu_measurement specific... */
-
- if (confidence < 0) {
- /* we did not hit confidence, but were we asked to look for it? */
- if (iteration_max > 1) {
- display_confidence();
- }
- }
-
- if (local_cpu_usage || remote_cpu_usage) {
- local_cpu_method = format_cpu_method(cpu_method);
- remote_cpu_method = format_cpu_method(tcp_rr_result->cpu_method);
-
- switch (verbosity) {
- case 0:
- if (local_cpu_usage) {
- fprintf(where,
- cpu_fmt_0,
- local_service_demand,
- local_cpu_method);
- }
- else {
- fprintf(where,
- cpu_fmt_0,
- remote_service_demand,
- remote_cpu_method);
- }
- break;
- case 1:
- case 2:
- if (print_headers) {
- fprintf(where,
- cpu_title,
- local_cpu_method,
- remote_cpu_method);
- }
-
- fprintf(where,
- cpu_fmt_1_line_1, /* the format string */
- lss_size, /* local sendbuf size */
- lsr_size,
- req_size, /* how large were the requests */
- rsp_size, /* guess */
- elapsed_time, /* how long was the test */
- thruput,
- local_cpu_utilization, /* local cpu */
- remote_cpu_utilization, /* remote cpu */
- local_service_demand, /* local service demand */
- remote_service_demand); /* remote service demand */
- fprintf(where,
- cpu_fmt_1_line_2,
- rss_size,
- rsr_size);
- break;
- }
- }
- else {
- /* The tester did not wish to measure service demand. */
-
- switch (verbosity) {
- case 0:
- fprintf(where,
- tput_fmt_0,
- thruput);
- break;
- case 1:
- case 2:
- if (print_headers) {
- fprintf(where,tput_title,format_units());
- }
-
- fprintf(where,
- tput_fmt_1_line_1, /* the format string */
- lss_size,
- lsr_size,
- req_size, /* how large were the requests */
- rsp_size, /* how large were the responses */
- elapsed_time, /* how long did it take */
- thruput);
- fprintf(where,
- tput_fmt_1_line_2,
- rss_size, /* remote recvbuf size */
- rsr_size);
-
- break;
- }
- }
-
- /* it would be a good thing to include information about some of the */
- /* other parameters that may have been set for this test, but at the */
- /* moment, I do not wish to figure-out all the formatting, so I will */
- /* just put this comment here to help remind me that it is something */
- /* that should be done at a later time. */
-
- /* how to handle the verbose information in the presence of */
- /* confidence intervals is yet to be determined... raj 11/94 */
- if (verbosity > 1) {
- /* The user wanted to know it all, so we will give it to him. */
- /* This information will include as much as we can find about */
- /* TCP statistics, the alignments of the sends and receives */
- /* and all that sort of rot... */
-
- fprintf(where,
- ksink_fmt,
- local_send_align,
- remote_recv_offset,
- local_send_offset,
- remote_recv_offset);
-
-#ifdef WANT_HISTOGRAM
- fprintf(where,"\nHistogram of request/response times\n");
- fflush(where);
- HIST_report(time_hist);
-#endif /* WANT_HISTOGRAM */
-
- }
-
-}
-
- /* this routine implements the receive (netserver) side of a TCP_RR */
- /* test */
-void
-recv_tcp_nbrr()
-{
-
- struct ring_elt *send_ring;
- struct ring_elt *recv_ring;
-
- struct sockaddr_in myaddr_in,
- peeraddr_in;
- SOCKET s_listen,s_data;
- netperf_socklen_t addrlen;
- char *temp_message_ptr;
- int trans_received;
- int trans_remaining;
- int bytes_sent;
- int request_bytes_recvd;
- int request_bytes_remaining;
- int timed_out = 0;
- float elapsed_time;
-
- struct addrinfo *local_res;
- char local_name[BUFSIZ];
- char port_buffer[PORTBUFSIZE];
-
- struct tcp_rr_request_struct *tcp_rr_request;
- struct tcp_rr_response_struct *tcp_rr_response;
- struct tcp_rr_results_struct *tcp_rr_results;
-
- tcp_rr_request =
- (struct tcp_rr_request_struct *)netperf_request.content.test_specific_data;
- tcp_rr_response =
- (struct tcp_rr_response_struct *)netperf_response.content.test_specific_data;
- tcp_rr_results =
- (struct tcp_rr_results_struct *)netperf_response.content.test_specific_data;
-
- if (debug) {
- fprintf(where,"netserver: recv_tcp_nbrr: entered...\n");
- fflush(where);
- }
-
- /* We want to set-up the listen socket with all the desired */
- /* parameters and then let the initiator know that all is ready. If */
- /* socket size defaults are to be used, then the initiator will have */
- /* sent us 0's. If the socket sizes cannot be changed, then we will */
- /* send-back what they are. If that information cannot be determined, */
- /* then we send-back -1's for the sizes. If things go wrong for any */
- /* reason, we will drop back ten yards and punt. */
-
- /* If anything goes wrong, we want the remote to know about it. It */
- /* would be best if the error that the remote reports to the user is */
- /* the actual error we encountered, rather than some bogus unexpected */
- /* response type message. */
-
- if (debug) {
- fprintf(where,"recv_tcp_nbrr: setting the response type...\n");
- fflush(where);
- }
-
- netperf_response.content.response_type = TCP_RR_RESPONSE;
-
- if (debug) {
- fprintf(where,"recv_tcp_nbrr: the response type is set...\n");
- fflush(where);
- }
-
- /* allocate the recv and send rings with the requested alignments */
- /* and offsets. raj 7/94 */
- if (debug) {
- fprintf(where,"recv_tcp_nbrr: requested recv alignment of %d offset %d\n",
- tcp_rr_request->recv_alignment,
- tcp_rr_request->recv_offset);
- fprintf(where,"recv_tcp_nbrr: requested send alignment of %d offset %d\n",
- tcp_rr_request->send_alignment,
- tcp_rr_request->send_offset);
- fflush(where);
- }
-
- /* at some point, these need to come to us from the remote system */
- if (send_width == 0) send_width = 1;
- if (recv_width == 0) recv_width = 1;
-
- send_ring = allocate_buffer_ring(send_width,
- tcp_rr_request->response_size,
- tcp_rr_request->send_alignment,
- tcp_rr_request->send_offset);
-
- recv_ring = allocate_buffer_ring(recv_width,
- tcp_rr_request->request_size,
- tcp_rr_request->recv_alignment,
- tcp_rr_request->recv_offset);
-
-
- /* Let's clear-out our sockaddr for the sake of cleanlines. Then we */
- /* can put in OUR values !-) At some point, we may want to nail this */
- /* socket to a particular network-level address, but for now, */
- /* INADDR_ANY should be just fine. */
-
- bzero((char *)&myaddr_in,
- sizeof(myaddr_in));
- myaddr_in.sin_family = AF_INET;
- myaddr_in.sin_addr.s_addr = INADDR_ANY;
- myaddr_in.sin_port = htons((unsigned short)tcp_rr_request->port);
-
- /* Grab a socket to listen on, and then listen on it. */
-
- if (debug) {
- fprintf(where,"recv_tcp_nbrr: grabbing a socket...\n");
- fflush(where);
- }
-
- /* create_data_socket expects to find some things in the global */
- /* variables, so set the globals based on the values in the request. */
- /* once the socket has been created, we will set the response values */
- /* based on the updated value of those globals. raj 7/94 */
- lss_size_req = tcp_rr_request->send_buf_size;
- lsr_size_req = tcp_rr_request->recv_buf_size;
- loc_nodelay = tcp_rr_request->no_delay;
- loc_rcvavoid = tcp_rr_request->so_rcvavoid;
- loc_sndavoid = tcp_rr_request->so_sndavoid;
-
- set_hostname_and_port(local_name,
- port_buffer,
- nf_to_af(tcp_rr_request->ipfamily),
- tcp_rr_request->port);
-
- local_res = complete_addrinfo(local_name,
- local_name,
- port_buffer,
- nf_to_af(tcp_rr_request->ipfamily),
- SOCK_STREAM,
- IPPROTO_TCP,
- 0);
-
- s_listen = create_data_socket(local_res);
-
- if (s_listen == INVALID_SOCKET) {
- netperf_response.content.serv_errno = errno;
- send_response();
-
- exit(1);
- }
-
- /* Let's get an address assigned to this socket so we can tell the */
- /* initiator how to reach the data socket. There may be a desire to */
- /* nail this socket to a specific IP address in a multi-homed, */
- /* multi-connection situation, but for now, we'll ignore the issue */
- /* and concentrate on single connection testing. */
-
- if (bind(s_listen,
- (struct sockaddr *)&myaddr_in,
- sizeof(myaddr_in)) == SOCKET_ERROR) {
- netperf_response.content.serv_errno = errno;
- close(s_listen);
- send_response();
-
- exit(1);
- }
-
- /* Now, let's set-up the socket to listen for connections */
- if (listen(s_listen, 5) == SOCKET_ERROR) {
- netperf_response.content.serv_errno = errno;
- close(s_listen);
- send_response();
-
- exit(1);
- }
-
-
- /* now get the port number assigned by the system */
- addrlen = sizeof(myaddr_in);
- if (getsockname(s_listen,
- (struct sockaddr *)&myaddr_in, &addrlen) == SOCKET_ERROR){
- netperf_response.content.serv_errno = errno;
- close(s_listen);
- send_response();
-
- exit(1);
- }
-
- /* Now myaddr_in contains the port and the internet address this is */
- /* returned to the sender also implicitly telling the sender that the */
- /* socket buffer sizing has been done. */
-
- tcp_rr_response->data_port_number = (int) ntohs(myaddr_in.sin_port);
- netperf_response.content.serv_errno = 0;
-
- /* But wait, there's more. If the initiator wanted cpu measurements, */
- /* then we must call the calibrate routine, which will return the max */
- /* rate back to the initiator. If the CPU was not to be measured, or */
- /* something went wrong with the calibration, we will return a 0.0 to */
- /* the initiator. */
-
- tcp_rr_response->cpu_rate = 0.0; /* assume no cpu */
- tcp_rr_response->measure_cpu = 0;
-
- if (tcp_rr_request->measure_cpu) {
- tcp_rr_response->measure_cpu = 1;
- tcp_rr_response->cpu_rate = calibrate_local_cpu(tcp_rr_request->cpu_rate);
- }
-
-
- /* before we send the response back to the initiator, pull some of */
- /* the socket parms from the globals */
- tcp_rr_response->send_buf_size = lss_size;
- tcp_rr_response->recv_buf_size = lsr_size;
- tcp_rr_response->no_delay = loc_nodelay;
- tcp_rr_response->so_rcvavoid = loc_rcvavoid;
- tcp_rr_response->so_sndavoid = loc_sndavoid;
- tcp_rr_response->test_length = tcp_rr_request->test_length;
- send_response();
-
- addrlen = sizeof(peeraddr_in);
-
- if ((s_data = accept(s_listen,
- (struct sockaddr *)&peeraddr_in,
- &addrlen)) == INVALID_SOCKET) {
- /* Let's just punt. The remote will be given some information */
- close(s_listen);
- exit(1);
- }
-
- if (debug) {
- fprintf(where,"recv_tcp_nbrr: accept completes on the data connection.\n");
- fflush(where);
- }
-
-#ifdef KLUDGE_SOCKET_OPTIONS
- /* this is for those systems which *INCORRECTLY* fail to pass */
- /* attributes across an accept() call. Including this goes against */
- /* my better judgement :( raj 11/95 */
-
- kludge_socket_options(s_data);
-
-#endif /* KLUDGE_SOCKET_OPTIONS */
-
- /* now that we are connected, mark the socket as non-blocking */
- if (!set_nonblock(s_data)) {
- close(s_data);
- exit(1);
- }
-
-
- /* Now it's time to start receiving data on the connection. We will */
- /* first grab the apropriate counters and then start grabbing. */
-
- cpu_start(tcp_rr_request->measure_cpu);
-
-#ifdef WIN32
- /* this is used so the timer thread can close the socket out from */
- /* under us, which to date is the easiest/cleanest/least */
- /* Windows-specific way I can find to force the winsock calls to */
- /* return WSAEINTR with the test is over. anything that will run on */
- /* 95 and NT and is closer to what netperf expects from Unix signals */
- /* and such would be appreciated raj 1/96 */
- win_kludge_socket = s_data;
-#endif /* WIN32 */
-
- /* The loop will exit when the sender does a shutdown, which will */
- /* return a length of zero */
-
- if (tcp_rr_request->test_length > 0) {
- times_up = 0;
- trans_remaining = 0;
- start_timer(tcp_rr_request->test_length + PAD_TIME);
- }
- else {
- times_up = 1;
- trans_remaining = tcp_rr_request->test_length * -1;
- }
-
- trans_received = 0;
-
- while ((!times_up) || (trans_remaining > 0)) {
- temp_message_ptr = recv_ring->buffer_ptr;
- request_bytes_remaining = tcp_rr_request->request_size;
- while(request_bytes_remaining > 0) {
- if((request_bytes_recvd=recv(s_data,
- temp_message_ptr,
- request_bytes_remaining,
- 0)) == SOCKET_ERROR) {
- if ( SOCKET_EINTR(request_bytes_recvd))
- {
- /* the timer popped */
- timed_out = 1;
- break;
- }
-#ifndef WIN32 // But what does WinNT indicate in this situation...
- else if (errno == EAGAIN) {
- Set_errno(0);
- if (times_up) {
- timed_out = 1;
- break;
- }
- continue;
- }
-#endif
- else {
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
- }
- else {
- request_bytes_remaining -= request_bytes_recvd;
- temp_message_ptr += request_bytes_recvd;
- }
- }
-
- recv_ring = recv_ring->next;
-
- if (timed_out) {
- /* we hit the end of the test based on time - lets */
- /* bail out of here now... */
- fprintf(where,"yo5\n");
- fflush(where);
- break;
- }
-
- /* Now, send the response to the remote */
- if((bytes_sent=send(s_data,
- send_ring->buffer_ptr,
- tcp_rr_request->response_size,
- 0)) == SOCKET_ERROR) {
- if (SOCKET_EINTR(bytes_sent)) {
- /* the test timer has popped */
- timed_out = 1;
- fprintf(where,"yo6\n");
- fflush(where);
- break;
- }
- netperf_response.content.serv_errno = 992;
- send_response();
- exit(1);
- }
-
- send_ring = send_ring->next;
-
- trans_received++;
- if (trans_remaining) {
- trans_remaining--;
- }
- }
-
-
- /* The loop now exits due to timeout or transaction count being */
- /* reached */
-
- cpu_stop(tcp_rr_request->measure_cpu,&elapsed_time);
-
- stop_timer();
-
- if (timed_out) {
- /* we ended the test by time, which was at least 2 seconds */
- /* longer than we wanted to run. so, we want to subtract */
- /* PAD_TIME from the elapsed_time. */
- elapsed_time -= PAD_TIME;
- }
-
- /* send the results to the sender */
-
- if (debug) {
- fprintf(where,
- "recv_tcp_nbrr: got %d transactions\n",
- trans_received);
- fflush(where);
- }
-
- tcp_rr_results->bytes_received = (trans_received *
- (tcp_rr_request->request_size +
- tcp_rr_request->response_size));
- tcp_rr_results->trans_received = trans_received;
- tcp_rr_results->elapsed_time = elapsed_time;
- tcp_rr_results->cpu_method = cpu_method;
- tcp_rr_results->num_cpus = lib_num_loc_cpus;
- if (tcp_rr_request->measure_cpu) {
- tcp_rr_results->cpu_util = calc_cpu_util(elapsed_time);
- }
-
- if (debug) {
- fprintf(where,
- "recv_tcp_nbrr: test complete, sending results.\n");
- fflush(where);
- }
-
- /* we are done with the socket, free it */
- close(s_data);
-
- send_response();
-
-}
-
-#endif /* DO_NBRR */
-
-
- /* this test is intended to test the performance of establishing a */
- /* connection, and then closing it again. this test is of somewhat */
- /* arcane interest since no packets are exchanged between the */
- /* user-space processes, but it will show the raw overhead of */
- /* establishing a TCP connection. that service demand could then be */
- /* compared with the sum of the service demands of a TCP_CRR and */
- /* TCP_RR test - presumeably, they would all relate */
-
-void
-send_tcp_cc(char remote_host[])
-{
-
- char *tput_title = "\
-Local /Remote\n\
-Socket Size Request Resp. Elapsed Trans.\n\
-Send Recv Size Size Time Rate \n\
-bytes Bytes bytes bytes secs. per sec \n\n";
-
- char *tput_fmt_0 =
- "%7.2f\n";
-
- char *tput_fmt_1_line_1 = "\
-%-6d %-6d %-6d %-6d %-6.2f %7.2f \n";
- char *tput_fmt_1_line_2 = "\
-%-6d %-6d\n";
-
- char *cpu_title = "\
-Local /Remote\n\
-Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\
-Send Recv Size Size Time Rate local remote local remote\n\
-bytes bytes bytes bytes secs. per sec %% %% us/Tr us/Tr\n\n";
-
- char *cpu_fmt_0 =
- "%6.3f\n";
-
- char *cpu_fmt_1_line_1 = "\
-%-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f\n";
-
- char *cpu_fmt_1_line_2 = "\
-%-6d %-6d\n";
-
- char *ksink_fmt = "\n\
-Alignment Offset\n\
-Local Remote Local Remote\n\
-Send Recv Send Recv\n\
-%5d %5d %5d %5d\n";
-
-
- int timed_out = 0;
- float elapsed_time;
-
- char temp_message_ptr[1];
- int nummessages;
- SOCKET send_socket;
- int trans_remaining;
- double bytes_xferd;
- int rsp_bytes_left = 1;
- int rsp_bytes_recvd;
-
- float local_cpu_utilization;
- float local_service_demand;
- float remote_cpu_utilization;
- float remote_service_demand;
- double thruput;
-
- struct addrinfo *local_res;
- struct addrinfo *remote_res;
-
- int myport;
- int ret;
-
- struct tcp_cc_request_struct *tcp_cc_request;
- struct tcp_cc_response_struct *tcp_cc_response;
- struct tcp_cc_results_struct *tcp_cc_result;
-
- tcp_cc_request =
- (struct tcp_cc_request_struct *)netperf_request.content.test_specific_data;
- tcp_cc_response =
- (struct tcp_cc_response_struct *)netperf_response.content.test_specific_data;
- tcp_cc_result =
- (struct tcp_cc_results_struct *)netperf_response.content.test_specific_data;
-
-
-#ifdef WANT_HISTOGRAM
- if (verbosity > 1) {
- time_hist = HIST_new();
- }
-#endif /* WANT_HISTOGRAM */
-
- /* since we are now disconnected from the code that established the */
- /* control socket, and since we want to be able to use different */
- /* protocols and such, we are passed the name of the remote host and */
- /* must turn that into the test specific addressing information. */
-
- complete_addrinfos(&remote_res,
- &local_res,
- remote_host,
- SOCK_STREAM,
- IPPROTO_TCP,
- 0);
-
- if ( print_headers ) {
- print_top_test_header("TCP Connect/Close TEST",local_res,remote_res);
- }
-
- /* initialize a few counters */
-
- nummessages = 0;
- bytes_xferd = 0.0;
- times_up = 0;
-
- /* since there are no data buffers in this test, we need no send or */
- /* recv rings */
-
- if (debug) {
- fprintf(where,"send_tcp_cc: send_socket obtained...\n");
- }
-
- /* If the user has requested cpu utilization measurements, we must */
- /* calibrate the cpu(s). We will perform this task within the tests */
- /* themselves. If the user has specified the cpu rate, then */
- /* calibrate_local_cpu will return rather quickly as it will have */
- /* nothing to do. If local_cpu_rate is zero, then we will go through */
- /* all the "normal" calibration stuff and return the rate back.*/
-
- if (local_cpu_usage) {
- local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
- }
-
- /* Tell the remote end to do a listen. The server alters the socket */
- /* paramters on the other side at this point, hence the reason for */
- /* all the values being passed in the setup message. If the user did */
- /* not specify any of the parameters, they will be passed as 0, which */
- /* will indicate to the remote that no changes beyond the system's */
- /* default should be used. Alignment is the exception, it will */
- /* default to 8, which will be no alignment alterations. */
-
- netperf_request.content.request_type = DO_TCP_CC;
- tcp_cc_request->recv_buf_size = rsr_size_req;
- tcp_cc_request->send_buf_size = rss_size_req;
- tcp_cc_request->recv_alignment = remote_recv_align;
- tcp_cc_request->recv_offset = remote_recv_offset;
- tcp_cc_request->send_alignment = remote_send_align;
- tcp_cc_request->send_offset = remote_send_offset;
- tcp_cc_request->request_size = req_size;
- tcp_cc_request->response_size = rsp_size;
- tcp_cc_request->no_delay = rem_nodelay;
- tcp_cc_request->measure_cpu = remote_cpu_usage;
- tcp_cc_request->cpu_rate = remote_cpu_rate;
- tcp_cc_request->so_rcvavoid = rem_rcvavoid;
- tcp_cc_request->so_sndavoid = rem_sndavoid;
- if (test_time) {
- tcp_cc_request->test_length = test_time;
- }
- else {
- tcp_cc_request->test_length = test_trans * -1;
- }
- tcp_cc_request->port = atoi(remote_data_port);
- tcp_cc_request->ipfamily = af_to_nf(remote_res->ai_family);
-
- if (debug > 1) {
- fprintf(where,"netperf: send_tcp_cc: requesting TCP crr test\n");
- }
-
- send_request();
-
- /* The response from the remote will contain all of the relevant */
- /* socket parameters for this test type. We will put them back into */
- /* the variables here so they can be displayed if desired. The */
- /* remote will have calibrated CPU if necessary, and will have done */
- /* all the needed set-up we will have calibrated the cpu locally */
- /* before sending the request, and will grab the counter value right */
- /* after the connect returns. The remote will grab the counter right */
- /* after the accept call. This saves the hassle of extra messages */
- /* being sent for the TCP tests. */
-
- recv_response();
-
- if (!netperf_response.content.serv_errno) {
- rsr_size = tcp_cc_response->recv_buf_size;
- rss_size = tcp_cc_response->send_buf_size;
- rem_nodelay = tcp_cc_response->no_delay;
- remote_cpu_usage= tcp_cc_response->measure_cpu;
- remote_cpu_rate = tcp_cc_response->cpu_rate;
- /* make sure that port numbers are in network order */
- set_port_number(remote_res,(unsigned short)tcp_cc_response->data_port_number);
-
- if (debug) {
- fprintf(where,"remote listen done.\n");
- fprintf(where,"remote port is %d\n",get_port_number(remote_res));
- fflush(where);
- }
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- fprintf(where,
- "netperf: remote error %d",
- netperf_response.content.serv_errno);
- perror("");
- fflush(where);
- exit(1);
- }
-
-#ifdef WANT_DEMO
- DEMO_RR_SETUP(100)
-#endif
-
- /* pick a nice random spot between client_port_min and */
- /* client_port_max for our initial port number */
- srand(getpid());
- if (client_port_max - client_port_min) {
- myport = client_port_min +
- (rand() % (client_port_max - client_port_min));
- }
- else {
- myport = client_port_min;
- }
- /* there will be a ++ before the first call to bind, so subtract one */
- myport--;
-
- /* Set-up the test end conditions. For a request/response test, they */
- /* can be either time or transaction based. */
-
- if (test_time) {
- /* The user wanted to end the test after a period of time. */
- times_up = 0;
- trans_remaining = 0;
- start_timer(test_time);
- }
- else {
- /* The tester wanted to send a number of bytes. */
- trans_remaining = test_bytes;
- times_up = 1;
- }
-
- /* The cpu_start routine will grab the current time and possibly */
- /* value of the idle counter for later use in measuring cpu */
- /* utilization and/or service demand and thruput. */
-
- cpu_start(local_cpu_usage);
-
-#ifdef WANT_DEMO
- if (demo_mode) {
- HIST_timestamp(demo_one_ptr);
- }
-#endif
-
- /* We use an "OR" to control test execution. When the test is */
- /* controlled by time, the byte count check will always return false. */
- /* When the test is controlled by byte count, the time test will */
- /* always return false. When the test is finished, the whole */
- /* expression will go false and we will stop sending data. I think I */
- /* just arbitrarily decrement trans_remaining for the timed test, but */
- /* will not do that just yet... One other question is whether or not */
- /* the send buffer and the receive buffer should be the same buffer. */
-
- while ((!times_up) || (trans_remaining > 0)) {
-
-#ifdef WANT_HISTOGRAM
- if (verbosity > 1) {
- /* timestamp just before our call to create the socket, and then */
- /* again just after the receive raj 3/95 */
- HIST_timestamp(&time_one);
- }
-#endif /* WANT_HISTOGRAM */
-
- /* set up the data socket */
- /* newport: is this label really required any longer? */
- /* pick a new port number */
- myport++;
-
- /* wrap the port number when we get to client_port_max. NOTE, some */
- /* broken TCP's might treat the port number as a signed 16 bit */
- /* quantity. we aren't interested in testing such broken */
- /* implementations :) so we won't make sure that it is below 32767 */
- /* raj 8/94 */
- if (myport >= client_port_max) {
- myport = client_port_min;
- }
-
- /* we do not want to use the port number that the server is */
- /* sitting at - this would cause us to fail in a loopback test. we */
- /* could just rely on the failure of the bind to get us past this, */
- /* but I'm guessing that in this one case at least, it is much */
- /* faster, given that we *know* that port number is already in use */
- /* (or rather would be in a loopback test) */
-
- if (myport == get_port_number(remote_res)) myport++;
-
- if (debug) {
- if ((nummessages % 100) == 0) {
- printf("port %d\n",myport);
- }
- }
- set_port_number(local_res, (unsigned short)myport);
- send_socket = create_data_socket(local_res);
-
- if (send_socket == INVALID_SOCKET) {
- perror("netperf: send_tcp_cc: tcp stream data socket");
- exit(1);
- }
-
- /* we used to have a call to bind() here, but that is being
- taken care of by create_data_socket(). raj 2005-02-08 */
-
- /* Connect up to the remote port on the data socket */
- if ((ret = connect(send_socket,
- remote_res->ai_addr,
- remote_res->ai_addrlen)) == INVALID_SOCKET){
- if (SOCKET_EINTR(ret))
- {
- /* we hit the end of a */
- /* timed test. */
- timed_out = 1;
- break;
- }
- perror("netperf: data socket connect failed");
- printf("\tattempted to connect on socket %d to port %d",
- send_socket,
- get_port_number(remote_res));
- printf(" from port %u \n",get_port_number(local_res));
- exit(1);
- }
-
- /* we hang in a recv() to get the remote's close indication */
-
- rsp_bytes_recvd=recv(send_socket,
- temp_message_ptr,
- rsp_bytes_left,
- 0);
-
-
- if (rsp_bytes_recvd == 0) {
- /* connection close, call close. we assume that the requisite */
- /* number of bytes have been received */
-
-#ifdef WANT_HISTOGRAM
- if (verbosity > 1) {
- HIST_timestamp(&time_two);
- HIST_add(time_hist,delta_micro(&time_one,&time_two));
- }
-#endif /* WANT_HISTOGRAM */
-
-#ifdef WANT_DEMO
- DEMO_RR_INTERVAL(1)
-#endif
-
- nummessages++;
- if (trans_remaining) {
- trans_remaining--;
- }
-
- if (debug > 3) {
- fprintf(where,
- "Transaction %d completed on local port %u\n",
- nummessages,
- get_port_number(local_res));
- fflush(where);
- }
-
- close(send_socket);
-
- }
- else {
- /* it was less than zero - an error occured */
- if (SOCKET_EINTR(rsp_bytes_recvd))
- {
- /* We hit the end of a timed test. */
- timed_out = 1;
- break;
- }
- perror("send_tcp_cc: data recv error");
- exit(1);
- }
-
- }
-
-
- /* this call will always give us the elapsed time for the test, and */
- /* will also store-away the necessaries for cpu utilization */
-
- cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being measured? */
- /* how long did we really run? */
-
- /* Get the statistics from the remote end. The remote will have */
- /* calculated service demand and all those interesting things. If it */
- /* wasn't supposed to care, it will return obvious values. */
-
- recv_response();
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote results obtained\n");
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- fprintf(where,
- "netperf: remote error %d",
- netperf_response.content.serv_errno);
- perror("");
- fflush(where);
-
- exit(1);
- }
-
- /* We now calculate what our thruput was for the test. In the future, */
- /* we may want to include a calculation of the thruput measured by */
- /* the remote, but it should be the case that for a TCP stream test, */
- /* that the two numbers should be *very* close... We calculate */
- /* bytes_sent regardless of the way the test length was controlled. */
- /* If it was time, we needed to, and if it was by bytes, the user may */
- /* have specified a number of bytes that wasn't a multiple of the */
- /* send_size, so we really didn't send what he asked for ;-) We use */
- /* Kbytes/s as the units of thruput for a TCP stream test, where K = */
- /* 1024. A future enhancement *might* be to choose from a couple of */
- /* unit selections. */
-
- bytes_xferd = (req_size * nummessages) + (rsp_size * nummessages);
- thruput = calc_thruput(bytes_xferd);
-
- if (local_cpu_usage || remote_cpu_usage) {
- /* We must now do a little math for service demand and cpu */
- /* utilization for the system(s) */
- /* Of course, some of the information might be bogus because */
- /* there was no idle counter in the kernel(s). We need to make */
- /* a note of this for the user's benefit...*/
- if (local_cpu_usage) {
- if (local_cpu_rate == 0.0) {
- fprintf(where,"WARNING WARNING WARNING WARNING WARNING WARNING WARNING!\n");
- fprintf(where,"Local CPU usage numbers based on process information only!\n");
- fflush(where);
- }
- local_cpu_utilization = calc_cpu_util(0.0);
- /* since calc_service demand is doing ms/Kunit we will */
- /* multiply the number of transaction by 1024 to get */
- /* "good" numbers */
- local_service_demand = calc_service_demand((double) nummessages*1024,
- 0.0,
- 0.0,
- 0);
- }
- else {
- local_cpu_utilization = (float) -1.0;
- local_service_demand = (float) -1.0;
- }
-
- if (remote_cpu_usage) {
- if (remote_cpu_rate == 0.0) {
- fprintf(where,"DANGER DANGER DANGER DANGER DANGER DANGER DANGER!\n");
- fprintf(where,"Remote CPU usage numbers based on process information only!\n");
- fflush(where);
- }
- remote_cpu_utilization = tcp_cc_result->cpu_util;
- /* since calc_service demand is doing ms/Kunit we will */
- /* multiply the number of transaction by 1024 to get */
- /* "good" numbers */
- remote_service_demand = calc_service_demand((double) nummessages*1024,
- 0.0,
- remote_cpu_utilization,
- tcp_cc_result->num_cpus);
- }
- else {
- remote_cpu_utilization = (float) -1.0;
- remote_service_demand = (float) -1.0;
- }
-
- /* We are now ready to print all the information. If the user */
- /* has specified zero-level verbosity, we will just print the */
- /* local service demand, or the remote service demand. If the */
- /* user has requested verbosity level 1, he will get the basic */
- /* "streamperf" numbers. If the user has specified a verbosity */
- /* of greater than 1, we will display a veritable plethora of */
- /* background information from outside of this block as it it */
- /* not cpu_measurement specific... */
-
- switch (verbosity) {
- case 0:
- if (local_cpu_usage) {
- fprintf(where,
- cpu_fmt_0,
- local_service_demand);
- }
- else {
- fprintf(where,
- cpu_fmt_0,
- remote_service_demand);
- }
- break;
- case 1:
- case 2:
-
- if (print_headers) {
- fprintf(where,
- cpu_title,
- local_cpu_method,
- remote_cpu_method);
- }
-
- fprintf(where,
- cpu_fmt_1_line_1, /* the format string */
- lss_size, /* local sendbuf size */
- lsr_size,
- req_size, /* how large were the requests */
- rsp_size, /* guess */
- elapsed_time, /* how long was the test */
- nummessages/elapsed_time,
- local_cpu_utilization, /* local cpu */
- remote_cpu_utilization, /* remote cpu */
- local_service_demand, /* local service demand */
- remote_service_demand); /* remote service demand */
- fprintf(where,
- cpu_fmt_1_line_2,
- rss_size,
- rsr_size);
- break;
- }
- }
- else {
- /* The tester did not wish to measure service demand. */
- switch (verbosity) {
- case 0:
- fprintf(where,
- tput_fmt_0,
- nummessages/elapsed_time);
- break;
- case 1:
- case 2:
- if (print_headers) {
- fprintf(where,tput_title,format_units());
- }
-
- fprintf(where,
- tput_fmt_1_line_1, /* the format string */
- lss_size,
- lsr_size,
- req_size, /* how large were the requests */
- rsp_size, /* how large were the responses */
- elapsed_time, /* how long did it take */
- nummessages/elapsed_time);
- fprintf(where,
- tput_fmt_1_line_2,
- rss_size, /* remote recvbuf size */
- rsr_size);
-
- break;
- }
- }
-
- /* it would be a good thing to include information about some of the */
- /* other parameters that may have been set for this test, but at the */
- /* moment, I do not wish to figure-out all the formatting, so I will */
- /* just put this comment here to help remind me that it is something */
- /* that should be done at a later time. */
-
- if (verbosity > 1) {
- /* The user wanted to know it all, so we will give it to him. */
- /* This information will include as much as we can find about */
- /* TCP statistics, the alignments of the sends and receives */
- /* and all that sort of rot... */
-
- fprintf(where,
- ksink_fmt,
- local_send_align,
- remote_recv_offset,
- local_send_offset,
- remote_recv_offset);
-
-#ifdef WANT_HISTOGRAM
- fprintf(where,"\nHistogram of request/response times\n");
- fflush(where);
- HIST_report(time_hist);
-#endif /* WANT_HISTOGRAM */
-
- }
-
-}
-
-
-void
-recv_tcp_cc()
-{
-
- char *message;
-
- struct addrinfo *local_res;
- char local_name[BUFSIZ];
- char port_buffer[PORTBUFSIZE];
-
- struct sockaddr_storage myaddr_in, peeraddr_in;
- SOCKET s_listen,s_data;
- netperf_socklen_t addrlen;
- char *recv_message_ptr;
- char *send_message_ptr;
- int trans_received;
- int trans_remaining;
- int timed_out = 0;
- float elapsed_time;
-
- struct tcp_cc_request_struct *tcp_cc_request;
- struct tcp_cc_response_struct *tcp_cc_response;
- struct tcp_cc_results_struct *tcp_cc_results;
-
- tcp_cc_request =
- (struct tcp_cc_request_struct *)netperf_request.content.test_specific_data;
- tcp_cc_response =
- (struct tcp_cc_response_struct *)netperf_response.content.test_specific_data;
- tcp_cc_results =
- (struct tcp_cc_results_struct *)netperf_response.content.test_specific_data;
-
- if (debug) {
- fprintf(where,"netserver: recv_tcp_cc: entered...\n");
- fflush(where);
- }
-
- /* We want to set-up the listen socket with all the desired */
- /* parameters and then let the initiator know that all is ready. If */
- /* socket size defaults are to be used, then the initiator will have */
- /* sent us 0's. If the socket sizes cannot be changed, then we will */
- /* send-back what they are. If that information cannot be determined, */
- /* then we send-back -1's for the sizes. If things go wrong for any */
- /* reason, we will drop back ten yards and punt. */
-
- /* If anything goes wrong, we want the remote to know about it. It */
- /* would be best if the error that the remote reports to the user is */
- /* the actual error we encountered, rather than some bogus unexpected */
- /* response type message. */
-
- if (debug) {
- fprintf(where,"recv_tcp_cc: setting the response type...\n");
- fflush(where);
- }
-
- netperf_response.content.response_type = TCP_CC_RESPONSE;
-
- if (debug) {
- fprintf(where,"recv_tcp_cc: the response type is set...\n");
- fflush(where);
- }
-
- /* set-up the data buffer with the requested alignment and offset */
- message = (char *)malloc(DATABUFFERLEN);
- if (message == NULL) {
- printf("malloc(%d) failed!\n", DATABUFFERLEN);
- exit(1);
- }
-
- /* We now alter the message_ptr variables to be at the desired */
- /* alignments with the desired offsets. */
-
- if (debug) {
- fprintf(where,
- "recv_tcp_cc: requested recv alignment of %d offset %d\n",
- tcp_cc_request->recv_alignment,
- tcp_cc_request->recv_offset);
- fprintf(where,
- "recv_tcp_cc: requested send alignment of %d offset %d\n",
- tcp_cc_request->send_alignment,
- tcp_cc_request->send_offset);
- fflush(where);
- }
-
- recv_message_ptr = ALIGN_BUFFER(message, tcp_cc_request->recv_alignment, tcp_cc_request->recv_offset);
-
- send_message_ptr = ALIGN_BUFFER(message, tcp_cc_request->send_alignment, tcp_cc_request->send_offset);
-
- if (debug) {
- fprintf(where,"recv_tcp_cc: receive alignment and offset set...\n");
- fflush(where);
- }
-
- /* Grab a socket to listen on, and then listen on it. */
-
- if (debug) {
- fprintf(where,"recv_tcp_cc: grabbing a socket...\n");
- fflush(where);
- }
-
- /* create_data_socket expects to find some things in the global */
- /* variables, so set the globals based on the values in the request. */
- /* once the socket has been created, we will set the response values */
- /* based on the updated value of those globals. raj 7/94 */
- lss_size_req = tcp_cc_request->send_buf_size;
- lsr_size_req = tcp_cc_request->recv_buf_size;
- loc_nodelay = tcp_cc_request->no_delay;
- loc_rcvavoid = tcp_cc_request->so_rcvavoid;
- loc_sndavoid = tcp_cc_request->so_sndavoid;
-
- set_hostname_and_port(local_name,
- port_buffer,
- nf_to_af(tcp_cc_request->ipfamily),
- tcp_cc_request->port);
-
- local_res = complete_addrinfo(local_name,
- local_name,
- port_buffer,
- nf_to_af(tcp_cc_request->ipfamily),
- SOCK_STREAM,
- IPPROTO_TCP,
- 0);
-
- s_listen = create_data_socket(local_res);
-
- if (s_listen == INVALID_SOCKET) {
- netperf_response.content.serv_errno = errno;
- send_response();
- if (debug) {
- fprintf(where,"could not create data socket\n");
- fflush(where);
- }
- exit(1);
- }
-
-#ifdef WIN32
- /* The test timer can fire during operations on the listening socket,
- so to make the start_timer below work we have to move
- it to close s_listen while we are blocked on accept. */
- win_kludge_socket2 = s_listen;
-#endif
-
-
- /* Now, let's set-up the socket to listen for connections */
- if (listen(s_listen, 5) == SOCKET_ERROR) {
- netperf_response.content.serv_errno = errno;
- close(s_listen);
- send_response();
- if (debug) {
- fprintf(where,"could not listen\n");
- fflush(where);
- }
- exit(1);
- }
-
- /* now get the port number assigned by the system */
- addrlen = sizeof(myaddr_in);
- if (getsockname(s_listen,
- (struct sockaddr *)&myaddr_in,
- &addrlen) == SOCKET_ERROR){
- netperf_response.content.serv_errno = errno;
- close(s_listen);
- send_response();
- if (debug) {
- fprintf(where,"could not geetsockname\n");
- fflush(where);
- }
- exit(1);
- }
-
- /* Now myaddr_in contains the port and the internet address this is */
- /* returned to the sender also implicitly telling the sender that the */
- /* socket buffer sizing has been done. */
-
- tcp_cc_response->data_port_number =
- (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port);
- if (debug) {
- fprintf(where,"telling the remote to call me at %d\n",
- tcp_cc_response->data_port_number);
- fflush(where);
- }
- netperf_response.content.serv_errno = 0;
-
- /* But wait, there's more. If the initiator wanted cpu measurements, */
- /* then we must call the calibrate routine, which will return the max */
- /* rate back to the initiator. If the CPU was not to be measured, or */
- /* something went wrong with the calibration, we will return a 0.0 to */
- /* the initiator. */
-
- tcp_cc_response->cpu_rate = (float)0.0; /* assume no cpu */
- if (tcp_cc_request->measure_cpu) {
- tcp_cc_response->measure_cpu = 1;
- tcp_cc_response->cpu_rate =
- calibrate_local_cpu(tcp_cc_request->cpu_rate);
- }
-
-
-
- /* before we send the response back to the initiator, pull some of */
- /* the socket parms from the globals */
- tcp_cc_response->send_buf_size = lss_size;
- tcp_cc_response->recv_buf_size = lsr_size;
- tcp_cc_response->no_delay = loc_nodelay;
- tcp_cc_response->so_rcvavoid = loc_rcvavoid;
- tcp_cc_response->so_sndavoid = loc_sndavoid;
-
- send_response();
-
- addrlen = sizeof(peeraddr_in);
-
- /* Now it's time to start receiving data on the connection. We will */
- /* first grab the apropriate counters and then start grabbing. */
-
- cpu_start(tcp_cc_request->measure_cpu);
-
- /* The loop will exit when the sender does a shutdown, which will */
- /* return a length of zero */
-
- if (tcp_cc_request->test_length > 0) {
- times_up = 0;
- trans_remaining = 0;
- start_timer(tcp_cc_request->test_length + PAD_TIME);
- }
- else {
- times_up = 1;
- trans_remaining = tcp_cc_request->test_length * -1;
- }
-
- trans_received = 0;
-
- while ((!times_up) || (trans_remaining > 0)) {
-#ifdef WIN32
- /* The test timer will probably fire during this accept,
- so to make the start_timer above work we have to move
- it to close s_listen while we are blocked on accept. */
- win_kludge_socket = s_listen;
-#endif
- /* accept a connection from the remote */
- if ((s_data=accept(s_listen,
- (struct sockaddr *)&peeraddr_in,
- &addrlen)) == INVALID_SOCKET) {
- if (errno == EINTR) {
- /* the timer popped */
- timed_out = 1;
- break;
- }
- fprintf(where,"recv_tcp_cc: accept: errno = %d\n",errno);
- fflush(where);
- close(s_listen);
-
- exit(1);
- }
-
-#ifdef KLUDGE_SOCKET_OPTIONS
- /* this is for those systems which *INCORRECTLY* fail to pass */
- /* attributes across an accept() call. Including this goes against */
- /* my better judgement :( raj 11/95 */
-
- kludge_socket_options(s_data);
-
-#endif /* KLUDGE_SOCKET_OPTIONS */
-
-#ifdef WIN32
- /* this is used so the timer thread can close the socket out from */
- /* under us, which to date is the easiest/cleanest/least */
- /* Windows-specific way I can find to force the winsock calls to */
- /* return WSAEINTR with the test is over. anything that will run on */
- /* 95 and NT and is closer to what netperf expects from Unix signals */
- /* and such would be appreciated raj 1/96 */
- win_kludge_socket = s_data;
-#endif /* WIN32 */
-
- if (debug) {
- fprintf(where,"recv_tcp_cc: accepted data connection.\n");
- fflush(where);
- }
-
-
- /* close the connection. the server will likely do a graceful */
- /* close of the connection, insuring that all data has arrived at */
- /* the client. for this it will call shutdown(), and then recv() and */
- /* then close(). I'm reasonably confident that this is the */
- /* appropriate sequence of calls - I would like to hear of */
- /* examples in web servers to the contrary. raj 10/95*/
- close(s_data);
-
- trans_received++;
- if (trans_remaining) {
- trans_remaining--;
- }
-
- if (debug) {
- fprintf(where,
- "recv_tcp_cc: Transaction %d complete\n",
- trans_received);
- fflush(where);
- }
-
- }
-
-
- /* The loop now exits due to timeout or transaction count being */
- /* reached */
-
- cpu_stop(tcp_cc_request->measure_cpu,&elapsed_time);
-
- if (timed_out) {
- /* we ended the test by time, which was at least 2 seconds */
- /* longer than we wanted to run. so, we want to subtract */
- /* PAD_TIME from the elapsed_time. */
- elapsed_time -= PAD_TIME;
- }
- /* send the results to the sender */
-
- if (debug) {
- fprintf(where,
- "recv_tcp_cc: got %d transactions\n",
- trans_received);
- fflush(where);
- }
-
- tcp_cc_results->bytes_received = (trans_received *
- (tcp_cc_request->request_size +
- tcp_cc_request->response_size));
- tcp_cc_results->trans_received = trans_received;
- tcp_cc_results->elapsed_time = elapsed_time;
- if (tcp_cc_request->measure_cpu) {
- tcp_cc_results->cpu_util = calc_cpu_util(elapsed_time);
- }
-
- if (debug) {
- fprintf(where,
- "recv_tcp_cc: test complete, sending results.\n");
- fflush(where);
- }
-
- send_response();
-
-}
-
-void
-print_sockets_usage()
-{
-
- fwrite(sockets_usage, sizeof(char), strlen(sockets_usage), stdout);
- exit(1);
-
-}
-
-void
-scan_sockets_args(int argc, char *argv[])
-
-{
-
-#define SOCKETS_ARGS "b:CDnNhH:L:m:M:p:P:r:s:S:T:Vw:W:z46"
-
- extern char *optarg; /* pointer to option string */
-
- int c;
-
- char
- arg1[BUFSIZ], /* argument holders */
- arg2[BUFSIZ];
-
- if (debug) {
- int i;
- printf("%s called with the following argument vector\n",
- __func__);
- for (i = 0; i< argc; i++) {
- printf("%s ",argv[i]);
- }
- printf("\n");
- }
-
- strncpy(local_data_port,"0",sizeof(local_data_port));
- strncpy(remote_data_port,"0",sizeof(remote_data_port));
-
- /* Go through all the command line arguments and break them */
- /* out. For those options that take two parms, specifying only */
- /* the first will set both to that value. Specifying only the */
- /* second will leave the first untouched. To change only the */
- /* first, use the form "first," (see the routine break_args.. */
-
- while ((c= getopt(argc, argv, SOCKETS_ARGS)) != EOF) {
- switch (c) {
- case '?':
- case '4':
- remote_data_family = AF_INET;
- local_data_family = AF_INET;
- break;
- case '6':
-#if defined(AF_INET6)
- remote_data_family = AF_INET6;
- local_data_family = AF_INET6;
-#else
- fprintf(stderr,
- "This netperf was not compiled on an IPv6 capable host!\n");
- fflush(stderr);
- exit(-1);
-#endif
- break;
- case 'h':
- print_sockets_usage();
- exit(1);
- case 'b':
-#ifdef WANT_FIRST_BURST
- first_burst_size = atoi(optarg);
-#else /* WANT_FIRST_BURST */
- printf("Initial request burst functionality not compiled-in!\n");
-#endif /* WANT_FIRST_BURST */
- break;
- case 'C':
-#ifdef TCP_CORK
- /* set TCP_CORK */
- loc_tcpcork = 1;
- rem_tcpcork = 1; /* however, at first, we ony have cork affect loc */
-#else
- printf("WARNING: TCP_CORK not available on this platform!\n");
-#endif /* TCP_CORK */
- break;
- case 'D':
- /* set the TCP nodelay flag */
- loc_nodelay = 1;
- rem_nodelay = 1;
- break;
- case 'H':
- break_args_explicit(optarg,arg1,arg2);
- if (arg1[0]) {
- /* make sure we leave room for the NULL termination boys and
- girls. raj 2005-02-82 */
- remote_data_address = malloc(strlen(arg1)+1);
- strncpy(remote_data_address,arg1,strlen(arg1));
- }
- if (arg2[0])
- remote_data_family = parse_address_family(arg2);
- break;
- case 'L':
- break_args_explicit(optarg,arg1,arg2);
- if (arg1[0]) {
- /* make sure we leave room for the NULL termination boys and
- girls. raj 2005-02-82 */
- local_data_address = malloc(strlen(arg1)+1);
- strncpy(local_data_address,arg1,strlen(arg1));
- }
- if (arg2[0])
- local_data_family = parse_address_family(arg2);
- break;
- case 's':
- /* set local socket sizes */
- break_args(optarg,arg1,arg2);
- if (arg1[0])
- lss_size_req = convert(arg1);
- if (arg2[0])
- lsr_size_req = convert(arg2);
- break;
- case 'S':
- /* set remote socket sizes */
- break_args(optarg,arg1,arg2);
- if (arg1[0])
- rss_size_req = convert(arg1);
- if (arg2[0])
- rsr_size_req = convert(arg2);
- break;
- case 'r':
- /* set the request/response sizes */
- break_args(optarg,arg1,arg2);
- if (arg1[0])
- req_size = convert(arg1);
- if (arg2[0])
- rsp_size = convert(arg2);
- break;
- case 'm':
- /* set the send size */
- send_size = convert(optarg);
- break;
- case 'M':
- /* set the recv size */
- recv_size = convert(optarg);
- break;
- case 'n':
- /* set the local socket type*/
- local_connected = 1;
- break;
- case 'N':
- /* set the remote socket type*/
- remote_connected = 1;
- break;
- case 'p':
- /* set the min and max port numbers for the TCP_CRR and TCP_TRR */
- /* tests. */
- break_args(optarg,arg1,arg2);
- if (arg1[0])
- client_port_min = atoi(arg1);
- if (arg2[0])
- client_port_max = atoi(arg2);
- break;
- case 'P':
- /* set the local and remote data port numbers for the tests to
- allow them to run through those blankety blank end-to-end
- breaking firewalls. raj 2004-06-15 */
- break_args(optarg,arg1,arg2);
- if (arg1[0])
- strncpy(local_data_port,arg1,sizeof(local_data_port));
- if (arg2[0])
- strncpy(remote_data_port,arg2,sizeof(remote_data_port));
- break;
- case 't':
- /* set the test name */
- strcpy(test_name,optarg);
- break;
- case 'W':
- /* set the "width" of the user space data */
- /* buffer. This will be the number of */
- /* send_size buffers malloc'd in the */
- /* *_STREAM test. It may be enhanced to set */
- /* both send and receive "widths" but for now */
- /* it is just the sending *_STREAM. */
- send_width = convert(optarg);
- break;
- case 'V' :
- /* we want to do copy avoidance and will set */
- /* it for everything, everywhere, if we really */
- /* can. of course, we don't know anything */
- /* about the remote... */
-#ifdef SO_SND_COPYAVOID
- loc_sndavoid = 1;
-#else
- loc_sndavoid = 0;
- printf("Local send copy avoidance not available.\n");
-#endif
-#ifdef SO_RCV_COPYAVOID
- loc_rcvavoid = 1;
-#else
- loc_rcvavoid = 0;
- printf("Local recv copy avoidance not available.\n");
-#endif
- rem_sndavoid = 1;
- rem_rcvavoid = 1;
- break;
- };
- }
-
-#if defined(WANT_FIRST_BURST)
-#if defined(WANT_HISTOGRAM)
- /* if WANT_FIRST_BURST and WANT_HISTOGRAM are defined and the user
- indeed wants a non-zero first burst size, and we would emit a
- histogram, then we should emit a warning that the two are not
- compatible. raj 2006-01-31 */
- if ((first_burst_size > 0) && (verbosity >= 2)) {
- fprintf(stderr,
- "WARNING! Histograms and first bursts are incompatible!\n");
- fflush(stderr);
- }
-#endif
-#endif
-
- /* we do not want to make remote_data_address non-NULL because if
- the user has not specified a remote adata address, we want to
- take it from the hostname in the -H global option. raj
- 2005-02-08 */
-
- /* so, if there is to be no control connection, we want to have some
- different settings for a few things */
-
- if (no_control) {
-
- if (strcmp(remote_data_port,"0") == 0) {
- /* we need to select either the discard port, echo port or
- chargen port dedepending on the test name. raj 2007-02-08 */
- if (strstr(test_name,"STREAM") ||
- strstr(test_name,"SENDFILE")) {
- strncpy(remote_data_port,"discard",sizeof(remote_data_port));
- }
- else if (strstr(test_name,"RR")) {
- strncpy(remote_data_port,"echo",sizeof(remote_data_port));
- }
- else if (strstr(test_name,"MAERTS")) {
- strncpy(remote_data_port,"chargen",sizeof(remote_data_port));
- }
- else {
- printf("No default port known for the %s test, please set one yourself\n",test_name);
- exit(-1);
- }
- }
- remote_data_port[sizeof(remote_data_port) - 1] = '\0';
-
- /* I go back and forth on whether these should become -1 or if
- they should become 0 for a no_control test. what do you think?
- raj 2006-02-08 */
-
- rem_rcvavoid = -1;
- rem_sndavoid = -1;
- rss_size_req = -1;
- rsr_size_req = -1;
- rem_nodelay = -1;
-
- if (strstr(test_name,"STREAM") ||
- strstr(test_name,"SENDFILE")) {
- recv_size = -1;
- }
- else if (strstr(test_name,"RR")) {
- /* I am however _certain_ that for a no control RR test the
- response size must equal the request size since 99 times out
- of ten we will be speaking to the echo service somewhere */
- rsp_size = req_size;
- }
- else if (strstr(test_name,"MAERTS")) {
- send_size = -1;
- }
- else {
- printf("No default port known for the %s test, please set one yourself\n",test_name);
- exit(-1);
- }
- }
-}
diff --git a/nettest_bsd.h b/nettest_bsd.h
deleted file mode 100644
index 5491290..0000000
--- a/nettest_bsd.h
+++ /dev/null
@@ -1,471 +0,0 @@
-/*
- Copyright (C) 1993-2004 Hewlett-Packard Company
-*/
-
- /* This file contains the test-specific definitions for netperf's BSD */
- /* sockets tests */
-
-/* well boys and girls, seems that while AF_INET is "2" and AF_UNSPEC
- is "0" the world over, AF_INET6 is different values depending on
- the platform... grrr. On HP-UX 11i it is "22" and on Linux 2.6 it
- is "10" sooooo... we have to define our own space for netperf to
- enable us to pass values around from machine to machine. raj
- 2005-02-08 */
-#define NF_UNSPEC 0
-#define NF_INET 4
-#define NF_INET6 6
-
-struct tcp_stream_request_struct {
- int send_buf_size;
- int recv_buf_size; /* how big does the client want it - the */
- /* receive socket buffer that is */
- int receive_size; /* how many bytes do we want to receive at one */
- /* time? */
- int recv_alignment; /* what is the alignment of the receive */
- /* buffer? */
- int recv_offset; /* and at what offset from that alignment? */
- int no_delay; /* do we disable the nagle algorithm for send */
- /* coalescing? */
- int measure_cpu; /* does the client want server cpu utilization */
- /* measured? */
- float cpu_rate; /* do we know how fast the cpu is already? */
- int test_length; /* how long is the test? */
- int so_rcvavoid; /* do we want the remote to avoid copies on */
- /* receives? */
- int so_sndavoid; /* do we want the remote to avoid send copies? */
- int dirty_count; /* how many integers in the receive buffer */
- /* should be made dirty before calling recv? */
- int clean_count; /* how many integers should be read from the */
- /* recv buffer before calling recv? */
- int port; /* the port to which the recv side should bind
- to allow netperf to run through those evil
- firewall things */
- int ipfamily; /* the address family of ipaddress */
-};
-
-struct tcp_stream_response_struct {
- int recv_buf_size; /* how big does the client want it */
- int receive_size;
- int no_delay;
- int measure_cpu; /* does the client want server cpu */
- int test_length; /* how long is the test? */
- int send_buf_size;
- int data_port_number; /* connect to me here */
- float cpu_rate; /* could we measure */
- int so_rcvavoid; /* could the remote avoid receive copies? */
- int so_sndavoid; /* could the remote avoid send copies? */
-};
-
-struct tcp_stream_results_struct {
- double bytes_received;
- unsigned int recv_calls;
- float elapsed_time; /* how long the test ran */
- float cpu_util; /* -1 if not measured */
- float serv_dem; /* -1 if not measured */
- int cpu_method; /* how was cpu util measured? */
- int num_cpus; /* how many CPUs had the remote? */
-};
-
-struct tcp_maerts_request_struct {
- int send_buf_size;
- int recv_buf_size; /* how big does the client want it - the */
- /* receive socket buffer that is */
- int send_size; /* how many bytes do we want netserver to send
- at one time? */
- int send_alignment; /* what is the alignment of the send */
- /* buffer? */
- int send_offset; /* and at what offset from that alignment? */
- int no_delay; /* do we disable the nagle algorithm for send */
- /* coalescing? */
- int measure_cpu; /* does the client want server cpu utilization */
- /* measured? */
- float cpu_rate; /* do we know how fast the cpu is already? */
- int test_length; /* how long is the test? */
- int so_rcvavoid; /* do we want the remote to avoid copies on */
- /* receives? */
- int so_sndavoid; /* do we want the remote to avoid send copies? */
- int dirty_count; /* how many integers in the send buffer */
- /* should be made dirty before calling recv? */
- int clean_count; /* how many integers should be read from the */
- /* recv buffer before calling recv? */
- int port; /* the port to which the recv side should bind
- to allow netperf to run through those evil
- firewall things */
- int ipfamily;
-};
-
-struct tcp_maerts_response_struct {
- int recv_buf_size; /* how big does the client want it */
- int send_size;
- int no_delay;
- int measure_cpu; /* does the client want server cpu */
- int test_length; /* how long is the test? */
- int send_buf_size;
- int data_port_number; /* connect to me here */
- float cpu_rate; /* could we measure */
- int so_rcvavoid; /* could the remote avoid receive copies? */
- int so_sndavoid; /* could the remote avoid send copies? */
-};
-
-struct tcp_maerts_results_struct {
- double bytes_sent;
- unsigned int send_calls;
- float elapsed_time; /* how long the test ran */
- float cpu_util; /* -1 if not measured */
- float serv_dem; /* -1 if not measured */
- int cpu_method; /* how was cpu util measured? */
- int num_cpus; /* how many CPUs had the remote? */
-};
-
-struct tcp_rr_request_struct {
- int recv_buf_size; /* how big does the client want it */
- int send_buf_size;
- int recv_alignment;
- int recv_offset;
- int send_alignment;
- int send_offset;
- int request_size;
- int response_size;
- int no_delay;
- int measure_cpu; /* does the client want server cpu */
- float cpu_rate; /* do we know how fast the cpu is? */
- int test_length; /* how long is the test? */
- int so_rcvavoid; /* do we want the remote to avoid receive */
- /* copies? */
- int so_sndavoid; /* do we want the remote to avoid send copies? */
- int port; /* the port to which the recv side should bind
- to allow netperf to run through those evil
- firewall things */
- int ipfamily;
-};
-
-struct tcp_rr_response_struct {
- int recv_buf_size; /* how big does the client want it */
- int no_delay;
- int measure_cpu; /* does the client want server cpu */
- int test_length; /* how long is the test? */
- int send_buf_size;
- int data_port_number; /* connect to me here */
- float cpu_rate; /* could we measure */
- int so_rcvavoid; /* could the remote avoid receive copies? */
- int so_sndavoid; /* could the remote avoid send copies? */
-};
-
-struct tcp_rr_results_struct {
- unsigned int bytes_received; /* ignored initially */
- unsigned int recv_calls; /* ignored initially */
- unsigned int trans_received; /* not ignored */
- float elapsed_time; /* how long the test ran */
- float cpu_util; /* -1 if not measured */
- float serv_dem; /* -1 if not measured */
- int cpu_method; /* how was cpu util measured? */
- int num_cpus; /* how many CPUs had the remote? */
-};
-
-struct tcp_conn_rr_request_struct {
- int recv_buf_size; /* how big does the client want it */
- int send_buf_size;
- int recv_alignment;
- int recv_offset;
- int send_alignment;
- int send_offset;
- int request_size;
- int response_size;
- int no_delay;
- int measure_cpu; /* does the client want server cpu */
- float cpu_rate; /* do we know how fast the cpu is? */
- int test_length; /* how long is the test? */
- int so_rcvavoid; /* do we want the remote to avoid receive */
- /* copies? */
- int so_sndavoid; /* do we want the remote to avoid send copies? */
- int port; /* the port to which the recv side should bind
- to allow netperf to run through those evil
- firewall things */
- int ipfamily;
-};
-
-
-struct tcp_conn_rr_response_struct {
- int recv_buf_size; /* how big does the client want it */
- int no_delay;
- int measure_cpu; /* does the client want server cpu */
- int test_length; /* how long is the test? */
- int send_buf_size;
- int data_port_number; /* connect to me here */
- float cpu_rate; /* could we measure */
- int so_rcvavoid; /* could the remote avoid receive copies? */
- int so_sndavoid; /* could the remote avoid send copies? */
-};
-
-struct tcp_conn_rr_results_struct {
- unsigned int bytes_received; /* ignored initially */
- unsigned int recv_calls; /* ignored initially */
- unsigned int trans_received; /* not ignored */
- float elapsed_time; /* how long the test ran */
- float cpu_util; /* -1 if not measured */
- float serv_dem; /* -1 if not measured */
- int cpu_method; /* how was cpu util measured? */
- int num_cpus; /* how many CPUs had the remote? */
-};
-
-struct tcp_tran_rr_request_struct {
- int recv_buf_size; /* how big does the client want it */
- int send_buf_size;
- int recv_alignment;
- int recv_offset;
- int send_alignment;
- int send_offset;
- int request_size;
- int response_size;
- int no_delay;
- int measure_cpu; /* does the client want server cpu */
- float cpu_rate; /* do we know how fast the cpu is? */
- int test_length; /* how long is the test? */
- int so_rcvavoid; /* do we want the remote to avoid receive */
- /* copies? */
- int so_sndavoid; /* do we want the remote to avoid send copies? */
- int port; /* the port to which the recv side should bind
- to allow netperf to run through those evil
- firewall things */
- int ipfamily;
-};
-
-
-struct tcp_tran_rr_response_struct {
- int recv_buf_size; /* how big does the client want it */
- int no_delay;
- int measure_cpu; /* does the client want server cpu */
- int test_length; /* how long is the test? */
- int send_buf_size;
- int data_port_number; /* connect to me here */
- float cpu_rate; /* could we measure */
- int so_rcvavoid; /* could the remote avoid receive copies? */
- int so_sndavoid; /* could the remote avoid send copies? */
-};
-
-struct tcp_tran_rr_results_struct {
- unsigned int bytes_received; /* ignored initially */
- unsigned int recv_calls; /* ignored initially */
- unsigned int trans_received; /* not ignored */
- float elapsed_time; /* how long the test ran */
- float cpu_util; /* -1 if not measured */
- float serv_dem; /* -1 if not measured */
- int cpu_method; /* how was cpu util measured? */
- int num_cpus; /* how many CPUs had the remote? */
-
-};
-
-struct udp_stream_request_struct {
- int recv_buf_size;
- int message_size;
- int recv_connected;
- int recv_alignment;
- int recv_offset;
- int checksum_off;
- int measure_cpu;
- float cpu_rate;
- int test_length;
- int so_rcvavoid; /* do we want the remote to avoid receive */
- /* copies? */
- int so_sndavoid; /* do we want the remote to avoid send copies? */
- int port; /* the port to which the recv side should bind
- to allow netperf to run through those evil
- firewall things */
- int ipfamily;
-
-};
-
-struct udp_stream_response_struct {
- int recv_buf_size;
- int send_buf_size;
- int measure_cpu;
- int test_length;
- int data_port_number;
- float cpu_rate;
- int so_rcvavoid; /* could the remote avoid receive copies? */
- int so_sndavoid; /* could the remote avoid send copies? */
-};
-
-struct udp_stream_results_struct {
- unsigned int messages_recvd;
- unsigned int bytes_received;
- float elapsed_time;
- float cpu_util;
- int cpu_method; /* how was cpu util measured? */
- int num_cpus; /* how many CPUs had the remote? */
-};
-
-
-struct udp_rr_request_struct {
- int recv_buf_size; /* how big does the client want it */
- int send_buf_size;
- int recv_alignment;
- int recv_offset;
- int send_alignment;
- int send_offset;
- int request_size;
- int response_size;
- int no_delay;
- int measure_cpu; /* does the client want server cpu */
- float cpu_rate; /* do we know how fast the cpu is? */
- int test_length; /* how long is the test? */
- int so_rcvavoid; /* do we want the remote to avoid receive */
- /* copies? */
- int so_sndavoid; /* do we want the remote to avoid send copies? */
- int port; /* the port to which the recv side should bind
- to allow netperf to run through those evil
- firewall things */
- int ipfamily;
-};
-
-struct udp_rr_response_struct {
- int recv_buf_size; /* how big does the client want it */
- int no_delay;
- int measure_cpu; /* does the client want server cpu */
- int test_length; /* how long is the test? */
- int send_buf_size;
- int data_port_number; /* connect to me here */
- float cpu_rate; /* could we measure */
- int so_rcvavoid; /* could the remote avoid receive copies? */
- int so_sndavoid; /* could the remote avoid send copies? */
-};
-
-struct udp_rr_results_struct {
- unsigned int bytes_received; /* ignored initially */
- unsigned int recv_calls; /* ignored initially */
- unsigned int trans_received; /* not ignored */
- float elapsed_time; /* how long the test ran */
- float cpu_util; /* -1 if not measured */
- float serv_dem; /* -1 if not measured */
- int cpu_method; /* how was cpu util measured? */
- int num_cpus; /* how many CPUs had the remote? */
-};
-
-struct tcp_cc_request_struct {
- int recv_buf_size; /* how big does the client want it */
- int send_buf_size;
- int recv_alignment;
- int recv_offset;
- int send_alignment;
- int send_offset;
- int request_size;
- int response_size;
- int no_delay;
- int measure_cpu; /* does the client want server cpu */
- float cpu_rate; /* do we know how fast the cpu is? */
- int test_length; /* how long is the test? */
- int so_rcvavoid; /* do we want the remote to avoid receive */
- /* copies? */
- int so_sndavoid; /* do we want the remote to avoid send copies? */
- int port; /* the port to which the recv side should bind
- to allow netperf to run through those evil
- firewall things */
- int ipfamily;
-};
-
-
-struct tcp_cc_response_struct {
- int recv_buf_size; /* how big does the client want it */
- int no_delay;
- int measure_cpu; /* does the client want server cpu */
- int test_length; /* how long is the test? */
- int send_buf_size;
- int data_port_number; /* connect to me here */
- float cpu_rate; /* could we measure */
- int so_rcvavoid; /* could the remote avoid receive copies? */
- int so_sndavoid; /* could the remote avoid send copies? */
-};
-
-struct tcp_cc_results_struct {
- unsigned int bytes_received; /* ignored initially */
- unsigned int recv_calls; /* ignored initially */
- unsigned int trans_received; /* not ignored */
- float elapsed_time; /* how long the test ran */
- float cpu_util; /* -1 if not measured */
- float serv_dem; /* -1 if not measured */
- int cpu_method; /* how was cpu util measured? */
- int num_cpus; /* how many CPUs had the remote? */
-};
-
-extern int rss_size_req, /* requested remote socket send buffer size */
- rsr_size_req, /* requested remote socket recv buffer size */
- rss_size, /* remote socket send buffer size */
- rsr_size, /* remote socket recv buffer size */
- lss_size_req, /* requested local socket send buffer size */
- lsr_size_req, /* requested local socket recv buffer size */
- lss_size, /* local socket send buffer size */
- lsr_size, /* local socket recv buffer size */
- req_size, /* request size */
- rsp_size, /* response size */
- send_size, /* how big are individual sends */
- recv_size, /* how big are individual receives */
- loc_nodelay, /* don't/do use NODELAY locally */
- rem_nodelay, /* don't/do use NODELAY remotely */
- loc_sndavoid, /* avoid send copies locally */
- loc_rcvavoid, /* avoid recv copies locally */
- rem_sndavoid, /* avoid send copies remotely */
- rem_rcvavoid; /* avoid recv_copies remotely */
-
-
-extern void scan_sockets_args(int argc, char *argv[]);
-extern struct addrinfo *complete_addrinfo(char *controlhost,
- char *data_address,
- char *port,
- int family,
- int type,
- int protocol,
- int flags);
-extern void complete_addrinfos(struct addrinfo **remote,
- struct addrinfo **local,
- char remote_host[],
- int type,
- int protocol,
- int flags);
-extern int af_to_nf(int af);
-extern int nf_to_af(int nf);
-extern void print_top_test_header(char test_name[],
- struct addrinfo *source,
- struct addrinfo *destination);
-extern void set_port_number(struct addrinfo *res,
- unsigned short port);
-extern void set_hostname_and_port(char *hostname,
- char *portstr,
- int family,
- int port);
-extern void send_tcp_stream(char remote_host[]);
-extern void send_tcp_maerts(char remote_host[]);
-extern void send_tcp_rr(char remote_host[]);
-extern void send_tcp_conn_rr(char remote_host[]);
-extern void send_tcp_cc(char remote_host[]);
-extern void send_udp_stream(char remote_host[]);
-extern void send_udp_rr(char remote_host[]);
-
-extern void recv_tcp_stream();
-extern void recv_tcp_maerts();
-extern void recv_tcp_rr();
-extern void recv_tcp_conn_rr();
-extern void recv_tcp_cc();
-extern void recv_udp_stream();
-extern void recv_udp_rr();
-
-extern void loc_cpu_rate();
-extern void rem_cpu_rate();
-
-#ifdef HAVE_ICSC_EXS
-extern void send_exs_tcp_stream(char remotehost[]);
-#endif /* HAVE_ICSC_EXS */
-
-#ifdef HAVE_SENDFILE
-extern void sendfile_tcp_stream(char remotehost[]);
-#endif /* HAVE_SENDFILE */
-
-#if !defined(HAVE_STRUCT_SOCKADDR_STORAGE) && !defined(sockaddr_storage)
-#define sockaddr_storage sockaddr_in
-#endif
-
-#ifdef DO_NBRR
-extern void send_tcp_nbrr(char remote_host[]);
-
-extern void recv_tcp_nbrr();
-#endif
-
diff --git a/nettest_dlpi.c b/nettest_dlpi.c
deleted file mode 100644
index ab3e79f..0000000
--- a/nettest_dlpi.c
+++ /dev/null
@@ -1,3798 +0,0 @@
-
-/****************************************************************/
-/* */
-/* nettest_dlpi.c */
-/* */
-/* the actual test routines... */
-/* */
-/* send_dlpi_co_stream() perform a CO DLPI stream test */
-/* recv_dlpi_co_stream() */
-/* send_dlpi_co_rr() perform a CO DLPI req/res */
-/* recv_dlpi_co_rr() */
-/* send_dlpi_cl_stream() perform a CL DLPI stream test */
-/* recv_dlpi_cl_stream() */
-/* send_dlpi_cl_rr() perform a CL DLPI req/res */
-/* recv_dlpi_cl_rr() */
-/* */
-/****************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef WANT_DLPI
-char nettest_dlpi_id[]="\
-@(#)nettest_dlpi.c (c) Copyright 1993,1995,2004 Hewlett-Packard Co. Version 2.4.3";
-
-#include <sys/types.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <signal.h>
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <malloc.h>
-#include <sys/stream.h>
-#include <sys/stropts.h>
-#include <sys/poll.h>
-#ifdef __osf__
-#include <sys/dlpihdr.h>
-#else /* __osf__ */
-#include <sys/dlpi.h>
-#ifdef __hpux__
-#include <sys/dlpi_ext.h>
-#endif /* __hpux__ */
-#endif /* __osf__ */
-
-#include "netlib.h"
-#include "netsh.h"
-#include "nettest_dlpi.h"
-
-/* these are some variables global to all the DLPI tests. declare */
-/* them static to make them global only to this file */
-
-static int
- rsw_size, /* remote send window size */
- rrw_size, /* remote recv window size */
- lsw_size, /* local send window size */
- lrw_size, /* local recv window size */
- req_size = 100, /* request size */
- rsp_size = 200, /* response size */
- send_size, /* how big are individual sends */
- recv_size; /* how big are individual receives */
-
-int
- loc_ppa = 4, /* the ppa for the local interface, */
- /* as shown as the NM Id in lanscan */
- rem_ppa = 4, /* the ppa for the remote interface */
- dlpi_sap = 84; /* which 802.2 SAP should we use? */
-
-char loc_dlpi_device[32] = "/dev/dlpi";
-char rem_dlpi_device[32] = "/dev/dlpi";
-
-char dlpi_usage[] = "\n\
-Usage: netperf [global options] -- [test options] \n\
-\n\
-CO/CL DLPI Test Options:\n\
- -D dev[,dev] Set the local/remote DLPI device file name\n\
- -h Display this text\n\
- -M bytes Set the recv size (DLCO_STREAM, DLCL_STREAM)\n\
- -m bytes Set the send size (DLCO_STREAM, DLCL_STREAM)\n\
- -p loc[,rem] Set the local/remote PPA for the test\n\
- -R bytes Set response size (DLCO_RR, DLCL_RR)\n\
- -r bytes Set request size (DLCO_RR, DLCL_RR)\n\
- -s sap Set the 802.2 sap for the test\n\
- -W send[,recv] Set remote send/recv window sizes\n\
- -w send[,recv] Set local send/recv window sizes\n\
-\n\
-For those options taking two parms, at least one must be specified;\n\
-specifying one value without a comma will set both parms to that\n\
-value, specifying a value with a leading comma will set just the second\n\
-parm, a value with a trailing comma will set just the first. To set\n\
-each parm to unique values, specify both and separate them with a\n\
-comma.\n";
-
-
-/* This routine implements the CO unidirectional data transfer test */
-/* (a.k.a. stream) for the sockets interface. It receives its */
-/* parameters via global variables from the shell and writes its */
-/* output to the standard output. */
-
-
-void
-send_dlpi_co_stream()
-{
-
- char *tput_title = "\
-Recv Send Send \n\
-Window Window Message Elapsed \n\
-Size Size Size Time Throughput \n\
-frames frames bytes secs. %s/sec \n\n";
-
- char *tput_fmt_0 =
- "%7.2f\n";
-
- char *tput_fmt_1 =
- "%5d %5d %6d %-6.2f %7.2f \n";
-
- char *cpu_title = "\
-Recv Send Send Utilization Service Demand\n\
-Window Window Message Elapsed Send Recv Send Recv\n\
-Size Size Size Time Throughput local remote local remote\n\
-frames frames bytes secs. %-8.8s/s %% %% us/KB us/KB\n\n";
-
- char *cpu_fmt_0 =
- "%6.3f\n";
-
- char *cpu_fmt_1 =
- "%5d %5d %6d %-6.2f %7.2f %-6.2f %-6.2f %-6.3f %-6.3f\n";
-
- char *ksink_fmt = "\n\
-Alignment Offset %-8.8s %-8.8s Sends %-8.8s Recvs\n\
-Local Remote Local Remote Xfered Per Per\n\
-Send Recv Send Recv Send (avg) Recv (avg)\n\
-%5d %5d %5d %5d %6.4g %6.2f %6d %6.2f %6d\n";
-
-
- float elapsed_time;
-
-#ifdef WANT_INTERVALS
- int interval_count;
-#endif /* WANT_INTERVALS */
-
- /* what we want is to have a buffer space that is at least one */
- /* send-size greater than our send window. this will insure that we */
- /* are never trying to re-use a buffer that may still be in the hands */
- /* of the transport. This buffer will be malloc'd after we have found */
- /* the size of the local senc socket buffer. We will want to deal */
- /* with alignment and offset concerns as well. */
-
- struct ring_elt *send_ring;
- char *message;
- char *message_ptr;
- struct strbuf send_message;
- char dlsap[BUFSIZ];
- int dlsap_len;
- int *message_int_ptr;
- int message_offset;
- int malloc_size;
-
- int len;
- int nummessages;
- int send_descriptor;
- int bytes_remaining;
- /* with links like fddi, one can send > 32 bits worth of bytes */
- /* during a test... ;-) */
- double bytes_sent;
-
-#ifdef DIRTY
- int i;
-#endif /* DIRTY */
-
- float local_cpu_utilization;
- float local_service_demand;
- float remote_cpu_utilization;
- float remote_service_demand;
- double thruput;
-
- struct dlpi_co_stream_request_struct *dlpi_co_stream_request;
- struct dlpi_co_stream_response_struct *dlpi_co_stream_response;
- struct dlpi_co_stream_results_struct *dlpi_co_stream_result;
-
- dlpi_co_stream_request =
- (struct dlpi_co_stream_request_struct *)netperf_request.content.test_specific_data;
- dlpi_co_stream_response =
- (struct dlpi_co_stream_response_struct *)netperf_response.content.test_specific_data;
- dlpi_co_stream_result =
- (struct dlpi_co_stream_results_struct *)netperf_response.content.test_specific_data;
-
- if ( print_headers ) {
- fprintf(where,"DLPI CO STREAM TEST\n");
- if (local_cpu_usage || remote_cpu_usage)
- fprintf(where,cpu_title,format_units());
- else
- fprintf(where,tput_title,format_units());
- }
-
- /* initialize a few counters */
-
- nummessages = 0;
- bytes_sent = 0.0;
- times_up = 0;
-
- /*set up the data descriptor */
- send_descriptor = dl_open(loc_dlpi_device,loc_ppa);
- if (send_descriptor < 0){
- perror("netperf: send_dlpi_co_stream: dlpi stream data descriptor");
- exit(1);
- }
-
- /* bind the puppy and get the assigned dlsap */
- dlsap_len = BUFSIZ;
- if (dl_bind(send_descriptor,
- dlpi_sap, DL_CODLS, dlsap, &dlsap_len) != 0) {
- fprintf(where,"send_dlpi_co_rr: bind failure\n");
- fflush(where);
- exit(1);
- }
-
- if (debug) {
- fprintf(where,"send_dlpi_co_stream: send_descriptor obtained...\n");
- }
-
-#ifdef DL_HP_SET_LOCAL_WIN_REQ
- if (lsw_size > 0) {
- if (debug > 1) {
- fprintf(where,"netperf: send_dlpi_co_stream: window send size altered from system default...\n");
- fprintf(where," send: %d\n",lsw_size);
- }
- }
- if (lrw_size > 0) {
- if (debug > 1) {
- fprintf(where,
- "netperf: send_dlpi_co_stream: window recv size altered from system default...\n");
- fprintf(where," recv: %d\n",lrw_size);
- }
- }
-
-
- /* Now, we will find-out what the size actually became, and report */
- /* that back to the user. If the call fails, we will just report a -1 */
- /* back to the initiator for the recv buffer size. */
-
-
- if (debug) {
- fprintf(where,
- "netperf: send_dlpi_co_stream: window sizes determined...\n");
- fprintf(where," send: %d recv: %d\n",lsw_size,lrw_size);
- ffluch(where);
- }
-
-#else /* DL_HP_SET_LOCAL_WIN_REQ */
-
- lsw_size = -1;
- lrw_size = -1;
-
-#endif /* DL_HP_SET_LOCAL_WIN_REQ */
-
- /* we should pick a default send_size, it should not be larger than */
- /* the min of the two interface MTU's, and should perhaps default to */
- /* the Interface MTU, but for now, we will default it to 1024... if */
- /* someone wants to change this, the should change the corresponding */
- /* lines in the recv_dlpi_co_stream routine */
-
- if (send_size == 0) {
- send_size = 1024;
- }
-
- /* set-up the data buffer with the requested alignment and offset. */
- /* After we have calculated the proper starting address, we want to */
- /* put that back into the message variable so we go back to the */
- /* proper place. note that this means that only the first send is */
- /* guaranteed to be at the alignment specified by the -a parameter. I */
- /* think that this is a little more "real-world" than what was found */
- /* in previous versions. note also that we have allocated a quantity */
- /* of memory that is at least one send-size greater than our socket */
- /* buffer size. We want to be sure that there are at least two */
- /* buffers allocated - this can be a bit of a problem when the */
- /* send_size is bigger than the socket size, so we must check... the */
- /* user may have wanted to explicitly set the "width" of our send */
- /* buffers, we should respect that wish... */
- if (send_width == 0) {
- send_width = (lsw_size/send_size) + 1;
- if (send_width == 1) send_width++;
- }
-
- send_ring = allocate_buffer_ring(send_width,
- send_size,
- local_send_align,
- local_send_offset);
-
- send_message.maxlen = send_size;
- send_message.len = send_size;
- send_message.buf = send_ring->buffer_ptr;
-
- /* If the user has requested cpu utilization measurements, we must */
- /* calibrate the cpu(s). We will perform this task within the tests */
- /* themselves. If the user has specified the cpu rate, then */
- /* calibrate_local_cpu will return rather quickly as it will have */
- /* nothing to do. If local_cpu_rate is zero, then we will go through */
- /* all the "normal" calibration stuff and return the rate back.*/
-
- if (local_cpu_usage) {
- local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
- }
-
- /* Tell the remote end to do a listen. The server alters the socket */
- /* paramters on the other side at this point, hence the reason for */
- /* all the values being passed in the setup message. If the user did */
- /* not specify any of the parameters, they will be passed as 0, which */
- /* will indicate to the remote that no changes beyond the system's */
- /* default should be used. */
-
- netperf_request.content.request_type = DO_DLPI_CO_STREAM;
- dlpi_co_stream_request->send_win_size = rsw_size;
- dlpi_co_stream_request->recv_win_size = rrw_size;
- dlpi_co_stream_request->receive_size = recv_size;
- dlpi_co_stream_request->recv_alignment= remote_recv_align;
- dlpi_co_stream_request->recv_offset = remote_recv_offset;
- dlpi_co_stream_request->measure_cpu = remote_cpu_usage;
- dlpi_co_stream_request->cpu_rate = remote_cpu_rate;
- dlpi_co_stream_request->ppa = rem_ppa;
- dlpi_co_stream_request->sap = dlpi_sap;
- dlpi_co_stream_request->dev_name_len = strlen(rem_dlpi_device);
- strcpy(dlpi_co_stream_request->dlpi_device,
- rem_dlpi_device);
-
-#ifdef __alpha
-
- /* ok - even on a DEC box, strings are strings. I didn't really want */
- /* to ntohl the words of a string. since I don't want to teach the */
- /* send_ and recv_ _request and _response routines about the types, */
- /* I will put "anti-ntohl" calls here. I imagine that the "pure" */
- /* solution would be to use XDR, but I am still leary of being able */
- /* to find XDR libs on all platforms I want running netperf. raj */
- {
- int *charword;
- int *initword;
- int *lastword;
-
- initword = (int *) dlpi_co_stream_request->dlpi_device;
- lastword = initword + ((strlen(rem_dlpi_device) + 3) / 4);
-
- for (charword = initword;
- charword < lastword;
- charword++) {
-
- *charword = ntohl(*charword);
- }
- }
-#endif /* __alpha */
-
- if (test_time) {
- dlpi_co_stream_request->test_length = test_time;
- }
- else {
- dlpi_co_stream_request->test_length = test_bytes;
- }
-#ifdef DIRTY
- dlpi_co_stream_request->dirty_count = rem_dirty_count;
- dlpi_co_stream_request->clean_count = rem_clean_count;
-#endif /* DIRTY */
-
-
- if (debug > 1) {
- fprintf(where,
- "netperf: send_dlpi_co_stream: requesting DLPI CO stream test\n");
- }
-
- send_request();
-
- /* The response from the remote will contain all of the relevant */
- /* parameters for this test type. We will put them back into */
- /* the variables here so they can be displayed if desired. The */
- /* remote will have calibrated CPU if necessary, and will have done */
- /* all the needed set-up we will have calibrated the cpu locally */
- /* before sending the request, and will grab the counter value right */
- /* after the connect returns. The remote will grab the counter right */
- /* after the accept call. This saves the hassle of extra messages */
- /* being sent for the TCP tests. */
-
- recv_response();
-
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote listen done.\n");
- rrw_size = dlpi_co_stream_response->recv_win_size;
- rsw_size = dlpi_co_stream_response->send_win_size;
- remote_cpu_usage= dlpi_co_stream_response->measure_cpu;
- remote_cpu_rate = dlpi_co_stream_response->cpu_rate;
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- perror("netperf: remote error");
- exit(1);
- }
-
- /* Connect up to the remote port on the data descriptor */
- if(dl_connect(send_descriptor,
- dlpi_co_stream_response->station_addr,
- dlpi_co_stream_response->station_addr_len) != 0) {
- fprintf(where,"recv_dlpi_co_stream: connect failure\n");
- fflush(where);
- exit(1);
- }
-
- /* Data Socket set-up is finished. If there were problems, either the */
- /* connect would have failed, or the previous response would have */
- /* indicated a problem. I failed to see the value of the extra */
- /* message after the accept on the remote. If it failed, we'll see it */
- /* here. If it didn't, we might as well start pumping data. */
-
- /* Set-up the test end conditions. For a stream test, they can be */
- /* either time or byte-count based. */
-
- if (test_time) {
- /* The user wanted to end the test after a period of time. */
- times_up = 0;
- bytes_remaining = 0;
- start_timer(test_time);
- }
- else {
- /* The tester wanted to send a number of bytes. */
- bytes_remaining = test_bytes;
- times_up = 1;
- }
-
- /* The cpu_start routine will grab the current time and possibly */
- /* value of the idle counter for later use in measuring cpu */
- /* utilization and/or service demand and thruput. */
-
- cpu_start(local_cpu_usage);
-
- /* We use an "OR" to control test execution. When the test is */
- /* controlled by time, the byte count check will always return false. */
- /* When the test is controlled by byte count, the time test will */
- /* always return false. When the test is finished, the whole */
- /* expression will go false and we will stop sending data. */
-
-#ifdef DIRTY
- /* initialize the random number generator for putting dirty stuff */
- /* into the send buffer. raj */
- srand((int) getpid());
-#endif /* DIRTY */
-
- while ((!times_up) || (bytes_remaining > 0)) {
-
-#ifdef DIRTY
- /* we want to dirty some number of consecutive integers in the buffer */
- /* we are about to send. we may also want to bring some number of */
- /* them cleanly into the cache. The clean ones will follow any dirty */
- /* ones into the cache. */
- message_int_ptr = (int *)message_ptr;
- for (i = 0; i < loc_dirty_count; i++) {
- *message_int_ptr = rand();
- message_int_ptr++;
- }
- for (i = 0; i < loc_clean_count; i++) {
- loc_dirty_count = *message_int_ptr;
- message_int_ptr++;
- }
-#endif /* DIRTY */
-
- if((putmsg(send_descriptor,
- 0,
- &send_message,
- 0)) != 0) {
- if (errno == EINTR)
- break;
- perror("netperf: data send error");
- exit(1);
- }
- send_ring = send_ring->next;
- send_message.buf = send_ring->buffer_ptr;
-#ifdef WANT_INTERVALS
- for (interval_count = 0;
- interval_count < interval_wate;
- interval_count++);
-#endif /* WANT_INTERVALS */
-
- if (debug > 4) {
- fprintf(where,"netperf: send_clpi_co_stream: putmsg called ");
- fprintf(where,"len is %d\n",send_message.len);
- fflush(where);
- }
-
- nummessages++;
- if (bytes_remaining) {
- bytes_remaining -= send_size;
- }
- }
-
- /* The test is over. Flush the buffers to the remote end. We do a */
- /* graceful release to insure that all data has been taken by the */
- /* remote. this needs a little work - there is no three-way */
- /* handshake with type two as there is with TCP, so there really */
- /* should be a message exchange here. however, we will finesse it by */
- /* saying that the tests shoudl run for a while. */
-
- if (debug) {
- fprintf(where,"sending test end signal \n");
- fflush(where);
- }
-
- send_message.len = (send_size - 1);
- if (send_message.len == 0) send_message.len = 2;
-
- if((putmsg(send_descriptor,
- 0,
- &send_message,
- 0)) != 0) {
- perror("netperf: data send error");
- exit(1);
- }
-
- /* this call will always give us the elapsed time for the test, and */
- /* will also store-away the necessaries for cpu utilization */
-
- cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being measured? */
- /* how long did we really run? */
-
- /* Get the statistics from the remote end. The remote will have */
- /* calculated service demand and all those interesting things. If it */
- /* wasn't supposed to care, it will return obvious values. */
-
- recv_response();
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote results obtained\n");
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- perror("netperf: remote error");
-
- exit(1);
- }
-
- /* We now calculate what our thruput was for the test. In the future, */
- /* we may want to include a calculation of the thruput measured by */
- /* the remote, but it should be the case that for a TCP stream test, */
- /* that the two numbers should be *very* close... We calculate */
- /* bytes_sent regardless of the way the test length was controlled. */
- /* If it was time, we needed to, and if it was by bytes, the user may */
- /* have specified a number of bytes that wasn't a multiple of the */
- /* send_size, so we really didn't send what he asked for ;-) */
-
- bytes_sent = ((double) send_size * (double) nummessages) + (double) len;
- thruput = calc_thruput(bytes_sent);
-
- if (local_cpu_usage || remote_cpu_usage) {
- /* We must now do a little math for service demand and cpu */
- /* utilization for the system(s) */
- /* Of course, some of the information might be bogus because */
- /* there was no idle counter in the kernel(s). We need to make */
- /* a note of this for the user's benefit...*/
- if (local_cpu_usage) {
- if (local_cpu_rate == 0.0) {
- fprintf(where,
- "WARNING WARNING WARNING WARNING WARNING WARNING WARNING!\n");
- fprintf(where,
- "Local CPU usage numbers based on process information only!\n");
- fflush(where);
- }
- local_cpu_utilization = calc_cpu_util(0.0);
- local_service_demand = calc_service_demand(bytes_sent,
- 0.0,
- 0.0,
- 0);
- }
- else {
- local_cpu_utilization = -1.0;
- local_service_demand = -1.0;
- }
-
- if (remote_cpu_usage) {
- if (remote_cpu_rate == 0.0) {
- fprintf(where,
- "DANGER DANGER DANGER DANGER DANGER DANGER DANGER!\n");
- fprintf(where,
- "Remote CPU usage numbers based on process information only!\n");
- fflush(where);
- }
- remote_cpu_utilization = dlpi_co_stream_result->cpu_util;
- remote_service_demand = calc_service_demand(bytes_sent,
- 0.0,
- remote_cpu_utilization,
- dlpi_co_stream_result->num_cpus);
- }
- else {
- remote_cpu_utilization = -1.0;
- remote_service_demand = -1.0;
- }
-
- /* We are now ready to print all the information. If the user */
- /* has specified zero-level verbosity, we will just print the */
- /* local service demand, or the remote service demand. If the */
- /* user has requested verbosity level 1, he will get the basic */
- /* "streamperf" numbers. If the user has specified a verbosity */
- /* of greater than 1, we will display a veritable plethora of */
- /* background information from outside of this block as it it */
- /* not cpu_measurement specific... */
-
- switch (verbosity) {
- case 0:
- if (local_cpu_usage) {
- fprintf(where,
- cpu_fmt_0,
- local_service_demand);
- }
- else {
- fprintf(where,
- cpu_fmt_0,
- remote_service_demand);
- }
- break;
- case 1:
- case 2:
- fprintf(where,
- cpu_fmt_1, /* the format string */
- rrw_size, /* remote recvbuf size */
- lsw_size, /* local sendbuf size */
- send_size, /* how large were the sends */
- elapsed_time, /* how long was the test */
- thruput, /* what was the xfer rate */
- local_cpu_utilization, /* local cpu */
- remote_cpu_utilization, /* remote cpu */
- local_service_demand, /* local service demand */
- remote_service_demand); /* remote service demand */
- break;
- }
- }
- else {
- /* The tester did not wish to measure service demand. */
- switch (verbosity) {
- case 0:
- fprintf(where,
- tput_fmt_0,
- thruput);
- break;
- case 1:
- case 2:
- fprintf(where,
- tput_fmt_1, /* the format string */
- rrw_size, /* remote recvbuf size */
- lsw_size, /* local sendbuf size */
- send_size, /* how large were the sends */
- elapsed_time, /* how long did it take */
- thruput);/* how fast did it go */
- break;
- }
- }
-
- /* it would be a good thing to include information about some of the */
- /* other parameters that may have been set for this test, but at the */
- /* moment, I do not wish to figure-out all the formatting, so I will */
- /* just put this comment here to help remind me that it is something */
- /* that should be done at a later time. */
-
- if (verbosity > 1) {
- /* The user wanted to know it all, so we will give it to him. */
- /* This information will include as much as we can find about */
- /* TCP statistics, the alignments of the sends and receives */
- /* and all that sort of rot... */
-
- fprintf(where,
- ksink_fmt,
- "Bytes",
- "Bytes",
- "Bytes",
- local_send_align,
- remote_recv_align,
- local_send_offset,
- remote_recv_offset,
- bytes_sent,
- bytes_sent / (double)nummessages,
- nummessages,
- bytes_sent / (double)dlpi_co_stream_result->recv_calls,
- dlpi_co_stream_result->recv_calls);
- }
-
-}
-
-
-/* This is the server-side routine for the tcp stream test. It is */
-/* implemented as one routine. I could break things-out somewhat, but */
-/* didn't feel it was necessary. */
-
-int
- recv_dlpi_co_stream()
-{
-
- int data_descriptor;
- int flags = 0;
- int measure_cpu;
- int bytes_received;
- int receive_calls;
- float elapsed_time;
-
- struct ring_elt *recv_ring;
- char *message_ptr;
- char *message;
- int *message_int_ptr;
- struct strbuf recv_message;
- int dirty_count;
- int clean_count;
- int i;
-
- struct dlpi_co_stream_request_struct *dlpi_co_stream_request;
- struct dlpi_co_stream_response_struct *dlpi_co_stream_response;
- struct dlpi_co_stream_results_struct *dlpi_co_stream_results;
-
- dlpi_co_stream_request = (struct dlpi_co_stream_request_struct *)netperf_request.content.test_specific_data;
- dlpi_co_stream_response = (struct dlpi_co_stream_response_struct *)netperf_response.content.test_specific_data;
- dlpi_co_stream_results = (struct dlpi_co_stream_results_struct *)netperf_response.content.test_specific_data;
-
- if (debug) {
- fprintf(where,"netserver: recv_dlpi_co_stream: entered...\n");
- fflush(where);
- }
-
- /* We want to set-up the listen socket with all the desired */
- /* parameters and then let the initiator know that all is ready. If */
- /* socket size defaults are to be used, then the initiator will have */
- /* sent us 0's. If the socket sizes cannot be changed, then we will */
- /* send-back what they are. If that information cannot be determined, */
- /* then we send-back -1's for the sizes. If things go wrong for any */
- /* reason, we will drop back ten yards and punt. */
-
- /* If anything goes wrong, we want the remote to know about it. It */
- /* would be best if the error that the remote reports to the user is */
- /* the actual error we encountered, rather than some bogus unexpected */
- /* response type message. */
-
- netperf_response.content.response_type = DLPI_CO_STREAM_RESPONSE;
-
- /* We now alter the message_ptr variable to be at the desired */
- /* alignment with the desired offset. */
-
- if (debug > 1) {
- fprintf(where,"recv_dlpi_co_stream: requested alignment of %d\n",
- dlpi_co_stream_request->recv_alignment);
- fflush(where);
- }
-
-
- /* Grab a descriptor to listen on, and then listen on it. */
-
- if (debug > 1) {
- fprintf(where,"recv_dlpi_co_stream: grabbing a descriptor...\n");
- fflush(where);
- }
-
-
-
-#ifdef __alpha
-
- /* ok - even on a DEC box, strings are strings. I din't really want */
- /* to ntohl the words of a string. since I don't want to teach the */
- /* send_ and recv_ _request and _response routines about the types, */
- /* I will put "anti-ntohl" calls here. I imagine that the "pure" */
- /* solution would be to use XDR, but I am still leary of being able */
- /* to find XDR libs on all platforms I want running netperf. raj */
- {
- int *charword;
- int *initword;
- int *lastword;
-
- initword = (int *) dlpi_co_stream_request->dlpi_device;
- lastword = initword + ((dlpi_co_stream_request->dev_name_len + 3) / 4);
-
- for (charword = initword;
- charword < lastword;
- charword++) {
-
- *charword = htonl(*charword);
- }
- }
-#endif /* __alpha */
-
- data_descriptor = dl_open(dlpi_co_stream_request->dlpi_device,
- dlpi_co_stream_request->ppa);
- if (data_descriptor < 0) {
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
-
- /* Let's get an address assigned to this descriptor so we can tell the */
- /* initiator how to reach the data descriptor. There may be a desire to */
- /* nail this descriptor to a specific address in a multi-homed, */
- /* multi-connection situation, but for now, we'll ignore the issue */
- /* and concentrate on single connection testing. */
-
- /* bind the sap and retrieve the dlsap assigned by the system */
- dlpi_co_stream_response->station_addr_len = 14; /* arbitrary */
- if (dl_bind(data_descriptor,
- dlpi_co_stream_request->sap,
- DL_CODLS,
- (char *)dlpi_co_stream_response->station_addr,
- &dlpi_co_stream_response->station_addr_len) != 0) {
- fprintf(where,"recv_dlpi_co_stream: bind failure\n");
- fflush(where);
- exit(1);
- }
-
- /* The initiator may have wished-us to modify the socket buffer */
- /* sizes. We should give it a shot. If he didn't ask us to change the */
- /* sizes, we should let him know what sizes were in use at this end. */
- /* If none of this code is compiled-in, then we will tell the */
- /* initiator that we were unable to play with the socket buffer by */
- /* setting the size in the response to -1. */
-
-#ifdef DL_HP_SET_LOCAL_WIN_REQ
-
- if (dlpi_co_stream_request->recv_win_size) {
- }
- /* Now, we will find-out what the size actually became, and report */
- /* that back to the user. If the call fails, we will just report a -1 */
- /* back to the initiator for the recv buffer size. */
-
-#else /* the system won't let us play with the buffers */
-
- dlpi_co_stream_response->recv_win_size = -1;
-
-#endif /* DL_HP_SET_LOCAL_WIN_REQ */
-
- /* what sort of sizes did we end-up with? */
- /* this bit of code whould default to the Interface MTU */
- if (dlpi_co_stream_request->receive_size == 0) {
- recv_size = 1024;
- }
- else {
- recv_size = dlpi_co_stream_request->receive_size;
- }
-
- /* tell the other fellow what our receive size became */
- dlpi_co_stream_response->receive_size = recv_size;
-
- /* just a little prep work for when we may have to behave like the */
- /* sending side... */
- message = (char *)malloc(recv_size * 2);
- if (message == NULL) {
- printf("malloc(%d) failed!\n", recv_size * 2);
- exit(1);
- }
-
- message_ptr = ALIGN_BUFFER(message, dlpi_co_stream_request->recv_alignment, dlpi_co_stream_request->recv_offset);
- recv_message.maxlen = recv_size;
- recv_message.len = 0;
- recv_message.buf = message_ptr;
-
- if (debug > 1) {
- fprintf(where,
- "recv_dlpi_co_stream: receive alignment and offset set...\n");
- fflush(where);
- }
-
- netperf_response.content.serv_errno = 0;
-
- /* But wait, there's more. If the initiator wanted cpu measurements, */
- /* then we must call the calibrate routine, which will return the max */
- /* rate back to the initiator. If the CPU was not to be measured, or */
- /* something went wrong with the calibration, we will return a -1 to */
- /* the initiator. */
-
- dlpi_co_stream_response->cpu_rate = 0.0; /* assume no cpu */
- if (dlpi_co_stream_request->measure_cpu) {
- dlpi_co_stream_response->measure_cpu = 1;
- dlpi_co_stream_response->cpu_rate =
- calibrate_local_cpu(dlpi_co_stream_request->cpu_rate);
- }
-
- send_response();
-
- /* accept a connection on this file descriptor. at some point, */
- /* dl_accept will "do the right thing" with the last two parms, but */
- /* for now it ignores them, so we will pass zeros. */
-
- if(dl_accept(data_descriptor, 0, 0) != 0) {
- fprintf(where,
- "recv_dlpi_co_stream: error in accept, errno %d\n",
- errno);
- fflush(where);
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
-
- if (debug) {
- fprintf(where,"netserver:recv_dlpi_co_stream: connection accepted\n");
- fflush(where);
- }
-
- /* Now it's time to start receiving data on the connection. We will */
- /* first grab the apropriate counters and then start grabbing. */
-
- cpu_start(dlpi_co_stream_request->measure_cpu);
-
-#ifdef DIRTY
- /* we want to dirty some number of consecutive integers in the buffer */
- /* we are about to recv. we may also want to bring some number of */
- /* them cleanly into the cache. The clean ones will follow any dirty */
- /* ones into the cache. */
-
- dirty_count = dlpi_co_stream_request->dirty_count;
- clean_count = dlpi_co_stream_request->clean_count;
- message_int_ptr = (int *)message_ptr;
- for (i = 0; i < dirty_count; i++) {
- *message_int_ptr = rand();
- message_int_ptr++;
- }
- for (i = 0; i < clean_count; i++) {
- dirty_count = *message_int_ptr;
- message_int_ptr++;
- }
-#endif /* DIRTY */
-
- recv_message.len = recv_size;
- while (recv_message.len == recv_size) {
- if (getmsg(data_descriptor,
- 0,
- &recv_message,
- &flags) != 0) {
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
- bytes_received += recv_message.len;
- receive_calls++;
-
- if (debug) {
- fprintf(where,
- "netserver:recv_dlpi_co_stream: getmsg accepted %d bytes\n",
- recv_message.len);
- fflush(where);
- }
-
-
-#ifdef DIRTY
- message_int_ptr = (int *)message_ptr;
- for (i = 0; i < dirty_count; i++) {
- *message_int_ptr = rand();
- message_int_ptr++;
- }
- for (i = 0; i < clean_count; i++) {
- dirty_count = *message_int_ptr;
- message_int_ptr++;
- }
-#endif /* DIRTY */
-
- }
-
- /* The loop now exits due to zero bytes received. */
- /* should perform a disconnect to signal the sender that */
- /* we have received all the data sent. */
-
- if (close(data_descriptor) == -1) {
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
-
- cpu_stop(dlpi_co_stream_request->measure_cpu,&elapsed_time);
-
- /* send the results to the sender */
-
- if (debug) {
- fprintf(where,
- "recv_dlpi_co_stream: got %d bytes\n",
- bytes_received);
- fprintf(where,
- "recv_dlpi_co_stream: got %d recvs\n",
- receive_calls);
- fflush(where);
- }
-
- dlpi_co_stream_results->bytes_received = bytes_received;
- dlpi_co_stream_results->elapsed_time = elapsed_time;
- dlpi_co_stream_results->recv_calls = receive_calls;
-
- if (dlpi_co_stream_request->measure_cpu) {
- dlpi_co_stream_results->cpu_util = calc_cpu_util(0.0);
- };
-
- if (debug > 1) {
- fprintf(where,
- "recv_dlpi_co_stream: test complete, sending results.\n");
- fflush(where);
- }
-
- send_response();
-}
-
-/*********************************/
-
-int send_dlpi_co_rr(char remote_host[])
-{
-
- char *tput_title = "\
- Local /Remote\n\
- Window Size Request Resp. Elapsed Trans.\n\
- Send Recv Size Size Time Rate \n\
- frames frames bytes bytes secs. per sec \n\n";
-
- char *tput_fmt_0 =
- "%7.2f\n";
-
- char *tput_fmt_1_line_1 = "\
- %-6d %-6d %-6d %-6d %-6.2f %7.2f \n";
- char *tput_fmt_1_line_2 = "\
- %-6d %-6d\n";
-
- char *cpu_title = "\
- Local /Remote\n\
- Window Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\
- Send Recv Size Size Time Rate local remote local remote\n\
- frames frames bytes bytes secs. per sec %% %% us/Tr us/Tr\n\n";
-
- char *cpu_fmt_0 =
- "%6.3f\n";
-
- char *cpu_fmt_1_line_1 = "\
- %-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f\n";
-
- char *cpu_fmt_1_line_2 = "\
- %-6d %-6d\n";
-
- char *ksink_fmt = "\
- Alignment Offset\n\
- Local Remote Local Remote\n\
- Send Recv Send Recv\n\
- %5d %5d %5d %5d\n";
-
-
- int timed_out = 0;
- float elapsed_time;
- int dlsap_len;
- char dlsap[BUFSIZ];
-
- int flags = 0;
- char *send_message_ptr;
- char *recv_message_ptr;
- char *temp_message_ptr;
- struct strbuf send_message;
- struct strbuf recv_message;
-
- int nummessages;
- int send_descriptor;
- int trans_remaining;
- double bytes_xferd;
-
- int rsp_bytes_left;
-
- /* we assume that station adresses fit within two ints */
- unsigned int remote_address[1];
-
- float local_cpu_utilization;
- float local_service_demand;
- float remote_cpu_utilization;
- float remote_service_demand;
- double thruput;
-
- struct dlpi_co_rr_request_struct *dlpi_co_rr_request;
- struct dlpi_co_rr_response_struct *dlpi_co_rr_response;
- struct dlpi_co_rr_results_struct *dlpi_co_rr_result;
-
- dlpi_co_rr_request =
- (struct dlpi_co_rr_request_struct *)netperf_request.content.test_specific_data;
- dlpi_co_rr_response =
- (struct dlpi_co_rr_response_struct *)netperf_response.content.test_specific_data;
- dlpi_co_rr_result =
- (struct dlpi_co_rr_results_struct *)netperf_response.content.test_specific_data;
-
- /* since we are now disconnected from the code that established the */
- /* control socket, and since we want to be able to use different */
- /* protocols and such, we are passed the name of the remote host and */
- /* must turn that into the test specific addressing information. */
-
- if ( print_headers ) {
- fprintf(where,"DLPI CO REQUEST/RESPONSE TEST\n");
- if (local_cpu_usage || remote_cpu_usage)
- fprintf(where,cpu_title,format_units());
- else
- fprintf(where,tput_title,format_units());
- }
-
- /* initialize a few counters */
-
- nummessages = 0;
- bytes_xferd = 0.0;
- times_up = 0;
-
- /* set-up the data buffers with the requested alignment and offset */
- temp_message_ptr = (char *)malloc(req_size+MAXALIGNMENT+MAXOFFSET);
- if (temp_message_ptr == NULL) {
- printf("malloc(%d) failed!\n", req_size+MAXALIGNMENT+MAXOFFSET);
- exit(1);
- }
- send_message_ptr = (char *)(( (long) temp_message_ptr +
- (long) local_send_align - 1) &
- ~((long) local_send_align - 1));
- send_message_ptr = send_message_ptr + local_send_offset;
- send_message.maxlen = req_size+MAXALIGNMENT+MAXOFFSET;
- send_message.len = req_size;
- send_message.buf = send_message_ptr;
-
- temp_message_ptr = (char *)malloc(rsp_size+MAXALIGNMENT+MAXOFFSET);
- if (temp_message_ptr == NULL) {
- printf("malloc(%d) failed!\n", rsp_size+MAXALIGNMENT+MAXOFFSET);
- exit(1);
- }
- recv_message_ptr = (char *)(( (long) temp_message_ptr +
- (long) local_recv_align - 1) &
- ~((long) local_recv_align - 1));
- recv_message_ptr = recv_message_ptr + local_recv_offset;
- recv_message.maxlen = rsp_size+MAXALIGNMENT+MAXOFFSET;
- recv_message.len = 0;
- recv_message.buf = send_message_ptr;
-
- /*set up the data socket */
-
- send_descriptor = dl_open(loc_dlpi_device,loc_ppa);
- if (send_descriptor < 0){
- perror("netperf: send_dlpi_co_rr: tcp stream data descriptor");
- exit(1);
- }
-
- if (debug) {
- fprintf(where,"send_dlpi_co_rr: send_descriptor obtained...\n");
- }
-
- /* bind the puppy and get the assigned dlsap */
-
- dlsap_len = BUFSIZ;
- if (dl_bind(send_descriptor,
- dlpi_sap, DL_CODLS, dlsap, &dlsap_len) != 0) {
- fprintf(where,"send_dlpi_co_rr: bind failure\n");
- fflush(where);
- exit(1);
- }
-
- /* Modify the local socket size. The reason we alter the send buffer */
- /* size here rather than when the connection is made is to take care */
- /* of decreases in buffer size. Decreasing the window size after */
- /* connection establishment is a TCP no-no. Also, by setting the */
- /* buffer (window) size before the connection is established, we can */
- /* control the TCP MSS (segment size). The MSS is never more that 1/2 */
- /* the minimum receive buffer size at each half of the connection. */
- /* This is why we are altering the receive buffer size on the sending */
- /* size of a unidirectional transfer. If the user has not requested */
- /* that the socket buffers be altered, we will try to find-out what */
- /* their values are. If we cannot touch the socket buffer in any way, */
- /* we will set the values to -1 to indicate that. */
-
-#ifdef DL_HP_SET_LOCAL_WIN_REQ
- if (lsw_size > 0) {
- if (debug > 1) {
- fprintf(where,"netperf: send_dlpi_co_rr: socket send size altered from system default...\n");
- fprintf(where," send: %d\n",lsw_size);
- }
- }
- if (lrw_size > 0) {
- if (debug > 1) {
- fprintf(where,"netperf: send_dlpi_co_rr: socket recv size altered from system default...\n");
- fprintf(where," recv: %d\n",lrw_size);
- }
- }
-
-
- /* Now, we will find-out what the size actually became, and report */
- /* that back to the user. If the call fails, we will just report a -1 */
- /* back to the initiator for the recv buffer size. */
-
-
- if (debug) {
- fprintf(where,"netperf: send_dlpi_co_rr: socket sizes determined...\n");
- fprintf(where," send: %d recv: %d\n",lsw_size,lrw_size);
- }
-
-#else /* DL_HP_SET_LOCAL_WIN_REQ */
-
- lsw_size = -1;
- lrw_size = -1;
-
-#endif /* DL_HP_SET_LOCAL_WIN_REQ */
-
- /* If the user has requested cpu utilization measurements, we must */
- /* calibrate the cpu(s). We will perform this task within the tests */
- /* themselves. If the user has specified the cpu rate, then */
- /* calibrate_local_cpu will return rather quickly as it will have */
- /* nothing to do. If local_cpu_rate is zero, then we will go through */
- /* all the "normal" calibration stuff and return the rate back.*/
-
- if (local_cpu_usage) {
- local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
- }
-
- /* Tell the remote end to do a listen. The server alters the socket */
- /* paramters on the other side at this point, hence the reason for */
- /* all the values being passed in the setup message. If the user did */
- /* not specify any of the parameters, they will be passed as 0, which */
- /* will indicate to the remote that no changes beyond the system's */
- /* default should be used. Alignment is the exception, it will */
- /* default to 8, which will be no alignment alterations. */
-
- netperf_request.content.request_type = DO_DLPI_CO_RR;
- dlpi_co_rr_request->recv_win_size = rrw_size;
- dlpi_co_rr_request->send_win_size = rsw_size;
- dlpi_co_rr_request->recv_alignment = remote_recv_align;
- dlpi_co_rr_request->recv_offset = remote_recv_offset;
- dlpi_co_rr_request->send_alignment = remote_send_align;
- dlpi_co_rr_request->send_offset = remote_send_offset;
- dlpi_co_rr_request->request_size = req_size;
- dlpi_co_rr_request->response_size = rsp_size;
- dlpi_co_rr_request->measure_cpu = remote_cpu_usage;
- dlpi_co_rr_request->cpu_rate = remote_cpu_rate;
- dlpi_co_rr_request->ppa = rem_ppa;
- dlpi_co_rr_request->sap = dlpi_sap;
- dlpi_co_rr_request->dev_name_len = strlen(rem_dlpi_device);
- strcpy(dlpi_co_rr_request->dlpi_device,
- rem_dlpi_device);
-#ifdef __alpha
-
- /* ok - even on a DEC box, strings are strings. I din't really want */
- /* to ntohl the words of a string. since I don't want to teach the */
- /* send_ and recv_ _request and _response routines about the types, */
- /* I will put "anti-ntohl" calls here. I imagine that the "pure" */
- /* solution would be to use XDR, but I am still leary of being able */
- /* to find XDR libs on all platforms I want running netperf. raj */
- {
- int *charword;
- int *initword;
- int *lastword;
-
- initword = (int *) dlpi_co_rr_request->dlpi_device;
- lastword = initword + ((strlen(rem_dlpi_device) + 3) / 4);
-
- for (charword = initword;
- charword < lastword;
- charword++) {
-
- *charword = ntohl(*charword);
- }
- }
-#endif /* __alpha */
-
- if (test_time) {
- dlpi_co_rr_request->test_length = test_time;
- }
- else {
- dlpi_co_rr_request->test_length = test_trans * -1;
- }
-
- if (debug > 1) {
- fprintf(where,"netperf: send_dlpi_co_rr: requesting TCP stream test\n");
- }
-
- send_request();
-
- /* The response from the remote will contain all of the relevant */
- /* socket parameters for this test type. We will put them back into */
- /* the variables here so they can be displayed if desired. The */
- /* remote will have calibrated CPU if necessary, and will have done */
- /* all the needed set-up we will have calibrated the cpu locally */
- /* before sending the request, and will grab the counter value right */
- /* after the connect returns. The remote will grab the counter right */
- /* after the accept call. This saves the hassle of extra messages */
- /* being sent for the TCP tests. */
-
- recv_response();
-
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote listen done.\n");
- rrw_size = dlpi_co_rr_response->recv_win_size;
- rsw_size = dlpi_co_rr_response->send_win_size;
- remote_cpu_usage= dlpi_co_rr_response->measure_cpu;
- remote_cpu_rate = dlpi_co_rr_response->cpu_rate;
-
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- perror("netperf: remote error");
-
- exit(1);
- }
-
- /*Connect up to the remote port on the data descriptor */
-
- if(dl_connect(send_descriptor,
- dlpi_co_rr_response->station_addr,
- dlpi_co_rr_response->station_addr_len) != 0) {
- fprintf(where,"send_dlpi_co_rr: connect failure\n");
- fflush(where);
- exit(1);
- }
-
- /* Data Socket set-up is finished. If there were problems, either the */
- /* connect would have failed, or the previous response would have */
- /* indicated a problem. I failed to see the value of the extra */
- /* message after the accept on the remote. If it failed, we'll see it */
- /* here. If it didn't, we might as well start pumping data. */
-
- /* Set-up the test end conditions. For a request/response test, they */
- /* can be either time or transaction based. */
-
- if (test_time) {
- /* The user wanted to end the test after a period of time. */
- times_up = 0;
- trans_remaining = 0;
- start_timer(test_time);
- }
- else {
- /* The tester wanted to send a number of bytes. */
- trans_remaining = test_bytes;
- times_up = 1;
- }
-
- /* The cpu_start routine will grab the current time and possibly */
- /* value of the idle counter for later use in measuring cpu */
- /* utilization and/or service demand and thruput. */
-
- cpu_start(local_cpu_usage);
-
- /* We use an "OR" to control test execution. When the test is */
- /* controlled by time, the byte count check will always return false. */
- /* When the test is controlled by byte count, the time test will */
- /* always return false. When the test is finished, the whole */
- /* expression will go false and we will stop sending data. I think I */
- /* just arbitrarily decrement trans_remaining for the timed test, but */
- /* will not do that just yet... One other question is whether or not */
- /* the send buffer and the receive buffer should be the same buffer. */
-
- while ((!times_up) || (trans_remaining > 0)) {
- /* send the request */
- if((putmsg(send_descriptor,
- 0,
- &send_message,
- 0)) != 0) {
- if (errno == EINTR) {
- /* we hit the end of a */
- /* timed test. */
- timed_out = 1;
- break;
- }
- perror("send_dlpi_co_rr: putmsg error");
- exit(1);
- }
-
- if (debug) {
- fprintf(where,"recv_message.len %d\n",recv_message.len);
- fprintf(where,"send_message.len %d\n",send_message.len);
- fflush(where);
- }
-
- /* receive the response */
- /* this needs some work with streams buffers if we are going to */
- /* support requests and responses larger than the MTU of the */
- /* network, but this can wait until later */
- rsp_bytes_left = rsp_size;
- recv_message.len = rsp_size;
- while(rsp_bytes_left > 0) {
- if((getmsg(send_descriptor,
- 0,
- &recv_message,
- &flags)) < 0) {
- if (errno == EINTR) {
- /* We hit the end of a timed test. */
- timed_out = 1;
- break;
- }
- perror("send_dlpi_co_rr: data recv error");
- exit(1);
- }
- rsp_bytes_left -= recv_message.len;
- }
-
- if (timed_out) {
- /* we may have been in a nested while loop - we need */
- /* another call to break. */
- break;
- }
-
- nummessages++;
- if (trans_remaining) {
- trans_remaining--;
- }
-
- if (debug > 3) {
- fprintf(where,
- "Transaction %d completed\n",
- nummessages);
- fflush(where);
- }
- }
-
- /* At this point we used to call shutdown onthe data socket to be */
- /* sure all the data was delivered, but this was not germane in a */
- /* request/response test, and it was causing the tests to "hang" when */
- /* they were being controlled by time. So, I have replaced this */
- /* shutdown call with a call to close that can be found later in the */
- /* procedure. */
-
- /* this call will always give us the elapsed time for the test, and */
- /* will also store-away the necessaries for cpu utilization */
-
- cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being measured? */
- /* how long did we really run? */
-
- /* Get the statistics from the remote end. The remote will have */
- /* calculated service demand and all those interesting things. If it */
- /* wasn't supposed to care, it will return obvious values. */
-
- recv_response();
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote results obtained\n");
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- perror("netperf: remote error");
-
- exit(1);
- }
-
- /* We now calculate what our thruput was for the test. In the future, */
- /* we may want to include a calculation of the thruput measured by */
- /* the remote, but it should be the case that for a TCP stream test, */
- /* that the two numbers should be *very* close... We calculate */
- /* bytes_sent regardless of the way the test length was controlled. */
- /* If it was time, we needed to, and if it was by bytes, the user may */
- /* have specified a number of bytes that wasn't a multiple of the */
- /* send_size, so we really didn't send what he asked for ;-) We use */
- /* Kbytes/s as the units of thruput for a TCP stream test, where K = */
- /* 1024. A future enhancement *might* be to choose from a couple of */
- /* unit selections. */
-
- bytes_xferd = (req_size * nummessages) + (rsp_size * nummessages);
- thruput = calc_thruput(bytes_xferd);
-
- if (local_cpu_usage || remote_cpu_usage) {
- /* We must now do a little math for service demand and cpu */
- /* utilization for the system(s) */
- /* Of course, some of the information might be bogus because */
- /* there was no idle counter in the kernel(s). We need to make */
- /* a note of this for the user's benefit...*/
- if (local_cpu_usage) {
- if (local_cpu_rate == 0.0) {
- fprintf(where,"WARNING WARNING WARNING WARNING WARNING WARNING WARNING!\n");
- fprintf(where,"Local CPU usage numbers based on process information only!\n");
- fflush(where);
- }
- local_cpu_utilization = calc_cpu_util(0.0);
- /* since calc_service demand is doing ms/Kunit we will */
- /* multiply the number of transaction by 1024 to get */
- /* "good" numbers */
- local_service_demand = calc_service_demand((double) nummessages*1024,
- 0.0,
- 0.0,
- 0);
- }
- else {
- local_cpu_utilization = -1.0;
- local_service_demand = -1.0;
- }
-
- if (remote_cpu_usage) {
- if (remote_cpu_rate == 0.0) {
- fprintf(where,"DANGER DANGER DANGER DANGER DANGER DANGER DANGER!\n");
- fprintf(where,"Remote CPU usage numbers based on process information only!\n");
- fflush(where);
- }
- remote_cpu_utilization = dlpi_co_rr_result->cpu_util;
- /* since calc_service demand is doing ms/Kunit we will */
- /* multiply the number of transaction by 1024 to get */
- /* "good" numbers */
- remote_service_demand = calc_service_demand((double) nummessages*1024,
- 0.0,
- remote_cpu_utilization,
- dlpi_co_rr_result->num_cpus);
- }
- else {
- remote_cpu_utilization = -1.0;
- remote_service_demand = -1.0;
- }
-
- /* We are now ready to print all the information. If the user */
- /* has specified zero-level verbosity, we will just print the */
- /* local service demand, or the remote service demand. If the */
- /* user has requested verbosity level 1, he will get the basic */
- /* "streamperf" numbers. If the user has specified a verbosity */
- /* of greater than 1, we will display a veritable plethora of */
- /* background information from outside of this block as it it */
- /* not cpu_measurement specific... */
-
- switch (verbosity) {
- case 0:
- if (local_cpu_usage) {
- fprintf(where,
- cpu_fmt_0,
- local_service_demand);
- }
- else {
- fprintf(where,
- cpu_fmt_0,
- remote_service_demand);
- }
- break;
- case 1:
- fprintf(where,
- cpu_fmt_1_line_1, /* the format string */
- lsw_size, /* local sendbuf size */
- lrw_size,
- req_size, /* how large were the requests */
- rsp_size, /* guess */
- elapsed_time, /* how long was the test */
- nummessages/elapsed_time,
- local_cpu_utilization, /* local cpu */
- remote_cpu_utilization, /* remote cpu */
- local_service_demand, /* local service demand */
- remote_service_demand); /* remote service demand */
- fprintf(where,
- cpu_fmt_1_line_2,
- rsw_size,
- rrw_size);
- break;
- }
- }
- else {
- /* The tester did not wish to measure service demand. */
- switch (verbosity) {
- case 0:
- fprintf(where,
- tput_fmt_0,
- nummessages/elapsed_time);
- break;
- case 1:
- fprintf(where,
- tput_fmt_1_line_1, /* the format string */
- lsw_size,
- lrw_size,
- req_size, /* how large were the requests */
- rsp_size, /* how large were the responses */
- elapsed_time, /* how long did it take */
- nummessages/elapsed_time);
- fprintf(where,
- tput_fmt_1_line_2,
- rsw_size, /* remote recvbuf size */
- rrw_size);
-
- break;
- }
- }
-
- /* it would be a good thing to include information about some of the */
- /* other parameters that may have been set for this test, but at the */
- /* moment, I do not wish to figure-out all the formatting, so I will */
- /* just put this comment here to help remind me that it is something */
- /* that should be done at a later time. */
-
- if (verbosity > 1) {
- /* The user wanted to know it all, so we will give it to him. */
- /* This information will include as much as we can find about */
- /* TCP statistics, the alignments of the sends and receives */
- /* and all that sort of rot... */
-
- fprintf(where,
- ksink_fmt);
- }
- /* The test is over. Kill the data descriptor */
-
- if (close(send_descriptor) == -1) {
- perror("send_dlpi_co_rr: cannot shutdown tcp stream descriptor");
- }
-
-}
-
-void
- send_dlpi_cl_stream(char remote_host[])
-{
- /************************************************************************/
- /* */
- /* UDP Unidirectional Send Test */
- /* */
- /************************************************************************/
- char *tput_title =
- "Window Message Elapsed Messages \n\
-Size Size Time Okay Errors Throughput\n\
-frames bytes secs # # %s/sec\n\n";
-
- char *tput_fmt_0 =
- "%7.2f\n";
-
- char *tput_fmt_1 =
- "%5d %5d %-7.2f %7d %6d %7.2f\n\
-%5d %-7.2f %7d %7.2f\n\n";
-
-
- char *cpu_title =
- "Window Message Elapsed Messages CPU Service\n\
-Size Size Time Okay Errors Throughput Util Demand\n\
-frames bytes secs # # %s/sec %% us/KB\n\n";
-
- char *cpu_fmt_0 =
- "%6.2f\n";
-
- char *cpu_fmt_1 =
- "%5d %5d %-7.2f %7d %6d %7.1f %-6.2f %-6.3f\n\
-%5d %-7.2f %7d %7.1f %-6.2f %-6.3f\n\n";
-
- int messages_recvd;
- float elapsed_time,
- local_cpu_utilization,
- remote_cpu_utilization;
-
- float local_service_demand, remote_service_demand;
- double local_thruput, remote_thruput;
- double bytes_sent;
- double bytes_recvd;
-
-
- int *message_int_ptr;
- char *message_ptr;
- char *message;
- char sctl_data[BUFSIZ];
- struct strbuf send_message;
- struct strbuf sctl_message;
- dl_unitdata_req_t *data_req = (dl_unitdata_req_t *)sctl_data;
-
- char dlsap[BUFSIZ];
- int dlsap_len;
- int message_offset;
- int message_max_offset;
- int failed_sends;
- int failed_cows;
- int messages_sent;
- int data_descriptor;
-
-
-#ifdef WANT_INTERVALS
- int interval_count;
-#endif /* WANT_INTERVALS */
-#ifdef DIRTY
- int i;
-#endif /* DIRTY */
-
- struct dlpi_cl_stream_request_struct *dlpi_cl_stream_request;
- struct dlpi_cl_stream_response_struct *dlpi_cl_stream_response;
- struct dlpi_cl_stream_results_struct *dlpi_cl_stream_results;
-
- dlpi_cl_stream_request = (struct dlpi_cl_stream_request_struct *)netperf_request.content.test_specific_data;
- dlpi_cl_stream_response = (struct dlpi_cl_stream_response_struct *)netperf_response.content.test_specific_data;
- dlpi_cl_stream_results = (struct dlpi_cl_stream_results_struct *)netperf_response.content.test_specific_data;
-
- if ( print_headers ) {
- printf("DLPI CL UNIDIRECTIONAL SEND TEST\n");
- if (local_cpu_usage || remote_cpu_usage)
- printf(cpu_title,format_units());
- else
- printf(tput_title,format_units());
- }
-
- failed_sends = 0;
- messages_sent = 0;
- times_up = 0;
-
- /*set up the data descriptor */
-
- data_descriptor = dl_open(loc_dlpi_device,loc_ppa);
- if (data_descriptor < 0){
- perror("send_dlpi_cl_stream: data descriptor");
- exit(1);
- }
-
- /* bind the puppy and get the assigned dlsap */
- dlsap_len = BUFSIZ;
- if (dl_bind(data_descriptor,
- dlpi_sap, DL_CLDLS, dlsap, &dlsap_len) != 0) {
- fprintf(where,"send_dlpi_cl_stream: bind failure\n");
- fflush(where);
- exit(1);
- }
-
- /* Modify the local socket size (SNDBUF size) */
-
-#ifdef DL_HP_SET_LOCAL_WIN_REQ
- if (lsw_size > 0) {
- if (debug > 1) {
- fprintf(where,"netperf: send_dlpi_cl_stream: descriptor send size altered from system default...\n");
- fprintf(where," send: %d\n",lsw_size);
- }
- }
- if (lrw_size > 0) {
- if (debug > 1) {
- fprintf(where,"netperf: send_dlpi_cl_stream: descriptor recv size altered from system default...\n");
- fprintf(where," recv: %d\n",lrw_size);
- }
- }
-
-
- /* Now, we will find-out what the size actually became, and report */
- /* that back to the user. If the call fails, we will just report a -1 */
- /* back to the initiator for the recv buffer size. */
-
-#else /* DL_HP_SET_LOCAL_WIN_REQ */
-
- lsw_size = -1;
- lrw_size = -1;
-
-#endif /* DL_HP_SET_LOCAL_WIN_REQ */
-
- /* now, we want to see if we need to set the send_size */
- if (send_size == 0) {
- send_size = 1024;
- }
-
-
- /* set-up the data buffer with the requested alignment and offset, */
- /* most of the numbers here are just a hack to pick something nice */
- /* and big in an attempt to never try to send a buffer a second time */
- /* before it leaves the node...unless the user set the width */
- /* explicitly. */
- if (send_width == 0) send_width = 32;
- message = (char *)malloc(send_size * (send_width + 1) + local_send_align + local_send_offset);
- if (message == NULL) {
- printf("malloc(%d) failed!\n", send_size * (send_width + 1) + local_send_align + local_send_offset);
- exit(1);
- }
- message_ptr = (char *)(( (long) message +
- (long) local_send_align - 1) &
- ~((long) local_send_align - 1));
- message_ptr = message_ptr + local_send_offset;
- message = message_ptr;
- send_message.maxlen = send_size;
- send_message.len = send_size;
- send_message.buf = message;
-
- sctl_message.maxlen = BUFSIZ;
- sctl_message.len = 0;
- sctl_message.buf = sctl_data;
-
- /* if the user supplied a cpu rate, this call will complete rather */
- /* quickly, otherwise, the cpu rate will be retured to us for */
- /* possible display. The Library will keep it's own copy of this data */
- /* for use elsewhere. We will only display it. (Does that make it */
- /* "opaque" to us?) */
-
- if (local_cpu_usage)
- local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
-
- /* Tell the remote end to set up the data connection. The server */
- /* sends back the port number and alters the socket parameters there. */
- /* Of course this is a datagram service so no connection is actually */
- /* set up, the server just sets up the socket and binds it. */
-
- netperf_request.content.request_type = DO_DLPI_CL_STREAM;
- dlpi_cl_stream_request->recv_win_size = rrw_size;
- dlpi_cl_stream_request->message_size = send_size;
- dlpi_cl_stream_request->recv_alignment = remote_recv_align;
- dlpi_cl_stream_request->recv_offset = remote_recv_offset;
- dlpi_cl_stream_request->measure_cpu = remote_cpu_usage;
- dlpi_cl_stream_request->cpu_rate = remote_cpu_rate;
- dlpi_cl_stream_request->ppa = rem_ppa;
- dlpi_cl_stream_request->sap = dlpi_sap;
- dlpi_cl_stream_request->dev_name_len = strlen(rem_dlpi_device);
- strcpy(dlpi_cl_stream_request->dlpi_device,
- rem_dlpi_device);
-
-#ifdef __alpha
-
- /* ok - even on a DEC box, strings are strings. I din't really want */
- /* to ntohl the words of a string. since I don't want to teach the */
- /* send_ and recv_ _request and _response routines about the types, */
- /* I will put "anti-ntohl" calls here. I imagine that the "pure" */
- /* solution would be to use XDR, but I am still leary of being able */
- /* to find XDR libs on all platforms I want running netperf. raj */
- {
- int *charword;
- int *initword;
- int *lastword;
-
- initword = (int *) dlpi_cl_stream_request->dlpi_device;
- lastword = initword + ((strlen(rem_dlpi_device) + 3) / 4);
-
- for (charword = initword;
- charword < lastword;
- charword++) {
-
- *charword = ntohl(*charword);
- }
- }
-#endif /* __alpha */
-
- if (test_time) {
- dlpi_cl_stream_request->test_length = test_time;
- }
- else {
- dlpi_cl_stream_request->test_length = test_bytes * -1;
- }
-
-
- send_request();
-
- recv_response();
-
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"send_dlpi_cl_stream: remote data connection done.\n");
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- perror("send_dlpi_cl_stream: error on remote");
- exit(1);
- }
-
- /* place some of the remote's addressing information into the send */
- /* structure so our sends can be sent to the correct place. Also get */
- /* some of the returned socket buffer information for user display. */
-
- /* set-up the destination addressing control info */
- data_req->dl_primitive = DL_UNITDATA_REQ;
- bcopy((char *)(dlpi_cl_stream_response->station_addr),
- ((char *)data_req + sizeof(dl_unitdata_req_t)),
- dlpi_cl_stream_response->station_addr_len);
- data_req->dl_dest_addr_offset = sizeof(dl_unitdata_req_t);
- data_req->dl_dest_addr_length = dlpi_cl_stream_response->station_addr_len;
- /* there is a dl_priority structure too, but I am ignoring it for */
- /* the time being. */
- /* however... it is best to put some value in there lest some code
- get grumpy about it - fix from Nicolas Thomas */
- data_req->dl_priority.dl_min = DL_QOS_DONT_CARE;
- data_req->dl_priority.dl_max = DL_QOS_DONT_CARE;
-
- sctl_message.len = sizeof(dl_unitdata_req_t) +
- data_req->dl_dest_addr_length;
-
- rrw_size = dlpi_cl_stream_response->recv_win_size;
- rsw_size = dlpi_cl_stream_response->send_win_size;
- remote_cpu_rate = dlpi_cl_stream_response->cpu_rate;
-
-
- /* set up the timer to call us after test_time */
- start_timer(test_time);
-
- /* Get the start count for the idle counter and the start time */
-
- cpu_start(local_cpu_usage);
-
-#ifdef WANT_INTERVALS
- interval_count = interval_burst;
-#endif /* WANT_INTERVALS */
-
- /* Send datagrams like there was no tomorrow */
- while (!times_up) {
-#ifdef DIRTY
- /* we want to dirty some number of consecutive integers in the buffer */
- /* we are about to send. we may also want to bring some number of */
- /* them cleanly into the cache. The clean ones will follow any dirty */
- /* ones into the cache. */
- message_int_ptr = (int *)message_ptr;
- for (i = 0; i < loc_dirty_count; i++) {
- *message_int_ptr = 4;
- message_int_ptr++;
- }
- for (i = 0; i < loc_clean_count; i++) {
- loc_dirty_count = *message_int_ptr;
- message_int_ptr++;
- }
-#endif /* DIRTY */
- if (putmsg(data_descriptor,
- &sctl_message,
- &send_message,
- 0) != 0) {
- if (errno == EINTR) {
- break;
- }
- if (errno == ENOBUFS) {
- /* we might not ever hit this with STREAMS, it would probably */
- /* be better to do a getinfo request at the end of the test to */
- /* get all sorts of gory statistics. in the meantime, we will */
- /* keep this code in place. */
- failed_sends++;
- continue;
- }
- perror("send_dlpi_cl_stream: data send error");
- if (debug) {
- fprintf(where,"messages_sent %u\n",messages_sent);
- fflush(where);
- }
- exit(1);
- }
- messages_sent++;
-
- /* now we want to move our pointer to the next position in the */
- /* data buffer...since there was a successful send */
-
-
-#ifdef WANT_INTERVALS
- /* in this case, the interval count is the count-down couter */
- /* to decide to sleep for a little bit */
- if ((interval_burst) && (--interval_count == 0)) {
- /* call the sleep routine for some milliseconds, if our */
- /* timer popped while we were in there, we want to */
- /* break out of the loop. */
- if (msec_sleep(interval_wate)) {
- break;
- }
- interval_count = interval_burst;
- }
-
-#endif /* WANT_INTERVALS */
-
- }
-
- /* This is a timed test, so the remote will be returning to us after */
- /* a time. We should not need to send any "strange" messages to tell */
- /* the remote that the test is completed, unless we decide to add a */
- /* number of messages to the test. */
-
- /* the test is over, so get stats and stuff */
- cpu_stop(local_cpu_usage,
- &elapsed_time);
-
- /* Get the statistics from the remote end */
- recv_response();
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"send_dlpi_cl_stream: remote results obtained\n");
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- perror("send_dlpi_cl_stream: error on remote");
- exit(1);
- }
-
- bytes_sent = send_size * messages_sent;
- local_thruput = calc_thruput(bytes_sent);
-
- messages_recvd = dlpi_cl_stream_results->messages_recvd;
- bytes_recvd = send_size * messages_recvd;
-
- /* we asume that the remote ran for as long as we did */
-
- remote_thruput = calc_thruput(bytes_recvd);
-
- /* print the results for this descriptor and message size */
-
- if (local_cpu_usage || remote_cpu_usage) {
- /* We must now do a little math for service demand and cpu */
- /* utilization for the system(s) We pass zeros for the local */
- /* cpu utilization and elapsed time to tell the routine to use */
- /* the libraries own values for those. */
- if (local_cpu_usage) {
- if (local_cpu_rate == 0.0) {
- fprintf(where,"WARNING WARNING WARNING WARNING WARNING WARNING WARNING!\n");
- fprintf(where,"Local CPU usage numbers based on process information only!\n");
- fflush(where);
- }
-
- local_cpu_utilization = calc_cpu_util(0.0);
- local_service_demand = calc_service_demand(bytes_sent,
- 0.0,
- 0.0,
- 0);
- }
- else {
- local_cpu_utilization = -1.0;
- local_service_demand = -1.0;
- }
-
- /* The local calculations could use variables being kept by */
- /* the local netlib routines. The remote calcuations need to */
- /* have a few things passed to them. */
- if (remote_cpu_usage) {
- if (remote_cpu_rate == 0.0) {
- fprintf(where,"DANGER DANGER DANGER DANGER DANGER DANGER DANGER!\n");
- fprintf(where,"REMOTE CPU usage numbers based on process information only!\n");
- fflush(where);
- }
-
- remote_cpu_utilization = dlpi_cl_stream_results->cpu_util;
- remote_service_demand = calc_service_demand(bytes_recvd,
- 0.0,
- remote_cpu_utilization,
- dlpi_cl_stream_results->num_cpus);
- }
- else {
- remote_cpu_utilization = -1.0;
- remote_service_demand = -1.0;
- }
-
- /* We are now ready to print all the information. If the user */
- /* has specified zero-level verbosity, we will just print the */
- /* local service demand, or the remote service demand. If the */
- /* user has requested verbosity level 1, he will get the basic */
- /* "streamperf" numbers. If the user has specified a verbosity */
- /* of greater than 1, we will display a veritable plethora of */
- /* background information from outside of this block as it it */
- /* not cpu_measurement specific... */
-
- switch (verbosity) {
- case 0:
- if (local_cpu_usage) {
- fprintf(where,
- cpu_fmt_0,
- local_service_demand);
- }
- else {
- fprintf(where,
- cpu_fmt_0,
- remote_service_demand);
- }
- break;
- case 1:
- fprintf(where,
- cpu_fmt_1, /* the format string */
- lsw_size, /* local sendbuf size */
- send_size, /* how large were the sends */
- elapsed_time, /* how long was the test */
- messages_sent,
- failed_sends,
- local_thruput, /* what was the xfer rate */
- local_cpu_utilization, /* local cpu */
- local_service_demand, /* local service demand */
- rrw_size,
- elapsed_time,
- messages_recvd,
- remote_thruput,
- remote_cpu_utilization, /* remote cpu */
- remote_service_demand); /* remote service demand */
- break;
- }
- }
- else {
- /* The tester did not wish to measure service demand. */
- switch (verbosity) {
- case 0:
- fprintf(where,
- tput_fmt_0,
- local_thruput);
- break;
- case 1:
- fprintf(where,
- tput_fmt_1, /* the format string */
- lsw_size, /* local sendbuf size */
- send_size, /* how large were the sends */
- elapsed_time, /* how long did it take */
- messages_sent,
- failed_sends,
- local_thruput,
- rrw_size, /* remote recvbuf size */
- elapsed_time,
- messages_recvd,
- remote_thruput
- );
- break;
- }
- }
-}
-
-int
- recv_dlpi_cl_stream()
-{
-
- char *message;
- int data_descriptor;
- int len;
- char *message_ptr;
- char rctl_data[BUFSIZ];
- struct strbuf recv_message;
- struct strbuf rctl_message;
- int flags = 0;
- /* these are to make reading some of the DLPI control messages easier */
- dl_unitdata_ind_t *data_ind = (dl_unitdata_ind_t *)rctl_data;
- dl_uderror_ind_t *uder_ind = (dl_uderror_ind_t *)rctl_data;
-
- int bytes_received = 0;
- float elapsed_time;
-
- int message_size;
- int messages_recvd = 0;
- int measure_cpu;
-
- struct dlpi_cl_stream_request_struct *dlpi_cl_stream_request;
- struct dlpi_cl_stream_response_struct *dlpi_cl_stream_response;
- struct dlpi_cl_stream_results_struct *dlpi_cl_stream_results;
-
- dlpi_cl_stream_request = (struct dlpi_cl_stream_request_struct *)netperf_request.content.test_specific_data;
- dlpi_cl_stream_response = (struct dlpi_cl_stream_response_struct *)netperf_response.content.test_specific_data;
- dlpi_cl_stream_results = (struct dlpi_cl_stream_results_struct *)netperf_response.content.test_specific_data;
-
- if (debug) {
- fprintf(where,"netserver: recv_dlpi_cl_stream: entered...\n");
- fflush(where);
- }
-
- /* We want to set-up the listen descriptor with all the desired */
- /* parameters and then let the initiator know that all is ready. If */
- /* socket size defaults are to be used, then the initiator will have */
- /* sent us 0's. If the socket sizes cannot be changed, then we will */
- /* send-back what they are. If that information cannot be determined, */
- /* then we send-back -1's for the sizes. If things go wrong for any */
- /* reason, we will drop back ten yards and punt. */
-
- /* If anything goes wrong, we want the remote to know about it. It */
- /* would be best if the error that the remote reports to the user is */
- /* the actual error we encountered, rather than some bogus unexpected */
- /* response type message. */
-
- if (debug > 1) {
- fprintf(where,"recv_dlpi_cl_stream: setting the response type...\n");
- fflush(where);
- }
-
- netperf_response.content.response_type = DLPI_CL_STREAM_RESPONSE;
-
- if (debug > 2) {
- fprintf(where,"recv_dlpi_cl_stream: the response type is set...\n");
- fflush(where);
- }
-
- /* set-up the data buffer with the requested alignment and offset */
- message = (char *)malloc(DATABUFFERLEN);
- if (message == NULL) {
- printf("malloc(%d) failed!\n", DATABUFFERLEN);
- exit(1);
- }
-
- /* We now alter the message_ptr variable to be at the desired */
- /* alignment with the desired offset. */
-
- if (debug > 1) {
- fprintf(where,"recv_dlpi_cl_stream: requested alignment of %d\n",
- dlpi_cl_stream_request->recv_alignment);
- fflush(where);
- }
-
- message_ptr = ALIGN_BUFFER(message, dlpi_cl_stream_request->recv_alignment, dlpi_cl_stream_request->recv_offset);
-
- if (dlpi_cl_stream_request->message_size > 0) {
- recv_message.maxlen = dlpi_cl_stream_request->message_size;
- }
- else {
- recv_message.maxlen = 4096;
- }
- recv_message.len = 0;
- recv_message.buf = message_ptr;
-
- rctl_message.maxlen = BUFSIZ;
- rctl_message.len = 0;
- rctl_message.buf = rctl_data;
-
- if (debug > 1) {
- fprintf(where,
- "recv_dlpi_cl_stream: receive alignment and offset set...\n");
- fflush(where);
- }
-
- if (debug > 1) {
- fprintf(where,"recv_dlpi_cl_stream: grabbing a descriptor...\n");
- fflush(where);
- }
-
-#ifdef __alpha
-
- /* ok - even on a DEC box, strings are strings. I din't really want */
- /* to ntohl the words of a string. since I don't want to teach the */
- /* send_ and recv_ _request and _response routines about the types, */
- /* I will put "anti-ntohl" calls here. I imagine that the "pure" */
- /* solution would be to use XDR, but I am still leary of being able */
- /* to find XDR libs on all platforms I want running netperf. raj */
- {
- int *charword;
- int *initword;
- int *lastword;
-
- initword = (int *) dlpi_cl_stream_request->dlpi_device;
- lastword = initword + ((dlpi_cl_stream_request->dev_name_len + 3) / 4);
-
- for (charword = initword;
- charword < lastword;
- charword++) {
-
- *charword = htonl(*charword);
- }
- }
-#endif /* __alpha */
-
- data_descriptor = dl_open(dlpi_cl_stream_request->dlpi_device,
- dlpi_cl_stream_request->ppa);
- if (data_descriptor < 0) {
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
-
- /* The initiator may have wished-us to modify the window */
- /* sizes. We should give it a shot. If he didn't ask us to change the */
- /* sizes, we should let him know what sizes were in use at this end. */
- /* If none of this code is compiled-in, then we will tell the */
- /* initiator that we were unable to play with the sizes by */
- /* setting the size in the response to -1. */
-
-#ifdef DL_HP_SET_LOCAL_WIN_REQ
-
- if (dlpi_cl_stream_request->recv_win_size) {
- dlpi_cl_stream_response->recv_win_size = -1;
- }
-
-#else /* the system won't let us play with the buffers */
-
- dlpi_cl_stream_response->recv_win_size = -1;
-
-#endif /* DL_HP_SET_LOCAL_WIN_REQ */
-
- dlpi_cl_stream_response->test_length = dlpi_cl_stream_request->test_length;
-
- /* bind the sap and retrieve the dlsap assigned by the system */
- dlpi_cl_stream_response->station_addr_len = 14; /* arbitrary */
- if (dl_bind(data_descriptor,
- dlpi_cl_stream_request->sap,
- DL_CLDLS,
- (char *)dlpi_cl_stream_response->station_addr,
- &dlpi_cl_stream_response->station_addr_len) != 0) {
- fprintf(where,"send_dlpi_cl_stream: bind failure\n");
- fflush(where);
- exit(1);
- }
-
- netperf_response.content.serv_errno = 0;
-
- /* But wait, there's more. If the initiator wanted cpu measurements, */
- /* then we must call the calibrate routine, which will return the max */
- /* rate back to the initiator. If the CPU was not to be measured, or */
- /* something went wrong with the calibration, we will return a -1 to */
- /* the initiator. */
-
- dlpi_cl_stream_response->cpu_rate = 0.0; /* assume no cpu */
- if (dlpi_cl_stream_request->measure_cpu) {
- /* We will pass the rate into the calibration routine. If the */
- /* user did not specify one, it will be 0.0, and we will do a */
- /* "real" calibration. Otherwise, all it will really do is */
- /* store it away... */
- dlpi_cl_stream_response->measure_cpu = 1;
- dlpi_cl_stream_response->cpu_rate = calibrate_local_cpu(dlpi_cl_stream_request->cpu_rate);
- }
-
- message_size = dlpi_cl_stream_request->message_size;
- test_time = dlpi_cl_stream_request->test_length;
-
- send_response();
-
- /* Now it's time to start receiving data on the connection. We will */
- /* first grab the apropriate counters and then start grabbing. */
-
- cpu_start(dlpi_cl_stream_request->measure_cpu);
-
- /* The loop will exit when the timer pops, or if we happen to recv a */
- /* message of less than send_size bytes... */
-
- times_up = 0;
- start_timer(test_time + PAD_TIME);
-
- if (debug) {
- fprintf(where,"recv_dlpi_cl_stream: about to enter inner sanctum.\n");
- fflush(where);
- }
-
- while (!times_up) {
- if((getmsg(data_descriptor,
- &rctl_message,
- &recv_message,
- &flags) != 0) ||
- (data_ind->dl_primitive != DL_UNITDATA_IND)) {
- if (errno == EINTR) {
- /* Again, we have likely hit test-end time */
- break;
- }
- fprintf(where,
- "dlpi_recv_cl_stream: getmsg failure: errno %d primitive 0x%x\n",
- errno,
- data_ind->dl_primitive);
- fflush(where);
- netperf_response.content.serv_errno = 996;
- send_response();
- exit(1);
- }
- messages_recvd++;
- }
-
- if (debug) {
- fprintf(where,"recv_dlpi_cl_stream: got %d messages.\n",messages_recvd);
- fflush(where);
- }
-
-
- /* The loop now exits due timer or < send_size bytes received. */
-
- cpu_stop(dlpi_cl_stream_request->measure_cpu,&elapsed_time);
-
- if (times_up) {
- /* we ended on a timer, subtract the PAD_TIME */
- elapsed_time -= (float)PAD_TIME;
- }
- else {
- stop_timer();
- }
-
- if (debug) {
- fprintf(where,"recv_dlpi_cl_stream: test ended in %f seconds.\n",elapsed_time);
- fflush(where);
- }
-
-
- /* We will count the "off" message */
- bytes_received = (messages_recvd * message_size) + len;
-
- /* send the results to the sender */
-
- if (debug) {
- fprintf(where,
- "recv_dlpi_cl_stream: got %d bytes\n",
- bytes_received);
- fflush(where);
- }
-
- netperf_response.content.response_type = DLPI_CL_STREAM_RESULTS;
- dlpi_cl_stream_results->bytes_received = bytes_received;
- dlpi_cl_stream_results->messages_recvd = messages_recvd;
- dlpi_cl_stream_results->elapsed_time = elapsed_time;
- if (dlpi_cl_stream_request->measure_cpu) {
- dlpi_cl_stream_results->cpu_util = calc_cpu_util(elapsed_time);
- }
- else {
- dlpi_cl_stream_results->cpu_util = -1.0;
- }
-
- if (debug > 1) {
- fprintf(where,
- "recv_dlpi_cl_stream: test complete, sending results.\n");
- fflush(where);
- }
-
- send_response();
-
-}
-
-int send_dlpi_cl_rr(char remote_host[])
-{
-
- char *tput_title = "\
-Local /Remote\n\
-Window Size Request Resp. Elapsed Trans.\n\
-Send Recv Size Size Time Rate \n\
-frames frames bytes bytes secs. per sec \n\n";
-
- char *tput_fmt_0 =
- "%7.2f\n";
-
- char *tput_fmt_1_line_1 = "\
-%-6d %-6d %-6d %-6d %-6.2f %7.2f \n";
- char *tput_fmt_1_line_2 = "\
-%-6d %-6d\n";
-
- char *cpu_title = "\
-Local /Remote\n\
-Window Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\
-Send Recv Size Size Time Rate local remote local remote\n\
-frames frames bytes bytes secs. per sec %% %% us/Tr us/Tr\n\n";
-
- char *cpu_fmt_0 =
- "%6.3f\n";
-
- char *cpu_fmt_1_line_1 = "\
-%-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f\n";
-
- char *cpu_fmt_1_line_2 = "\
-%-6d %-6d\n";
-
- char *ksink_fmt = "\
-Alignment Offset\n\
-Local Remote Local Remote\n\
-Send Recv Send Recv\n\
-%5d %5d %5d %5d\n";
-
-
- float elapsed_time;
-
- int dlsap_len;
- int flags = 0;
- char *send_message_ptr;
- char *recv_message_ptr;
- char *temp_message_ptr;
- char sctl_data[BUFSIZ];
- char rctl_data[BUFSIZ];
- char dlsap[BUFSIZ];
- struct strbuf send_message;
- struct strbuf recv_message;
- struct strbuf sctl_message;
- struct strbuf rctl_message;
-
- /* these are to make reading some of the DLPI control messages easier */
- dl_unitdata_ind_t *data_ind = (dl_unitdata_ind_t *)rctl_data;
- dl_unitdata_req_t *data_req = (dl_unitdata_req_t *)sctl_data;
- dl_uderror_ind_t *uder_ind = (dl_uderror_ind_t *)rctl_data;
-
- int nummessages;
- int send_descriptor;
- int trans_remaining;
- int bytes_xferd;
-
- float local_cpu_utilization;
- float local_service_demand;
- float remote_cpu_utilization;
- float remote_service_demand;
- double thruput;
-
-#ifdef WANT_INTERVALS
- /* timing stuff */
-#define MAX_KEPT_TIMES 1024
- int time_index = 0;
- int unused_buckets;
- int kept_times[MAX_KEPT_TIMES];
- int sleep_usecs;
- unsigned int total_times=0;
- struct timezone dummy_zone;
- struct timeval send_time;
- struct timeval recv_time;
- struct timeval sleep_timeval;
-#endif /* WANT_INTERVALS */
-
- struct dlpi_cl_rr_request_struct *dlpi_cl_rr_request;
- struct dlpi_cl_rr_response_struct *dlpi_cl_rr_response;
- struct dlpi_cl_rr_results_struct *dlpi_cl_rr_result;
-
- dlpi_cl_rr_request =
- (struct dlpi_cl_rr_request_struct *)netperf_request.content.test_specific_data;
- dlpi_cl_rr_response =
- (struct dlpi_cl_rr_response_struct *)netperf_response.content.test_specific_data;
- dlpi_cl_rr_result =
- (struct dlpi_cl_rr_results_struct *)netperf_response.content.test_specific_data;
-
- /* we want to zero out the times, so we can detect unused entries. */
-#ifdef WANT_INTERVALS
- time_index = 0;
- while (time_index < MAX_KEPT_TIMES) {
- kept_times[time_index] = 0;
- time_index += 1;
- }
- time_index = 0;
-#endif /* WANT_INTERVALS */
-
- if (print_headers) {
- fprintf(where,"DLPI CL REQUEST/RESPONSE TEST\n");
- if (local_cpu_usage || remote_cpu_usage)
- fprintf(where,cpu_title,format_units());
- else
- fprintf(where,tput_title,format_units());
- }
-
- /* initialize a few counters */
-
- nummessages = 0;
- bytes_xferd = 0;
- times_up = 0;
-
- /* set-up the data buffer with the requested alignment and offset */
- temp_message_ptr = (char *)malloc(req_size+MAXALIGNMENT+MAXOFFSET);
- if (temp_message_ptr == NULL) {
- printf("malloc(%d) failed!\n", req_size+MAXALIGNMENT+MAXOFFSET);
- exit(1);
- }
- send_message_ptr = (char *)(( (long)temp_message_ptr +
- (long) local_send_align - 1) &
- ~((long) local_send_align - 1));
- send_message_ptr = send_message_ptr + local_send_offset;
- send_message.maxlen = req_size;
- send_message.len = req_size;
- send_message.buf = send_message_ptr;
-
- temp_message_ptr = (char *)malloc(rsp_size+MAXALIGNMENT+MAXOFFSET);
- if (temp_message_ptr == NULL) {
- printf("malloc(%d) failed!\n", rsp_size+MAXALIGNMENT+MAXOFFSET);
- exit(1);
- }
- recv_message_ptr = (char *)(( (long)temp_message_ptr +
- (long) local_recv_align - 1) &
- ~((long) local_recv_align - 1));
- recv_message_ptr = recv_message_ptr + local_recv_offset;
- recv_message.maxlen = rsp_size;
- recv_message.len = 0;
- recv_message.buf = recv_message_ptr;
-
- sctl_message.maxlen = BUFSIZ;
- sctl_message.len = 0;
- sctl_message.buf = sctl_data;
-
- rctl_message.maxlen = BUFSIZ;
- rctl_message.len = 0;
- rctl_message.buf = rctl_data;
-
- /* lets get ourselves a file descriptor */
-
- send_descriptor = dl_open(loc_dlpi_device,loc_ppa);
- if (send_descriptor < 0){
- perror("netperf: send_dlpi_cl_rr: dlpi cl rr send descriptor");
- exit(1);
- }
-
- if (debug) {
- fprintf(where,"send_dlpi_cl_rr: send_descriptor obtained...\n");
- }
-
- /* bind the sap to the descriptor and get the dlsap */
- dlsap_len = BUFSIZ;
- if (dl_bind(send_descriptor,
- dlpi_sap,
- DL_CLDLS,
- dlsap,
- &dlsap_len) != 0) {
- fprintf(where,"send_dlpi_cl_rr: bind failure\n");
- fflush(where);
- exit(1);
- }
-
- /* Modify the local socket size. If the user has not requested that */
- /* the socket buffers be altered, we will try to find-out what their */
- /* values are. If we cannot touch the socket buffer in any way, we */
- /* will set the values to -1 to indicate that. The receive socket */
- /* must have enough space to hold addressing information so += a */
- /* sizeof struct sockaddr_in to it. */
-
- /* this is actually nothing code, and should be replaced with the */
- /* alalagous calls in the STREAM test where the window size is set */
- /* with the HP DLPI Extension. raj 8/94 */
-#ifdef SO_SNDBUF
- if (lsw_size > 0) {
- if (debug > 1) {
- fprintf(where,"netperf: send_dlpi_cl_rr: local window size altered from system default...\n");
- fprintf(where," window: %d\n",lsw_size);
- }
- }
- if (lrw_size > 0) {
- if (debug > 1) {
- fprintf(where,"netperf: send_dlpi_cl_rr: remote window size altered from system default...\n");
- fprintf(where," remote: %d\n",lrw_size);
- }
- }
-
-
- /* Now, we will find-out what the size actually became, and report */
- /* that back to the user. If the call fails, we will just report a -1 */
- /* back to the initiator for the recv buffer size. */
-
- if (debug) {
- fprintf(where,"netperf: send_dlpi_cl_rr: socket sizes determined...\n");
- fprintf(where," send: %d recv: %d\n",lsw_size,lrw_size);
- }
-
-#else /* SO_SNDBUF */
-
- lsw_size = -1;
- lrw_size = -1;
-
-#endif /* SO_SNDBUF */
-
- /* If the user has requested cpu utilization measurements, we must */
- /* calibrate the cpu(s). We will perform this task within the tests */
- /* themselves. If the user has specified the cpu rate, then */
- /* calibrate_local_cpu will return rather quickly as it will have */
- /* nothing to do. If local_cpu_rate is zero, then we will go through */
- /* all the "normal" calibration stuff and return the rate back. If */
- /* there is no idle counter in the kernel idle loop, the */
- /* local_cpu_rate will be set to -1. */
-
- if (local_cpu_usage) {
- local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
- }
-
- /* Tell the remote end to do a listen. The server alters the socket */
- /* paramters on the other side at this point, hence the reason for */
- /* all the values being passed in the setup message. If the user did */
- /* not specify any of the parameters, they will be passed as 0, which */
- /* will indicate to the remote that no changes beyond the system's */
- /* default should be used. Alignment is the exception, it will */
- /* default to 8, which will be no alignment alterations. */
-
- netperf_request.content.request_type = DO_DLPI_CL_RR;
- dlpi_cl_rr_request->recv_win_size = rrw_size;
- dlpi_cl_rr_request->send_win_size = rsw_size;
- dlpi_cl_rr_request->recv_alignment = remote_recv_align;
- dlpi_cl_rr_request->recv_offset = remote_recv_offset;
- dlpi_cl_rr_request->send_alignment = remote_send_align;
- dlpi_cl_rr_request->send_offset = remote_send_offset;
- dlpi_cl_rr_request->request_size = req_size;
- dlpi_cl_rr_request->response_size = rsp_size;
- dlpi_cl_rr_request->measure_cpu = remote_cpu_usage;
- dlpi_cl_rr_request->cpu_rate = remote_cpu_rate;
- dlpi_cl_rr_request->ppa = rem_ppa;
- dlpi_cl_rr_request->sap = dlpi_sap;
- dlpi_cl_rr_request->dev_name_len = strlen(rem_dlpi_device);
- strcpy(dlpi_cl_rr_request->dlpi_device,
- rem_dlpi_device);
-
-#ifdef __alpha
-
- /* ok - even on a DEC box, strings are strings. I din't really want */
- /* to ntohl the words of a string. since I don't want to teach the */
- /* send_ and recv_ _request and _response routines about the types, */
- /* I will put "anti-ntohl" calls here. I imagine that the "pure" */
- /* solution would be to use XDR, but I am still leary of being able */
- /* to find XDR libs on all platforms I want running netperf. raj */
- {
- int *charword;
- int *initword;
- int *lastword;
-
- initword = (int *) dlpi_cl_rr_request->dlpi_device;
- lastword = initword + ((strlen(rem_dlpi_device) + 3) / 4);
-
- for (charword = initword;
- charword < lastword;
- charword++) {
-
- *charword = ntohl(*charword);
- }
- }
-#endif /* __alpha */
-
- if (test_time) {
- dlpi_cl_rr_request->test_length = test_time;
- }
- else {
- dlpi_cl_rr_request->test_length = test_trans * -1;
- }
-
- if (debug > 1) {
- fprintf(where,"netperf: send_dlpi_cl_rr: requesting DLPI CL request/response test\n");
- }
-
- send_request();
-
- /* The response from the remote will contain all of the relevant */
- /* socket parameters for this test type. We will put them back into */
- /* the variables here so they can be displayed if desired. The */
- /* remote will have calibrated CPU if necessary, and will have done */
- /* all the needed set-up we will have calibrated the cpu locally */
- /* before sending the request, and will grab the counter value right */
- /* after the connect returns. The remote will grab the counter right */
- /* after the accept call. This saves the hassle of extra messages */
- /* being sent for the tests. */
-
- recv_response();
-
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote listen done.\n");
- rrw_size = dlpi_cl_rr_response->recv_win_size;
- rsw_size = dlpi_cl_rr_response->send_win_size;
- remote_cpu_usage= dlpi_cl_rr_response->measure_cpu;
- remote_cpu_rate = dlpi_cl_rr_response->cpu_rate;
-
- /* set-up the destination addressing control info */
- data_req->dl_primitive = DL_UNITDATA_REQ;
- bcopy((char *)(dlpi_cl_rr_response->station_addr),
- ((char *)data_req + sizeof(dl_unitdata_req_t)),
- dlpi_cl_rr_response->station_addr_len);
- data_req->dl_dest_addr_offset = sizeof(dl_unitdata_req_t);
- data_req->dl_dest_addr_length = dlpi_cl_rr_response->station_addr_len;
- /* there is a dl_priority structure too, but I am ignoring it for */
- /* the time being. */
- sctl_message.len = sizeof(dl_unitdata_req_t) +
- data_req->dl_dest_addr_length;
- /* famous last words - some DLPI providers get unhappy if the
- priority stuff is not initialized. fix from Nicolas Thomas. */
- data_req->dl_priority.dl_min = DL_QOS_DONT_CARE;
- data_req->dl_priority.dl_max = DL_QOS_DONT_CARE;
-
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- perror("netperf: remote error");
- exit(1);
- }
-
- /* Data Socket set-up is finished. If there were problems, either the */
- /* connect would have failed, or the previous response would have */
- /* indicated a problem. I failed to see the value of the extra */
- /* message after the accept on the remote. If it failed, we'll see it */
- /* here. If it didn't, we might as well start pumping data. */
-
- /* Set-up the test end conditions. For a request/response test, they */
- /* can be either time or transaction based. */
-
- if (test_time) {
- /* The user wanted to end the test after a period of time. */
- times_up = 0;
- trans_remaining = 0;
- start_timer(test_time);
- }
- else {
- /* The tester wanted to send a number of bytes. */
- trans_remaining = test_bytes;
- times_up = 1;
- }
-
- /* The cpu_start routine will grab the current time and possibly */
- /* value of the idle counter for later use in measuring cpu */
- /* utilization and/or service demand and thruput. */
-
- cpu_start(local_cpu_usage);
-
- /* We use an "OR" to control test execution. When the test is */
- /* controlled by time, the byte count check will always return false. */
- /* When the test is controlled by byte count, the time test will */
- /* always return false. When the test is finished, the whole */
- /* expression will go false and we will stop sending data. I think I */
- /* just arbitrarily decrement trans_remaining for the timed test, but */
- /* will not do that just yet... One other question is whether or not */
- /* the send buffer and the receive buffer should be the same buffer. */
- while ((!times_up) || (trans_remaining > 0)) {
- /* send the request */
-#ifdef WANT_INTERVALS
- gettimeofday(&send_time,&dummy_zone);
-#endif /* WANT_INTERVALS */
- if(putmsg(send_descriptor,
- &sctl_message,
- &send_message,
- 0) != 0) {
- if (errno == EINTR) {
- /* We likely hit */
- /* test-end time. */
- break;
- }
- /* there is more we could do here, but it can wait */
- perror("send_dlpi_cl_rr: data send error");
- exit(1);
- }
-
- /* receive the response. at some point, we will need to handle */
- /* sending responses which are greater than the datalink MTU. we */
- /* may also want to add some DLPI error checking, but for now we */
- /* will ignore that and just let errors stop the test with little */
- /* indication of what might actually be wrong. */
-
- if((getmsg(send_descriptor,
- &rctl_message,
- &recv_message,
- &flags) != 0) ||
- (data_ind->dl_primitive != DL_UNITDATA_IND)) {
- if (errno == EINTR) {
- /* Again, we have likely hit test-end time */
- break;
- }
- fprintf(where,
- "send_dlpi_cl_rr: recv error: errno %d primitive 0x%x\n",
- errno,
- data_ind->dl_primitive);
- fflush(where);
- exit(1);
- }
-#ifdef WANT_INTERVALS
- gettimeofday(&recv_time,&dummy_zone);
-
- /* now we do some arithmatic on the two timevals */
- if (recv_time.tv_usec < send_time.tv_usec) {
- /* we wrapped around a second */
- recv_time.tv_usec += 1000000;
- recv_time.tv_sec -= 1;
- }
-
- /* and store it away */
- kept_times[time_index] = (recv_time.tv_sec - send_time.tv_sec) * 1000000;
- kept_times[time_index] += (recv_time.tv_usec - send_time.tv_usec);
-
- /* at this point, we may wish to sleep for some period of */
- /* time, so we see how long that last transaction just took, */
- /* and sleep for the difference of that and the interval. We */
- /* will not sleep if the time would be less than a */
- /* millisecond. */
- if (interval_usecs > 0) {
- sleep_usecs = interval_usecs - kept_times[time_index];
- if (sleep_usecs > 1000) {
- /* we sleep */
- sleep_timeval.tv_sec = sleep_usecs / 1000000;
- sleep_timeval.tv_usec = sleep_usecs % 1000000;
- select(0,
- 0,
- 0,
- 0,
- &sleep_timeval);
- }
- }
-
- /* now up the time index */
- time_index = (time_index +1)%MAX_KEPT_TIMES;
-#endif /* WANT_INTERVALS */
- nummessages++;
- if (trans_remaining) {
- trans_remaining--;
- }
-
- if (debug > 3) {
- fprintf(where,"Transaction %d completed\n",nummessages);
- fflush(where);
- }
-
- }
-
- /* this call will always give us the elapsed time for the test, and */
- /* will also store-away the necessaries for cpu utilization */
-
- cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being measured? */
- /* how long did we really run? */
-
- /* Get the statistics from the remote end. The remote will have */
- /* calculated service demand and all those interesting things. If it */
- /* wasn't supposed to care, it will return obvious values. */
-
- recv_response();
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote results obtained\n");
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- perror("netperf: remote error");
-
- exit(1);
- }
-
- /* We now calculate what our thruput was for the test. In the future, */
- /* we may want to include a calculation of the thruput measured by */
- /* the remote, but it should be the case that for a UDP stream test, */
- /* that the two numbers should be *very* close... We calculate */
- /* bytes_sent regardless of the way the test length was controlled. */
- /* If it was time, we needed to, and if it was by bytes, the user may */
- /* have specified a number of bytes that wasn't a multiple of the */
- /* send_size, so we really didn't send what he asked for ;-) We use */
-
- bytes_xferd = (req_size * nummessages) + (rsp_size * nummessages);
- thruput = calc_thruput(bytes_xferd);
-
- if (local_cpu_usage || remote_cpu_usage) {
- /* We must now do a little math for service demand and cpu */
- /* utilization for the system(s) */
- /* Of course, some of the information might be bogus because */
- /* there was no idle counter in the kernel(s). We need to make */
- /* a note of this for the user's benefit...*/
- if (local_cpu_usage) {
- if (local_cpu_rate == 0.0) {
- fprintf(where,"WARNING WARNING WARNING WARNING WARNING WARNING WARNING!\n");
- fprintf(where,"Local CPU usage numbers based on process information only!\n");
- fflush(where);
- }
- local_cpu_utilization = calc_cpu_util(0.0);
- /* since calc_service demand is doing ms/Kunit we will */
- /* multiply the number of transaction by 1024 to get */
- /* "good" numbers */
- local_service_demand = calc_service_demand((double) nummessages*1024,
- 0.0,
- 0.0,
- 0);
- }
- else {
- local_cpu_utilization = -1.0;
- local_service_demand = -1.0;
- }
-
- if (remote_cpu_usage) {
- if (remote_cpu_rate == 0.0) {
- fprintf(where,"DANGER DANGER DANGER DANGER DANGER DANGER DANGER!\n");
- fprintf(where,"Remote CPU usage numbers based on process information only!\n");
- fflush(where);
- }
- remote_cpu_utilization = dlpi_cl_rr_result->cpu_util;
- /* since calc_service demand is doing ms/Kunit we will */
- /* multiply the number of transaction by 1024 to get */
- /* "good" numbers */
- remote_service_demand = calc_service_demand((double) nummessages*1024,
- 0.0,
- remote_cpu_utilization,
- dlpi_cl_rr_result->num_cpus);
- }
- else {
- remote_cpu_utilization = -1.0;
- remote_service_demand = -1.0;
- }
-
- /* We are now ready to print all the information. If the user */
- /* has specified zero-level verbosity, we will just print the */
- /* local service demand, or the remote service demand. If the */
- /* user has requested verbosity level 1, he will get the basic */
- /* "streamperf" numbers. If the user has specified a verbosity */
- /* of greater than 1, we will display a veritable plethora of */
- /* background information from outside of this block as it it */
- /* not cpu_measurement specific... */
-
- switch (verbosity) {
- case 0:
- if (local_cpu_usage) {
- fprintf(where,
- cpu_fmt_0,
- local_service_demand);
- }
- else {
- fprintf(where,
- cpu_fmt_0,
- remote_service_demand);
- }
- break;
- case 1:
- case 2:
- fprintf(where,
- cpu_fmt_1_line_1, /* the format string */
- lsw_size, /* local sendbuf size */
- lrw_size,
- req_size, /* how large were the requests */
- rsp_size, /* guess */
- elapsed_time, /* how long was the test */
- nummessages/elapsed_time,
- local_cpu_utilization, /* local cpu */
- remote_cpu_utilization, /* remote cpu */
- local_service_demand, /* local service demand */
- remote_service_demand); /* remote service demand */
- fprintf(where,
- cpu_fmt_1_line_2,
- rsw_size,
- rrw_size);
- break;
- }
- }
- else {
- /* The tester did not wish to measure service demand. */
- switch (verbosity) {
- case 0:
- fprintf(where,
- tput_fmt_0,
- nummessages/elapsed_time);
- break;
- case 1:
- case 2:
- fprintf(where,
- tput_fmt_1_line_1, /* the format string */
- lsw_size,
- lrw_size,
- req_size, /* how large were the requests */
- rsp_size, /* how large were the responses */
- elapsed_time, /* how long did it take */
- nummessages/elapsed_time);
- fprintf(where,
- tput_fmt_1_line_2,
- rsw_size, /* remote recvbuf size */
- rrw_size);
-
- break;
- }
- }
-
- /* it would be a good thing to include information about some of the */
- /* other parameters that may have been set for this test, but at the */
- /* moment, I do not wish to figure-out all the formatting, so I will */
- /* just put this comment here to help remind me that it is something */
- /* that should be done at a later time. */
-
- if (verbosity > 1) {
- /* The user wanted to know it all, so we will give it to him. */
- /* This information will include as much as we can find about */
- /* UDP statistics, the alignments of the sends and receives */
- /* and all that sort of rot... */
-
-#ifdef WANT_INTERVALS
- kept_times[MAX_KEPT_TIMES] = 0;
- time_index = 0;
- while (time_index < MAX_KEPT_TIMES) {
- if (kept_times[time_index] > 0) {
- total_times += kept_times[time_index];
- }
- else
- unused_buckets++;
- time_index += 1;
- }
- total_times /= (MAX_KEPT_TIMES-unused_buckets);
- fprintf(where,
- "Average response time %d usecs\n",
- total_times);
-#endif
- }
-}
-
-int
- recv_dlpi_cl_rr()
-{
-
- char *message;
- int data_descriptor;
- int flags = 0;
- int measure_cpu;
-
- char *recv_message_ptr;
- char *send_message_ptr;
- char sctl_data[BUFSIZ];
- char rctl_data[BUFSIZ];
- char dlsap[BUFSIZ];
- struct strbuf send_message;
- struct strbuf recv_message;
- struct strbuf sctl_message;
- struct strbuf rctl_message;
-
- /* these are to make reading some of the DLPI control messages easier */
- dl_unitdata_ind_t *data_ind = (dl_unitdata_ind_t *)rctl_data;
- dl_unitdata_req_t *data_req = (dl_unitdata_req_t *)sctl_data;
- dl_uderror_ind_t *uder_ind = (dl_uderror_ind_t *)rctl_data;
-
- int trans_received;
- int trans_remaining;
- float elapsed_time;
-
- struct dlpi_cl_rr_request_struct *dlpi_cl_rr_request;
- struct dlpi_cl_rr_response_struct *dlpi_cl_rr_response;
- struct dlpi_cl_rr_results_struct *dlpi_cl_rr_results;
-
- dlpi_cl_rr_request =
- (struct dlpi_cl_rr_request_struct *)netperf_request.content.test_specific_data;
- dlpi_cl_rr_response =
- (struct dlpi_cl_rr_response_struct *)netperf_response.content.test_specific_data;
- dlpi_cl_rr_results =
- (struct dlpi_cl_rr_results_struct *)netperf_response.content.test_specific_data;
-
- if (debug) {
- fprintf(where,"netserver: recv_dlpi_cl_rr: entered...\n");
- fflush(where);
- }
-
- /* We want to set-up the listen descriptor with all the desired */
- /* parameters and then let the initiator know that all is ready. If */
- /* socket size defaults are to be used, then the initiator will have */
- /* sent us 0's. If the descriptor sizes cannot be changed, then we will */
- /* send-back what they are. If that information cannot be determined, */
- /* then we send-back -1's for the sizes. If things go wrong for any */
- /* reason, we will drop back ten yards and punt. */
-
- /* If anything goes wrong, we want the remote to know about it. It */
- /* would be best if the error that the remote reports to the user is */
- /* the actual error we encountered, rather than some bogus unexpected */
- /* response type message. */
-
- if (debug) {
- fprintf(where,"recv_dlpi_cl_rr: setting the response type...\n");
- fflush(where);
- }
-
- netperf_response.content.response_type = DLPI_CL_RR_RESPONSE;
-
- if (debug) {
- fprintf(where,"recv_dlpi_cl_rr: the response type is set...\n");
- fflush(where);
- }
-
- /* set-up the data buffer with the requested alignment and offset */
- message = (char *)malloc(DATABUFFERLEN);
- if (message == NULL) {
- printf("malloc(%d) failed!\n", DATABUFFERLEN);
- exit(1);
- }
-
- /* We now alter the message_ptr variables to be at the desired */
- /* alignments with the desired offsets. */
-
- if (debug) {
- fprintf(where,
- "recv_dlpi_cl_rr: requested recv alignment of %d offset %d\n",
- dlpi_cl_rr_request->recv_alignment,
- dlpi_cl_rr_request->recv_offset);
- fprintf(where,
- "recv_dlpi_cl_rr: requested send alignment of %d offset %d\n",
- dlpi_cl_rr_request->send_alignment,
- dlpi_cl_rr_request->send_offset);
- fflush(where);
- }
-
- recv_message_ptr = ALIGN_BUFFER(message, dlpi_cl_rr_request->recv_alignment, dlpi_cl_rr_request->recv_offset);
- recv_message.maxlen = dlpi_cl_rr_request->request_size;
- recv_message.len = 0;
- recv_message.buf = recv_message_ptr;
-
- send_message_ptr = ALIGN_BUFFER(message, dlpi_cl_rr_request->send_alignment, dlpi_cl_rr_request->send_offset);
- send_message.maxlen = dlpi_cl_rr_request->response_size;
- send_message.len = dlpi_cl_rr_request->response_size;
- send_message.buf = send_message_ptr;
-
- sctl_message.maxlen = BUFSIZ;
- sctl_message.len = 0;
- sctl_message.buf = sctl_data;
-
- rctl_message.maxlen = BUFSIZ;
- rctl_message.len = 0;
- rctl_message.buf = rctl_data;
-
- if (debug) {
- fprintf(where,"recv_dlpi_cl_rr: receive alignment and offset set...\n");
- fprintf(where,"recv_dlpi_cl_rr: grabbing a socket...\n");
- fflush(where);
- }
-
-
-#ifdef __alpha
-
- /* ok - even on a DEC box, strings are strings. I din't really want */
- /* to ntohl the words of a string. since I don't want to teach the */
- /* send_ and recv_ _request and _response routines about the types, */
- /* I will put "anti-ntohl" calls here. I imagine that the "pure" */
- /* solution would be to use XDR, but I am still leary of being able */
- /* to find XDR libs on all platforms I want running netperf. raj */
- {
- int *charword;
- int *initword;
- int *lastword;
-
- initword = (int *) dlpi_cl_rr_request->dlpi_device;
- lastword = initword + ((dlpi_cl_rr_request->dev_name_len + 3) / 4);
-
- for (charword = initword;
- charword < lastword;
- charword++) {
-
- *charword = htonl(*charword);
- }
- }
-#endif /* __alpha */
-
- data_descriptor = dl_open(dlpi_cl_rr_request->dlpi_device,
- dlpi_cl_rr_request->ppa);
- if (data_descriptor < 0) {
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
-
-
- /* The initiator may have wished-us to modify the window */
- /* sizes. We should give it a shot. If he didn't ask us to change the */
- /* sizes, we should let him know what sizes were in use at this end. */
- /* If none of this code is compiled-in, then we will tell the */
- /* initiator that we were unable to play with the sizes by */
- /* setting the size in the response to -1. */
-
-#ifdef DL_HP_SET_LOCAL_WIN_REQ
-
- if (dlpi_cl_rr_request->recv_win_size) {
- }
-
- if (dlpi_cl_rr_request->send_win_size) {
- }
-
- /* Now, we will find-out what the sizes actually became, and report */
- /* them back to the user. If the calls fail, we will just report a -1 */
- /* back to the initiator for the buffer size. */
-
-#else /* the system won't let us play with the buffers */
-
- dlpi_cl_rr_response->recv_win_size = -1;
- dlpi_cl_rr_response->send_win_size = -1;
-
-#endif /* DL_HP_SET_LOCAL_WIN_REQ */
-
- /* bind the sap and retrieve the dlsap assigned by the system */
- dlpi_cl_rr_response->station_addr_len = 14; /* arbitrary */
- if (dl_bind(data_descriptor,
- dlpi_cl_rr_request->sap,
- DL_CLDLS,
- (char *)dlpi_cl_rr_response->station_addr,
- &dlpi_cl_rr_response->station_addr_len) != 0) {
- fprintf(where,"send_dlpi_cl_rr: bind failure\n");
- fflush(where);
- exit(1);
- }
-
- netperf_response.content.serv_errno = 0;
-
- /* But wait, there's more. If the initiator wanted cpu measurements, */
- /* then we must call the calibrate routine, which will return the max */
- /* rate back to the initiator. If the CPU was not to be measured, or */
- /* something went wrong with the calibration, we will return a 0.0 to */
- /* the initiator. */
-
- dlpi_cl_rr_response->cpu_rate = 0.0; /* assume no cpu */
- if (dlpi_cl_rr_request->measure_cpu) {
- dlpi_cl_rr_response->measure_cpu = 1;
- dlpi_cl_rr_response->cpu_rate = calibrate_local_cpu(dlpi_cl_rr_request->cpu_rate);
- }
-
- send_response();
-
- /* Now it's time to start receiving data on the connection. We will */
- /* first grab the apropriate counters and then start receiving. */
-
- cpu_start(dlpi_cl_rr_request->measure_cpu);
-
- if (dlpi_cl_rr_request->test_length > 0) {
- times_up = 0;
- trans_remaining = 0;
- start_timer(dlpi_cl_rr_request->test_length + PAD_TIME);
- }
-else {
- times_up = 1;
- trans_remaining = dlpi_cl_rr_request->test_length * -1;
-}
-
- while ((!times_up) || (trans_remaining > 0)) {
-
- /* receive the request from the other side. at some point we need */
- /* to handle "logical" requests and responses which are larger */
- /* than the data link MTU */
-
- if((getmsg(data_descriptor,
- &rctl_message,
- &recv_message,
- &flags) != 0) ||
- (data_ind->dl_primitive != DL_UNITDATA_IND)) {
- if (errno == EINTR) {
- /* Again, we have likely hit test-end time */
- break;
- }
- fprintf(where,
- "dlpi_recv_cl_rr: getmsg failure: errno %d primitive 0x%x\n",
- errno,
- data_ind->dl_primitive);
- fprintf(where,
- " recevied %u transactions\n",
- trans_received);
- fflush(where);
- netperf_response.content.serv_errno = 995;
- send_response();
- exit(1);
- }
-
- /* Now, send the response to the remote. first copy the dlsap */
- /* information from the receive to the sending control message */
-
- data_req->dl_dest_addr_offset = sizeof(dl_unitdata_req_t);
- bcopy((char *)data_ind + data_ind->dl_src_addr_offset,
- (char *)data_req + data_req->dl_dest_addr_offset,
- data_ind->dl_src_addr_length);
- data_req->dl_dest_addr_length = data_ind->dl_src_addr_length;
- data_req->dl_primitive = DL_UNITDATA_REQ;
- /* be sure to initialize the priority fields. fix from Nicholas
- Thomas */
- data_req->dl_priority.dl_min = DL_QOS_DONT_CARE;
- data_req->dl_priority.dl_max = DL_QOS_DONT_CARE;
-
- sctl_message.len = sizeof(dl_unitdata_req_t) +
- data_ind->dl_src_addr_length;
- if(putmsg(data_descriptor,
- &sctl_message,
- &send_message,
- 0) != 0) {
- if (errno == EINTR) {
- /* We likely hit */
- /* test-end time. */
- break;
- }
- /* there is more we could do here, but it can wait */
- fprintf(where,
- "dlpi_recv_cl_rr: putmsg failure: errno %d\n",
- errno);
- fflush(where);
- netperf_response.content.serv_errno = 993;
- send_response();
- exit(1);
- }
-
- trans_received++;
- if (trans_remaining) {
- trans_remaining--;
- }
-
- if (debug) {
- fprintf(where,
- "recv_dlpi_cl_rr: Transaction %d complete.\n",
- trans_received);
- fflush(where);
- }
-
- }
-
-
- /* The loop now exits due to timeout or transaction count being */
- /* reached */
-
- cpu_stop(dlpi_cl_rr_request->measure_cpu,&elapsed_time);
-
- if (times_up) {
- /* we ended the test by time, which was at least 2 seconds */
- /* longer than we wanted to run. so, we want to subtract */
- /* PAD_TIME from the elapsed_time. */
- elapsed_time -= PAD_TIME;
- }
- /* send the results to the sender */
-
- if (debug) {
- fprintf(where,
- "recv_dlpi_cl_rr: got %d transactions\n",
- trans_received);
- fflush(where);
- }
-
- dlpi_cl_rr_results->bytes_received = (trans_received *
- (dlpi_cl_rr_request->request_size +
- dlpi_cl_rr_request->response_size));
- dlpi_cl_rr_results->trans_received = trans_received;
- dlpi_cl_rr_results->elapsed_time = elapsed_time;
- if (dlpi_cl_rr_request->measure_cpu) {
- dlpi_cl_rr_results->cpu_util = calc_cpu_util(elapsed_time);
- }
-
- if (debug) {
- fprintf(where,
- "recv_dlpi_cl_rr: test complete, sending results.\n");
- fflush(where);
- }
-
- send_response();
-
-}
-
-int
- recv_dlpi_co_rr()
-{
-
- char *message;
- SOCKET s_listen,data_descriptor;
-
- int measure_cpu;
-
- int flags = 0;
- char *recv_message_ptr;
- char *send_message_ptr;
- struct strbuf send_message;
- struct strbuf recv_message;
-
- int trans_received;
- int trans_remaining;
- int request_bytes_remaining;
- int timed_out = 0;
- float elapsed_time;
-
- struct dlpi_co_rr_request_struct *dlpi_co_rr_request;
- struct dlpi_co_rr_response_struct *dlpi_co_rr_response;
- struct dlpi_co_rr_results_struct *dlpi_co_rr_results;
-
- dlpi_co_rr_request = (struct dlpi_co_rr_request_struct *)netperf_request.content.test_specific_data;
- dlpi_co_rr_response = (struct dlpi_co_rr_response_struct *)netperf_response.content.test_specific_data;
- dlpi_co_rr_results = (struct dlpi_co_rr_results_struct *)netperf_response.content.test_specific_data;
-
- if (debug) {
- fprintf(where,"netserver: recv_dlpi_co_rr: entered...\n");
- fflush(where);
- }
-
- /* We want to set-up the listen socket with all the desired */
- /* parameters and then let the initiator know that all is ready. If */
- /* socket size defaults are to be used, then the initiator will have */
- /* sent us 0's. If the socket sizes cannot be changed, then we will */
- /* send-back what they are. If that information cannot be determined, */
- /* then we send-back -1's for the sizes. If things go wrong for any */
- /* reason, we will drop back ten yards and punt. */
-
- /* If anything goes wrong, we want the remote to know about it. It */
- /* would be best if the error that the remote reports to the user is */
- /* the actual error we encountered, rather than some bogus unexpected */
- /* response type message. */
-
- if (debug) {
- fprintf(where,"recv_dlpi_co_rr: setting the response type...\n");
- fflush(where);
- }
-
- netperf_response.content.response_type = DLPI_CO_RR_RESPONSE;
-
- if (debug) {
- fprintf(where,"recv_dlpi_co_rr: the response type is set...\n");
- fflush(where);
- }
-
- /* set-up the data buffer with the requested alignment and offset */
- message = (char *)malloc(DATABUFFERLEN);
- if (message == NULL) {
- printf("malloc(%d) failed!\n", DATABUFFERLEN);
- exit(1);
- }
-
- /* We now alter the message_ptr variables to be at the desired */
- /* alignments with the desired offsets. */
-
- if (debug) {
- fprintf(where,
- "recv_dlpi_co_rr: requested recv alignment of %d offset %d\n",
- dlpi_co_rr_request->recv_alignment,
- dlpi_co_rr_request->recv_offset);
- fprintf(where,
- "recv_dlpi_co_rr: requested send alignment of %d offset %d\n",
- dlpi_co_rr_request->send_alignment,
- dlpi_co_rr_request->send_offset);
- fflush(where);
- }
-
- recv_message_ptr = ALIGN_BUFFER(message, dlpi_co_rr_request->recv_alignment, dlpi_co_rr_request->recv_offset);
- recv_message.maxlen = dlpi_co_rr_request->request_size;
- recv_message.len = 0;
- recv_message.buf = recv_message_ptr;
-
- send_message_ptr = ALIGN_BUFFER(message, dlpi_co_rr_request->send_alignment, dlpi_co_rr_request->send_offset);
- send_message.maxlen = dlpi_co_rr_request->response_size;
- send_message.len = dlpi_co_rr_request->response_size;
- send_message.buf = send_message_ptr;
-
- if (debug) {
- fprintf(where,"recv_dlpi_co_rr: receive alignment and offset set...\n");
- fprintf(where,"recv_dlpi_co_rr: send_message.buf %x .len %d .maxlen %d\n",
- send_message.buf,send_message.len,send_message.maxlen);
- fprintf(where,"recv_dlpi_co_rr: recv_message.buf %x .len %d .maxlen %d\n",
- recv_message.buf,recv_message.len,recv_message.maxlen);
- fflush(where);
- }
-
- /* Let's clear-out our sockaddr for the sake of cleanlines. Then we */
- /* can put in OUR values !-) At some point, we may want to nail this */
- /* socket to a particular network-level address, but for now, */
- /* INADDR_ANY should be just fine. */
-
- /* Grab a socket to listen on, and then listen on it. */
-
- if (debug) {
- fprintf(where,"recv_dlpi_co_rr: grabbing a socket...\n");
- fflush(where);
- }
-
- /* lets grab a file descriptor for a particular link */
-
-#ifdef __alpha
-
- /* ok - even on a DEC box, strings are strings. I din't really want */
- /* to ntohl the words of a string. since I don't want to teach the */
- /* send_ and recv_ _request and _response routines about the types, */
- /* I will put "anti-ntohl" calls here. I imagine that the "pure" */
- /* solution would be to use XDR, but I am still leary of being able */
- /* to find XDR libs on all platforms I want running netperf. raj */
- {
- int *charword;
- int *initword;
- int *lastword;
-
- initword = (int *) dlpi_co_rr_request->dlpi_device;
- lastword = initword + ((dlpi_co_rr_request->dev_name_len + 3) / 4);
-
- for (charword = initword;
- charword < lastword;
- charword++) {
-
- *charword = htonl(*charword);
- }
- }
-#endif /* __alpha */
-
- if ((data_descriptor = dl_open(dlpi_co_rr_request->dlpi_device,
- dlpi_co_rr_request->ppa)) < 0) {
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
-
- /* bind the file descriptor to a sap and get the resultant dlsap */
- dlpi_co_rr_response->station_addr_len = 14; /*arbitrary needs fixing */
- if (dl_bind(data_descriptor,
- dlpi_co_rr_request->sap,
- DL_CODLS,
- (char *)dlpi_co_rr_response->station_addr,
- &dlpi_co_rr_response->station_addr_len) != 0) {
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
-
- /* The initiator may have wished-us to modify the socket buffer */
- /* sizes. We should give it a shot. If he didn't ask us to change the */
- /* sizes, we should let him know what sizes were in use at this end. */
- /* If none of this code is compiled-in, then we will tell the */
- /* initiator that we were unable to play with the socket buffer by */
- /* setting the size in the response to -1. */
-
-#ifdef DL_HP_SET_LOCAL_WIN_REQ
-
- if (dlpi_co_rr_request->recv_win_size) {
- /* SMOP */
- }
-
- if (dlpi_co_rr_request->send_win_size) {
- /* SMOP */
- }
-
- /* Now, we will find-out what the sizes actually became, and report */
- /* them back to the user. If the calls fail, we will just report a -1 */
- /* back to the initiator for the buffer size. */
-
-#else /* the system won't let us play with the buffers */
-
- dlpi_co_rr_response->recv_win_size = -1;
- dlpi_co_rr_response->send_win_size = -1;
-
-#endif /* DL_HP_SET_LOCAL_WIN_REQ */
-
- /* we may have been requested to enable the copy avoidance features. */
- /* can we actually do this with DLPI, the world wonders */
-
- if (dlpi_co_rr_request->so_rcvavoid) {
-#ifdef SO_RCV_COPYAVOID
- dlpi_co_rr_response->so_rcvavoid = 0;
-#else
- /* it wasn't compiled in... */
- dlpi_co_rr_response->so_rcvavoid = 0;
-#endif
- }
-
- if (dlpi_co_rr_request->so_sndavoid) {
-#ifdef SO_SND_COPYAVOID
- dlpi_co_rr_response->so_sndavoid = 0;
-#else
- /* it wasn't compiled in... */
- dlpi_co_rr_response->so_sndavoid = 0;
-#endif
- }
-
- netperf_response.content.serv_errno = 0;
-
- /* But wait, there's more. If the initiator wanted cpu measurements, */
- /* then we must call the calibrate routine, which will return the max */
- /* rate back to the initiator. If the CPU was not to be measured, or */
- /* something went wrong with the calibration, we will return a 0.0 to */
- /* the initiator. */
-
- dlpi_co_rr_response->cpu_rate = 0.0; /* assume no cpu */
- if (dlpi_co_rr_request->measure_cpu) {
- dlpi_co_rr_response->measure_cpu = 1;
- dlpi_co_rr_response->cpu_rate = calibrate_local_cpu(dlpi_co_rr_request->cpu_rate);
- }
-
- send_response();
-
- /* accept a connection on this file descriptor. at some point, */
- /* dl_accept will "do the right thing" with the last two parms, but */
- /* for now it ignores them, so we will pass zeros. */
-
- if(dl_accept(data_descriptor, 0, 0) != 0) {
- fprintf(where,
- "recv_dlpi_co_rr: error in accept, errno %d\n",
- errno);
- fflush(where);
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
-
- if (debug) {
- fprintf(where,
- "recv_dlpi_co_rr: accept completes on the data connection.\n");
- fflush(where);
- }
-
- /* Now it's time to start receiving data on the connection. We will */
- /* first grab the apropriate counters and then start grabbing. */
-
- cpu_start(dlpi_co_rr_request->measure_cpu);
-
- /* The loop will exit when the sender does a shutdown, which will */
- /* return a length of zero */
-
- if (dlpi_co_rr_request->test_length > 0) {
- times_up = 0;
- trans_remaining = 0;
- start_timer(dlpi_co_rr_request->test_length + PAD_TIME);
- }
-else {
- times_up = 1;
- trans_remaining = dlpi_co_rr_request->test_length * -1;
-}
-
- while ((!times_up) || (trans_remaining > 0)) {
- request_bytes_remaining = dlpi_co_rr_request->request_size;
-
- /* receive the request from the other side. there needs to be some */
- /* more login in place for handling messages larger than link mtu, */
- /* but that can wait for later */
- while(request_bytes_remaining > 0) {
- if((getmsg(data_descriptor,
- 0,
- &recv_message,
- &flags)) < 0) {
- if (errno == EINTR) {
- /* the timer popped */
- timed_out = 1;
- break;
- }
-
- if (debug) {
- fprintf(where,"failed getmsg call errno %d\n",errno);
- fprintf(where,"recv_message.len %d\n",recv_message.len);
- fprintf(where,"send_message.len %d\n",send_message.len);
- fflush(where);
- }
-
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
- else {
- request_bytes_remaining -= recv_message.len;
- }
- }
-
- if (timed_out) {
- /* we hit the end of the test based on time - lets bail out of */
- /* here now... */
- break;
- }
-
- if (debug) {
- fprintf(where,"recv_message.len %d\n",recv_message.len);
- fprintf(where,"send_message.len %d\n",send_message.len);
- fflush(where);
- }
-
- /* Now, send the response to the remote */
- if((putmsg(data_descriptor,
- 0,
- &send_message,
- 0)) != 0) {
- if (errno == EINTR) {
- /* the test timer has popped */
- timed_out = 1;
- break;
- }
- netperf_response.content.serv_errno = 994;
- send_response();
- exit(1);
- }
-
- trans_received++;
- if (trans_remaining) {
- trans_remaining--;
- }
-
- if (debug) {
- fprintf(where,
- "recv_dlpi_co_rr: Transaction %d complete\n",
- trans_received);
- fflush(where);
- }
- }
-
-
- /* The loop now exits due to timeout or transaction count being */
- /* reached */
-
- cpu_stop(dlpi_co_rr_request->measure_cpu,&elapsed_time);
-
- if (timed_out) {
- /* we ended the test by time, which was at least 2 seconds */
- /* longer than we wanted to run. so, we want to subtract */
- /* PAD_TIME from the elapsed_time. */
- elapsed_time -= PAD_TIME;
- }
- /* send the results to the sender */
-
- if (debug) {
- fprintf(where,
- "recv_dlpi_co_rr: got %d transactions\n",
- trans_received);
- fflush(where);
- }
-
- dlpi_co_rr_results->bytes_received = (trans_received *
- (dlpi_co_rr_request->request_size +
- dlpi_co_rr_request->response_size));
- dlpi_co_rr_results->trans_received = trans_received;
- dlpi_co_rr_results->elapsed_time = elapsed_time;
- if (dlpi_co_rr_request->measure_cpu) {
- dlpi_co_rr_results->cpu_util = calc_cpu_util(elapsed_time);
- }
-
- if (debug) {
- fprintf(where,
- "recv_dlpi_co_rr: test complete, sending results.\n");
- fflush(where);
- }
-
- send_response();
-
-}
-
-/* this routine will display the usage string for the DLPI tests */
-void
- print_dlpi_usage()
-
-{
- fwrite(dlpi_usage, sizeof(char), strlen(dlpi_usage), stdout);
-}
-
-
-/* this routine will scan the command line for DLPI test arguments */
-void
- scan_dlpi_args(int argc, char *argv[])
-{
- extern int optind, opterrs; /* index of first unused arg */
- extern char *optarg; /* pointer to option string */
-
- int c;
-
- char arg1[BUFSIZ], /* argument holders */
- arg2[BUFSIZ];
-
- if (no_control) {
- fprintf(where,
- "The DLPI tests do not know how to run with no control connection\n");
- exit(-1);
- }
-
- /* Go through all the command line arguments and break them */
- /* out. For those options that take two parms, specifying only */
- /* the first will set both to that value. Specifying only the */
- /* second will leave the first untouched. To change only the */
- /* first, use the form first, (see the routine break_args.. */
-
-#define DLPI_ARGS "D:hM:m:p:r:s:W:w:"
-
- while ((c= getopt(argc, argv, DLPI_ARGS)) != EOF) {
- switch (c) {
- case '?':
- case 'h':
- print_dlpi_usage();
- exit(1);
- case 'D':
- /* set the dlpi device file name(s) */
- break_args(optarg,arg1,arg2);
- if (arg1[0])
- strcpy(loc_dlpi_device,arg1);
- if (arg2[0])
- strcpy(rem_dlpi_device,arg2);
- break;
- case 'm':
- /* set the send size */
- send_size = atoi(optarg);
- break;
- case 'M':
- /* set the recv size */
- recv_size = atoi(optarg);
- break;
- case 'p':
- /* set the local/remote ppa */
- break_args(optarg,arg1,arg2);
- if (arg1[0])
- loc_ppa = atoi(arg1);
- if (arg2[0])
- rem_ppa = atoi(arg2);
- break;
- case 'r':
- /* set the request/response sizes */
- break_args(optarg,arg1,arg2);
- if (arg1[0])
- req_size = atoi(arg1);
- if (arg2[0])
- rsp_size = atoi(arg2);
- break;
- case 's':
- /* set the 802.2 sap for the test */
- dlpi_sap = atoi(optarg);
- break;
- case 'w':
- /* set local window sizes */
- break_args(optarg,arg1,arg2);
- if (arg1[0])
- lsw_size = atoi(arg1);
- if (arg2[0])
- lrw_size = atoi(arg2);
- break;
- case 'W':
- /* set remote window sizes */
- break_args(optarg,arg1,arg2);
- if (arg1[0])
- rsw_size = atoi(arg1);
- if (arg2[0])
- rrw_size = atoi(arg2);
- break;
- };
- }
-}
-
-
-#endif /* WANT_DLPI */
diff --git a/nettest_dlpi.h b/nettest_dlpi.h
deleted file mode 100644
index 8169237..0000000
--- a/nettest_dlpi.h
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- Copyright (C) 1993, Hewlett-Packard Company
-*/
-
- /* This file contains the test-specific definitions for netperf's */
- /* DLPI tests */
-
-
-struct dlpi_co_stream_request_struct {
- int recv_win_size;
- int send_win_size;
- int receive_size; /* how many bytes do we want to */
- /* receive at one time? */
- int recv_alignment; /* what is the alignment of the */
- /* receive buffer? */
- int recv_offset; /* and at what offset from that */
- /* alignment? */
- int measure_cpu; /* does the client want server cpu */
- /* utilization measured? */
- float cpu_rate; /* do we know how fast the cpu is */
- /* already? */
- int test_length; /* how long is the test? */
- int so_rcvavoid; /* do we want the remote to avoid */
- /* copies on receives? */
- int so_sndavoid; /* do we want the remote to avoid send copies? */
- int dirty_count; /* how many integers in the receive buffer */
- /* should be made dirty before calling recv? */
- int clean_count; /* how many integers should be read from the */
- /* recv buffer before calling recv? */
- int sap; /* */
- int ppa; /* which device do we wish to use? */
- int dev_name_len; /* the length of the device name string. this */
- /* is used to put it into the proper order on */
- /* @#$% byte-swapped boxes... */
- char dlpi_device[32]; /* the path to the dlpi device */
-};
-
-struct dlpi_co_stream_response_struct {
- int recv_win_size; /* how big does the client want it */
- int send_win_size;
- int receive_size;
- int measure_cpu; /* does the client want server cpu */
- int test_length; /* how long is the test? */
- int data_port_number; /* connect to me here */
- float cpu_rate; /* could we measure */
- int so_rcvavoid; /* could the remote avoid receive copies? */
- int so_sndavoid; /* could the remote avoid send copies? */
- int station_addr_len;
- int station_addr[1];/* what is the station address for the */
- /* specified ppa? */
-};
-
-struct dlpi_co_stream_results_struct {
- int bytes_received; /* ignored initially */
- int recv_calls; /* ignored initially */
- float elapsed_time; /* how long the test ran */
- float cpu_util; /* -1 if not measured */
- float serv_dem; /* -1 if not measured */
- int cpu_method; /* how was CPU util measured? */
- int num_cpus; /* how many CPUs were there? */
-};
-
-struct dlpi_co_rr_request_struct {
- int recv_win_size; /* how big does the client want it */
- int send_win_size;
- int recv_alignment;
- int recv_offset;
- int send_alignment;
- int send_offset;
- int request_size;
- int response_size;
- int measure_cpu; /* does the client want server cpu */
- float cpu_rate; /* do we know how fast the cpu is? */
- int test_length; /* how long is the test? */
- int so_rcvavoid; /* do we want the remote to avoid receive copies? */
- int so_sndavoid; /* do we want the remote to avoid send copies? */
- int ppa; /* which device do we wish to use? */
- int sap; /* which sap should be used? */
- int dev_name_len; /* the length of the device name string. this */
- /* is used to put it into the proper order on */
- /* @#$% byte-swapped boxes... */
- char dlpi_device[32]; /* the path to the dlpi device */
-};
-
-struct dlpi_co_rr_response_struct {
- int recv_win_size; /* how big does the client want it */
- int send_win_size;
- int measure_cpu; /* does the client want server cpu */
- int test_length; /* how long is the test? */
- int data_port_number; /* connect to me here */
- float cpu_rate; /* could we measure */
- int so_rcvavoid; /* could the remote avoid receive copies? */
- int so_sndavoid; /* could the remote avoid send copies? */
- int station_addr_len; /* the length of the station address */
- int station_addr[1]; /* the remote's station address */
-};
-
-struct dlpi_co_rr_results_struct {
- int bytes_received; /* ignored initially */
- int recv_calls; /* ignored initially */
- int trans_received; /* not ignored */
- float elapsed_time; /* how long the test ran */
- float cpu_util; /* -1 if not measured */
- float serv_dem; /* -1 if not measured */
- int cpu_method; /* how was CPU util measured? */
- int num_cpus; /* how many CPUs were there? */
-};
-
-struct dlpi_cl_stream_request_struct {
- int recv_win_size;
- int message_size;
- int recv_alignment;
- int recv_offset;
- int checksum_off;
- int measure_cpu;
- float cpu_rate;
- int test_length;
- int so_rcvavoid; /* do we want the remote to avoid receive copies? */
- int so_sndavoid; /* do we want the remote to avoid send copies? */
- int ppa; /* which device do we wish to use? */
- int sap;
- int dev_name_len; /* the length of the device name string. this */
- /* is used to put it into the proper order on */
- /* @#$% byte-swapped boxes... */
- char dlpi_device[32]; /* the path to the dlpi device */
-};
-
-struct dlpi_cl_stream_response_struct {
- int recv_win_size;
- int send_win_size;
- int measure_cpu;
- int test_length;
- int data_port_number;
- float cpu_rate;
- int so_rcvavoid; /* could the remote avoid receive copies? */
- int so_sndavoid; /* could the remote avoid send copies? */
- int station_addr_len; /* the length of the station address */
- int station_addr[1]; /* the remote's station address */
-};
-
-struct dlpi_cl_stream_results_struct {
- int messages_recvd;
- int bytes_received;
- float elapsed_time;
- float cpu_util;
- int num_cpus;
-};
-
-
-struct dlpi_cl_rr_request_struct {
- int recv_win_size; /* how big does the client want it */
- int send_win_size;
- int recv_alignment;
- int recv_offset;
- int send_alignment;
- int send_offset;
- int request_size;
- int response_size;
- int no_delay;
- int measure_cpu; /* does the client want server cpu */
- float cpu_rate; /* do we know how fast the cpu is? */
- int test_length; /* how long is the test? */
- int so_rcvavoid; /* do we want the remote to avoid receive */
- /* copies? */
- int so_sndavoid; /* do we want the remote to avoid send copies? */
- int ppa; /* which device do we wish to use? */
- int sap; /* which sap? */
- int dev_name_len; /* the length of the device name string. this */
- /* is used to put it into the proper order on */
- /* @#$% byte-swapped boxes... */
- char dlpi_device[32]; /* the path to the dlpi device */
-};
-
-struct dlpi_cl_rr_response_struct {
- int recv_win_size; /* how big does the client want it */
- int send_win_size;
- int no_delay;
- int measure_cpu; /* does the client want server cpu */
- int test_length; /* how long is the test? */
- int data_port_number; /* connect to me here */
- float cpu_rate; /* could we measure */
- int so_rcvavoid; /* could the remote avoid receive copies? */
- int so_sndavoid; /* could the remote avoid send copies? */
- int station_addr_len; /* the length of the station address */
- int station_addr[1]; /* the remote's station address */
-};
-
-struct dlpi_cl_rr_results_struct {
- int bytes_received; /* ignored initially */
- int recv_calls; /* ignored initially */
- int trans_received; /* not ignored */
- float elapsed_time; /* how long the test ran */
- float cpu_util; /* -1 if not measured */
- float serv_dem; /* -1 if not measured */
- int cpu_method; /* how was CPU util measured? */
- int num_cpus; /* how many CPUs were there? */
-};
-
-extern void send_dlpi_co_stream();
-
-extern int recv_dlpi_co_stream();
-
-extern int send_dlpi_co_rr(char remote_host[]);
-
-extern void send_dlpi_cl_stream(char remote_host[]);
-
-extern int recv_dlpi_cl_stream();
-
-extern int send_dlpi_cl_rr(char remote_host[]);
-
-extern int recv_dlpi_cl_rr();
-
-extern int recv_dlpi_co_rr();
-
-extern void scan_dlpi_args(int argc, char *argv[]);
diff --git a/nettest_sctp.c b/nettest_sctp.c
deleted file mode 100644
index 7cfcd9f..0000000
--- a/nettest_sctp.c
+++ /dev/null
@@ -1,4869 +0,0 @@
-#ifndef lint
-char nettest_sctp[]="\
-@(#)nettest_sctp.c (c) Copyright 2005-2007 Hewlett-Packard Co. Version 2.4.3";
-#else
-#define DIRTY
-#define WANT_HISTOGRAM
-#define WANT_INTERVALS
-#endif /* lint */
-
-/****************************************************************/
-/* */
-/* nettest_sctp.c */
-/* */
-/* */
-/* scan_sctp_args() get the sctp command line args */
-/* */
-/* the actual test routines... */
-/* */
-/* send_sctp_stream() perform a sctp stream test */
-/* recv_sctp_stream() */
-/* send_sctp_rr() perform a sctp request/response */
-/* recv_sctp_rr() */
-/* send_sctp_stream_udp() perform a sctp request/response */
-/* recv_sctp_stream_upd() using UDP style API */
-/* send_sctp_rr_udp() perform a sctp request/response */
-/* recv_sctp_rr_upd() using UDP style API */
-/* */
-/* relies on create_data_socket in nettest_bsd.c */
-/****************************************************************/
-
-#if HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#if defined(WANT_SCTP)
-
-#include <sys/types.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <signal.h>
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#ifdef NOSTDLIBH
-#include <malloc.h>
-#else /* NOSTDLIBH */
-#include <stdlib.h>
-#endif /* NOSTDLIBH */
-
-#if !defined(__VMS)
-#include <sys/ipc.h>
-#endif /* !defined(__VMS) */
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <netinet/sctp.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-
-/* would seem that not all sctp.h files define a MSG_EOF, but that
- MSG_EOF can be the same as MSG_FIN so lets work with that
- assumption. initial find by Jon Pedersen. raj 2006-02-01 */
-#ifndef MSG_EOF
-#ifdef MSG_FIN
-#define MSG_EOF MSG_FIN
-#else
-#error Must have either MSG_EOF or MSG_FIN defined
-#endif
-#endif
-
-#include "netlib.h"
-#include "netsh.h"
-/* get some of the functions from nettest_bsd.c */
-#include "nettest_bsd.h"
-#include "nettest_sctp.h"
-
-#ifdef WANT_HISTOGRAM
-#ifdef __sgi
-#include <sys/time.h>
-#endif /* __sgi */
-#include "hist.h"
-#endif /* WANT_HISTOGRAM */
-
-#ifdef WANT_FIRST_BURST
-extern int first_burst_size;
-#endif /* WANT_FIRST_BURST */
-
-
-
-/* these variables are specific to SCTP tests. declare */
-/* them static to make them global only to this file. */
-
-static int
- msg_count = 0, /* number of messages to transmit on association */
- non_block = 0, /* default to blocking sockets */
- num_associations = 1; /* number of associations on the endpoint */
-
-static int confidence_iteration;
-static char local_cpu_method;
-static char remote_cpu_method;
-
-#ifdef WANT_HISTOGRAM
-static struct timeval time_one;
-static struct timeval time_two;
-static HIST time_hist;
-#endif /* WANT_HISTOGRAM */
-
-
-char sctp_usage[] = "\n\
-Usage: netperf [global options] -- [test options] \n\
-\n\
-SCTP Sockets Test Options:\n\
- -b number Send number requests at the start of _RR tests\n\
- -D [L][,R] Set SCTP_NODELAY locally and/or remotely\n\
- -h Display this text\n\
- -H name,fam Use name (or IP) and family as target of data connection\n\
- -L name,fam Use name (or IP) and family as source of data connextion\n\
- -m bytes Set the size of each sent message\n\
- -M bytes Set the size of each received messages\n\
- -P local[,remote] Set the local/remote port for the data socket\n\
- -r req,[rsp] Set request/response sizes (_RR tests)\n\
- -s send[,recv] Set local socket send/recv buffer sizes\n\
- -S send[,recv] Set remote socket send/recv buffer sizes\n\
- -V Enable copy avoidance if supported\n\
- -N number Specifies the number of messages to send (_STREAM tests)\n\
- -B run the test in non-blocking mode\n\
- -T number Number of associations to create (_MANY tests)\n\
- -4 Use AF_INET (eg IPv4) on both ends of the data conn\n\
- -6 Use AF_INET6 (eg IPv6) on both ends of the data conn\n\
-\n\
-For those options taking two parms, at least one must be specified;\n\
-specifying one value without a comma will set both parms to that\n\
-value, specifying a value with a leading comma will set just the second\n\
-parm, a value with a trailing comma will set just the first. To set\n\
-each parm to unique values, specify both and separate them with a\n\
-comma.\n";
-
-
- /* This routine is intended to retrieve interesting aspects of tcp */
- /* for the data connection. at first, it attempts to retrieve the */
- /* maximum segment size. later, it might be modified to retrieve */
- /* other information, but it must be information that can be */
- /* retrieved quickly as it is called during the timing of the test. */
- /* for that reason, a second routine may be created that can be */
- /* called outside of the timing loop */
-static
-void
-get_sctp_info(socket, mss)
- int socket;
- int *mss;
-{
-
- int sock_opt_len;
-
- if (sctp_opt_info(socket,
- 0,
- SCTP_MAXSEG,
- mss,
- &sock_opt_len) < 0) {
- lss_size = -1;
- }
-}
-
-
-static
-void
-sctp_enable_events(socket, ev_mask)
- int socket;
- int ev_mask;
-{
- struct sctp_event_subscribe ev;
-
- bzero(&ev, sizeof(ev));
-
- if (ev_mask & SCTP_SNDRCV_INFO_EV)
- ev.sctp_data_io_event = 1;
-
- if (ev_mask & SCTP_ASSOC_CHANGE_EV)
- ev.sctp_association_event = 1;
-
- if (ev_mask & SCTP_PEERADDR_CHANGE_EV)
- ev.sctp_address_event = 1;
-
- if (ev_mask & SCTP_SND_FAILED_EV)
- ev.sctp_send_failure_event = 1;
-
- if (ev_mask & SCTP_REMOTE_ERROR_EV)
- ev.sctp_peer_error_event = 1;
-
- if (ev_mask & SCTP_SHUTDOWN_EV)
- ev.sctp_shutdown_event = 1;
-
- if (ev_mask & SCTP_PD_EV)
- ev.sctp_partial_delivery_event = 1;
-
- if (ev_mask & SCTP_ADAPT_EV)
-#ifdef HAVE_SCTP_ADAPTATION_LAYER_EVENT
- ev.sctp_adaptation_layer_event = 1;
-#else
- ev.sctp_adaption_layer_event = 1;
-#endif
-
- if (setsockopt(socket,
- IPPROTO_SCTP,
-#ifdef SCTP_EVENTS
- SCTP_EVENTS,
-#else
- SCTP_SET_EVENTS,
-#endif
- (const char*)&ev,
- sizeof(ev)) != 0 ) {
- fprintf(where,
- "sctp_enable_event: could not set sctp events errno %d\n",
- errno);
- fflush(where);
- exit(1);
- }
-}
-
-
-static
-sctp_disposition_t
-sctp_process_event(socket, buf)
- int socket;
- void *buf;
-{
-
- struct sctp_assoc_change *sac;
- struct sctp_send_failed *ssf;
- struct sctp_paddr_change *spc;
- struct sctp_remote_error *sre;
- union sctp_notification *snp;
-
- snp = buf;
-
- switch (snp->sn_header.sn_type) {
- case SCTP_ASSOC_CHANGE:
- if (debug) {
- fprintf(where, "\tSCTP_ASSOC_CHANGE event, type:");
- fflush(where);
- }
- sac = &snp->sn_assoc_change;
- switch (sac->sac_type) {
- case SCTP_COMM_UP:
- if (debug) {
- fprintf(where, " SCTP_COMM_UP\n");
- fflush(where);
- }
- break;
- case SCTP_RESTART:
- if (debug) {
- fprintf(where, " SCTP_RESTART\n");
- fflush(where);
- }
- break;
- case SCTP_CANT_STR_ASSOC:
- if (debug) {
- fprintf(where, " SCTP_CANT_STR_ASSOC\n");
- fflush(where);
- }
- break; /* FIXME ignore above status changes */
- case SCTP_COMM_LOST:
- if (debug) {
- fprintf(where, " SCTP_COMM_LOST\n");
- fflush(where);
- }
- return SCTP_CLOSE;
- case SCTP_SHUTDOWN_COMP:
- if (debug) {
- fprintf(where, " SCTP_SHUTDOWN_COMPLETE\n");
- fflush(where);
- }
- return SCTP_CLOSE;
- break;
- }
-
- case SCTP_SEND_FAILED:
- if (debug) {
- fprintf(where, "\tSCTP_SEND_FAILED event\n");
- fflush(where);
- }
- ssf = &snp->sn_send_failed;
- break; /* FIXME ??? ignore this for now */
-
- case SCTP_PEER_ADDR_CHANGE:
- if (debug) {
- fprintf(where, "\tSCTP_PEER_ADDR_CHANGE event\n");
- fflush(where);
- }
- spc = &snp->sn_paddr_change;
- break; /* FIXME ??? ignore this for now */
-
- case SCTP_REMOTE_ERROR:
- if (debug) {
- fprintf(where, "\tSCTP_REMOTE_ERROR event\n");
- fflush(where);
- }
- sre = &snp->sn_remote_error;
- break; /* FIXME ??? ignore this for now */
- case SCTP_SHUTDOWN_EVENT:
- if (debug) {
- fprintf(where, "\tSCTP_SHUTDOWN event\n");
- fflush(where);
- }
- return SCTP_CLOSE;
- default:
- fprintf(where, "unknown type: %hu\n", snp->sn_header.sn_type);
- fflush(where);
- break;
- }
- return SCTP_OK;
-}
-
-
-
-/* This routine implements the SCTP unidirectional data transfer test */
-/* (a.k.a. stream) for the sockets interface. It receives its */
-/* parameters via global variables from the shell and writes its */
-/* output to the standard output. */
-
-
-void
-send_sctp_stream(remote_host)
-char remote_host[];
-{
-
- char *tput_title = "\
-Recv Send Send \n\
-Socket Socket Message Elapsed \n\
-Size Size Size Time Throughput \n\
-bytes bytes bytes secs. %s/sec \n\n";
-
- char *tput_fmt_0 =
- "%7.2f\n";
-
- char *tput_fmt_1 =
- "%6d %6d %6d %-6.2f %7.2f \n";
-
- char *cpu_title = "\
-Recv Send Send Utilization Service Demand\n\
-Socket Socket Message Elapsed Send Recv Send Recv\n\
-Size Size Size Time Throughput local remote local remote\n\
-bytes bytes bytes secs. %-8.8s/s %% %c %% %c us/KB us/KB\n\n";
-
- char *cpu_fmt_0 =
- "%6.3f %c\n";
-
- char *cpu_fmt_1 =
- "%6d %6d %6d %-6.2f %7.2f %-6.2f %-6.2f %-6.3f %-6.3f\n";
-
- char *ksink_fmt = "\n\
-Alignment Offset %-8.8s %-8.8s Sends %-8.8s Recvs\n\
-Local Remote Local Remote Xfered Per Per\n\
-Send Recv Send Recv Send (avg) Recv (avg)\n\
-%5d %5d %5d %5d %6.4g %6.2f %6d %6.2f %6d\n";
-
- char *ksink_fmt2 = "\n\
-Maximum\n\
-Segment\n\
-Size (bytes)\n\
-%6d\n";
-
-
- float elapsed_time;
-
-#ifdef WANT_INTERVALS
- int interval_count;
- sigset_t signal_set;
-#endif
-
- /* what we want is to have a buffer space that is at least one */
- /* send-size greater than our send window. this will insure that we */
- /* are never trying to re-use a buffer that may still be in the hands */
- /* of the transport. This buffer will be malloc'd after we have found */
- /* the size of the local senc socket buffer. We will want to deal */
- /* with alignment and offset concerns as well. */
-
-#ifdef DIRTY
- int *message_int_ptr;
-#endif
-
- struct ring_elt *send_ring;
-
- int len;
- unsigned int nummessages = 0;
- int send_socket;
- int bytes_remaining;
- int sctp_mss;
- int timed_out;
-
- /* with links like fddi, one can send > 32 bits worth of bytes */
- /* during a test... ;-) at some point, this should probably become a */
- /* 64bit integral type, but those are not entirely common yet */
- double bytes_sent = 0.0;
-
-#ifdef DIRTY
- int i;
-#endif /* DIRTY */
-
- float local_cpu_utilization;
- float local_service_demand;
- float remote_cpu_utilization;
- float remote_service_demand;
-
- double thruput;
-
- struct addrinfo *remote_res;
- struct addrinfo *local_res;
- struct addrinfo *local_remote_res;
- struct addrinfo *local_local_res;
-
- struct sctp_stream_request_struct *sctp_stream_request;
- struct sctp_stream_response_struct *sctp_stream_response;
- struct sctp_stream_results_struct *sctp_stream_result;
-
- sctp_stream_request =
- (struct sctp_stream_request_struct *)netperf_request.content.test_specific_data;
- sctp_stream_response =
- (struct sctp_stream_response_struct *)netperf_response.content.test_specific_data;
- sctp_stream_result =
- (struct sctp_stream_results_struct *)netperf_response.content.test_specific_data;
-
-#ifdef WANT_HISTOGRAM
- time_hist = HIST_new();
-#endif /* WANT_HISTOGRAM */
- /* since we are now disconnected from the code that established the */
- /* control socket, and since we want to be able to use different */
- /* protocols and such, we are passed the name of the remote host and */
- /* must turn that into the test specific addressing information. */
-
- /* complete_addrinfos will either succede or exit the process */
- complete_addrinfos(&remote_res,
- &local_res,
- remote_host,
- SOCK_STREAM,
- IPPROTO_SCTP,
- 0);
-
- if ( print_headers ) {
- print_top_test_header("SCTP STREAM TEST", local_res, remote_res);
- }
-
- send_ring = NULL;
- confidence_iteration = 1;
- init_stat();
-
- /* we have a great-big while loop which controls the number of times */
- /* we run a particular test. this is for the calculation of a */
- /* confidence interval (I really should have stayed awake during */
- /* probstats :). If the user did not request confidence measurement */
- /* (no confidence is the default) then we will only go though the */
- /* loop once. the confidence stuff originates from the folks at IBM */
-
- while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
- (confidence_iteration <= iteration_min)) {
-
- /* initialize a few counters. we have to remember that we might be */
- /* going through the loop more than once. */
-
- nummessages = 0;
- bytes_sent = 0.0;
- times_up = 0;
- timed_out = 0;
-
- /*set up the data socket */
- send_socket = create_data_socket(local_res);
-
- if (send_socket == INVALID_SOCKET){
- perror("netperf: send_sctp_stream: sctp stream data socket");
- exit(1);
- }
-
- if (debug) {
- fprintf(where,"send_sctp_stream: send_socket obtained...\n");
- }
-
- /* at this point, we have either retrieved the socket buffer sizes, */
- /* or have tried to set them, so now, we may want to set the send */
- /* size based on that (because the user either did not use a -m */
- /* option, or used one with an argument of 0). If the socket buffer */
- /* size is not available, we will set the send size to 4KB - no */
- /* particular reason, just arbitrary... */
- if (send_size == 0) {
- if (lss_size > 0) {
- send_size = lss_size;
- }
- else {
- send_size = 4096;
- }
- }
-
- /* set-up the data buffer ring with the requested alignment and offset. */
- /* note also that we have allocated a quantity */
- /* of memory that is at least one send-size greater than our socket */
- /* buffer size. We want to be sure that there are at least two */
- /* buffers allocated - this can be a bit of a problem when the */
- /* send_size is bigger than the socket size, so we must check... the */
- /* user may have wanted to explicitly set the "width" of our send */
- /* buffers, we should respect that wish... */
- if (send_width == 0) {
- send_width = (lss_size/send_size) + 1;
- if (send_width == 1) send_width++;
- }
-
- if (send_ring == NULL) {
- /* only allocate the send ring once. this is a networking test, */
- /* not a memory allocation test. this way, we do not need a */
- /* deallocate_buffer_ring() routine, and I don't feel like */
- /* writing one anyway :) raj 11/94 */
- send_ring = allocate_buffer_ring(send_width,
- send_size,
- local_send_align,
- local_send_offset);
- }
-
- /* If the user has requested cpu utilization measurements, we must */
- /* calibrate the cpu(s). We will perform this task within the tests */
- /* themselves. If the user has specified the cpu rate, then */
- /* calibrate_local_cpu will return rather quickly as it will have */
- /* nothing to do. If local_cpu_rate is zero, then we will go through */
- /* all the "normal" calibration stuff and return the rate back. */
-
- if (local_cpu_usage) {
- local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
- }
-
- /* Tell the remote end to do a listen. The server alters the socket */
- /* paramters on the other side at this point, hence the reason for */
- /* all the values being passed in the setup message. If the user did */
- /* not specify any of the parameters, they will be passed as 0, which */
- /* will indicate to the remote that no changes beyond the system's */
- /* default should be used. Alignment is the exception, it will */
- /* default to 1, which will be no alignment alterations. */
-
- netperf_request.content.request_type = DO_SCTP_STREAM;
- sctp_stream_request->send_buf_size = rss_size_req;
- sctp_stream_request->recv_buf_size = rsr_size_req;
- sctp_stream_request->receive_size = recv_size;
- sctp_stream_request->no_delay = rem_nodelay;
- sctp_stream_request->recv_alignment = remote_recv_align;
- sctp_stream_request->recv_offset = remote_recv_offset;
- sctp_stream_request->measure_cpu = remote_cpu_usage;
- sctp_stream_request->cpu_rate = remote_cpu_rate;
- if (test_time) {
- sctp_stream_request->test_length = test_time;
- }
- else {
- if (msg_count)
- test_bytes = send_size * msg_count;
-
- sctp_stream_request->test_length = test_bytes;
- }
- sctp_stream_request->so_rcvavoid = rem_rcvavoid;
- sctp_stream_request->so_sndavoid = rem_sndavoid;
-#ifdef DIRTY
- sctp_stream_request->dirty_count = rem_dirty_count;
- sctp_stream_request->clean_count = rem_clean_count;
-#endif /* DIRTY */
- sctp_stream_request->port = htonl(atoi(remote_data_port));
- sctp_stream_request->ipfamily = af_to_nf(remote_res->ai_family);
- sctp_stream_request->non_blocking = non_block;
-
-
- if (debug > 1) {
- fprintf(where,
- "netperf: send_sctp_stream: requesting sctp stream test\n");
- }
-
- send_request();
-
- /* The response from the remote will contain all of the relevant */
- /* socket parameters for this test type. We will put them back into */
- /* the variables here so they can be displayed if desired. The */
- /* remote will have calibrated CPU if necessary, and will have done */
- /* all the needed set-up we will have calibrated the cpu locally */
- /* before sending the request, and will grab the counter value right*/
- /* after the connect returns. The remote will grab the counter right*/
- /* after the accept call. This saves the hassle of extra messages */
- /* being sent for the sctp tests. */
-
- recv_response();
-
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote listen done.\n");
- rsr_size = sctp_stream_response->recv_buf_size;
- rss_size = sctp_stream_response->send_buf_size;
- rem_nodelay = sctp_stream_response->no_delay;
- remote_cpu_usage= sctp_stream_response->measure_cpu;
- remote_cpu_rate = sctp_stream_response->cpu_rate;
-
- /* we have to make sure that the server port number is in */
- /* network order */
- set_port_number(remote_res, (short)sctp_stream_response->data_port_number);
-
- rem_rcvavoid = sctp_stream_response->so_rcvavoid;
- rem_sndavoid = sctp_stream_response->so_sndavoid;
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- fprintf(where,
- "netperf: remote error %d",
- netperf_response.content.serv_errno);
- perror("");
- fflush(where);
-
- exit(1);
- }
-
- /*Connect up to the remote port on the data socket */
- if (connect(send_socket,
- remote_res->ai_addr,
- remote_res->ai_addrlen) == INVALID_SOCKET) {
- perror("netperf: send_sctp_stream: data socket connect failed");
- exit(1);
- }
-
- sctp_enable_events(send_socket, SCTP_ASSOC_CHANGE_EV);
-
- if (non_block) {
- /* now that we are connected, mark the socket as non-blocking */
- if (!set_nonblock(send_socket)) {
- perror("netperf: fcntl");
- exit(1);
- }
- }
-
- /* Data Socket set-up is finished. If there were problems, either */
- /* the connect would have failed, or the previous response would */
- /* have indicated a problem. I failed to see the value of the */
- /* extra message after the accept on the remote. If it failed, */
- /* we'll see it here. If it didn't, we might as well start pumping */
- /* data. */
-
- /* Set-up the test end conditions. For a stream test, they can be */
- /* either time or byte-count based. */
-
- if (test_time) {
- /* The user wanted to end the test after a period of time. */
- times_up = 0;
- bytes_remaining = 0;
- /* in previous revisions, we had the same code repeated throught */
- /* all the test suites. this was unnecessary, and meant more */
- /* work for me when I wanted to switch to POSIX signals, so I */
- /* have abstracted this out into a routine in netlib.c. if you */
- /* are experiencing signal problems, you might want to look */
- /* there. raj 11/94 */
- start_timer(test_time);
- }
- else {
- /* The tester wanted to send a number of bytes. */
- bytes_remaining = test_bytes;
- times_up = 1;
- }
-
- /* The cpu_start routine will grab the current time and possibly */
- /* value of the idle counter for later use in measuring cpu */
- /* utilization and/or service demand and thruput. */
-
- cpu_start(local_cpu_usage);
-
-#ifdef WANT_INTERVALS
- if ((interval_burst) || (demo_mode)) {
- /* zero means that we never pause, so we never should need the */
- /* interval timer, unless we are in demo_mode */
- start_itimer(interval_wate);
- }
- interval_count = interval_burst;
- /* get the signal set for the call to sigsuspend */
- if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &signal_set) != 0) {
- fprintf(where,
- "send_sctp_stream: unable to get sigmask errno %d\n",
- errno);
- fflush(where);
- exit(1);
- }
-#endif /* WANT_INTERVALS */
-
-#ifdef DIRTY
- /* initialize the random number generator for putting dirty stuff */
- /* into the send buffer. raj */
- srand((int) getpid());
-#endif
-
- /* before we start, initialize a few variables */
-
- /* We use an "OR" to control test execution. When the test is */
- /* controlled by time, the byte count check will always return false. */
- /* When the test is controlled by byte count, the time test will */
- /* always return false. When the test is finished, the whole */
- /* expression will go false and we will stop sending data. */
-
- while ((!times_up) || (bytes_remaining > 0)) {
-
-#ifdef DIRTY
- /* we want to dirty some number of consecutive integers in the buffer */
- /* we are about to send. we may also want to bring some number of */
- /* them cleanly into the cache. The clean ones will follow any dirty */
- /* ones into the cache. at some point, we might want to replace */
- /* the rand() call with something from a table to reduce our call */
- /* overhead during the test, but it is not a high priority item. */
- message_int_ptr = (int *)(send_ring->buffer_ptr);
- for (i = 0; i < loc_dirty_count; i++) {
- *message_int_ptr = rand();
- message_int_ptr++;
- }
- for (i = 0; i < loc_clean_count; i++) {
- loc_dirty_count = *message_int_ptr;
- message_int_ptr++;
- }
-#endif /* DIRTY */
-
-#ifdef WANT_HISTOGRAM
- /* timestamp just before we go into send and then again just after */
- /* we come out raj 8/94 */
- HIST_timestamp(&time_one);
-#endif /* WANT_HISTOGRAM */
-
- while ((len=sctp_sendmsg(send_socket,
- send_ring->buffer_ptr, send_size,
- NULL, 0,
- 0, 0, 0, 0, 0)) != send_size) {
- if (non_block && errno == EAGAIN)
- continue;
- else if ((len >=0) || SOCKET_EINTR(len)) {
- /* the test was interrupted, must be the end of test */
- timed_out = 1;
- break;
- }
- perror("netperf: data send error");
- printf("len was %d\n",len);
- exit(1);
- }
-
- if (timed_out)
- break; /* we timed out durint sendmsg, done with test */
-
-#ifdef WANT_HISTOGRAM
- /* timestamp the exit from the send call and update the histogram */
- HIST_timestamp(&time_two);
- HIST_add(time_hist,delta_micro(&time_one,&time_two));
-#endif /* WANT_HISTOGRAM */
-
-#ifdef WANT_INTERVALS
- if (demo_mode) {
- units_this_tick += send_size;
- }
- /* in this case, the interval count is the count-down couter */
- /* to decide to sleep for a little bit */
- if ((interval_burst) && (--interval_count == 0)) {
- /* call sigsuspend and wait for the interval timer to get us */
- /* out */
- if (debug > 1) {
- fprintf(where,"about to suspend\n");
- fflush(where);
- }
- if (sigsuspend(&signal_set) == EFAULT) {
- fprintf(where,
- "send_sctp_stream: fault with sigsuspend.\n");
- fflush(where);
- exit(1);
- }
- interval_count = interval_burst;
- }
-#endif /* WANT_INTERVALS */
-
- /* now we want to move our pointer to the next position in the */
- /* data buffer...we may also want to wrap back to the "beginning" */
- /* of the bufferspace, so we will mod the number of messages sent */
- /* by the send width, and use that to calculate the offset to add */
- /* to the base pointer. */
- nummessages++;
- send_ring = send_ring->next;
- if (bytes_remaining) {
- bytes_remaining -= send_size;
- }
- }
-
- /* The test is over. Flush the buffers to the remote end. We do a */
- /* graceful release to insure that all data has been taken by the */
- /* remote. */
-
- /* but first, if the verbosity is greater than 1, find-out what */
- /* the sctp maximum segment_size was (if possible) */
- if (verbosity > 1) {
- sctp_mss = -1;
- get_sctp_info(send_socket, &sctp_mss);
- }
-
- shutdown(send_socket, SHUT_WR);
-
- /* The test server will signal to us when it wants to shutdown.
- * In blocking mode, we can call recvmsg. In non-blocking
- * mode, we need to select on the socket for reading.
- * We'll assume that all returns are succefull
- */
- if (non_block) {
- fd_set readfds;
-
- FD_ZERO(&readfds);
- FD_SET(send_socket, &readfds);
- select(send_socket+1, &readfds, NULL, NULL, NULL);
- } else {
- sctp_recvmsg(send_socket, send_ring->buffer_ptr, send_size, NULL,
- 0, NULL, 0);
- }
-
- /* this call will always give us the elapsed time for the test, and */
- /* will also store-away the necessaries for cpu utilization */
-
- cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */
- /* measured and how */
- /* long did we really */
- /* run? */
-
- /* we are finished with the socket, so close it to prevent hitting */
- /* the limit on maximum open files. */
- close(send_socket);
-
- /* Get the statistics from the remote end. The remote will have */
- /* calculated service demand and all those interesting things. If it */
- /* wasn't supposed to care, it will return obvious values. */
-
- recv_response();
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote results obtained\n");
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- fprintf(where,
- "netperf: remote error %d",
- netperf_response.content.serv_errno);
- perror("");
- fflush(where);
-
- exit(1);
- }
-
- /* We now calculate what our thruput was for the test. In the future, */
- /* we may want to include a calculation of the thruput measured by */
- /* the remote, but it should be the case that for a sctp stream test, */
- /* that the two numbers should be *very* close... We calculate */
- /* bytes_sent regardless of the way the test length was controlled. */
- /* If it was time, we needed to, and if it was by bytes, the user may */
- /* have specified a number of bytes that wasn't a multiple of the */
- /* send_size, so we really didn't send what he asked for ;-) */
-
- bytes_sent = ntohd(sctp_stream_result->bytes_received);
-
- thruput = (double) calc_thruput(bytes_sent);
-
- if (local_cpu_usage || remote_cpu_usage) {
- /* We must now do a little math for service demand and cpu */
- /* utilization for the system(s) */
- /* Of course, some of the information might be bogus because */
- /* there was no idle counter in the kernel(s). We need to make */
- /* a note of this for the user's benefit...*/
- if (local_cpu_usage) {
-
- local_cpu_utilization = calc_cpu_util(0.0);
- local_service_demand = calc_service_demand(bytes_sent,
- 0.0,
- 0.0,
- 0);
- }
- else {
- local_cpu_utilization = (float) -1.0;
- local_service_demand = (float) -1.0;
- }
-
- if (remote_cpu_usage) {
-
- remote_cpu_utilization = sctp_stream_result->cpu_util;
- remote_service_demand = calc_service_demand(bytes_sent,
- 0.0,
- remote_cpu_utilization,
- sctp_stream_result->num_cpus);
- }
- else {
- remote_cpu_utilization = (float) -1.0;
- remote_service_demand = (float) -1.0;
- }
- }
- else {
- /* we were not measuring cpu, for the confidence stuff, we */
- /* should make it -1.0 */
- local_cpu_utilization = (float) -1.0;
- local_service_demand = (float) -1.0;
- remote_cpu_utilization = (float) -1.0;
- remote_service_demand = (float) -1.0;
- }
-
- /* at this point, we want to calculate the confidence information. */
- /* if debugging is on, calculate_confidence will print-out the */
- /* parameters we pass it */
-
- calculate_confidence(confidence_iteration,
- elapsed_time,
- thruput,
- local_cpu_utilization,
- remote_cpu_utilization,
- local_service_demand,
- remote_service_demand);
-
-
- confidence_iteration++;
- }
-
- /* at this point, we have finished making all the runs that we */
- /* will be making. so, we should extract what the calcuated values */
- /* are for all the confidence stuff. we could make the values */
- /* global, but that seemed a little messy, and it did not seem worth */
- /* all the mucking with header files. so, we create a routine much */
- /* like calcualte_confidence, which just returns the mean values. */
- /* raj 11/94 */
-
- retrieve_confident_values(&elapsed_time,
- &thruput,
- &local_cpu_utilization,
- &remote_cpu_utilization,
- &local_service_demand,
- &remote_service_demand);
-
- /* We are now ready to print all the information. If the user */
- /* has specified zero-level verbosity, we will just print the */
- /* local service demand, or the remote service demand. If the */
- /* user has requested verbosity level 1, he will get the basic */
- /* "streamperf" numbers. If the user has specified a verbosity */
- /* of greater than 1, we will display a veritable plethora of */
- /* background information from outside of this block as it it */
- /* not cpu_measurement specific... */
-
- if (confidence < 0) {
- /* we did not hit confidence, but were we asked to look for it? */
- if (iteration_max > 1) {
- display_confidence();
- }
- }
-
- if (local_cpu_usage || remote_cpu_usage) {
- local_cpu_method = format_cpu_method(cpu_method);
- remote_cpu_method = format_cpu_method(sctp_stream_result->cpu_method);
-
- switch (verbosity) {
- case 0:
- if (local_cpu_usage) {
- fprintf(where,
- cpu_fmt_0,
- local_service_demand,
- local_cpu_method);
- }
- else {
- fprintf(where,
- cpu_fmt_0,
- remote_service_demand,
- remote_cpu_method);
- }
- break;
- case 1:
- case 2:
- if (print_headers) {
- fprintf(where,
- cpu_title,
- format_units(),
- local_cpu_method,
- remote_cpu_method);
- }
-
- fprintf(where,
- cpu_fmt_1, /* the format string */
- rsr_size, /* remote recvbuf size */
- lss_size, /* local sendbuf size */
- send_size, /* how large were the sends */
- elapsed_time, /* how long was the test */
- thruput, /* what was the xfer rate */
- local_cpu_utilization, /* local cpu */
- remote_cpu_utilization, /* remote cpu */
- local_service_demand, /* local service demand */
- remote_service_demand); /* remote service demand */
- break;
- }
- }
- else {
- /* The tester did not wish to measure service demand. */
-
- switch (verbosity) {
- case 0:
- fprintf(where,
- tput_fmt_0,
- thruput);
- break;
- case 1:
- case 2:
- if (print_headers) {
- fprintf(where,tput_title,format_units());
- }
- fprintf(where,
- tput_fmt_1, /* the format string */
- rsr_size, /* remote recvbuf size */
- lss_size, /* local sendbuf size */
- send_size, /* how large were the sends */
- elapsed_time, /* how long did it take */
- thruput);/* how fast did it go */
- break;
- }
- }
-
- /* it would be a good thing to include information about some of the */
- /* other parameters that may have been set for this test, but at the */
- /* moment, I do not wish to figure-out all the formatting, so I will */
- /* just put this comment here to help remind me that it is something */
- /* that should be done at a later time. */
-
- if (verbosity > 1) {
- /* The user wanted to know it all, so we will give it to him. */
- /* This information will include as much as we can find about */
- /* sctp statistics, the alignments of the sends and receives */
- /* and all that sort of rot... */
-
- /* this stuff needs to be worked-out in the presence of confidence */
- /* intervals and multiple iterations of the test... raj 11/94 */
-
- fprintf(where,
- ksink_fmt,
- "Bytes",
- "Bytes",
- "Bytes",
- local_send_align,
- remote_recv_align,
- local_send_offset,
- remote_recv_offset,
- bytes_sent,
- bytes_sent / (double)nummessages,
- nummessages,
- bytes_sent / (double)sctp_stream_result->recv_calls,
- sctp_stream_result->recv_calls);
- fprintf(where,
- ksink_fmt2,
- sctp_mss);
- fflush(where);
-#ifdef WANT_HISTOGRAM
- fprintf(where,"\n\nHistogram of time spent in send() call.\n");
- fflush(where);
- HIST_report(time_hist);
-#endif /* WANT_HISTOGRAM */
- }
-
-}
-
-
-
-
-/* This is the server-side routine for the sctp stream test. It is */
-/* implemented as one routine. I could break things-out somewhat, but */
-/* didn't feel it was necessary. */
-
-void
-recv_sctp_stream()
-{
-
- struct sockaddr_in myaddr_in; /* needed to get port number */
- struct sockaddr_storage peeraddr; /* used in accept */
- int s_listen,s_data;
- int addrlen;
- int len;
- unsigned int receive_calls;
- float elapsed_time;
- double bytes_received;
-
- struct ring_elt *recv_ring;
-
- struct addrinfo *local_res;
- char local_name[BUFSIZ];
- char port_buffer[PORTBUFSIZE];
- int msg_flags = 0;
-
-#ifdef DIRTY
- int *message_int_ptr;
- int dirty_count;
- int clean_count;
- int i;
-#endif
-
-#ifdef DO_SELECT
- fd_set readfds;
- struct timeval timeout;
-#endif /* DO_SELECT */
-
- struct sctp_stream_request_struct *sctp_stream_request;
- struct sctp_stream_response_struct *sctp_stream_response;
- struct sctp_stream_results_struct *sctp_stream_results;
-
-#ifdef DO_SELECT
- FD_ZERO(&readfds);
- timeout.tv_sec = 1;
- timeout.tv_usec = 0;
-#endif /* DO_SELECT */
-
- sctp_stream_request =
- (struct sctp_stream_request_struct *)netperf_request.content.test_specific_data;
- sctp_stream_response =
- (struct sctp_stream_response_struct *)netperf_response.content.test_specific_data;
- sctp_stream_results =
- (struct sctp_stream_results_struct *)netperf_response.content.test_specific_data;
-
- if (debug) {
- fprintf(where,"netserver: recv_sctp_stream: entered...\n");
- fflush(where);
- }
-
- /* We want to set-up the listen socket with all the desired */
- /* parameters and then let the initiator know that all is ready. If */
- /* socket size defaults are to be used, then the initiator will have */
- /* sent us 0's. If the socket sizes cannot be changed, then we will */
- /* send-back what they are. If that information cannot be determined, */
- /* then we send-back -1's for the sizes. If things go wrong for any */
- /* reason, we will drop back ten yards and punt. */
-
- /* If anything goes wrong, we want the remote to know about it. It */
- /* would be best if the error that the remote reports to the user is */
- /* the actual error we encountered, rather than some bogus unexpected */
- /* response type message. */
-
- if (debug) {
- fprintf(where,"recv_sctp_stream: setting the response type...\n");
- fflush(where);
- }
-
- netperf_response.content.response_type = SCTP_STREAM_RESPONSE;
-
- if (debug) {
- fprintf(where,"recv_sctp_stream: the response type is set...\n");
- fflush(where);
- }
-
- /* We now alter the message_ptr variable to be at the desired */
- /* alignment with the desired offset. */
-
- if (debug) {
- fprintf(where,"recv_sctp_stream: requested alignment of %d\n",
- sctp_stream_request->recv_alignment);
- fflush(where);
- }
-
- /* create_data_socket expects to find some things in the global */
- /* variables, so set the globals based on the values in the request. */
- /* once the socket has been created, we will set the response values */
- /* based on the updated value of those globals. raj 7/94 */
- lss_size_req = sctp_stream_request->send_buf_size;
- lsr_size_req = sctp_stream_request->recv_buf_size;
- loc_nodelay = sctp_stream_request->no_delay;
- loc_rcvavoid = sctp_stream_request->so_rcvavoid;
- loc_sndavoid = sctp_stream_request->so_sndavoid;
- non_block = sctp_stream_request->non_blocking;
-
- set_hostname_and_port(local_name,
- port_buffer,
- nf_to_af(sctp_stream_request->ipfamily),
- sctp_stream_request->port);
-
- local_res = complete_addrinfo(local_name,
- local_name,
- port_buffer,
- nf_to_af(sctp_stream_request->ipfamily),
- SOCK_STREAM,
- IPPROTO_SCTP,
- 0);
-
- s_listen = create_data_socket(local_res);
-
- if (s_listen < 0) {
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
-
- /* what sort of sizes did we end-up with? */
- if (sctp_stream_request->receive_size == 0) {
- if (lsr_size > 0) {
- recv_size = lsr_size;
- }
- else {
- recv_size = 4096;
- }
- }
- else {
- recv_size = sctp_stream_request->receive_size;
- }
-
- /* we want to set-up our recv_ring in a manner analagous to what we */
- /* do on the sending side. this is more for the sake of symmetry */
- /* than for the needs of say copy avoidance, but it might also be */
- /* more realistic - this way one could conceivably go with a */
- /* double-buffering scheme when taking the data an putting it into */
- /* the filesystem or something like that. raj 7/94 */
-
- if (recv_width == 0) {
- recv_width = (lsr_size/recv_size) + 1;
- if (recv_width == 1) recv_width++;
- }
-
- recv_ring = allocate_buffer_ring(recv_width,
- recv_size,
- sctp_stream_request->recv_alignment,
- sctp_stream_request->recv_offset);
-
- if (debug) {
- fprintf(where,"recv_sctp_stream: set recv_size = %d, align = %d, offset = %d.\n",
- recv_size, sctp_stream_request->recv_alignment,
- sctp_stream_request->recv_offset);
- fflush(where);
- }
-
- /* now get the port number assigned by the system */
- addrlen = sizeof(myaddr_in);
- if (getsockname(s_listen,
- (struct sockaddr *)&myaddr_in,
- &addrlen) == -1){
- netperf_response.content.serv_errno = errno;
- close(s_listen);
- send_response();
-
- exit(1);
- }
-
- /* Now myaddr_in contains the port and the internet address this is */
- /* returned to the sender also implicitly telling the sender that the */
- /* socket buffer sizing has been done. */
-
- sctp_stream_response->data_port_number = (int) ntohs(myaddr_in.sin_port);
- netperf_response.content.serv_errno = 0;
-
- /* But wait, there's more. If the initiator wanted cpu measurements, */
- /* then we must call the calibrate routine, which will return the max */
- /* rate back to the initiator. If the CPU was not to be measured, or */
- /* something went wrong with the calibration, we will return a -1 to */
- /* the initiator. */
-
- sctp_stream_response->cpu_rate = (float)0.0; /* assume no cpu */
- if (sctp_stream_request->measure_cpu) {
- sctp_stream_response->measure_cpu = 1;
- sctp_stream_response->cpu_rate =
- calibrate_local_cpu(sctp_stream_request->cpu_rate);
- }
- else {
- sctp_stream_response->measure_cpu = 0;
- }
-
- /* before we send the response back to the initiator, pull some of */
- /* the socket parms from the globals */
- sctp_stream_response->send_buf_size = lss_size;
- sctp_stream_response->recv_buf_size = lsr_size;
- sctp_stream_response->no_delay = loc_nodelay;
- sctp_stream_response->so_rcvavoid = loc_rcvavoid;
- sctp_stream_response->so_sndavoid = loc_sndavoid;
- sctp_stream_response->receive_size = recv_size;
-
- /* Now, let's set-up the socket to listen for connections */
- if (listen(s_listen, 5) == -1) {
- netperf_response.content.serv_errno = errno;
- close(s_listen);
- send_response();
-
- exit(1);
- }
-
- send_response();
-
- addrlen = sizeof(peeraddr);
-
- if ((s_data = accept(s_listen,
- (struct sockaddr *)&peeraddr,
- &addrlen)) == INVALID_SOCKET) {
- /* Let's just punt. The remote will be given some information */
- close(s_listen);
- exit(1);
- }
-
- sctp_enable_events(s_data, SCTP_ASSOC_CHANGE_EV | SCTP_SHUTDOWN_EV);
-
- /* now that we are connected, mark the socket as non-blocking */
- if (non_block) {
- fprintf(where, "setting socket as nonblocking\n");
- fflush(where);
- if (!set_nonblock(s_data)) {
- close(s_data);
- exit(1);
- }
- }
-
-#ifdef KLUDGE_SOCKET_OPTIONS
- /* this is for those systems which *INCORRECTLY* fail to pass */
- /* attributes across an accept() call. Including this goes against */
- /* my better judgement :( raj 11/95 */
-
- kludge_socket_options(s_data);
-
-#endif /* KLUDGE_SOCKET_OPTIONS */
-
- /* Now it's time to start receiving data on the connection. We will */
- /* first grab the apropriate counters and then start grabbing. */
-
- cpu_start(sctp_stream_request->measure_cpu);
-
- /* The loop will exit when the sender does a shutdown, which will */
- /* return a length of zero */
-
-#ifdef DIRTY
- /* we want to dirty some number of consecutive integers in the buffer */
- /* we are about to recv. we may also want to bring some number of */
- /* them cleanly into the cache. The clean ones will follow any dirty */
- /* ones into the cache. */
-
- dirty_count = sctp_stream_request->dirty_count;
- clean_count = sctp_stream_request->clean_count;
- message_int_ptr = (int *)recv_ring->buffer_ptr;
- for (i = 0; i < dirty_count; i++) {
- *message_int_ptr = rand();
- message_int_ptr++;
- }
- for (i = 0; i < clean_count; i++) {
- dirty_count = *message_int_ptr;
- message_int_ptr++;
- }
-#endif /* DIRTY */
-
- bytes_received = 0;
- receive_calls = 0;
-
- while ((len = sctp_recvmsg(s_data,
- recv_ring->buffer_ptr, recv_size,
- NULL, 0, NULL, &msg_flags)) != 0) {
- if (len == SOCKET_ERROR) {
- if (non_block && errno == EAGAIN) {
- if (debug){
- fprintf(where,
- "recv_sctp_stream: sctp_recvmsg timed out, trying again\n");
- fflush(where);
- }
- Set_errno(0);
- continue;
- }
- if (debug) {
- fprintf(where,
- "recv_sctp_stream: sctp_recvmsg error %d, exiting",
- errno);
- fflush(where);
- }
- netperf_response.content.serv_errno = errno;
- send_response();
- close(s_data);
- exit(1);
- }
-
- if (msg_flags & MSG_NOTIFICATION) {
- msg_flags = 0;
- if (debug) {
- fprintf(where,
- "recv_sctp_stream: Got notification... processing\n");
- fflush(where);
- }
- if (sctp_process_event(s_data, recv_ring->buffer_ptr) == SCTP_CLOSE)
- break; /* break out of the recvmsg loop */
-
- continue;
- }
-
- bytes_received += len;
- receive_calls++;
-
- /* more to the next buffer in the recv_ring */
- recv_ring = recv_ring->next;
-
-#ifdef PAUSE
- sleep(1);
-#endif /* PAUSE */
-
-#ifdef DIRTY
- message_int_ptr = (int *)(recv_ring->buffer_ptr);
- for (i = 0; i < dirty_count; i++) {
- *message_int_ptr = rand();
- message_int_ptr++;
- }
- for (i = 0; i < clean_count; i++) {
- dirty_count = *message_int_ptr;
- message_int_ptr++;
- }
-#endif /* DIRTY */
-
-#ifdef DO_SELECT
- FD_SET(s_data,&readfds);
- select(s_data+1,&readfds,NULL,NULL,&timeout);
-#endif /* DO_SELECT */
-
- }
-
- /* perform a shutdown to signal the sender that */
- /* we have received all the data sent. raj 4/93 */
-
- if (close(s_data) == -1) {
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
-
- cpu_stop(sctp_stream_request->measure_cpu,&elapsed_time);
-
- /* send the results to the sender */
-
- if (debug) {
- fprintf(where,
- "recv_sctp_stream: got %g bytes\n",
- bytes_received);
- fprintf(where,
- "recv_sctp_stream: got %d recvs\n",
- receive_calls);
- fflush(where);
- }
-
- sctp_stream_results->bytes_received = htond(bytes_received);
- sctp_stream_results->elapsed_time = elapsed_time;
- sctp_stream_results->recv_calls = receive_calls;
-
- if (sctp_stream_request->measure_cpu) {
- sctp_stream_results->cpu_util = calc_cpu_util(0.0);
- };
-
- if (debug) {
- fprintf(where,
- "recv_sctp_stream: test complete, sending results.\n");
- fprintf(where,
- " bytes_received %g receive_calls %d\n",
- bytes_received,
- receive_calls);
- fprintf(where,
- " len %d\n",
- len);
- fflush(where);
- }
-
- sctp_stream_results->cpu_method = cpu_method;
- sctp_stream_results->num_cpus = lib_num_loc_cpus;
- send_response();
-
- /* we are now done with the sockets */
- close(s_listen);
-
-}
-
-
-/* This routine implements the SCTP unidirectional data transfer test */
-/* (a.k.a. stream) for the sockets interface. It receives its */
-/* parameters via global variables from the shell and writes its */
-/* output to the standard output. */
-
-
-void
-send_sctp_stream_1toMany(remote_host)
-char remote_host[];
-{
-
- char *tput_title = "\
-Recv Send Send \n\
-Socket Socket Message Elapsed \n\
-Size Size Size Time Throughput \n\
-bytes bytes bytes secs. %s/sec \n\n";
-
- char *tput_fmt_0 =
- "%7.2f\n";
-
- char *tput_fmt_1 =
- "%6d %6d %6d %-6.2f %7.2f \n";
-
- char *cpu_title = "\
-Recv Send Send Utilization Service Demand\n\
-Socket Socket Message Elapsed Send Recv Send Recv\n\
-Size Size Size Time Throughput local remote local remote\n\
-bytes bytes bytes secs. %-8.8s/s %% %c %% %c us/KB us/KB\n\n";
-
- char *cpu_fmt_0 =
- "%6.3f %c\n";
-
- char *cpu_fmt_1 =
- "%6d %6d %6d %-6.2f %7.2f %-6.2f %-6.2f %-6.3f %-6.3f\n";
-
- char *ksink_fmt = "\n\
-Alignment Offset %-8.8s %-8.8s Sends %-8.8s Recvs\n\
-Local Remote Local Remote Xfered Per Per\n\
-Send Recv Send Recv Send (avg) Recv (avg)\n\
-%5d %5d %5d %5d %6.4g %6.2f %6d %6.2f %6d\n";
-
- char *ksink_fmt2 = "\n\
-Maximum\n\
-Segment\n\
-Size (bytes)\n\
-%6d\n";
-
-
- float elapsed_time;
-
-#ifdef WANT_INTERVALS
- int interval_count;
- sigset_t signal_set;
-#endif
-
- /* what we want is to have a buffer space that is at least one */
- /* send-size greater than our send window. this will insure that we */
- /* are never trying to re-use a buffer that may still be in the hands */
- /* of the transport. This buffer will be malloc'd after we have found */
- /* the size of the local senc socket buffer. We will want to deal */
- /* with alignment and offset concerns as well. */
-
-#ifdef DIRTY
- int *message_int_ptr;
-#endif
-
- struct ring_elt *send_ring;
-
- int len;
- unsigned int nummessages = 0;
- int *send_socket;
- int bytes_remaining;
- int sctp_mss;
-
- /* with links like fddi, one can send > 32 bits worth of bytes */
- /* during a test... ;-) at some point, this should probably become a */
- /* 64bit integral type, but those are not entirely common yet */
- double bytes_sent = 0.0;
-
-#ifdef DIRTY
- int i;
-#endif /* DIRTY */
- int j;
-
- float local_cpu_utilization;
- float local_service_demand;
- float remote_cpu_utilization;
- float remote_service_demand;
-
- double thruput;
-
- struct addrinfo *remote_res;
- struct addrinfo *local_res;
- struct addrinfo *last_remote_res;
- struct addrinfo *last_local_res;
-
- struct sctp_stream_request_struct *sctp_stream_request;
- struct sctp_stream_response_struct *sctp_stream_response;
- struct sctp_stream_results_struct *sctp_stream_result;
-
- sctp_stream_request =
- (struct sctp_stream_request_struct *)netperf_request.content.test_specific_data;
- sctp_stream_response =
- (struct sctp_stream_response_struct *)netperf_response.content.test_specific_data;
- sctp_stream_result =
- (struct sctp_stream_results_struct *)netperf_response.content.test_specific_data;
-
-#ifdef WANT_HISTOGRAM
- time_hist = HIST_new();
-#endif /* WANT_HISTOGRAM */
-
- complete_addrinfos(&remote_res,
- &local_res,
- remote_host,
- SOCK_SEQPACKET,
- IPPROTO_SCTP,
- 0);
-
- if ( print_headers ) {
- print_top_test_header("SCTP 1-TO-MANY STREAM TEST",local_res,remote_res);
- }
-
- send_ring = NULL;
- confidence_iteration = 1;
- init_stat();
-
- send_socket = malloc(sizeof (int) * num_associations);
- if (send_socket == NULL) {
- fprintf(where, "send_sctp_stream_1toMany: failed to allocation sockets!\n");
- exit(1);
- }
-
- /* we have a great-big while loop which controls the number of times */
- /* we run a particular test. this is for the calculation of a */
- /* confidence interval (I really should have stayed awake during */
- /* probstats :). If the user did not request confidence measurement */
- /* (no confidence is the default) then we will only go though the */
- /* loop once. the confidence stuff originates from the folks at IBM */
-
- while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
- (confidence_iteration <= iteration_min)) {
-
- int j=0;
- int timed_out = 0;
-
-
- /* initialize a few counters. we have to remember that we might be */
- /* going through the loop more than once. */
-
- nummessages = 0;
- bytes_sent = 0.0;
- times_up = 0;
-
- /* at this point, we have either retrieved the socket buffer sizes, */
- /* or have tried to set them, so now, we may want to set the send */
- /* size based on that (because the user either did not use a -m */
- /* option, or used one with an argument of 0). If the socket buffer */
- /* size is not available, we will set the send size to 4KB - no */
- /* particular reason, just arbitrary... */
- if (send_size == 0) {
- if (lss_size > 0) {
- send_size = lss_size;
- }
- else {
- send_size = 4096;
- }
- }
-
- /* set-up the data buffer ring with the requested alignment and offset. */
- /* note also that we have allocated a quantity */
- /* of memory that is at least one send-size greater than our socket */
- /* buffer size. We want to be sure that there are at least two */
- /* buffers allocated - this can be a bit of a problem when the */
- /* send_size is bigger than the socket size, so we must check... the */
- /* user may have wanted to explicitly set the "width" of our send */
- /* buffers, we should respect that wish... */
- if (send_width == 0) {
- send_width = (lss_size/send_size) + 1;
- if (send_width == 1) send_width++;
- }
-
- if (send_ring == NULL) {
- /* only allocate the send ring once. this is a networking test, */
- /* not a memory allocation test. this way, we do not need a */
- /* deallocate_buffer_ring() routine, and I don't feel like */
- /* writing one anyway :) raj 11/94 */
- send_ring = allocate_buffer_ring(send_width,
- send_size,
- local_send_align,
- local_send_offset);
- }
-
- /* If the user has requested cpu utilization measurements, we must */
- /* calibrate the cpu(s). We will perform this task within the tests */
- /* themselves. If the user has specified the cpu rate, then */
- /* calibrate_local_cpu will return rather quickly as it will have */
- /* nothing to do. If local_cpu_rate is zero, then we will go through */
- /* all the "normal" calibration stuff and return the rate back. */
-
- if (local_cpu_usage) {
- local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
- }
-
- /* Tell the remote end to do a listen. The server alters the socket */
- /* paramters on the other side at this point, hence the reason for */
- /* all the values being passed in the setup message. If the user did */
- /* not specify any of the parameters, they will be passed as 0, which */
- /* will indicate to the remote that no changes beyond the system's */
- /* default should be used. Alignment is the exception, it will */
- /* default to 1, which will be no alignment alterations. */
-
- netperf_request.content.request_type = DO_SCTP_STREAM_MANY;
- sctp_stream_request->send_buf_size = rss_size_req;
- sctp_stream_request->recv_buf_size = rsr_size_req;
- sctp_stream_request->receive_size = recv_size;
- sctp_stream_request->no_delay = rem_nodelay;
- sctp_stream_request->recv_alignment = remote_recv_align;
- sctp_stream_request->recv_offset = remote_recv_offset;
- sctp_stream_request->measure_cpu = remote_cpu_usage;
- sctp_stream_request->cpu_rate = remote_cpu_rate;
- if (test_time) {
- sctp_stream_request->test_length = test_time;
- }
- else {
- if (msg_count)
- test_bytes = send_size * msg_count;
-
- sctp_stream_request->test_length = test_bytes*num_associations;
- }
- sctp_stream_request->so_rcvavoid = rem_rcvavoid;
- sctp_stream_request->so_sndavoid = rem_sndavoid;
-#ifdef DIRTY
- sctp_stream_request->dirty_count = rem_dirty_count;
- sctp_stream_request->clean_count = rem_clean_count;
-#endif /* DIRTY */
- sctp_stream_request->port = (atoi(remote_data_port));
- sctp_stream_request->ipfamily = af_to_nf(remote_res->ai_family);
- sctp_stream_request->non_blocking = non_block;
-
-
- if (debug > 1) {
- fprintf(where,
- "netperf: send_sctp_stream_1toMany: requesting sctp stream test\n");
- }
-
- send_request();
-
- /* The response from the remote will contain all of the relevant */
- /* socket parameters for this test type. We will put them back into */
- /* the variables here so they can be displayed if desired. The */
- /* remote will have calibrated CPU if necessary, and will have done */
- /* all the needed set-up we will have calibrated the cpu locally */
- /* before sending the request, and will grab the counter value right*/
- /* after the connect returns. The remote will grab the counter right*/
- /* after the accept call. This saves the hassle of extra messages */
- /* being sent for the sctp tests. */
-
- recv_response();
-
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote listen done.\n");
- rsr_size = sctp_stream_response->recv_buf_size;
- rss_size = sctp_stream_response->send_buf_size;
- rem_nodelay = sctp_stream_response->no_delay;
- remote_cpu_usage= sctp_stream_response->measure_cpu;
- remote_cpu_rate = sctp_stream_response->cpu_rate;
-
- /* we have to make sure that the server port number is in */
- /* network order */
- set_port_number(remote_res, (unsigned short)sctp_stream_response->data_port_number);
- rem_rcvavoid = sctp_stream_response->so_rcvavoid;
- rem_sndavoid = sctp_stream_response->so_sndavoid;
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- fprintf(where,
- "netperf: remote error %d",
- netperf_response.content.serv_errno);
- perror("");
- fflush(where);
-
- exit(1);
- }
-
- /*set up the the array of data sockets and connect them to the server */
-
- for (j = 0; j < num_associations; j++) {
- send_socket[j] = create_data_socket(local_res);
-
- if (send_socket[j] < 0){
- perror("netperf: send_sctp_stream_1toMany: sctp stream data socket");
- exit(1);
- }
-
- if (debug) {
- fprintf(where,"send_sctp_stream_1toMany: send_socket obtained...\n");
- }
-
- /*Connect up to the remote port on the data socket */
- if (connect(send_socket[j],
- remote_res->ai_addr,
- remote_res->ai_addrlen) == INVALID_SOCKET){
- perror("netperf: send_sctp_stream_1toMany: data socket connect failed");
- exit(1);
- }
-
- /* Do it after connect is successfull, so that we don't see COMM_UP */
- sctp_enable_events(send_socket[j], SCTP_ASSOC_CHANGE_EV);
-
- if (non_block) {
- /* now that we are connected, mark the socket as non-blocking */
- if (!set_nonblock(send_socket[j])) {
- perror("netperf: fcntl");
- exit(1);
- }
- }
- }
-
- /* Data Socket set-up is finished. If there were problems, either */
- /* the connect would have failed, or the previous response would */
- /* have indicated a problem. I failed to see the value of the */
- /* extra message after the accept on the remote. If it failed, */
- /* we'll see it here. If it didn't, we might as well start pumping */
- /* data. */
-
- /* Set-up the test end conditions. For a stream test, they can be */
- /* either time or byte-count based. */
-
- if (test_time) {
- /* The user wanted to end the test after a period of time. */
- times_up = 0;
- bytes_remaining = 0;
- /* in previous revisions, we had the same code repeated throught */
- /* all the test suites. this was unnecessary, and meant more */
- /* work for me when I wanted to switch to POSIX signals, so I */
- /* have abstracted this out into a routine in netlib.c. if you */
- /* are experiencing signal problems, you might want to look */
- /* there. raj 11/94 */
- start_timer(test_time);
- }
- else {
- /* The tester wanted to send a number of bytes. */
- bytes_remaining = test_bytes * num_associations;
- times_up = 1;
- }
-
- /* The cpu_start routine will grab the current time and possibly */
- /* value of the idle counter for later use in measuring cpu */
- /* utilization and/or service demand and thruput. */
-
- cpu_start(local_cpu_usage);
-
-#ifdef WANT_INTERVALS
- if ((interval_burst) || (demo_mode)) {
- /* zero means that we never pause, so we never should need the */
- /* interval timer, unless we are in demo_mode */
- start_itimer(interval_wate);
- }
- interval_count = interval_burst;
- /* get the signal set for the call to sigsuspend */
- if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &signal_set) != 0) {
- fprintf(where,
- "send_sctp_stream_1toMany: unable to get sigmask errno %d\n",
- errno);
- fflush(where);
- exit(1);
- }
-#endif /* WANT_INTERVALS */
-
-#ifdef DIRTY
- /* initialize the random number generator for putting dirty stuff */
- /* into the send buffer. raj */
- srand((int) getpid());
-#endif
-
- /* before we start, initialize a few variables */
-
- /* We use an "OR" to control test execution. When the test is */
- /* controlled by time, the byte count check will always return false. */
- /* When the test is controlled by byte count, the time test will */
- /* always return false. When the test is finished, the whole */
- /* expression will go false and we will stop sending data. */
-
- while ((!times_up) || (bytes_remaining > 0)) {
-
-#ifdef DIRTY
- /* we want to dirty some number of consecutive integers in the buffer */
- /* we are about to send. we may also want to bring some number of */
- /* them cleanly into the cache. The clean ones will follow any dirty */
- /* ones into the cache. at some point, we might want to replace */
- /* the rand() call with something from a table to reduce our call */
- /* overhead during the test, but it is not a high priority item. */
- message_int_ptr = (int *)(send_ring->buffer_ptr);
- for (i = 0; i < loc_dirty_count; i++) {
- *message_int_ptr = rand();
- message_int_ptr++;
- }
- for (i = 0; i < loc_clean_count; i++) {
- loc_dirty_count = *message_int_ptr;
- message_int_ptr++;
- }
-#endif /* DIRTY */
-
-#ifdef WANT_HISTOGRAM
- /* timestamp just before we go into send and then again just after */
- /* we come out raj 8/94 */
- gettimeofday(&time_one,NULL);
-#endif /* WANT_HISTOGRAM */
-
- for (j = 0; j < num_associations; j++) {
-
- if((len=sctp_sendmsg(send_socket[j],
- send_ring->buffer_ptr,
- send_size,
- (struct sockaddr *)remote_res->ai_addr,
- remote_res->ai_addrlen,
- 0, 0, 0, 0, 0)) != send_size) {
- if ((len >=0) || SOCKET_EINTR(len)) {
- /* the test was interrupted, must be the end of test */
- timed_out = 1;
- break;
- } else if (non_block && errno == EAGAIN) {
- j--; /* send again on the same socket */
- Set_errno(0);
- continue;
- }
- perror("netperf: data send error");
- printf("len was %d\n",len);
- exit(1);
- }
- }
-
- if (timed_out)
- break; /* test is over, try next iteration */
-
-#ifdef WANT_HISTOGRAM
- /* timestamp the exit from the send call and update the histogram */
- gettimeofday(&time_two,NULL);
- HIST_add(time_hist,delta_micro(&time_one,&time_two));
-#endif /* WANT_HISTOGRAM */
-
-#ifdef WANT_INTERVALS
- if (demo_mode) {
- units_this_tick += send_size;
- }
- /* in this case, the interval count is the count-down couter */
- /* to decide to sleep for a little bit */
- if ((interval_burst) && (--interval_count == 0)) {
- /* call sigsuspend and wait for the interval timer to get us */
- /* out */
- if (debug > 1) {
- fprintf(where,"about to suspend\n");
- fflush(where);
- }
- if (sigsuspend(&signal_set) == EFAULT) {
- fprintf(where,
- "send_sctp_stream_1toMany: fault with sigsuspend.\n");
- fflush(where);
- exit(1);
- }
- interval_count = interval_burst;
- }
-#endif /* WANT_INTERVALS */
-
- /* now we want to move our pointer to the next position in the */
- /* data buffer...we may also want to wrap back to the "beginning" */
- /* of the bufferspace, so we will mod the number of messages sent */
- /* by the send width, and use that to calculate the offset to add */
- /* to the base pointer. */
- nummessages++;
- send_ring = send_ring->next;
- if (bytes_remaining) {
- bytes_remaining -= send_size;
- }
- }
-
- /* The test is over. Flush the buffers to the remote end. We do a */
- /* graceful release to insure that all data has been taken by the */
- /* remote. */
-
- /* but first, if the verbosity is greater than 1, find-out what */
- /* the sctp maximum segment_size was (if possible) */
- if (verbosity > 1) {
- sctp_mss = -1;
- get_sctp_info(send_socket[0], &sctp_mss);
- }
-
- /* signal the server that we are all done writing, this will
- * initiate a shutdonw of one of the associations on the
- * server and trigger an event telling the server it's all done
- */
- sctp_sendmsg(send_socket[0], NULL, 0, remote_res->ai_addr,
- remote_res->ai_addrlen, 0, MSG_EOF, 0, 0, 0);
-
-
- /* The test server will initiate closure of all associations
- * when it's done reading. We want a basic mechanism to catch this
- * and are using SCTP events for this.
- * In blocking mode, we can call recvmsg with the last socket we created.
- * In non-blocking mode, we need to select on the socket for reading.
- * We'll assume that all returns are succefull and signify
- * closure.
- * It is sufficient to do this on a single socket in the client.
- * We choose to do it on a socket other then the one that send MSG_EOF.
- * This means that anything comming in on that socket will be a shutdown.
- */
- if (non_block) {
- fd_set readfds;
-
- FD_ZERO(&readfds);
- FD_SET(send_socket[num_associations-1], &readfds);
- select(send_socket[num_associations-1]+1, &readfds, NULL, NULL, NULL);
- } else {
- sctp_recvmsg(send_socket[num_associations], send_ring->buffer_ptr,
- send_size, NULL, 0, NULL, 0);
- }
-
- /* this call will always give us the elapsed time for the test, and */
- /* will also store-away the necessaries for cpu utilization */
-
- cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */
- /* measured and how */
- /* long did we really */
- /* run? */
-
- /* we are finished with our sockets, so close them to prevent hitting */
- /* the limit on maximum open files. */
- for (j = 0; j < num_associations; j++)
- close(send_socket[j]);
-
- /* Get the statistics from the remote end. The remote will have */
- /* calculated service demand and all those interesting things. If it */
- /* wasn't supposed to care, it will return obvious values. */
-
- recv_response();
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote results obtained\n");
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- fprintf(where,
- "netperf: remote error %d",
- netperf_response.content.serv_errno);
- perror("");
- fflush(where);
-
- exit(1);
- }
-
- /* We now calculate what our thruput was for the test. In the future, */
- /* we may want to include a calculation of the thruput measured by */
- /* the remote, but it should be the case that for a sctp stream test, */
- /* that the two numbers should be *very* close... We calculate */
- /* bytes_sent regardless of the way the test length was controlled. */
- /* If it was time, we needed to, and if it was by bytes, the user may */
- /* have specified a number of bytes that wasn't a multiple of the */
- /* send_size, so we really didn't send what he asked for ;-) */
-
- bytes_sent = ntohd(sctp_stream_result->bytes_received);
-
- thruput = (double) calc_thruput(bytes_sent);
-
- if (local_cpu_usage || remote_cpu_usage) {
- /* We must now do a little math for service demand and cpu */
- /* utilization for the system(s) */
- /* Of course, some of the information might be bogus because */
- /* there was no idle counter in the kernel(s). We need to make */
- /* a note of this for the user's benefit...*/
- if (local_cpu_usage) {
-
- local_cpu_utilization = calc_cpu_util(0.0);
- local_service_demand = calc_service_demand(bytes_sent,
- 0.0,
- 0.0,
- 0);
- }
- else {
- local_cpu_utilization = (float) -1.0;
- local_service_demand = (float) -1.0;
- }
-
- if (remote_cpu_usage) {
-
- remote_cpu_utilization = sctp_stream_result->cpu_util;
- remote_service_demand = calc_service_demand(bytes_sent,
- 0.0,
- remote_cpu_utilization,
- sctp_stream_result->num_cpus);
- }
- else {
- remote_cpu_utilization = (float) -1.0;
- remote_service_demand = (float) -1.0;
- }
- }
- else {
- /* we were not measuring cpu, for the confidence stuff, we */
- /* should make it -1.0 */
- local_cpu_utilization = (float) -1.0;
- local_service_demand = (float) -1.0;
- remote_cpu_utilization = (float) -1.0;
- remote_service_demand = (float) -1.0;
- }
-
- /* at this point, we want to calculate the confidence information. */
- /* if debugging is on, calculate_confidence will print-out the */
- /* parameters we pass it */
-
- calculate_confidence(confidence_iteration,
- elapsed_time,
- thruput,
- local_cpu_utilization,
- remote_cpu_utilization,
- local_service_demand,
- remote_service_demand);
-
-
- confidence_iteration++;
- }
-
- /* at this point, we have finished making all the runs that we */
- /* will be making. so, we should extract what the calcuated values */
- /* are for all the confidence stuff. we could make the values */
- /* global, but that seemed a little messy, and it did not seem worth */
- /* all the mucking with header files. so, we create a routine much */
- /* like calcualte_confidence, which just returns the mean values. */
- /* raj 11/94 */
-
- retrieve_confident_values(&elapsed_time,
- &thruput,
- &local_cpu_utilization,
- &remote_cpu_utilization,
- &local_service_demand,
- &remote_service_demand);
-
- /* We are now ready to print all the information. If the user */
- /* has specified zero-level verbosity, we will just print the */
- /* local service demand, or the remote service demand. If the */
- /* user has requested verbosity level 1, he will get the basic */
- /* "streamperf" numbers. If the user has specified a verbosity */
- /* of greater than 1, we will display a veritable plethora of */
- /* background information from outside of this block as it it */
- /* not cpu_measurement specific... */
-
- if (confidence < 0) {
- /* we did not hit confidence, but were we asked to look for it? */
- if (iteration_max > 1) {
- display_confidence();
- }
- }
-
- if (local_cpu_usage || remote_cpu_usage) {
- local_cpu_method = format_cpu_method(cpu_method);
- remote_cpu_method = format_cpu_method(sctp_stream_result->cpu_method);
-
- switch (verbosity) {
- case 0:
- if (local_cpu_usage) {
- fprintf(where,
- cpu_fmt_0,
- local_service_demand,
- local_cpu_method);
- }
- else {
- fprintf(where,
- cpu_fmt_0,
- remote_service_demand,
- remote_cpu_method);
- }
- break;
- case 1:
- case 2:
- if (print_headers) {
- fprintf(where,
- cpu_title,
- format_units(),
- local_cpu_method,
- remote_cpu_method);
- }
-
- fprintf(where,
- cpu_fmt_1, /* the format string */
- rsr_size, /* remote recvbuf size */
- lss_size, /* local sendbuf size */
- send_size, /* how large were the sends */
- elapsed_time, /* how long was the test */
- thruput, /* what was the xfer rate */
- local_cpu_utilization, /* local cpu */
- remote_cpu_utilization, /* remote cpu */
- local_service_demand, /* local service demand */
- remote_service_demand); /* remote service demand */
- break;
- }
- }
- else {
- /* The tester did not wish to measure service demand. */
-
- switch (verbosity) {
- case 0:
- fprintf(where,
- tput_fmt_0,
- thruput);
- break;
- case 1:
- case 2:
- if (print_headers) {
- fprintf(where,tput_title,format_units());
- }
- fprintf(where,
- tput_fmt_1, /* the format string */
- rsr_size, /* remote recvbuf size */
- lss_size, /* local sendbuf size */
- send_size, /* how large were the sends */
- elapsed_time, /* how long did it take */
- thruput);/* how fast did it go */
- break;
- }
- }
-
- /* it would be a good thing to include information about some of the */
- /* other parameters that may have been set for this test, but at the */
- /* moment, I do not wish to figure-out all the formatting, so I will */
- /* just put this comment here to help remind me that it is something */
- /* that should be done at a later time. */
-
- if (verbosity > 1) {
- /* The user wanted to know it all, so we will give it to him. */
- /* This information will include as much as we can find about */
- /* sctp statistics, the alignments of the sends and receives */
- /* and all that sort of rot... */
-
- /* this stuff needs to be worked-out in the presence of confidence */
- /* intervals and multiple iterations of the test... raj 11/94 */
-
- fprintf(where,
- ksink_fmt,
- "Bytes",
- "Bytes",
- "Bytes",
- local_send_align,
- remote_recv_align,
- local_send_offset,
- remote_recv_offset,
- bytes_sent,
- bytes_sent / (double)nummessages,
- nummessages,
- bytes_sent / (double)sctp_stream_result->recv_calls,
- sctp_stream_result->recv_calls);
- fprintf(where,
- ksink_fmt2,
- sctp_mss);
- fflush(where);
-#ifdef WANT_HISTOGRAM
- fprintf(where,"\n\nHistogram of time spent in send() call.\n");
- fflush(where);
- HIST_report(time_hist);
-#endif /* WANT_HISTOGRAM */
- }
-
-}
-
-
-
-/* This is the server-side routine for the sctp stream test. It is */
-/* implemented as one routine. I could break things-out somewhat, but */
-/* didn't feel it was necessary. */
-
-void
-recv_sctp_stream_1toMany()
-{
-
- struct sockaddr_in myaddr_in;
- int s_recv;
- int addrlen;
- int len;
- unsigned int receive_calls;
- float elapsed_time;
- double bytes_received;
- int msg_flags = 0;
-
- struct ring_elt *recv_ring;
-
- struct addrinfo *local_res;
- char local_name[BUFSIZ];
- char port_buffer[PORTBUFSIZE];
-
-#ifdef DIRTY
- int *message_int_ptr;
- int dirty_count;
- int clean_count;
- int i;
-#endif
-
-#ifdef DO_SELECT
- fd_set readfds;
- struct timeval timeout;
-#endif
-
- struct sctp_stream_request_struct *sctp_stream_request;
- struct sctp_stream_response_struct *sctp_stream_response;
- struct sctp_stream_results_struct *sctp_stream_results;
-
-#ifdef DO_SELECT
- FD_ZERO(&readfds);
- timeout.tv_sec = 1;
- timeout.tv_usec = 0;
-#endif
-
- sctp_stream_request =
- (struct sctp_stream_request_struct *)netperf_request.content.test_specific_data;
- sctp_stream_response =
- (struct sctp_stream_response_struct *)netperf_response.content.test_specific_data;
- sctp_stream_results =
- (struct sctp_stream_results_struct *)netperf_response.content.test_specific_data;
-
- if (debug) {
- fprintf(where,"netserver: recv_sctp_stream: entered...\n");
- fflush(where);
- }
-
- /* We want to set-up the listen socket with all the desired */
- /* parameters and then let the initiator know that all is ready. If */
- /* socket size defaults are to be used, then the initiator will have */
- /* sent us 0's. If the socket sizes cannot be changed, then we will */
- /* send-back what they are. If that information cannot be determined, */
- /* then we send-back -1's for the sizes. If things go wrong for any */
- /* reason, we will drop back ten yards and punt. */
-
- /* If anything goes wrong, we want the remote to know about it. It */
- /* would be best if the error that the remote reports to the user is */
- /* the actual error we encountered, rather than some bogus unexpected */
- /* response type message. */
-
- if (debug) {
- fprintf(where,"recv_sctp_stream_1toMany: setting the response type...\n");
- fflush(where);
- }
-
- netperf_response.content.response_type = SCTP_STREAM_MANY_RESPONSE;
-
- if (debug) {
- fprintf(where,"recv_sctp_stream_1toMany: the response type is set...\n");
- fflush(where);
- }
-
- /* We now alter the message_ptr variable to be at the desired */
- /* alignment with the desired offset. */
-
- if (debug) {
- fprintf(where,"recv_sctp_stream_1toMany: requested alignment of %d\n",
- sctp_stream_request->recv_alignment);
- fflush(where);
- }
-
- /* create_data_socket expects to find some things in the global */
- /* variables, so set the globals based on the values in the request. */
- /* once the socket has been created, we will set the response values */
- /* based on the updated value of those globals. raj 7/94 */
- lss_size_req = sctp_stream_request->send_buf_size;
- lsr_size_req = sctp_stream_request->recv_buf_size;
- loc_nodelay = sctp_stream_request->no_delay;
- loc_rcvavoid = sctp_stream_request->so_rcvavoid;
- loc_sndavoid = sctp_stream_request->so_sndavoid;
- non_block = sctp_stream_request->non_blocking;
-
- set_hostname_and_port(local_name,
- port_buffer,
- nf_to_af(sctp_stream_request->ipfamily),
- sctp_stream_request->port);
-
- local_res = complete_addrinfo(local_name,
- local_name,
- port_buffer,
- nf_to_af(sctp_stream_request->ipfamily),
- SOCK_SEQPACKET,
- IPPROTO_SCTP,
- 0);
-
- s_recv = create_data_socket(local_res);
-
- if (s_recv < 0) {
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
-
- /* what sort of sizes did we end-up with? */
- if (sctp_stream_request->receive_size == 0) {
- if (lsr_size > 0) {
- recv_size = lsr_size;
- }
- else {
- recv_size = 4096;
- }
- }
- else {
- recv_size = sctp_stream_request->receive_size;
- }
-
- /* we want to set-up our recv_ring in a manner analagous to what we */
- /* do on the sending side. this is more for the sake of symmetry */
- /* than for the needs of say copy avoidance, but it might also be */
- /* more realistic - this way one could conceivably go with a */
- /* double-buffering scheme when taking the data an putting it into */
- /* the filesystem or something like that. raj 7/94 */
-
- if (recv_width == 0) {
- recv_width = (lsr_size/recv_size) + 1;
- if (recv_width == 1) recv_width++;
- }
-
- recv_ring = allocate_buffer_ring(recv_width,
- recv_size,
- sctp_stream_request->recv_alignment,
- sctp_stream_request->recv_offset);
-
- if (debug) {
- fprintf(where,"recv_sctp_stream: receive alignment and offset set...\n");
- fflush(where);
- }
-
- /* Now, let's set-up the socket to listen for connections */
- if (listen(s_recv, 5) == -1) {
- netperf_response.content.serv_errno = errno;
- close(s_recv);
- send_response();
-
- exit(1);
- }
-
- /* now get the port number assigned by the system */
- addrlen = sizeof(myaddr_in);
- if (getsockname(s_recv,
- (struct sockaddr *)&myaddr_in,
- &addrlen) == -1){
- netperf_response.content.serv_errno = errno;
- close(s_recv);
- send_response();
-
- exit(1);
- }
-
- /* Now myaddr_in contains the port and the internet address this is */
- /* returned to the sender also implicitly telling the sender that the */
- /* socket buffer sizing has been done. */
-
- sctp_stream_response->data_port_number = (int) ntohs(myaddr_in.sin_port);
- netperf_response.content.serv_errno = 0;
-
- /* But wait, there's more. If the initiator wanted cpu measurements, */
- /* then we must call the calibrate routine, which will return the max */
- /* rate back to the initiator. If the CPU was not to be measured, or */
- /* something went wrong with the calibration, we will return a -1 to */
- /* the initiator. */
-
- sctp_stream_response->cpu_rate = (float)0.0; /* assume no cpu */
- if (sctp_stream_request->measure_cpu) {
- sctp_stream_response->measure_cpu = 1;
- sctp_stream_response->cpu_rate =
- calibrate_local_cpu(sctp_stream_request->cpu_rate);
- }
- else {
- sctp_stream_response->measure_cpu = 0;
- }
-
- /* before we send the response back to the initiator, pull some of */
- /* the socket parms from the globals */
- sctp_stream_response->send_buf_size = lss_size;
- sctp_stream_response->recv_buf_size = lsr_size;
- sctp_stream_response->no_delay = loc_nodelay;
- sctp_stream_response->so_rcvavoid = loc_rcvavoid;
- sctp_stream_response->so_sndavoid = loc_sndavoid;
- sctp_stream_response->receive_size = recv_size;
-
- send_response();
-
-
- sctp_enable_events(s_recv, SCTP_ASSOC_CHANGE_EV | SCTP_SHUTDOWN_EV);
-
- /* now that we are connected, mark the socket as non-blocking */
- if (non_block) {
- if (!set_nonblock(s_recv)) {
- close(s_recv);
- exit(1);
- }
- }
-
-
- /* Now it's time to start receiving data on the connection. We will */
- /* first grab the apropriate counters and then start grabbing. */
-
- cpu_start(sctp_stream_request->measure_cpu);
-
- /* The loop will exit when the sender does a shutdown, which will */
- /* return a length of zero */
-
-#ifdef DIRTY
- /* we want to dirty some number of consecutive integers in the buffer */
- /* we are about to recv. we may also want to bring some number of */
- /* them cleanly into the cache. The clean ones will follow any dirty */
- /* ones into the cache. */
-
- dirty_count = sctp_stream_request->dirty_count;
- clean_count = sctp_stream_request->clean_count;
- message_int_ptr = (int *)recv_ring->buffer_ptr;
- for (i = 0; i < dirty_count; i++) {
- *message_int_ptr = rand();
- message_int_ptr++;
- }
- for (i = 0; i < clean_count; i++) {
- dirty_count = *message_int_ptr;
- message_int_ptr++;
- }
-#endif /* DIRTY */
-
- bytes_received = 0;
- receive_calls = 0;
-
- while ((len = sctp_recvmsg(s_recv, recv_ring->buffer_ptr, recv_size,
- NULL, 0, /* we don't care who it's from */
- NULL, &msg_flags)) != 0) {
- if (len < 0) {
- if (non_block && errno == EAGAIN) {
- Set_errno(0);
- continue;
- }
- netperf_response.content.serv_errno = errno;
- send_response();
- close(s_recv);
- exit(1);
- }
-
- if (msg_flags & MSG_NOTIFICATION) {
- if (sctp_process_event(s_recv, recv_ring->buffer_ptr) == SCTP_CLOSE)
- break;
-
- continue;
- }
-
- bytes_received += len;
- receive_calls++;
-
- /* more to the next buffer in the recv_ring */
- recv_ring = recv_ring->next;
-
-#ifdef PAUSE
- sleep(1);
-#endif /* PAUSE */
-
-#ifdef DIRTY
- message_int_ptr = (int *)(recv_ring->buffer_ptr);
- for (i = 0; i < dirty_count; i++) {
- *message_int_ptr = rand();
- message_int_ptr++;
- }
- for (i = 0; i < clean_count; i++) {
- dirty_count = *message_int_ptr;
- message_int_ptr++;
- }
-#endif /* DIRTY */
-
-#ifdef DO_SELECT
- FD_SET(s_recv,&readfds);
- select(s_recv+1,&readfds,NULL,NULL,&timeout);
-#endif /* DO_SELECT */
-
- }
-
- /* perform a shutdown to signal the sender. in this case, sctp
- * will close all associations on this socket
- */
- if (close(s_recv) == -1) {
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
-
- cpu_stop(sctp_stream_request->measure_cpu,&elapsed_time);
-
- /* send the results to the sender */
-
- if (debug) {
- fprintf(where,
- "recv_sctp_stream: got %g bytes\n",
- bytes_received);
- fprintf(where,
- "recv_sctp_stream: got %d recvs\n",
- receive_calls);
- fflush(where);
- }
-
- sctp_stream_results->bytes_received = htond(bytes_received);
- sctp_stream_results->elapsed_time = elapsed_time;
- sctp_stream_results->recv_calls = receive_calls;
-
- if (sctp_stream_request->measure_cpu) {
- sctp_stream_results->cpu_util = calc_cpu_util(0.0);
- };
-
- if (debug) {
- fprintf(where,
- "recv_sctp_stream: test complete, sending results.\n");
- fprintf(where,
- " bytes_received %g receive_calls %d\n",
- bytes_received,
- receive_calls);
- fprintf(where,
- " len %d\n",
- len);
- fflush(where);
- }
-
- sctp_stream_results->cpu_method = cpu_method;
- sctp_stream_results->num_cpus = lib_num_loc_cpus;
- send_response();
-}
-
-
- /* this routine implements the sending (netperf) side of the SCTP_RR */
- /* test. */
-
-void
-send_sctp_rr(remote_host)
- char remote_host[];
-{
-
- char *tput_title = "\
-Local /Remote\n\
-Socket Size Request Resp. Elapsed Trans.\n\
-Send Recv Size Size Time Rate \n\
-bytes Bytes bytes bytes secs. per sec \n\n";
-
- char *tput_fmt_0 =
- "%7.2f\n";
-
- char *tput_fmt_1_line_1 = "\
-%-6d %-6d %-6d %-6d %-6.2f %7.2f \n";
- char *tput_fmt_1_line_2 = "\
-%-6d %-6d\n";
-
- char *cpu_title = "\
-Local /Remote\n\
-Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\
-Send Recv Size Size Time Rate local remote local remote\n\
-bytes bytes bytes bytes secs. per sec %% %c %% %c us/Tr us/Tr\n\n";
-
- char *cpu_fmt_0 =
- "%6.3f %c\n";
-
- char *cpu_fmt_1_line_1 = "\
-%-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f\n";
-
- char *cpu_fmt_1_line_2 = "\
-%-6d %-6d\n";
-
- char *ksink_fmt = "\
-Alignment Offset\n\
-Local Remote Local Remote\n\
-Send Recv Send Recv\n\
-%5d %5d %5d %5d\n";
-
-
- int timed_out = 0;
- float elapsed_time;
-
- int len;
- char *temp_message_ptr;
- int nummessages;
- int send_socket;
- int trans_remaining;
- int msg_flags = 0;
- double bytes_xferd;
-
- struct ring_elt *send_ring;
- struct ring_elt *recv_ring;
-
- int rsp_bytes_left;
- int rsp_bytes_recvd;
-
- float local_cpu_utilization;
- float local_service_demand;
- float remote_cpu_utilization;
- float remote_service_demand;
- double thruput;
-
- struct sockaddr_storage peer;
- struct addrinfo *remote_res;
- struct addrinfo *local_res;
-
- struct sctp_rr_request_struct *sctp_rr_request;
- struct sctp_rr_response_struct *sctp_rr_response;
- struct sctp_rr_results_struct *sctp_rr_result;
-
-#ifdef WANT_INTERVALS
- int interval_count;
- sigset_t signal_set;
-#endif /* WANT_INTERVALS */
-
- sctp_rr_request =
- (struct sctp_rr_request_struct *)netperf_request.content.test_specific_data;
- sctp_rr_response =
- (struct sctp_rr_response_struct *)netperf_response.content.test_specific_data;
- sctp_rr_result =
- (struct sctp_rr_results_struct *)netperf_response.content.test_specific_data;
-
-#ifdef WANT_HISTOGRAM
- time_hist = HIST_new();
-#endif /* WANT_HISTOGRAM */
-
- /* since we are now disconnected from the code that established the */
- /* control socket, and since we want to be able to use different */
- /* protocols and such, we are passed the name of the remote host and */
- /* must turn that into the test specific addressing information. */
-
- /* complete_addrinfos will either succede or exit the process */
- complete_addrinfos(&remote_res,
- &local_res,
- remote_host,
- SOCK_STREAM,
- IPPROTO_SCTP,
- 0);
-
- if ( print_headers ) {
- print_top_test_header("SCTP REQUEST/RESPONSE TEST", local_res, remote_res);
- }
-
- /* initialize a few counters */
-
- send_ring = NULL;
- recv_ring = NULL;
- confidence_iteration = 1;
- init_stat();
-
- /* we have a great-big while loop which controls the number of times */
- /* we run a particular test. this is for the calculation of a */
- /* confidence interval (I really should have stayed awake during */
- /* probstats :). If the user did not request confidence measurement */
- /* (no confidence is the default) then we will only go though the */
- /* loop once. the confidence stuff originates from the folks at IBM */
-
- while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
- (confidence_iteration <= iteration_min)) {
-
- /* initialize a few counters. we have to remember that we might be */
- /* going through the loop more than once. */
-
- nummessages = 0;
- bytes_xferd = 0.0;
- times_up = 0;
- timed_out = 0;
- trans_remaining = 0;
-
- /* set-up the data buffers with the requested alignment and offset. */
- /* since this is a request/response test, default the send_width and */
- /* recv_width to 1 and not two raj 7/94 */
-
- if (send_width == 0) send_width = 1;
- if (recv_width == 0) recv_width = 1;
-
- if (send_ring == NULL) {
- send_ring = allocate_buffer_ring(send_width,
- req_size,
- local_send_align,
- local_send_offset);
- }
-
- if (recv_ring == NULL) {
- recv_ring = allocate_buffer_ring(recv_width,
- rsp_size,
- local_recv_align,
- local_recv_offset);
- }
-
- /*set up the data socket */
- send_socket = create_data_socket(local_res);
-
- if (send_socket < 0){
- perror("netperf: send_sctp_rr: sctp stream data socket");
- exit(1);
- }
-
- if (debug) {
- fprintf(where,"send_sctp_rr: send_socket obtained...\n");
- }
-
- /* If the user has requested cpu utilization measurements, we must */
- /* calibrate the cpu(s). We will perform this task within the tests */
- /* themselves. If the user has specified the cpu rate, then */
- /* calibrate_local_cpu will return rather quickly as it will have */
- /* nothing to do. If local_cpu_rate is zero, then we will go through */
- /* all the "normal" calibration stuff and return the rate back.*/
-
- if (local_cpu_usage) {
- local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
- }
-
- /* Tell the remote end to do a listen. The server alters the socket */
- /* paramters on the other side at this point, hence the reason for */
- /* all the values being passed in the setup message. If the user did */
- /* not specify any of the parameters, they will be passed as 0, which */
- /* will indicate to the remote that no changes beyond the system's */
- /* default should be used. Alignment is the exception, it will */
- /* default to 8, which will be no alignment alterations. */
-
- netperf_request.content.request_type = DO_SCTP_RR;
- sctp_rr_request->recv_buf_size = rsr_size_req;
- sctp_rr_request->send_buf_size = rss_size_req;
- sctp_rr_request->recv_alignment = remote_recv_align;
- sctp_rr_request->recv_offset = remote_recv_offset;
- sctp_rr_request->send_alignment = remote_send_align;
- sctp_rr_request->send_offset = remote_send_offset;
- sctp_rr_request->request_size = req_size;
- sctp_rr_request->response_size = rsp_size;
- sctp_rr_request->no_delay = rem_nodelay;
- sctp_rr_request->measure_cpu = remote_cpu_usage;
- sctp_rr_request->cpu_rate = remote_cpu_rate;
- sctp_rr_request->so_rcvavoid = rem_rcvavoid;
- sctp_rr_request->so_sndavoid = rem_sndavoid;
- if (test_time) {
- sctp_rr_request->test_length = test_time;
- }
- else {
- sctp_rr_request->test_length = test_trans * -1;
- }
- sctp_rr_request->non_blocking = non_block;
- sctp_rr_request->ipfamily = af_to_nf(remote_res->ai_family);
-
- if (debug > 1) {
- fprintf(where,"netperf: send_sctp_rr: requesting SCTP rr test\n");
- }
-
- send_request();
-
- /* The response from the remote will contain all of the relevant */
- /* socket parameters for this test type. We will put them back into */
- /* the variables here so they can be displayed if desired. The */
- /* remote will have calibrated CPU if necessary, and will have done */
- /* all the needed set-up we will have calibrated the cpu locally */
- /* before sending the request, and will grab the counter value right*/
- /* after the connect returns. The remote will grab the counter right*/
- /* after the accept call. This saves the hassle of extra messages */
- /* being sent for the sctp tests. */
-
- recv_response();
-
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote listen done.\n");
- rsr_size = sctp_rr_response->recv_buf_size;
- rss_size = sctp_rr_response->send_buf_size;
- rem_nodelay = sctp_rr_response->no_delay;
- remote_cpu_usage = sctp_rr_response->measure_cpu;
- remote_cpu_rate = sctp_rr_response->cpu_rate;
- /* make sure that port numbers are in network order */
- set_port_number(remote_res,
- (unsigned short)sctp_rr_response->data_port_number);
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- fprintf(where,
- "netperf: remote error %d",
- netperf_response.content.serv_errno);
- perror("");
- fflush(where);
-
- exit(1);
- }
-
- /*Connect up to the remote port on the data socket */
- if (connect(send_socket,
- remote_res->ai_addr,
- remote_res->ai_addrlen) <0){
- perror("netperf: send_sctp_rr data socket connect failed");
- exit(1);
- }
-
- /* don't need events for 1-to-1 API with request-response tests */
- sctp_enable_events(send_socket, 0);
-
- /* set non-blocking if needed */
- if (non_block) {
- if (!set_nonblock(send_socket)) {
- close(send_socket);
- exit(1);
- }
- }
-
- /* Data Socket set-up is finished. If there were problems, either the */
- /* connect would have failed, or the previous response would have */
- /* indicated a problem. I failed to see the value of the extra */
- /* message after the accept on the remote. If it failed, we'll see it */
- /* here. If it didn't, we might as well start pumping data. */
-
- /* Set-up the test end conditions. For a request/response test, they */
- /* can be either time or transaction based. */
-
- if (test_time) {
- /* The user wanted to end the test after a period of time. */
- times_up = 0;
- trans_remaining = 0;
- start_timer(test_time);
- }
- else {
- /* The tester wanted to send a number of bytes. */
- trans_remaining = test_bytes;
- times_up = 1;
- }
-
- /* The cpu_start routine will grab the current time and possibly */
- /* value of the idle counter for later use in measuring cpu */
- /* utilization and/or service demand and thruput. */
-
- cpu_start(local_cpu_usage);
-
-#ifdef WANT_INTERVALS
- if ((interval_burst) || (demo_mode)) {
- /* zero means that we never pause, so we never should need the */
- /* interval timer, unless we are in demo_mode */
- start_itimer(interval_wate);
- }
- interval_count = interval_burst;
- /* get the signal set for the call to sigsuspend */
- if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &signal_set) != 0) {
- fprintf(where,
- "send_sctp_rr: unable to get sigmask errno %d\n",
- errno);
- fflush(where);
- exit(1);
- }
-#endif /* WANT_INTERVALS */
-
- /* We use an "OR" to control test execution. When the test is */
- /* controlled by time, the byte count check will always return false. */
- /* When the test is controlled by byte count, the time test will */
- /* always return false. When the test is finished, the whole */
- /* expression will go false and we will stop sending data. I think I */
- /* just arbitrarily decrement trans_remaining for the timed test, but */
- /* will not do that just yet... One other question is whether or not */
- /* the send buffer and the receive buffer should be the same buffer. */
-
-#ifdef WANT_FIRST_BURST
- {
- int i;
- for (i = 0; i < first_burst_size; i++) {
- if((len=sctp_sendmsg(send_socket,
- send_ring->buffer_ptr, req_size,
- NULL, 0, /* don't need addrs with 1-to-1 */
- 0, 0, 0, 0, 0)) != req_size) {
- /* we should never hit the end of the test in the first burst */
- perror("send_sctp_rr: initial burst data send error");
- exit(1);
- }
- }
- }
-#endif /* WANT_FIRST_BURST */
-
- while ((!times_up) || (trans_remaining > 0)) {
- /* send the request. we assume that if we use a blocking socket, */
- /* the request will be sent at one shot. */
-
-#ifdef WANT_HISTOGRAM
- /* timestamp just before our call to send, and then again just */
- /* after the receive raj 8/94 */
- HIST_timestamp(&time_one);
-#endif /* WANT_HISTOGRAM */
-
- while ((len=sctp_sendmsg(send_socket,
- send_ring->buffer_ptr, req_size,
- NULL, 0, /* don't need addrs with 1-to-1 */
- 0, 0, 0, 0, 0)) != req_size) {
- if (non_block && errno == EAGAIN) {
- /* try sending again */
- continue;
- } else if (SOCKET_EINTR(len) || (errno == 0)) {
- /* we hit the end of a */
- /* timed test. */
- timed_out = 1;
- break;
- }
- perror("send_sctp_rr: data send error");
- exit(1);
- }
-
- if (timed_out) {
- /* we timed out while sending. break out another level */
- break;
- }
- send_ring = send_ring->next;
-
- /* receive the response */
- rsp_bytes_left = rsp_size;
- temp_message_ptr = recv_ring->buffer_ptr;
- do {
- msg_flags = 0;
- if ((rsp_bytes_recvd=sctp_recvmsg(send_socket,
- temp_message_ptr, rsp_bytes_left,
- NULL, 0,
- NULL, &msg_flags)) < 0) {
- if (errno == EINTR) {
- /* We hit the end of a timed test. */
- timed_out = 1;
- break;
- } else if (non_block && errno == EAGAIN) {
- continue;
- }
- perror("send_sctp_rr: data recv error");
- exit(1);
- }
- rsp_bytes_left -= rsp_bytes_recvd;
- temp_message_ptr += rsp_bytes_recvd;
- } while (!(msg_flags & MSG_EOR));
-
- recv_ring = recv_ring->next;
-
- if (timed_out) {
- /* we may have been in a nested while loop - we need */
- /* another call to break. */
- break;
- }
-
-#ifdef WANT_HISTOGRAM
- HIST_timestamp(&time_two);
- HIST_add(time_hist,delta_micro(&time_one,&time_two));
-#endif /* WANT_HISTOGRAM */
-#ifdef WANT_INTERVALS
- if (demo_mode) {
- units_this_tick += 1;
- }
- /* in this case, the interval count is the count-down couter */
- /* to decide to sleep for a little bit */
- if ((interval_burst) && (--interval_count == 0)) {
- /* call sigsuspend and wait for the interval timer to get us */
- /* out */
- if (debug > 1) {
- fprintf(where,"about to suspend\n");
- fflush(where);
- }
- if (sigsuspend(&signal_set) == EFAULT) {
- fprintf(where,
- "send_sctp_rr: fault with signal set!\n");
- fflush(where);
- exit(1);
- }
- interval_count = interval_burst;
- }
-#endif /* WANT_INTERVALS */
-
- nummessages++;
- if (trans_remaining) {
- trans_remaining--;
- }
-
- if (debug > 3) {
- if ((nummessages % 100) == 0) {
- fprintf(where,
- "Transaction %d completed\n",
- nummessages);
- fflush(where);
- }
- }
- }
-
- /* At this point we used to call shutdown on the data socket to be */
- /* sure all the data was delivered, but this was not germane in a */
- /* request/response test, and it was causing the tests to "hang" when */
- /* they were being controlled by time. So, I have replaced this */
- /* shutdown call with a call to close that can be found later in the */
- /* procedure. */
-
- /* this call will always give us the elapsed time for the test, and */
- /* will also store-away the necessaries for cpu utilization */
-
- cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */
- /* measured? how long */
- /* did we really run? */
-
- /* Get the statistics from the remote end. The remote will have */
- /* calculated CPU utilization. If it wasn't supposed to care, it */
- /* will return obvious values. */
-
- recv_response();
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote results obtained\n");
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- fprintf(where,"netperf: remote error %d",
- netperf_response.content.serv_errno);
- perror("");
- fflush(where);
- exit(1);
- }
-
- /* We now calculate what our throughput was for the test. */
-
- bytes_xferd = (req_size * nummessages) + (rsp_size * nummessages);
- thruput = nummessages/elapsed_time;
-
- if (local_cpu_usage || remote_cpu_usage) {
- /* We must now do a little math for service demand and cpu */
- /* utilization for the system(s) */
- /* Of course, some of the information might be bogus because */
- /* there was no idle counter in the kernel(s). We need to make */
- /* a note of this for the user's benefit...*/
- if (local_cpu_usage) {
- local_cpu_utilization = calc_cpu_util(0.0);
- /* since calc_service demand is doing ms/Kunit we will */
- /* multiply the number of transaction by 1024 to get */
- /* "good" numbers */
- local_service_demand = calc_service_demand((double) nummessages*1024,
- 0.0,
- 0.0,
- 0);
- }
- else {
- local_cpu_utilization = (float) -1.0;
- local_service_demand = (float) -1.0;
- }
-
- if (remote_cpu_usage) {
- remote_cpu_utilization = sctp_rr_result->cpu_util;
- /* since calc_service demand is doing ms/Kunit we will */
- /* multiply the number of transaction by 1024 to get */
- /* "good" numbers */
- remote_service_demand = calc_service_demand((double) nummessages*1024,
- 0.0,
- remote_cpu_utilization,
- sctp_rr_result->num_cpus);
- }
- else {
- remote_cpu_utilization = (float) -1.0;
- remote_service_demand = (float) -1.0;
- }
-
- }
- else {
- /* we were not measuring cpu, for the confidence stuff, we */
- /* should make it -1.0 */
- local_cpu_utilization = (float) -1.0;
- local_service_demand = (float) -1.0;
- remote_cpu_utilization = (float) -1.0;
- remote_service_demand = (float) -1.0;
- }
-
- /* at this point, we want to calculate the confidence information. */
- /* if debugging is on, calculate_confidence will print-out the */
- /* parameters we pass it */
-
- calculate_confidence(confidence_iteration,
- elapsed_time,
- thruput,
- local_cpu_utilization,
- remote_cpu_utilization,
- local_service_demand,
- remote_service_demand);
-
-
- confidence_iteration++;
-
- /* we are now done with the socket, so close it */
- close(send_socket);
-
- }
-
- retrieve_confident_values(&elapsed_time,
- &thruput,
- &local_cpu_utilization,
- &remote_cpu_utilization,
- &local_service_demand,
- &remote_service_demand);
-
- /* We are now ready to print all the information. If the user */
- /* has specified zero-level verbosity, we will just print the */
- /* local service demand, or the remote service demand. If the */
- /* user has requested verbosity level 1, he will get the basic */
- /* "streamperf" numbers. If the user has specified a verbosity */
- /* of greater than 1, we will display a veritable plethora of */
- /* background information from outside of this block as it it */
- /* not cpu_measurement specific... */
-
- if (confidence < 0) {
- /* we did not hit confidence, but were we asked to look for it? */
- if (iteration_max > 1) {
- display_confidence();
- }
- }
-
- if (local_cpu_usage || remote_cpu_usage) {
- local_cpu_method = format_cpu_method(cpu_method);
- remote_cpu_method = format_cpu_method(sctp_rr_result->cpu_method);
-
- switch (verbosity) {
- case 0:
- if (local_cpu_usage) {
- fprintf(where,
- cpu_fmt_0,
- local_service_demand,
- local_cpu_method);
- }
- else {
- fprintf(where,
- cpu_fmt_0,
- remote_service_demand,
- remote_cpu_method);
- }
- break;
- case 1:
- case 2:
- if (print_headers) {
- fprintf(where,
- cpu_title,
- local_cpu_method,
- remote_cpu_method);
- }
-
- fprintf(where,
- cpu_fmt_1_line_1, /* the format string */
- lss_size, /* local sendbuf size */
- lsr_size,
- req_size, /* how large were the requests */
- rsp_size, /* guess */
- elapsed_time, /* how long was the test */
- thruput,
- local_cpu_utilization, /* local cpu */
- remote_cpu_utilization, /* remote cpu */
- local_service_demand, /* local service demand */
- remote_service_demand); /* remote service demand */
- fprintf(where,
- cpu_fmt_1_line_2,
- rss_size,
- rsr_size);
- break;
- }
- }
- else {
- /* The tester did not wish to measure service demand. */
-
- switch (verbosity) {
- case 0:
- fprintf(where,
- tput_fmt_0,
- thruput);
- break;
- case 1:
- case 2:
- if (print_headers) {
- fprintf(where,tput_title,format_units());
- }
-
- fprintf(where,
- tput_fmt_1_line_1, /* the format string */
- lss_size,
- lsr_size,
- req_size, /* how large were the requests */
- rsp_size, /* how large were the responses */
- elapsed_time, /* how long did it take */
- thruput);
- fprintf(where,
- tput_fmt_1_line_2,
- rss_size, /* remote recvbuf size */
- rsr_size);
-
- break;
- }
- }
-
- /* it would be a good thing to include information about some of the */
- /* other parameters that may have been set for this test, but at the */
- /* moment, I do not wish to figure-out all the formatting, so I will */
- /* just put this comment here to help remind me that it is something */
- /* that should be done at a later time. */
-
- /* how to handle the verbose information in the presence of */
- /* confidence intervals is yet to be determined... raj 11/94 */
- if (verbosity > 1) {
- /* The user wanted to know it all, so we will give it to him. */
- /* This information will include as much as we can find about */
- /* TCP statistics, the alignments of the sends and receives */
- /* and all that sort of rot... */
-
- fprintf(where,
- ksink_fmt,
- local_send_align,
- remote_recv_offset,
- local_send_offset,
- remote_recv_offset);
-
-#ifdef WANT_HISTOGRAM
- fprintf(where,"\nHistogram of request/response times\n");
- fflush(where);
- HIST_report(time_hist);
-#endif /* WANT_HISTOGRAM */
-
- }
-
-}
-
-
- /* this routine implements the receive (netserver) side of a TCP_RR */
- /* test */
-void
-recv_sctp_rr()
-{
-
- struct ring_elt *send_ring;
- struct ring_elt *recv_ring;
-
- struct addrinfo *local_res;
- char local_name[BUFSIZ];
- char port_buffer[PORTBUFSIZE];
-
- struct sockaddr_in myaddr_in, peeraddr_in;
- int s_listen, s_data;
- int addrlen;
- char *temp_message_ptr;
- int trans_received;
- int trans_remaining;
- int bytes_sent;
- int request_bytes_recvd;
- int request_bytes_remaining;
- int timed_out = 0;
- float elapsed_time;
-
- struct sctp_rr_request_struct *sctp_rr_request;
- struct sctp_rr_response_struct *sctp_rr_response;
- struct sctp_rr_results_struct *sctp_rr_results;
-
- sctp_rr_request =
- (struct sctp_rr_request_struct *)netperf_request.content.test_specific_data;
- sctp_rr_response =
- (struct sctp_rr_response_struct *)netperf_response.content.test_specific_data;
- sctp_rr_results =
- (struct sctp_rr_results_struct *)netperf_response.content.test_specific_data;
-
- if (debug) {
- fprintf(where,"netserver: recv_sctp_rr: entered...\n");
- fflush(where);
- }
-
- /* We want to set-up the listen socket with all the desired */
- /* parameters and then let the initiator know that all is ready. If */
- /* socket size defaults are to be used, then the initiator will have */
- /* sent us 0's. If the socket sizes cannot be changed, then we will */
- /* send-back what they are. If that information cannot be determined, */
- /* then we send-back -1's for the sizes. If things go wrong for any */
- /* reason, we will drop back ten yards and punt. */
-
- /* If anything goes wrong, we want the remote to know about it. It */
- /* would be best if the error that the remote reports to the user is */
- /* the actual error we encountered, rather than some bogus unexpected */
- /* response type message. */
-
- if (debug) {
- fprintf(where,"recv_sctp_rr: setting the response type...\n");
- fflush(where);
- }
-
- netperf_response.content.response_type = SCTP_RR_RESPONSE;
-
- if (debug) {
- fprintf(where,"recv_sctp_rr: the response type is set...\n");
- fflush(where);
- }
-
- /* allocate the recv and send rings with the requested alignments */
- /* and offsets. raj 7/94 */
- if (debug) {
- fprintf(where,"recv_sctp_rr: requested recv alignment of %d offset %d\n",
- sctp_rr_request->recv_alignment,
- sctp_rr_request->recv_offset);
- fprintf(where,"recv_sctp_rr: requested send alignment of %d offset %d\n",
- sctp_rr_request->send_alignment,
- sctp_rr_request->send_offset);
- fflush(where);
- }
-
- /* at some point, these need to come to us from the remote system */
- if (send_width == 0) send_width = 1;
- if (recv_width == 0) recv_width = 1;
-
- send_ring = allocate_buffer_ring(send_width,
- sctp_rr_request->response_size,
- sctp_rr_request->send_alignment,
- sctp_rr_request->send_offset);
-
- recv_ring = allocate_buffer_ring(recv_width,
- sctp_rr_request->request_size,
- sctp_rr_request->recv_alignment,
- sctp_rr_request->recv_offset);
-
-
- /* Grab a socket to listen on, and then listen on it. */
-
- if (debug) {
- fprintf(where,"recv_sctp_rr: grabbing a socket...\n");
- fflush(where);
- }
-
- /* create_data_socket expects to find some things in the global */
- /* variables, so set the globals based on the values in the request. */
- /* once the socket has been created, we will set the response values */
- /* based on the updated value of those globals. raj 7/94 */
- lss_size_req = sctp_rr_request->send_buf_size;
- lsr_size_req = sctp_rr_request->recv_buf_size;
- loc_nodelay = sctp_rr_request->no_delay;
- loc_rcvavoid = sctp_rr_request->so_rcvavoid;
- loc_sndavoid = sctp_rr_request->so_sndavoid;
- non_block = sctp_rr_request->non_blocking;
-
- set_hostname_and_port(local_name,
- port_buffer,
- nf_to_af(sctp_rr_request->ipfamily),
- sctp_rr_request->port);
-
- local_res = complete_addrinfo(local_name,
- local_name,
- port_buffer,
- nf_to_af(sctp_rr_request->ipfamily),
- SOCK_STREAM,
- IPPROTO_SCTP,
- 0);
-
- s_listen = create_data_socket(local_res);
-
- if (s_listen < 0) {
- netperf_response.content.serv_errno = errno;
- send_response();
-
- exit(1);
- }
-
- /* Now, let's set-up the socket to listen for connections */
- if (listen(s_listen, 5) == -1) {
- netperf_response.content.serv_errno = errno;
- close(s_listen);
- send_response();
-
- exit(1);
- }
-
-
- /* now get the port number assigned by the system */
- addrlen = sizeof(myaddr_in);
- if (getsockname(s_listen,
- (struct sockaddr *)&myaddr_in, &addrlen) == -1){
- netperf_response.content.serv_errno = errno;
- close(s_listen);
- send_response();
-
- exit(1);
- }
-
- /* Now myaddr_in contains the port and the internet address this is */
- /* returned to the sender also implicitly telling the sender that the */
- /* socket buffer sizing has been done. */
-
- sctp_rr_response->data_port_number = (int) ntohs(myaddr_in.sin_port);
- netperf_response.content.serv_errno = 0;
-
- /* But wait, there's more. If the initiator wanted cpu measurements, */
- /* then we must call the calibrate routine, which will return the max */
- /* rate back to the initiator. If the CPU was not to be measured, or */
- /* something went wrong with the calibration, we will return a 0.0 to */
- /* the initiator. */
-
- sctp_rr_response->cpu_rate = (float)0.0; /* assume no cpu */
- sctp_rr_response->measure_cpu = 0;
-
- if (sctp_rr_request->measure_cpu) {
- sctp_rr_response->measure_cpu = 1;
- sctp_rr_response->cpu_rate = calibrate_local_cpu(sctp_rr_request->cpu_rate);
- }
-
-
- /* before we send the response back to the initiator, pull some of */
- /* the socket parms from the globals */
- sctp_rr_response->send_buf_size = lss_size;
- sctp_rr_response->recv_buf_size = lsr_size;
- sctp_rr_response->no_delay = loc_nodelay;
- sctp_rr_response->so_rcvavoid = loc_rcvavoid;
- sctp_rr_response->so_sndavoid = loc_sndavoid;
- sctp_rr_response->test_length = sctp_rr_request->test_length;
- send_response();
-
- addrlen = sizeof(peeraddr_in);
-
- if ((s_data = accept(s_listen,
- (struct sockaddr *)&peeraddr_in,
- &addrlen)) == -1) {
- /* Let's just punt. The remote will be given some information */
- close(s_listen);
-
- exit(1);
- }
-
- /* we do not need events on a 1-to-1 RR test. The test will finish
- * once all transactions are done.
- */
-
- /* now that we are connected, mark the socket as non-blocking */
- if (non_block) {
- if (!set_nonblock(s_data)) {
- perror("netperf: set_nonblock");
- exit(1);
- }
- }
-
-#ifdef KLUDGE_SOCKET_OPTIONS
- /* this is for those systems which *INCORRECTLY* fail to pass */
- /* attributes across an accept() call. Including this goes against */
- /* my better judgement :( raj 11/95 */
-
- kludge_socket_options(s_data);
-
-#endif /* KLUDGE_SOCKET_OPTIONS */
-
- if (debug) {
- fprintf(where,"recv_sctp_rr: accept completes on the data connection.\n");
- fflush(where);
- }
-
- /* Now it's time to start receiving data on the connection. We will */
- /* first grab the apropriate counters and then start grabbing. */
-
- cpu_start(sctp_rr_request->measure_cpu);
-
- /* The loop will exit when we hit the end of the test time, or when */
- /* we have exchanged the requested number of transactions. */
-
- if (sctp_rr_request->test_length > 0) {
- times_up = 0;
- trans_remaining = 0;
- start_timer(sctp_rr_request->test_length + PAD_TIME);
- }
- else {
- times_up = 1;
- trans_remaining = sctp_rr_request->test_length * -1;
- }
-
- trans_received = 0;
-
- while ((!times_up) || (trans_remaining > 0)) {
- int msg_flags = 0;
-
- temp_message_ptr = recv_ring->buffer_ptr;
- request_bytes_remaining = sctp_rr_request->request_size;
- while(!(msg_flags & MSG_EOR)) {
- if((request_bytes_recvd=sctp_recvmsg(s_data,
- temp_message_ptr,
- request_bytes_remaining,
- NULL, 0,
- NULL, &msg_flags)) < 0) {
- if (errno == EINTR) {
- /* the timer popped */
- timed_out = 1;
- break;
- } else if (non_block && errno == EAGAIN) {
- continue; /* while request_bytes_remaining */
- }
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
- request_bytes_remaining -= request_bytes_recvd;
- temp_message_ptr += request_bytes_recvd;
- }
-
- recv_ring = recv_ring->next;
-
- if (timed_out) {
- /* we hit the end of the test based on time - lets */
- /* bail out of here now... */
- if (debug) {
- fprintf(where,"yo55\n");
- fflush(where);
- }
- break;
- }
-
-
- /* Now, send the response to the remote
- * In 1-to-1 API destination addr is not needed.
- */
- while ((bytes_sent=sctp_sendmsg(s_data,
- send_ring->buffer_ptr,
- sctp_rr_request->response_size,
- NULL, 0,
- 0, 0, 0, 0, 0)) == -1) {
- if (errno == EINTR) {
- /* the test timer has popped */
- timed_out = 1;
- break;
- } else if (non_block && errno == EAGAIN) {
- continue;
- }
-
- netperf_response.content.serv_errno = 982;
- send_response();
- exit(1);
- }
-
- if (timed_out) {
- /* we hit the end of the test based on time - lets */
- /* bail out of here now... */
- if (debug) {
- fprintf(where,"yo6\n");
- fflush(where);
- }
- break;
- }
-
- send_ring = send_ring->next;
-
- trans_received++;
- if (trans_remaining) {
- trans_remaining--;
- }
- }
-
-
- /* The loop now exits due to timeout or transaction count being */
- /* reached */
-
- cpu_stop(sctp_rr_request->measure_cpu,&elapsed_time);
-
- stop_timer();
-
- if (timed_out) {
- /* we ended the test by time, which was at least 2 seconds */
- /* longer than we wanted to run. so, we want to subtract */
- /* PAD_TIME from the elapsed_time. */
- elapsed_time -= PAD_TIME;
- }
-
- /* send the results to the sender */
-
- if (debug) {
- fprintf(where,
- "recv_sctp_rr: got %d transactions\n",
- trans_received);
- fflush(where);
- }
-
- sctp_rr_results->bytes_received = (trans_received *
- (sctp_rr_request->request_size +
- sctp_rr_request->response_size));
- sctp_rr_results->trans_received = trans_received;
- sctp_rr_results->elapsed_time = elapsed_time;
- sctp_rr_results->cpu_method = cpu_method;
- sctp_rr_results->num_cpus = lib_num_loc_cpus;
- if (sctp_rr_request->measure_cpu) {
- sctp_rr_results->cpu_util = calc_cpu_util(elapsed_time);
- }
-
- if (debug) {
- fprintf(where,
- "recv_sctp_rr: test complete, sending results.\n");
- fflush(where);
- }
-
- /* we are now done with the sockets */
- send_response();
-
- close(s_data);
- close(s_listen);
-
-}
-
-
-
-/* this routine implements the sending (netperf) side of the
- SCTP_RR_1TOMANY test */
-
-void
-send_sctp_rr_1toMany(remote_host)
- char remote_host[];
-{
-
- char *tput_title = "\
-Local /Remote\n\
-Socket Size Request Resp. Elapsed Trans.\n\
-Send Recv Size Size Time Rate \n\
-bytes Bytes bytes bytes secs. per sec \n\n";
-
- char *tput_fmt_0 =
- "%7.2f\n";
-
- char *tput_fmt_1_line_1 = "\
-%-6d %-6d %-6d %-6d %-6.2f %7.2f \n";
- char *tput_fmt_1_line_2 = "\
-%-6d %-6d\n";
-
- char *cpu_title = "\
-Local /Remote\n\
-Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\
-Send Recv Size Size Time Rate local remote local remote\n\
-bytes bytes bytes bytes secs. per sec %% %c %% %c us/Tr us/Tr\n\n";
-
- char *cpu_fmt_0 =
- "%6.3f %c\n";
-
- char *cpu_fmt_1_line_1 = "\
-%-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f\n";
-
- char *cpu_fmt_1_line_2 = "\
-%-6d %-6d\n";
-
- char *ksink_fmt = "\
-Alignment Offset\n\
-Local Remote Local Remote\n\
-Send Recv Send Recv\n\
-%5d %5d %5d %5d\n";
-
-
- int timed_out = 0;
- float elapsed_time;
-
- int len, j = 0;
- char *temp_message_ptr;
- int nummessages;
- int *send_socket;
- int trans_remaining;
- double bytes_xferd;
- int msg_flags = 0;
-
- struct ring_elt *send_ring;
- struct ring_elt *recv_ring;
-
- int rsp_bytes_left;
- int rsp_bytes_recvd;
-
- float local_cpu_utilization;
- float local_service_demand;
- float remote_cpu_utilization;
- float remote_service_demand;
- double thruput;
-
- struct sockaddr_storage peer;
- struct addrinfo *local_res;
- struct addrinfo *remote_res;
-
- struct sctp_rr_request_struct *sctp_rr_request;
- struct sctp_rr_response_struct *sctp_rr_response;
- struct sctp_rr_results_struct *sctp_rr_result;
-
-#ifdef WANT_INTERVALS
- int interval_count;
- sigset_t signal_set;
-#endif /* WANT_INTERVALS */
-
- sctp_rr_request =
- (struct sctp_rr_request_struct *)netperf_request.content.test_specific_data;
- sctp_rr_response =
- (struct sctp_rr_response_struct *)netperf_response.content.test_specific_data;
- sctp_rr_result =
- (struct sctp_rr_results_struct *)netperf_response.content.test_specific_data;
-
-#ifdef WANT_HISTOGRAM
- time_hist = HIST_new();
-#endif /* WANT_HISTOGRAM */
-
- /* since we are now disconnected from the code that established the */
- /* control socket, and since we want to be able to use different */
- /* protocols and such, we are passed the name of the remote host and */
- /* must turn that into the test specific addressing information. */
-
- complete_addrinfos(&remote_res,
- &local_res,
- remote_host,
- SOCK_SEQPACKET,
- IPPROTO_SCTP,
- 0);
-
- if ( print_headers ) {
- print_top_test_header("SCTP 1-TO-MANY REQUEST/RESPONSE TEST",local_res,remote_res);
- }
-
- /* initialize a few counters */
-
- send_ring = NULL;
- recv_ring = NULL;
- confidence_iteration = 1;
- init_stat();
-
- send_socket = malloc(sizeof(int) * num_associations);
- if (send_socket == NULL) {
- fprintf(where,
- "Could not create the socket array for %d associations",
- num_associations);
- fflush(where);
- exit(1);
- }
-
- /* we have a great-big while loop which controls the number of times */
- /* we run a particular test. this is for the calculation of a */
- /* confidence interval (I really should have stayed awake during */
- /* probstats :). If the user did not request confidence measurement */
- /* (no confidence is the default) then we will only go though the */
- /* loop once. the confidence stuff originates from the folks at IBM */
-
- while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
- (confidence_iteration <= iteration_min)) {
-
- /* initialize a few counters. we have to remember that we might be */
- /* going through the loop more than once. */
-
- nummessages = 0;
- bytes_xferd = 0.0;
- times_up = 0;
- timed_out = 0;
- trans_remaining = 0;
-
- /* set-up the data buffers with the requested alignment and offset. */
- /* since this is a request/response test, default the send_width and */
- /* recv_width to 1 and not two raj 7/94 */
-
- if (send_width == 0) send_width = 1;
- if (recv_width == 0) recv_width = 1;
-
- if (send_ring == NULL) {
- send_ring = allocate_buffer_ring(send_width,
- req_size,
- local_send_align,
- local_send_offset);
- }
-
- if (recv_ring == NULL) {
- recv_ring = allocate_buffer_ring(recv_width,
- rsp_size,
- local_recv_align,
- local_recv_offset);
- }
-
- /* If the user has requested cpu utilization measurements, we must */
- /* calibrate the cpu(s). We will perform this task within the tests */
- /* themselves. If the user has specified the cpu rate, then */
- /* calibrate_local_cpu will return rather quickly as it will have */
- /* nothing to do. If local_cpu_rate is zero, then we will go through */
- /* all the "normal" calibration stuff and return the rate back.*/
-
- if (local_cpu_usage) {
- local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
- }
-
- /* Tell the remote end to do a listen. The server alters the socket */
- /* paramters on the other side at this point, hence the reason for */
- /* all the values being passed in the setup message. If the user did */
- /* not specify any of the parameters, they will be passed as 0, which */
- /* will indicate to the remote that no changes beyond the system's */
- /* default should be used. Alignment is the exception, it will */
- /* default to 8, which will be no alignment alterations. */
-
- netperf_request.content.request_type = DO_SCTP_RR_MANY;
- sctp_rr_request->recv_buf_size = rsr_size_req;
- sctp_rr_request->send_buf_size = rss_size_req;
- sctp_rr_request->recv_alignment = remote_recv_align;
- sctp_rr_request->recv_offset = remote_recv_offset;
- sctp_rr_request->send_alignment = remote_send_align;
- sctp_rr_request->send_offset = remote_send_offset;
- sctp_rr_request->request_size = req_size;
- sctp_rr_request->response_size = rsp_size;
- sctp_rr_request->no_delay = rem_nodelay;
- sctp_rr_request->measure_cpu = remote_cpu_usage;
- sctp_rr_request->cpu_rate = remote_cpu_rate;
- sctp_rr_request->so_rcvavoid = rem_rcvavoid;
- sctp_rr_request->so_sndavoid = rem_sndavoid;
- if (test_time) {
- sctp_rr_request->test_length = test_time;
- }
- else {
- sctp_rr_request->test_length = test_trans * num_associations
- * -1;
- }
- sctp_rr_request->non_blocking = non_block;
- sctp_rr_request->port = atoi(remote_data_port);
- sctp_rr_request->ipfamily = af_to_nf(remote_res->ai_family);
- if (debug > 1) {
- fprintf(where,"netperf: send_sctp_rr_1toMany: requesting SCTP rr test\n");
- }
-
- send_request();
-
- /* The response from the remote will contain all of the relevant */
- /* socket parameters for this test type. We will put them back into */
- /* the variables here so they can be displayed if desired. The */
- /* remote will have calibrated CPU if necessary, and will have done */
- /* all the needed set-up we will have calibrated the cpu locally */
- /* before sending the request, and will grab the counter value right*/
- /* after the connect returns. The remote will grab the counter right*/
- /* after the accept call. This saves the hassle of extra messages */
- /* being sent for the sctp tests. */
-
- recv_response();
-
- if (!netperf_response.content.serv_errno) {
- rsr_size = sctp_rr_response->recv_buf_size;
- rss_size = sctp_rr_response->send_buf_size;
- rem_nodelay = sctp_rr_response->no_delay;
- remote_cpu_usage = sctp_rr_response->measure_cpu;
- remote_cpu_rate = sctp_rr_response->cpu_rate;
- /* make sure that port numbers are in network order */
- set_port_number(remote_res,
- (unsigned short)sctp_rr_response->data_port_number);
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- fprintf(where,
- "netperf: remote error %d",
- netperf_response.content.serv_errno);
- perror("");
- fflush(where);
-
- exit(1);
- }
-
- /*set up the data socket list */
- for (j = 0; j < num_associations; j++) {
- send_socket[j] = create_data_socket(local_res);
-
- if (send_socket < 0){
- perror("netperf: send_sctp_rr_1toMany: sctp stream data socket");
- exit(1);
- }
-
- /*Connect up to the remote port on the data socket */
- if (connect(send_socket[j],
- remote_res->ai_addr,
- remote_res->ai_addrlen) < 0){
- perror("netperf: data socket connect failed");
-
- exit(1);
- }
-
- /* The client end of the 1-to-Many test uses 1-to-1 sockets.
- * it doesn't need events.
- */
- sctp_enable_events(send_socket[j], 0);
-
- if (non_block) {
- if (!set_nonblock(send_socket[j])) {
- close(send_socket[j]);
- exit(1);
- }
- }
- }
-
- /* Data Socket set-up is finished. If there were problems, either the */
- /* connect would have failed, or the previous response would have */
- /* indicated a problem. I failed to see the value of the extra */
- /* message after the accept on the remote. If it failed, we'll see it */
- /* here. If it didn't, we might as well start pumping data. */
-
- /* Set-up the test end conditions. For a request/response test, they */
- /* can be either time or transaction based. */
-
- if (test_time) {
- /* The user wanted to end the test after a period of time. */
- times_up = 0;
- trans_remaining = 0;
- start_timer(test_time);
- }
- else {
- /* The tester wanted to send a number of bytes. */
- trans_remaining = test_bytes * num_associations;
- times_up = 1;
- }
-
- /* The cpu_start routine will grab the current time and possibly */
- /* value of the idle counter for later use in measuring cpu */
- /* utilization and/or service demand and thruput. */
-
- cpu_start(local_cpu_usage);
-
-#ifdef WANT_INTERVALS
- if ((interval_burst) || (demo_mode)) {
- /* zero means that we never pause, so we never should need the */
- /* interval timer, unless we are in demo_mode */
- start_itimer(interval_wate);
- }
- interval_count = interval_burst;
- /* get the signal set for the call to sigsuspend */
- if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &signal_set) != 0) {
- fprintf(where,
- "send_sctp_rr_1toMany: unable to get sigmask errno %d\n",
- errno);
- fflush(where);
- exit(1);
- }
-#endif /* WANT_INTERVALS */
-
- /* We use an "OR" to control test execution. When the test is */
- /* controlled by time, the byte count check will always return false. */
- /* When the test is controlled by byte count, the time test will */
- /* always return false. When the test is finished, the whole */
- /* expression will go false and we will stop sending data. I think I */
- /* just arbitrarily decrement trans_remaining for the timed test, but */
- /* will not do that just yet... One other question is whether or not */
- /* the send buffer and the receive buffer should be the same buffer. */
-
-#ifdef WANT_FIRST_BURST
- {
- int i;
- for (j = 0; j < num_associations; j++) {
- for (i = 0; i < first_burst_size; i++) {
- if((len=sctp_sendmsg(send_socket[j],
- send_ring->buffer_ptr, send_size,
- remote_res->ai_addr,
- remote_res->ai_addrlen,
- 0, 0, 0, 0, 0)) != req_size) {
- /* we should never hit the end of the test in the first burst */
- perror("send_sctp_rr_1toMany: initial burst data send error");
- exit(1);
- }
- }
- }
- }
-#endif /* WANT_FIRST_BURST */
-
- while ((!times_up) || (trans_remaining > 0)) {
- /* send the request. we assume that if we use a blocking socket, */
- /* the request will be sent at one shot. */
-
- /* this is a fairly poor way of testing 1toMany connections.
- * For each association we measure round trip time to account for
- * any delay in lookups and delivery. To stress the server a bit
- * more we would need a distributed client test, or at least multiple
- * processes. I want to force as much paralellism as possible, but
- * this will do for the fist take. vlad
- */
- for (j = 0; j < num_associations; j++) {
-#ifdef WANT_HISTOGRAM
- /* timestamp just before our call to send, and then again just */
- /* after the receive raj 8/94 */
- gettimeofday(&time_one,NULL);
-#endif /* WANT_HISTOGRAM */
-
- while ((len=sctp_sendmsg(send_socket[j],
- send_ring->buffer_ptr, send_size,
- remote_res->ai_addr,
- remote_res->ai_addrlen,
- 0, 0, 0, 0, 0)) != req_size) {
- if (non_block && errno == EAGAIN) {
- /* try sending again */
- continue;
- } else if ((errno == EINTR) || (errno == 0)) {
- /* we hit the end of a */
- /* timed test. */
- timed_out = 1;
- break;
- }
- perror("send_sctp_rr_1toMany: data send error");
- exit(1);
- }
-
- if (timed_out) {
- /* we may have been in a nested while loop - we need */
- /* another call to break. */
- break;
- }
-
- /* setup for the next time */
- send_ring = send_ring->next;
-
- rsp_bytes_left = rsp_size;
- temp_message_ptr = recv_ring->buffer_ptr;
- while (!(msg_flags & MSG_EOR)) {
- if((rsp_bytes_recvd = sctp_recvmsg(send_socket[j],
- temp_message_ptr,
- rsp_bytes_left,
- NULL, 0,
- NULL, &msg_flags)) < 0) {
- if (errno == EINTR) {
- /* We hit the end of a timed test. */
- timed_out = 1;
- break;
- } else if (non_block && errno == EAGAIN) {
- continue;
- }
- perror("send_sctp_rr_1toMany: data recv error");
- exit(1);
- }
- rsp_bytes_left -= rsp_bytes_recvd;
- temp_message_ptr += rsp_bytes_recvd;
- }
- recv_ring = recv_ring->next;
-
- if (timed_out) {
- /* we may have been in a nested while loop - we need */
- /* another call to break. */
- break;
- }
-
-#ifdef WANT_HISTOGRAM
- gettimeofday(&time_two,NULL);
- HIST_add(time_hist,delta_micro(&time_one,&time_two));
-#endif /* WANT_HISTOGRAM */
-
- nummessages++;
- if (trans_remaining) {
- trans_remaining--;
- }
-
- if (debug > 3) {
- if ((nummessages % 100) == 0) {
- fprintf(where,
- "Transaction %d completed\n",
- nummessages);
- fflush(where);
- }
- }
- }
- }
-
- /* At this point we used to call shutdown on the data socket to be */
- /* sure all the data was delivered, but this was not germane in a */
- /* request/response test, and it was causing the tests to "hang" when */
- /* they were being controlled by time. So, I have replaced this */
- /* shutdown call with a call to close that can be found later in the */
- /* procedure. */
-
- /* this call will always give us the elapsed time for the test, and */
- /* will also store-away the necessaries for cpu utilization */
-
- cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */
- /* measured? how long */
- /* did we really run? */
-
- /* Get the statistics from the remote end. The remote will have */
- /* calculated CPU utilization. If it wasn't supposed to care, it */
- /* will return obvious values. */
-
- recv_response();
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote results obtained\n");
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- fprintf(where,"netperf: remote error %d",
- netperf_response.content.serv_errno);
- perror("");
- fflush(where);
- exit(1);
- }
-
- /* We now calculate what our throughput was for the test. */
-
- bytes_xferd = (req_size * nummessages) + (rsp_size * nummessages);
- thruput = nummessages/elapsed_time;
-
- if (local_cpu_usage || remote_cpu_usage) {
- /* We must now do a little math for service demand and cpu */
- /* utilization for the system(s) */
- /* Of course, some of the information might be bogus because */
- /* there was no idle counter in the kernel(s). We need to make */
- /* a note of this for the user's benefit...*/
- if (local_cpu_usage) {
- local_cpu_utilization = calc_cpu_util(0.0);
- /* since calc_service demand is doing ms/Kunit we will */
- /* multiply the number of transaction by 1024 to get */
- /* "good" numbers */
- local_service_demand = calc_service_demand((double) nummessages*1024,
- 0.0,
- 0.0,
- 0);
- }
- else {
- local_cpu_utilization = (float) -1.0;
- local_service_demand = (float) -1.0;
- }
-
- if (remote_cpu_usage) {
- remote_cpu_utilization = sctp_rr_result->cpu_util;
- /* since calc_service demand is doing ms/Kunit we will */
- /* multiply the number of transaction by 1024 to get */
- /* "good" numbers */
- remote_service_demand = calc_service_demand((double) nummessages*1024,
- 0.0,
- remote_cpu_utilization,
- sctp_rr_result->num_cpus);
- }
- else {
- remote_cpu_utilization = (float) -1.0;
- remote_service_demand = (float) -1.0;
- }
-
- }
- else {
- /* we were not measuring cpu, for the confidence stuff, we */
- /* should make it -1.0 */
- local_cpu_utilization = (float) -1.0;
- local_service_demand = (float) -1.0;
- remote_cpu_utilization = (float) -1.0;
- remote_service_demand = (float) -1.0;
- }
-
- /* at this point, we want to calculate the confidence information. */
- /* if debugging is on, calculate_confidence will print-out the */
- /* parameters we pass it */
-
- calculate_confidence(confidence_iteration,
- elapsed_time,
- thruput,
- local_cpu_utilization,
- remote_cpu_utilization,
- local_service_demand,
- remote_service_demand);
-
-
- confidence_iteration++;
-
- /* we are now done with the socket, so close it */
- for (j = 0; j < num_associations; j++)
- close(send_socket[j]);
- }
-
- retrieve_confident_values(&elapsed_time,
- &thruput,
- &local_cpu_utilization,
- &remote_cpu_utilization,
- &local_service_demand,
- &remote_service_demand);
-
- /* We are now ready to print all the information. If the user */
- /* has specified zero-level verbosity, we will just print the */
- /* local service demand, or the remote service demand. If the */
- /* user has requested verbosity level 1, he will get the basic */
- /* "streamperf" numbers. If the user has specified a verbosity */
- /* of greater than 1, we will display a veritable plethora of */
- /* background information from outside of this block as it it */
- /* not cpu_measurement specific... */
-
- if (confidence < 0) {
- /* we did not hit confidence, but were we asked to look for it? */
- if (iteration_max > 1) {
- display_confidence();
- }
- }
-
- if (local_cpu_usage || remote_cpu_usage) {
- local_cpu_method = format_cpu_method(cpu_method);
- remote_cpu_method = format_cpu_method(sctp_rr_result->cpu_method);
-
- switch (verbosity) {
- case 0:
- if (local_cpu_usage) {
- fprintf(where,
- cpu_fmt_0,
- local_service_demand,
- local_cpu_method);
- }
- else {
- fprintf(where,
- cpu_fmt_0,
- remote_service_demand,
- remote_cpu_method);
- }
- break;
- case 1:
- case 2:
- if (print_headers) {
- fprintf(where,
- cpu_title,
- local_cpu_method,
- remote_cpu_method);
- }
-
- fprintf(where,
- cpu_fmt_1_line_1, /* the format string */
- lss_size, /* local sendbuf size */
- lsr_size,
- req_size, /* how large were the requests */
- rsp_size, /* guess */
- elapsed_time, /* how long was the test */
- thruput,
- local_cpu_utilization, /* local cpu */
- remote_cpu_utilization, /* remote cpu */
- local_service_demand, /* local service demand */
- remote_service_demand); /* remote service demand */
- fprintf(where,
- cpu_fmt_1_line_2,
- rss_size,
- rsr_size);
- break;
- }
- }
- else {
- /* The tester did not wish to measure service demand. */
-
- switch (verbosity) {
- case 0:
- fprintf(where,
- tput_fmt_0,
- thruput);
- break;
- case 1:
- case 2:
- if (print_headers) {
- fprintf(where,tput_title,format_units());
- }
-
- fprintf(where,
- tput_fmt_1_line_1, /* the format string */
- lss_size,
- lsr_size,
- req_size, /* how large were the requests */
- rsp_size, /* how large were the responses */
- elapsed_time, /* how long did it take */
- thruput);
- fprintf(where,
- tput_fmt_1_line_2,
- rss_size, /* remote recvbuf size */
- rsr_size);
-
- break;
- }
- }
-
- /* it would be a good thing to include information about some of the */
- /* other parameters that may have been set for this test, but at the */
- /* moment, I do not wish to figure-out all the formatting, so I will */
- /* just put this comment here to help remind me that it is something */
- /* that should be done at a later time. */
-
- /* how to handle the verbose information in the presence of */
- /* confidence intervals is yet to be determined... raj 11/94 */
- if (verbosity > 1) {
- /* The user wanted to know it all, so we will give it to him. */
- /* This information will include as much as we can find about */
- /* TCP statistics, the alignments of the sends and receives */
- /* and all that sort of rot... */
-
- fprintf(where,
- ksink_fmt,
- local_send_align,
- remote_recv_offset,
- local_send_offset,
- remote_recv_offset);
-
-#ifdef WANT_HISTOGRAM
- fprintf(where,"\nHistogram of request/response times\n");
- fflush(where);
- HIST_report(time_hist);
-#endif /* WANT_HISTOGRAM */
-
- }
-
-}
-
-
- /* this routine implements the receive (netserver) side of a TCP_RR */
- /* test */
-void
-recv_sctp_rr_1toMany()
-{
-
- struct ring_elt *send_ring;
- struct ring_elt *recv_ring;
-
-
- struct sockaddr_in myaddr_in; /* needed to get the port number */
- struct sockaddr_storage peeraddr; /* to communicate with peer */
- struct addrinfo *local_res;
- char local_name[BUFSIZ];
- char port_buffer[PORTBUFSIZE];
- int msg_flags;
-
- int s_rcv;
- int addrlen;
- char *temp_message_ptr;
- int trans_received;
- int trans_remaining;
- int bytes_sent;
- int bytes_recvd;
- int recv_buf_size;
- int timed_out = 0;
- float elapsed_time;
-
- struct sctp_rr_request_struct *sctp_rr_request;
- struct sctp_rr_response_struct *sctp_rr_response;
- struct sctp_rr_results_struct *sctp_rr_results;
-
- sctp_rr_request =
- (struct sctp_rr_request_struct *)netperf_request.content.test_specific_data;
- sctp_rr_response =
- (struct sctp_rr_response_struct *)netperf_response.content.test_specific_data;
- sctp_rr_results =
- (struct sctp_rr_results_struct *)netperf_response.content.test_specific_data;
-
- if (debug) {
- fprintf(where,"netserver: recv_sctp_rr_1toMany: entered...\n");
- fflush(where);
- }
-
- /* We want to set-up the listen socket with all the desired */
- /* parameters and then let the initiator know that all is ready. If */
- /* socket size defaults are to be used, then the initiator will have */
- /* sent us 0's. If the socket sizes cannot be changed, then we will */
- /* send-back what they are. If that information cannot be determined, */
- /* then we send-back -1's for the sizes. If things go wrong for any */
- /* reason, we will drop back ten yards and punt. */
-
- /* If anything goes wrong, we want the remote to know about it. It */
- /* would be best if the error that the remote reports to the user is */
- /* the actual error we encountered, rather than some bogus unexpected */
- /* response type message. */
-
- if (debug) {
- fprintf(where,"recv_sctp_rr_1toMany: setting the response type...\n");
- fflush(where);
- }
-
- netperf_response.content.response_type = SCTP_RR_MANY_RESPONSE;
-
- if (debug) {
- fprintf(where,"recv_sctp_rr_1toMany: the response type is set...\n");
- fflush(where);
- }
-
- /* allocate the recv and send rings with the requested alignments */
- /* and offsets. raj 7/94 */
- if (debug) {
- fprintf(where,"recv_sctp_rr_1toMany: requested recv alignment of %d offset %d\n",
- sctp_rr_request->recv_alignment,
- sctp_rr_request->recv_offset);
- fprintf(where,"recv_sctp_rr_1toMany: requested send alignment of %d offset %d\n",
- sctp_rr_request->send_alignment,
- sctp_rr_request->send_offset);
- fflush(where);
- }
-
- /* at some point, these need to come to us from the remote system */
- if (send_width == 0) send_width = 1;
- if (recv_width == 0) recv_width = 1;
-
- send_ring = allocate_buffer_ring(send_width,
- sctp_rr_request->response_size,
- sctp_rr_request->send_alignment,
- sctp_rr_request->send_offset);
-
- recv_ring = allocate_buffer_ring(recv_width,
- sctp_rr_request->request_size,
- sctp_rr_request->recv_alignment,
- sctp_rr_request->recv_offset);
-
-
- /* create_data_socket expects to find some things in the global */
- /* variables, so set the globals based on the values in the request. */
- /* once the socket has been created, we will set the response values */
- /* based on the updated value of those globals. raj 7/94 */
- lss_size_req = sctp_rr_request->send_buf_size;
- lsr_size_req = sctp_rr_request->recv_buf_size;
- loc_nodelay = sctp_rr_request->no_delay;
- loc_rcvavoid = sctp_rr_request->so_rcvavoid;
- loc_sndavoid = sctp_rr_request->so_sndavoid;
- non_block = sctp_rr_request->non_blocking;
-
- set_hostname_and_port(local_name,
- port_buffer,
- nf_to_af(sctp_rr_request->ipfamily),
- sctp_rr_request->port);
-
- local_res = complete_addrinfo(local_name,
- local_name,
- port_buffer,
- nf_to_af(sctp_rr_request->ipfamily),
- SOCK_SEQPACKET,
- IPPROTO_SCTP,
- 0);
-
- /* Grab a socket to listen on, and then listen on it. */
- if (debug) {
- fprintf(where,"recv_sctp_rr_1toMany: grabbing a socket...\n");
- fflush(where);
- }
-
- s_rcv = create_data_socket(local_res);
-
- if (s_rcv < 0) {
- netperf_response.content.serv_errno = errno;
- send_response();
-
- exit(1);
- }
-
- /* Now, let's set-up the socket to listen for connections */
- if (listen(s_rcv, 5) == -1) {
- netperf_response.content.serv_errno = errno;
- close(s_rcv);
- send_response();
-
- exit(1);
- }
-
-
- /* now get the port number assigned by the system */
- addrlen = sizeof(myaddr_in);
- if (getsockname(s_rcv,
- (struct sockaddr *)&myaddr_in, &addrlen) == -1){
- netperf_response.content.serv_errno = errno;
- close(s_rcv);
- send_response();
-
- exit(1);
- }
-
- /* Now myaddr_in contains the port and the internet address this is */
- /* returned to the sender also implicitly telling the sender that the */
- /* socket buffer sizing has been done. */
-
- sctp_rr_response->data_port_number = (int) ntohs(myaddr_in.sin_port);
- netperf_response.content.serv_errno = 0;
-
- /* But wait, there's more. If the initiator wanted cpu measurements, */
- /* then we must call the calibrate routine, which will return the max */
- /* rate back to the initiator. If the CPU was not to be measured, or */
- /* something went wrong with the calibration, we will return a 0.0 to */
- /* the initiator. */
-
- sctp_rr_response->cpu_rate = (float)0.0; /* assume no cpu */
- sctp_rr_response->measure_cpu = 0;
-
- if (sctp_rr_request->measure_cpu) {
- sctp_rr_response->measure_cpu = 1;
- sctp_rr_response->cpu_rate = calibrate_local_cpu(sctp_rr_request->cpu_rate);
- }
-
-
- /* before we send the response back to the initiator, pull some of */
- /* the socket parms from the globals */
- sctp_rr_response->send_buf_size = lss_size;
- sctp_rr_response->recv_buf_size = lsr_size;
- sctp_rr_response->no_delay = loc_nodelay;
- sctp_rr_response->so_rcvavoid = loc_rcvavoid;
- sctp_rr_response->so_sndavoid = loc_sndavoid;
- sctp_rr_response->test_length = sctp_rr_request->test_length;
- send_response();
-
- /* Don't need events */
- sctp_enable_events(s_rcv, 0);
-
- /* now that we are connected, mark the socket as non-blocking */
- if (non_block) {
- if (!set_nonblock(s_rcv)) {
- perror("netperf: set_nonblock");
- exit(1);
- }
- }
-
- /* FIXME: The way 1-to-Many test operates right now, we are including
- * association setup time into our measurements. The reason for this
- * is that the client creates multiple endpoints and connects each
- * endpoint to us using the connect call. On this end we simply call
- * recvmsg() to get data becuase there is no equivalen of accept() for
- * 1-to-Many API.
- * I think this is OK, but if it were to be fixed, the server side
- * would need to know how many associations are being setup and
- * have a recvmsg() loop with SCTP_ASSOC_CHANGE events waiting for
- * all the associations to be be established.
- * I am punting on this for now.
- */
-
-
- addrlen = sizeof(peeraddr);
-
- /* Now it's time to start receiving data on the connection. We will */
- /* first grab the apropriate counters and then start grabbing. */
-
- cpu_start(sctp_rr_request->measure_cpu);
-
- /* The loop will exit when we hit the end of the test time, or when */
- /* we have exchanged the requested number of transactions. */
-
- if (sctp_rr_request->test_length > 0) {
- times_up = 0;
- trans_remaining = 0;
- start_timer(sctp_rr_request->test_length + PAD_TIME);
- }
- else {
- times_up = 1;
- trans_remaining = sctp_rr_request->test_length * -1;
- }
-
- trans_received = 0;
-
- while ((!times_up) || (trans_remaining > 0)) {
-
- recv_buf_size = sctp_rr_request->request_size;
-
- /* Receive the data. We don't particularly care which association
- * the data came in on. We'll simply be doing a receive untill
- * we get and MSG_EOR flag (meaning that a single transmission was
- * received) and a send to the same address, so the RR would be for
- * the same associations.
- * We can get away with this because the client will establish all
- * the associations before transmitting any data. Any partial data
- * will not have EOR thus will we will not send a response untill
- * we get everything.
- */
-
- do {
- msg_flags = 0;
- if((bytes_recvd = sctp_recvmsg(s_rcv,
- recv_ring->buffer_ptr,
- recv_buf_size,
- (struct sockaddr *)&peeraddr, &addrlen,
- 0, &msg_flags)) == SOCKET_ERROR) {
- if (SOCKET_EINTR(bytes_recvd)) {
- /* the timer popped */
- timed_out = 1;
- break;
- } else if (non_block & errno == EAGAIN) {
- /* do recvmsg again */
- continue;
- }
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
- } while(!(msg_flags & MSG_EOR));
-
- recv_ring = recv_ring->next;
-
- if (timed_out) {
- /* we hit the end of the test based on time - lets */
- /* bail out of here now... */
- if (debug) {
- fprintf(where,"yo5\n");
- fflush(where);
- }
- break;
- }
-
- /* Now, send the response to the remote */
- while ((bytes_sent=sctp_sendmsg(s_rcv,
- send_ring->buffer_ptr,
- sctp_rr_request->response_size,
- (struct sockaddr *)&peeraddr, addrlen,
- 0, 0, 0, 0, 0)) == SOCKET_ERROR) {
- if (SOCKET_EINTR(bytes_sent)) {
- /* the test timer has popped */
- timed_out = 1;
- break;
- } else if (non_block && errno == EAGAIN) {
- continue;
- }
-
- netperf_response.content.serv_errno = 992;
- send_response();
- exit(1);
- }
-
- if (timed_out) {
- if (debug) {
- fprintf(where,"yo6\n");
- fflush(where);
- }
- /* we hit the end of the test based on time - lets */
- /* bail out of here now... */
- break;
- }
-
- send_ring = send_ring->next;
-
- trans_received++;
- if (trans_remaining) {
- trans_remaining--;
- }
- }
-
-
- /* The loop now exits due to timeout or transaction count being */
- /* reached */
-
- cpu_stop(sctp_rr_request->measure_cpu,&elapsed_time);
-
- stop_timer();
-
- if (timed_out) {
- /* we ended the test by time, which was at least 2 seconds */
- /* longer than we wanted to run. so, we want to subtract */
- /* PAD_TIME from the elapsed_time. */
- elapsed_time -= PAD_TIME;
- }
-
- /* send the results to the sender */
-
- if (debug) {
- fprintf(where,
- "recv_sctp_rr: got %d transactions\n",
- trans_received);
- fflush(where);
- }
-
- sctp_rr_results->bytes_received = (trans_received *
- (sctp_rr_request->request_size +
- sctp_rr_request->response_size));
- sctp_rr_results->trans_received = trans_received;
- sctp_rr_results->elapsed_time = elapsed_time;
- sctp_rr_results->cpu_method = cpu_method;
- sctp_rr_results->num_cpus = lib_num_loc_cpus;
- if (sctp_rr_request->measure_cpu) {
- sctp_rr_results->cpu_util = calc_cpu_util(elapsed_time);
- }
-
- if (debug) {
- fprintf(where,
- "recv_sctp_rr: test complete, sending results.\n");
- fflush(where);
- }
-
- /* we are now done with the sockets */
- close(s_rcv);
-
- send_response();
-
-}
-
-
-void
-print_sctp_usage()
-{
-
- printf("%s",sctp_usage);
- exit(1);
-
-}
-void
-scan_sctp_args(argc, argv)
- int argc;
- char *argv[];
-
-{
-
-#define SOCKETS_ARGS "BDhH:I:L:m:M:P:r:s:S:VN:T:46"
-
- extern char *optarg; /* pointer to option string */
-
- int c;
-
- char
- arg1[BUFSIZ], /* argument holders */
- arg2[BUFSIZ];
-
- if (no_control) {
- fprintf(where,
- "The SCTP tests do not know how to deal with no control tests\n");
- exit(-1);
- }
-
- strncpy(local_data_port,"0",sizeof(local_data_port));
- strncpy(remote_data_port,"0",sizeof(remote_data_port));
-
- /* Go through all the command line arguments and break them */
- /* out. For those options that take two parms, specifying only */
- /* the first will set both to that value. Specifying only the */
- /* second will leave the first untouched. To change only the */
- /* first, use the form "first," (see the routine break_args.. */
-
- while ((c= getopt(argc, argv, SOCKETS_ARGS)) != EOF) {
- switch (c) {
- case '?':
- case '4':
- remote_data_family = AF_INET;
- local_data_family = AF_INET;
- break;
- case '6':
-#if defined(AF_INET6)
- remote_data_family = AF_INET6;
- local_data_family = AF_INET6;
-#else
- fprintf(stderr,
- "This netperf was not compiled on an IPv6 capable host!\n");
- fflush(stderr);
- exit(-1);
-#endif
- break;
- case 'h':
- print_sctp_usage();
- exit(1);
- case 'b':
-#ifdef WANT_FIRST_BURST
- first_burst_size = atoi(optarg);
-#else /* WANT_FIRST_BURST */
- printf("Initial request burst functionality not compiled-in!\n");
-#endif /* WANT_FIRST_BURST */
- break;
- case 'D':
- /* set the nodelay flag */
- loc_nodelay = 1;
- rem_nodelay = 1;
- break;
- case 'H':
- break_args_explicit(optarg,arg1,arg2);
- if (arg1[0]) {
- /* make sure we leave room for the NULL termination boys and
- girls. raj 2005-02-82 */
- remote_data_address = malloc(strlen(arg1)+1);
- strncpy(remote_data_address,arg1,strlen(arg1));
- }
- if (arg2[0])
- remote_data_family = parse_address_family(arg2);
- break;
- case 'L':
- break_args_explicit(optarg,arg1,arg2);
- if (arg1[0]) {
- /* make sure we leave room for the NULL termination boys and
- girls. raj 2005-02-82 */
- local_data_address = malloc(strlen(arg1)+1);
- strncpy(local_data_address,arg1,strlen(arg1));
- }
- if (arg2[0])
- local_data_family = parse_address_family(arg2);
- break;
- case 'P':
- /* set the local and remote data port numbers for the tests to
- allow them to run through those blankety blank end-to-end
- breaking firewalls. raj 2004-06-15 */
- break_args(optarg,arg1,arg2);
- if (arg1[0])
- strncpy(local_data_port,arg1,sizeof(local_data_port));
- if (arg2[0])
- strncpy(remote_data_port,arg2,sizeof(remote_data_port));
- break;
- case 's':
- /* set local socket sizes */
- break_args(optarg,arg1,arg2);
- if (arg1[0])
- lss_size_req = convert(arg1);
- if (arg2[0])
- lsr_size_req = convert(arg2);
- break;
- case 'S':
- /* set remote socket sizes */
- break_args(optarg,arg1,arg2);
- if (arg1[0])
- rss_size_req = convert(arg1);
- if (arg2[0])
- rsr_size_req = convert(arg2);
- break;
- case 'r':
- /* set the request/response sizes */
- break_args(optarg,arg1,arg2);
- if (arg1[0])
- req_size = convert(arg1);
- if (arg2[0])
- rsp_size = convert(arg2);
- break;
- case 'm':
- /* set size of the buffer for each sent message */
- send_size = convert(optarg);
- break;
- case 'M':
- /* set the size of the buffer for each received message */
- recv_size = convert(optarg);
- break;
- case 't':
- /* set the test name */
- strcpy(test_name,optarg);
- break;
- case 'W':
- /* set the "width" of the user space data */
- /* buffer. This will be the number of */
- /* send_size buffers malloc'd in the */
- /* *_STREAM test. It may be enhanced to set */
- /* both send and receive "widths" but for now */
- /* it is just the sending *_STREAM. */
- send_width = convert(optarg);
- break;
- case 'V':
- /* we want to do copy avoidance and will set */
- /* it for everything, everywhere, if we really */
- /* can. of course, we don't know anything */
- /* about the remote... */
-#ifdef SO_SND_COPYAVOID
- loc_sndavoid = 1;
-#else
- loc_sndavoid = 0;
- printf("Local send copy avoidance not available.\n");
-#endif
-#ifdef SO_RCV_COPYAVOID
- loc_rcvavoid = 1;
-#else
- loc_rcvavoid = 0;
- printf("Local recv copy avoidance not available.\n");
-#endif
- rem_sndavoid = 1;
- rem_rcvavoid = 1;
- break;
- case 'N':
- /* this opton allows the user to set the number of
- * messages to send. This in effect modifies the test
- * time. If we know the message size, then the we can
- * express the test time as message_size * number_messages
- */
- msg_count = convert (optarg);
- if (msg_count > 0)
- test_time = 0;
- break;
- case 'B':
- non_block = 1;
- break;
- case 'T':
- num_associations = atoi(optarg);
- if (num_associations <= 1) {
- printf("Number of SCTP associations must be >= 1\n");
- exit(1);
- }
- break;
- };
- }
-}
-
-#endif /* WANT_SCTP */
diff --git a/nettest_sctp.h b/nettest_sctp.h
deleted file mode 100644
index 5297853..0000000
--- a/nettest_sctp.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- Copyright (C) 1993-2003 Hewlett-Packard Company
-*/
-
- /* This file contains the test-specific definitions for netperf's BSD */
- /* sockets tests */
-
-
-struct sctp_stream_request_struct {
- int send_buf_size;
- int recv_buf_size; /* how big does the client want it - the */
- /* receive socket buffer that is */
- int receive_size; /* how many bytes do we want to receive at one */
- /* time? */
- int recv_alignment; /* what is the alignment of the receive */
- /* buffer? */
- int recv_offset; /* and at what offset from that alignment? */
- int no_delay; /* do we disable the nagle algorithm for send */
- /* coalescing? */
- int measure_cpu; /* does the client want server cpu utilization */
- /* measured? */
- float cpu_rate; /* do we know how fast the cpu is already? */
- int test_length; /* how long is the test? */
- int so_rcvavoid; /* do we want the remote to avoid copies on */
- /* receives? */
- int so_sndavoid; /* do we want the remote to avoid send copies? */
- int dirty_count; /* how many integers in the receive buffer */
- /* should be made dirty before calling recv? */
- int clean_count; /* how many integers should be read from the */
- /* recv buffer before calling recv? */
- int port; /* the to port to which recv side should bind
- to allow netperf to run through firewalls */
- int ipfamily; /* address family of ipaddress */
- int non_blocking; /* run the test in non-blocking mode */
-};
-
-struct sctp_stream_response_struct {
- int recv_buf_size; /* how big does the client want it */
- int receive_size;
- int no_delay;
- int measure_cpu; /* does the client want server cpu */
- int test_length; /* how long is the test? */
- int send_buf_size;
- int data_port_number; /* connect to me here */
- float cpu_rate; /* could we measure */
- int so_rcvavoid; /* could the remote avoid receive copies? */
- int so_sndavoid; /* could the remote avoid send copies? */
- int non_blocking; /* run the test in non-blocking mode */
-};
-
-struct sctp_stream_results_struct {
- double bytes_received;
- unsigned int recv_calls;
- float elapsed_time; /* how long the test ran */
- float cpu_util; /* -1 if not measured */
- float serv_dem; /* -1 if not measured */
- int cpu_method; /* how was cpu util measured? */
- int num_cpus; /* how many CPUs had the remote? */
-};
-
-struct sctp_rr_request_struct {
- int recv_buf_size; /* how big does the client want it */
- int send_buf_size;
- int recv_alignment;
- int recv_offset;
- int send_alignment;
- int send_offset;
- int request_size;
- int response_size;
- int no_delay;
- int measure_cpu; /* does the client want server cpu */
- float cpu_rate; /* do we know how fast the cpu is? */
- int test_length; /* how long is the test? */
- int so_rcvavoid; /* do we want the remote to avoid receive */
- /* copies? */
- int so_sndavoid; /* do we want the remote to avoid send copies? */
- int port; /* the to port to which recv side should bind
- to allow netperf to run through firewalls */
- int ipfamily; /* address family of ipaddress */
- int non_blocking; /* run the test in non-blocking mode */
-};
-
-struct sctp_rr_response_struct {
- int recv_buf_size; /* how big does the client want it */
- int no_delay;
- int measure_cpu; /* does the client want server cpu */
- int test_length; /* how long is the test? */
- int send_buf_size;
- int data_port_number; /* connect to me here */
- float cpu_rate; /* could we measure */
- int so_rcvavoid; /* could the remote avoid receive copies? */
- int so_sndavoid; /* could the remote avoid send copies? */
- int non_blocking; /* run the test in non-blocking mode */
-};
-
-struct sctp_rr_results_struct {
- unsigned int bytes_received; /* ignored initially */
- unsigned int recv_calls; /* ignored initially */
- unsigned int trans_received; /* not ignored */
- float elapsed_time; /* how long the test ran */
- float cpu_util; /* -1 if not measured */
- float serv_dem; /* -1 if not measured */
- int cpu_method; /* how was cpu util measured? */
- int num_cpus; /* how many CPUs had the remote? */
-};
-
-#define SCTP_SNDRCV_INFO_EV 0x01
-#define SCTP_ASSOC_CHANGE_EV 0x02
-#define SCTP_PEERADDR_CHANGE_EV 0x04
-#define SCTP_SND_FAILED_EV 0x08
-#define SCTP_REMOTE_ERROR_EV 0x10
-#define SCTP_SHUTDOWN_EV 0x20
-#define SCTP_PD_EV 0x40
-#define SCTP_ADAPT_EV 0x80
-
-typedef enum sctp_disposition {
- SCTP_OK = 1,
- SCTP_CLOSE,
-} sctp_disposition_t;
-
-extern void send_sctp_stream();
-extern void send_sctp_rr();
-
-extern void recv_sctp_stream();
-extern void recv_sctp_rr();
-
-extern void loc_cpu_rate();
-extern void rem_cpu_rate();
diff --git a/nettest_sdp.c b/nettest_sdp.c
deleted file mode 100644
index 696fd3e..0000000
--- a/nettest_sdp.c
+++ /dev/null
@@ -1,3553 +0,0 @@
-#ifndef lint
-char nettest_sdp[]="\
-@(#)nettest_sdp.c (c) Copyright 2007 Hewlett-Packard Co. Version 2.4.4";
-#else
-#define DIRTY
-#define WANT_HISTOGRAM
-#define WANT_INTERVALS
-#endif /* lint */
-
-/****************************************************************/
-/* */
-/* nettest_sdp.c */
-/* */
-/* */
-/* scan_sdp_args() get the sdp command line args */
-/* */
-/* the actual test routines... */
-/* */
-/* send_sdp_stream() perform a sdp stream test */
-/* recv_sdp_stream() */
-/* send_sdp_rr() perform a sdp request/response */
-/* recv_sdp_rr() */
-/* */
-/* relies on create_data_socket in nettest_bsd.c */
-/****************************************************************/
-
-#if HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#if defined(WANT_SDP)
-
-#include <sys/types.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <signal.h>
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#ifdef NOSTDLIBH
-#include <malloc.h>
-#else /* NOSTDLIBH */
-#include <stdlib.h>
-#endif /* NOSTDLIBH */
-
-#if !defined(__VMS)
-#include <sys/ipc.h>
-#endif /* !defined(__VMS) */
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-
-/* would seem that not all sdp.h files define a MSG_EOF, but that
- MSG_EOF can be the same as MSG_FIN so lets work with that
- assumption. initial find by Jon Pedersen. raj 2006-02-01 */
-#ifndef MSG_EOF
-#ifdef MSG_FIN
-#define MSG_EOF MSG_FIN
-#else
-#error Must have either MSG_EOF or MSG_FIN defined
-#endif
-#endif
-
-#include "netlib.h"
-#include "netsh.h"
-/* get some of the functions from nettest_bsd.c */
-#include "nettest_bsd.h"
-#include "nettest_sdp.h"
-
-#ifdef WANT_HISTOGRAM
-#ifdef __sgi
-#include <sys/time.h>
-#endif /* __sgi */
-#include "hist.h"
-#endif /* WANT_HISTOGRAM */
-
-#ifdef WANT_FIRST_BURST
-extern int first_burst_size;
-#endif /* WANT_FIRST_BURST */
-
-
-
-/* these variables are specific to SDP tests. declare */
-/* them static to make them global only to this file. */
-
-static int
- msg_count = 0, /* number of messages to transmit on association */
- non_block = 0, /* default to blocking sockets */
- num_associations = 1; /* number of associations on the endpoint */
-
-static int confidence_iteration;
-static char local_cpu_method;
-static char remote_cpu_method;
-
-#ifdef WANT_HISTOGRAM
-static struct timeval time_one;
-static struct timeval time_two;
-static HIST time_hist;
-#endif /* WANT_HISTOGRAM */
-
-
-char sdp_usage[] = "\n\
-Usage: netperf [global options] -- [test options] \n\
-\n\
-SDP Sockets Test Options:\n\
- -b number Send number requests at the start of _RR tests\n\
- -D [L][,R] Set SDP_NODELAY locally and/or remotely\n\
- -h Display this text\n\
- -H name,fam Use name (or IP) and family as target of data connection\n\
- -L name,fam Use name (or IP) and family as source of data connextion\n\
- -m bytes Set the size of each sent message\n\
- -M bytes Set the size of each received messages\n\
- -P local[,remote] Set the local/remote port for the data socket\n\
- -r req,[rsp] Set request/response sizes (_RR tests)\n\
- -s send[,recv] Set local socket send/recv buffer sizes\n\
- -S send[,recv] Set remote socket send/recv buffer sizes\n\
- -V Enable copy avoidance if supported\n\
- -4 Use AF_INET (eg IPv4) on both ends of the data conn\n\
- -6 Use AF_INET6 (eg IPv6) on both ends of the data conn\n\
-\n\
-For those options taking two parms, at least one must be specified;\n\
-specifying one value without a comma will set both parms to that\n\
-value, specifying a value with a leading comma will set just the second\n\
-parm, a value with a trailing comma will set just the first. To set\n\
-each parm to unique values, specify both and separate them with a\n\
-comma.\n";
-
-
- /* This routine is intended to retrieve interesting aspects of sdp */
- /* for the data connection. at first, it attempts to retrieve the */
- /* maximum segment size. later, it might be modified to retrieve */
- /* other information, but it must be information that can be */
- /* retrieved quickly as it is called during the timing of the test. */
- /* for that reason, a second routine may be created that can be */
- /* called outside of the timing loop */
-static
-void
-get_sdp_info(int socket, int * mss)
-{
-
-#ifdef TCP_MAXSEG
- netperf_socklen_t sock_opt_len;
-
- sock_opt_len = sizeof(netperf_socklen_t);
- if (getsockopt(socket,
- getprotobyname("tcp")->p_proto,
- TCP_MAXSEG,
- (char *)mss,
- &sock_opt_len) == SOCKET_ERROR) {
- fprintf(where,
- "netperf: get_sdp_info: getsockopt TCP_MAXSEG: errno %d\n",
- errno);
- fflush(where);
- *mss = -1;
- }
-#else
- *mss = -1;
-#endif /* TCP_MAXSEG */
-
-}
-
-void
-send_sdp_stream(char remote_host[])
-{
-
- char *tput_title = "\
-Recv Send Send \n\
-Socket Socket Message Elapsed \n\
-Size Size Size Time Throughput \n\
-bytes bytes bytes secs. %s/sec \n\n";
-
- char *tput_fmt_0 =
- "%7.2f %s\n";
-
- char *tput_fmt_1 =
- "%6d %6d %6d %-6.2f %7.2f %s\n";
-
- char *cpu_title = "\
-Recv Send Send Utilization Service Demand\n\
-Socket Socket Message Elapsed Send Recv Send Recv\n\
-Size Size Size Time Throughput local remote local remote\n\
-bytes bytes bytes secs. %-8.8s/s %% %c %% %c us/KB us/KB\n\n";
-
- char *cpu_fmt_0 =
- "%6.3f %c %s\n";
-
- char *cpu_fmt_1 =
- "%6d %6d %6d %-6.2f %7.2f %-6.2f %-6.2f %-6.3f %-6.3f %s\n";
-
- char *ksink_fmt = "\n\
-Alignment Offset %-8.8s %-8.8s Sends %-8.8s Recvs\n\
-Local Remote Local Remote Xfered Per Per\n\
-Send Recv Send Recv Send (avg) Recv (avg)\n\
-%5d %5d %5d %5d %6.4g %6.2f %6d %6.2f %6d\n";
-
- char *ksink_fmt2 = "\n\
-Maximum\n\
-Segment\n\
-Size (bytes)\n\
-%6d\n";
-
-
- float elapsed_time;
-
- /* what we want is to have a buffer space that is at least one */
- /* send-size greater than our send window. this will insure that we */
- /* are never trying to re-use a buffer that may still be in the hands */
- /* of the transport. This buffer will be malloc'd after we have found */
- /* the size of the local senc socket buffer. We will want to deal */
- /* with alignment and offset concerns as well. */
-
- struct ring_elt *send_ring;
-
- int len;
- unsigned int nummessages = 0;
- SOCKET send_socket;
- int bytes_remaining;
- int sdp_mss = -1; /* possibly uninitialized on printf far below */
-
- /* with links like fddi, one can send > 32 bits worth of bytes */
- /* during a test... ;-) at some point, this should probably become a */
- /* 64bit integral type, but those are not entirely common yet */
-
- unsigned long long local_bytes_sent = 0;
- double bytes_sent = 0.0;
-
- float local_cpu_utilization;
- float local_service_demand;
- float remote_cpu_utilization;
- float remote_service_demand;
-
- double thruput;
-
- struct addrinfo *remote_res;
- struct addrinfo *local_res;
-
- struct sdp_stream_request_struct *sdp_stream_request;
- struct sdp_stream_response_struct *sdp_stream_response;
- struct sdp_stream_results_struct *sdp_stream_result;
-
- sdp_stream_request =
- (struct sdp_stream_request_struct *)netperf_request.content.test_specific_data;
- sdp_stream_response =
- (struct sdp_stream_response_struct *)netperf_response.content.test_specific_data;
- sdp_stream_result =
- (struct sdp_stream_results_struct *)netperf_response.content.test_specific_data;
-
-#ifdef WANT_HISTOGRAM
- if (verbosity > 1) {
- time_hist = HIST_new();
- }
-#endif /* WANT_HISTOGRAM */
- /* since we are now disconnected from the code that established the */
- /* control socket, and since we want to be able to use different */
- /* protocols and such, we are passed the name of the remote host and */
- /* must turn that into the test specific addressing information. */
-
- /* complete_addrinfos will either succede or exit the process */
- complete_addrinfos(&remote_res,
- &local_res,
- remote_host,
- SOCK_STREAM,
- IPPROTO_TCP,
- 0);
-
- if ( print_headers ) {
- print_top_test_header("SDP STREAM TEST",local_res,remote_res);
- }
-
- send_ring = NULL;
- confidence_iteration = 1;
- init_stat();
-
- /* we have a great-big while loop which controls the number of times */
- /* we run a particular test. this is for the calculation of a */
- /* confidence interval (I really should have stayed awake during */
- /* probstats :). If the user did not request confidence measurement */
- /* (no confidence is the default) then we will only go though the */
- /* loop once. the confidence stuff originates from the folks at IBM */
-
- while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
- (confidence_iteration <= iteration_min)) {
-
- /* initialize a few counters. we have to remember that we might be */
- /* going through the loop more than once. */
-
- nummessages = 0;
- bytes_sent = 0.0;
- times_up = 0;
-
- /*set up the data socket */
- /* fake things out by changing local_res->ai_family to AF_INET_SDP */
- local_res->ai_family = AF_INET_SDP;
- local_res->ai_protocol = 0;
- send_socket = create_data_socket(local_res);
-
- if (send_socket == INVALID_SOCKET){
- perror("netperf: send_sdp_stream: sdp stream data socket");
- exit(1);
- }
-
- if (debug) {
- fprintf(where,"send_sdp_stream: send_socket obtained...\n");
- }
-
- /* at this point, we have either retrieved the socket buffer sizes, */
- /* or have tried to set them, so now, we may want to set the send */
- /* size based on that (because the user either did not use a -m */
- /* option, or used one with an argument of 0). If the socket buffer */
- /* size is not available, we will set the send size to 4KB - no */
- /* particular reason, just arbitrary... */
- if (send_size == 0) {
- if (lss_size > 0) {
- send_size = lss_size;
- }
- else {
- send_size = 4096;
- }
- }
-
- /* set-up the data buffer ring with the requested alignment and offset. */
- /* note also that we have allocated a quantity */
- /* of memory that is at least one send-size greater than our socket */
- /* buffer size. We want to be sure that there are at least two */
- /* buffers allocated - this can be a bit of a problem when the */
- /* send_size is bigger than the socket size, so we must check... the */
- /* user may have wanted to explicitly set the "width" of our send */
- /* buffers, we should respect that wish... */
- if (send_width == 0) {
- send_width = (lss_size/send_size) + 1;
- if (send_width == 1) send_width++;
- }
-
- if (send_ring == NULL) {
- /* only allocate the send ring once. this is a networking test, */
- /* not a memory allocation test. this way, we do not need a */
- /* deallocate_buffer_ring() routine, and I don't feel like */
- /* writing one anyway :) raj 11/94 */
- send_ring = allocate_buffer_ring(send_width,
- send_size,
- local_send_align,
- local_send_offset);
- }
-
- /* If the user has requested cpu utilization measurements, we must */
- /* calibrate the cpu(s). We will perform this task within the tests */
- /* themselves. If the user has specified the cpu rate, then */
- /* calibrate_local_cpu will return rather quickly as it will have */
- /* nothing to do. If local_cpu_rate is zero, then we will go through */
- /* all the "normal" calibration stuff and return the rate back. */
-
- if (local_cpu_usage) {
- local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
- }
-
- if (!no_control) {
- /* Tell the remote end to do a listen. The server alters the
- socket paramters on the other side at this point, hence the
- reason for all the values being passed in the setup
- message. If the user did not specify any of the parameters,
- they will be passed as 0, which will indicate to the remote
- that no changes beyond the system's default should be
- used. Alignment is the exception, it will default to 1, which
- will be no alignment alterations. */
-
- netperf_request.content.request_type = DO_SDP_STREAM;
- sdp_stream_request->send_buf_size = rss_size_req;
- sdp_stream_request->recv_buf_size = rsr_size_req;
- sdp_stream_request->receive_size = recv_size;
- sdp_stream_request->no_delay = rem_nodelay;
- sdp_stream_request->recv_alignment = remote_recv_align;
- sdp_stream_request->recv_offset = remote_recv_offset;
- sdp_stream_request->measure_cpu = remote_cpu_usage;
- sdp_stream_request->cpu_rate = remote_cpu_rate;
- if (test_time) {
- sdp_stream_request->test_length = test_time;
- }
- else {
- sdp_stream_request->test_length = test_bytes;
- }
- sdp_stream_request->so_rcvavoid = rem_rcvavoid;
- sdp_stream_request->so_sndavoid = rem_sndavoid;
-#ifdef DIRTY
- sdp_stream_request->dirty_count = rem_dirty_count;
- sdp_stream_request->clean_count = rem_clean_count;
-#endif /* DIRTY */
- sdp_stream_request->port = atoi(remote_data_port);
- sdp_stream_request->ipfamily = af_to_nf(remote_res->ai_family);
- if (debug > 1) {
- fprintf(where,
- "netperf: send_sdp_stream: requesting SDP stream test\n");
- }
-
- send_request();
-
- /* The response from the remote will contain all of the relevant
- socket parameters for this test type. We will put them back
- into the variables here so they can be displayed if desired.
- The remote will have calibrated CPU if necessary, and will
- have done all the needed set-up we will have calibrated the
- cpu locally before sending the request, and will grab the
- counter value right after the connect returns. The remote
- will grab the counter right after the accept call. This saves
- the hassle of extra messages being sent for the SDP
- tests. */
-
- recv_response();
-
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote listen done.\n");
- rsr_size = sdp_stream_response->recv_buf_size;
- rss_size = sdp_stream_response->send_buf_size;
- rem_nodelay = sdp_stream_response->no_delay;
- remote_cpu_usage= sdp_stream_response->measure_cpu;
- remote_cpu_rate = sdp_stream_response->cpu_rate;
-
- /* we have to make sure that the server port number is in
- network order */
- set_port_number(remote_res,
- (short)sdp_stream_response->data_port_number);
-
- rem_rcvavoid = sdp_stream_response->so_rcvavoid;
- rem_sndavoid = sdp_stream_response->so_sndavoid;
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- fprintf(where,
- "netperf: remote error %d",
- netperf_response.content.serv_errno);
- perror("");
- fflush(where);
-
- exit(1);
- }
- }
-
-#ifdef WANT_DEMO
- DEMO_STREAM_SETUP(lss_size,rsr_size)
-#endif
-
- /*Connect up to the remote port on the data socket */
- if (connect(send_socket,
- remote_res->ai_addr,
- remote_res->ai_addrlen) == INVALID_SOCKET){
- perror("netperf: send_sdp_stream: data socket connect failed");
- exit(1);
- }
-
- /* Data Socket set-up is finished. If there were problems, either */
- /* the connect would have failed, or the previous response would */
- /* have indicated a problem. I failed to see the value of the */
- /* extra message after the accept on the remote. If it failed, */
- /* we'll see it here. If it didn't, we might as well start pumping */
- /* data. */
-
- /* Set-up the test end conditions. For a stream test, they can be */
- /* either time or byte-count based. */
-
- if (test_time) {
- /* The user wanted to end the test after a period of time. */
- times_up = 0;
- bytes_remaining = 0;
- /* in previous revisions, we had the same code repeated throught */
- /* all the test suites. this was unnecessary, and meant more */
- /* work for me when I wanted to switch to POSIX signals, so I */
- /* have abstracted this out into a routine in netlib.c. if you */
- /* are experiencing signal problems, you might want to look */
- /* there. raj 11/94 */
- start_timer(test_time);
- }
- else {
- /* The tester wanted to send a number of bytes. */
- bytes_remaining = test_bytes;
- times_up = 1;
- }
-
- /* The cpu_start routine will grab the current time and possibly */
- /* value of the idle counter for later use in measuring cpu */
- /* utilization and/or service demand and thruput. */
-
- cpu_start(local_cpu_usage);
-
- /* we only start the interval timer if we are using the
- timer-timed intervals rather than the sit and spin ones. raj
- 2006-02-06 */
-#if defined(WANT_INTERVALS)
- INTERVALS_INIT();
-#endif /* WANT_INTERVALS */
-
- /* before we start, initialize a few variables */
-
-#ifdef WANT_DEMO
- if (demo_mode) {
- HIST_timestamp(demo_one_ptr);
- }
-#endif
-
-
- /* We use an "OR" to control test execution. When the test is */
- /* controlled by time, the byte count check will always return false. */
- /* When the test is controlled by byte count, the time test will */
- /* always return false. When the test is finished, the whole */
- /* expression will go false and we will stop sending data. */
-
- while ((!times_up) || (bytes_remaining > 0)) {
-
-#ifdef DIRTY
- access_buffer(send_ring->buffer_ptr,
- send_size,
- loc_dirty_count,
- loc_clean_count);
-#endif /* DIRTY */
-
-#ifdef WANT_HISTOGRAM
- if (verbosity > 1) {
- /* timestamp just before we go into send and then again just
- after we come out raj 8/94 */
- /* but lets only do this if there is going to be a histogram
- displayed */
- HIST_timestamp(&time_one);
- }
-#endif /* WANT_HISTOGRAM */
-
- if((len=send(send_socket,
- send_ring->buffer_ptr,
- send_size,
- 0)) != send_size) {
- if ((len >=0) || SOCKET_EINTR(len)) {
- /* the test was interrupted, must be the end of test */
- break;
- }
- perror("netperf: data send error");
- printf("len was %d\n",len);
- exit(1);
- }
-
- local_bytes_sent += send_size;
-
-#ifdef WANT_HISTOGRAM
- if (verbosity > 1) {
- /* timestamp the exit from the send call and update the histogram */
- HIST_timestamp(&time_two);
- HIST_add(time_hist,delta_micro(&time_one,&time_two));
- }
-#endif /* WANT_HISTOGRAM */
-
-#ifdef WANT_DEMO
- DEMO_STREAM_INTERVAL(send_size)
-#endif
-
-#if defined(WANT_INTERVALS)
- INTERVALS_WAIT();
-#endif /* WANT_INTERVALS */
-
- /* now we want to move our pointer to the next position in the */
- /* data buffer...we may also want to wrap back to the "beginning" */
- /* of the bufferspace, so we will mod the number of messages sent */
- /* by the send width, and use that to calculate the offset to add */
- /* to the base pointer. */
- nummessages++;
- send_ring = send_ring->next;
- if (bytes_remaining) {
- bytes_remaining -= send_size;
- }
- }
-
- /* The test is over. Flush the buffers to the remote end. We do a */
- /* graceful release to insure that all data has been taken by the */
- /* remote. */
-
- /* but first, if the verbosity is greater than 1, find-out what */
- /* the SDP maximum segment_size was (if possible) */
- if (verbosity > 1) {
- sdp_mss = -1;
- get_sdp_info(send_socket,&sdp_mss);
- }
-
- if (shutdown(send_socket,SHUT_WR) == SOCKET_ERROR) {
- perror("netperf: cannot shutdown sdp stream socket");
- exit(1);
- }
-
- /* hang a recv() off the socket to block until the remote has */
- /* brought all the data up into the application. it will do a */
- /* shutdown to cause a FIN to be sent our way. We will assume that */
- /* any exit from the recv() call is good... raj 4/93 */
-
- recv(send_socket, send_ring->buffer_ptr, send_size, 0);
-
- /* this call will always give us the elapsed time for the test, and */
- /* will also store-away the necessaries for cpu utilization */
-
- cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */
- /* measured and how */
- /* long did we really */
- /* run? */
-
- /* we are finished with the socket, so close it to prevent hitting */
- /* the limit on maximum open files. */
-
- close(send_socket);
-
- if (!no_control) {
- /* Get the statistics from the remote end. The remote will have
- calculated service demand and all those interesting
- things. If it wasn't supposed to care, it will return obvious
- values. */
-
- recv_response();
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote results obtained\n");
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- fprintf(where,
- "netperf: remote error %d",
- netperf_response.content.serv_errno);
- perror("");
- fflush(where);
-
- exit(1);
- }
-
- /* We now calculate what our thruput was for the test. In the
- future, we may want to include a calculation of the thruput
- measured by the remote, but it should be the case that for a
- SDP stream test, that the two numbers should be *very*
- close... We calculate bytes_sent regardless of the way the
- test length was controlled. If it was time, we needed to,
- and if it was by bytes, the user may have specified a number
- of bytes that wasn't a multiple of the send_size, so we
- really didn't send what he asked for ;-) */
-
- bytes_sent = ntohd(sdp_stream_result->bytes_received);
- }
- else {
- bytes_sent = (double)local_bytes_sent;
- }
-
- thruput = calc_thruput(bytes_sent);
-
- if (local_cpu_usage || remote_cpu_usage) {
- /* We must now do a little math for service demand and cpu */
- /* utilization for the system(s) */
- /* Of course, some of the information might be bogus because */
- /* there was no idle counter in the kernel(s). We need to make */
- /* a note of this for the user's benefit...*/
- if (local_cpu_usage) {
-
- local_cpu_utilization = calc_cpu_util(0.0);
- local_service_demand = calc_service_demand(bytes_sent,
- 0.0,
- 0.0,
- 0);
- }
- else {
- local_cpu_utilization = (float) -1.0;
- local_service_demand = (float) -1.0;
- }
-
- if (remote_cpu_usage) {
-
- remote_cpu_utilization = sdp_stream_result->cpu_util;
- remote_service_demand = calc_service_demand(bytes_sent,
- 0.0,
- remote_cpu_utilization,
- sdp_stream_result->num_cpus);
- }
- else {
- remote_cpu_utilization = (float) -1.0;
- remote_service_demand = (float) -1.0;
- }
- }
- else {
- /* we were not measuring cpu, for the confidence stuff, we */
- /* should make it -1.0 */
- local_cpu_utilization = (float) -1.0;
- local_service_demand = (float) -1.0;
- remote_cpu_utilization = (float) -1.0;
- remote_service_demand = (float) -1.0;
- }
-
- /* at this point, we want to calculate the confidence information. */
- /* if debugging is on, calculate_confidence will print-out the */
- /* parameters we pass it */
-
- calculate_confidence(confidence_iteration,
- elapsed_time,
- thruput,
- local_cpu_utilization,
- remote_cpu_utilization,
- local_service_demand,
- remote_service_demand);
-
-
- confidence_iteration++;
- }
-
- /* at this point, we have finished making all the runs that we */
- /* will be making. so, we should extract what the calcuated values */
- /* are for all the confidence stuff. we could make the values */
- /* global, but that seemed a little messy, and it did not seem worth */
- /* all the mucking with header files. so, we create a routine much */
- /* like calcualte_confidence, which just returns the mean values. */
- /* raj 11/94 */
-
- retrieve_confident_values(&elapsed_time,
- &thruput,
- &local_cpu_utilization,
- &remote_cpu_utilization,
- &local_service_demand,
- &remote_service_demand);
-
- /* We are now ready to print all the information. If the user */
- /* has specified zero-level verbosity, we will just print the */
- /* local service demand, or the remote service demand. If the */
- /* user has requested verbosity level 1, he will get the basic */
- /* "streamperf" numbers. If the user has specified a verbosity */
- /* of greater than 1, we will display a veritable plethora of */
- /* background information from outside of this block as it it */
- /* not cpu_measurement specific... */
-
- if (confidence < 0) {
- /* we did not hit confidence, but were we asked to look for it? */
- if (iteration_max > 1) {
- display_confidence();
- }
- }
-
- if (local_cpu_usage || remote_cpu_usage) {
- local_cpu_method = format_cpu_method(cpu_method);
- remote_cpu_method = format_cpu_method(sdp_stream_result->cpu_method);
-
- switch (verbosity) {
- case 0:
- if (local_cpu_usage) {
- fprintf(where,
- cpu_fmt_0,
- local_service_demand,
- local_cpu_method,
- ((print_headers) ||
- (result_brand == NULL)) ? "" : result_brand);
- }
- else {
- fprintf(where,
- cpu_fmt_0,
- remote_service_demand,
- remote_cpu_method,
- ((print_headers) ||
- (result_brand == NULL)) ? "" : result_brand);
- }
- break;
- case 1:
- case 2:
- if (print_headers) {
- fprintf(where,
- cpu_title,
- format_units(),
- local_cpu_method,
- remote_cpu_method);
- }
-
- fprintf(where,
- cpu_fmt_1, /* the format string */
- rsr_size, /* remote recvbuf size */
- lss_size, /* local sendbuf size */
- send_size, /* how large were the sends */
- elapsed_time, /* how long was the test */
- thruput, /* what was the xfer rate */
- local_cpu_utilization, /* local cpu */
- remote_cpu_utilization, /* remote cpu */
- local_service_demand, /* local service demand */
- remote_service_demand, /* remote service demand */
- ((print_headers) ||
- (result_brand == NULL)) ? "" : result_brand);
- break;
- }
- }
- else {
- /* The tester did not wish to measure service demand. */
-
- switch (verbosity) {
- case 0:
- fprintf(where,
- tput_fmt_0,
- thruput,
- ((print_headers) ||
- (result_brand == NULL)) ? "" : result_brand);
- break;
- case 1:
- case 2:
- if (print_headers) {
- fprintf(where,tput_title,format_units());
- }
- fprintf(where,
- tput_fmt_1, /* the format string */
- rsr_size, /* remote recvbuf size */
- lss_size, /* local sendbuf size */
- send_size, /* how large were the sends */
- elapsed_time, /* how long did it take */
- thruput, /* how fast did it go */
- ((print_headers) ||
- (result_brand == NULL)) ? "" : result_brand);
- break;
- }
- }
-
- /* it would be a good thing to include information about some of the */
- /* other parameters that may have been set for this test, but at the */
- /* moment, I do not wish to figure-out all the formatting, so I will */
- /* just put this comment here to help remind me that it is something */
- /* that should be done at a later time. */
-
- if (verbosity > 1) {
- /* The user wanted to know it all, so we will give it to him. */
- /* This information will include as much as we can find about */
- /* SDP statistics, the alignments of the sends and receives */
- /* and all that sort of rot... */
-
- /* this stuff needs to be worked-out in the presence of confidence */
- /* intervals and multiple iterations of the test... raj 11/94 */
-
- fprintf(where,
- ksink_fmt,
- "Bytes",
- "Bytes",
- "Bytes",
- local_send_align,
- remote_recv_align,
- local_send_offset,
- remote_recv_offset,
- bytes_sent,
- bytes_sent / (double)nummessages,
- nummessages,
- bytes_sent / (double)sdp_stream_result->recv_calls,
- sdp_stream_result->recv_calls);
- fprintf(where,
- ksink_fmt2,
- sdp_mss);
- fflush(where);
-#ifdef WANT_HISTOGRAM
- fprintf(where,"\n\nHistogram of time spent in send() call.\n");
- fflush(where);
- HIST_report(time_hist);
-#endif /* WANT_HISTOGRAM */
- }
-
-}
-
-
-
-/* This routine implements the netperf-side SDP unidirectional data
- transfer test (a.k.a. stream) for the sockets interface where the
- data flow is from the netserver to the netperf. It receives its
- parameters via global variables from the shell and writes its
- output to the standard output. */
-
-
-void
-send_sdp_maerts(char remote_host[])
-{
-
- char *tput_title = "\
-Recv Send Send \n\
-Socket Socket Message Elapsed \n\
-Size Size Size Time Throughput \n\
-bytes bytes bytes secs. %s/sec \n\n";
-
- char *tput_fmt_0 =
- "%7.2f %s\n";
-
- char *tput_fmt_1 =
- "%6d %6d %6d %-6.2f %7.2f \n %s";
-
- char *cpu_title = "\
-Recv Send Send Utilization Service Demand\n\
-Socket Socket Message Elapsed Send Recv Send Recv\n\
-Size Size Size Time Throughput local remote local remote\n\
-bytes bytes bytes secs. %-8.8s/s %% %c %% %c us/KB us/KB\n\n";
-
- char *cpu_fmt_0 =
- "%6.3f %c %s\n";
-
- char *cpu_fmt_1 =
- "%6d %6d %6d %-6.2f %7.2f %-6.2f %-6.2f %-6.3f %-6.3f %s\n";
-
- char *ksink_fmt = "\n\
-Alignment Offset %-8.8s %-8.8s Recvs %-8.8s Sends\n\
-Local Remote Local Remote Xfered Per Per\n\
-Recv Send Recv Send Recv (avg) Send (avg)\n\
-%5d %5d %5d %5d %6.4g %6.2f %6d %6.2f %6d\n";
-
- char *ksink_fmt2 = "\n\
-Maximum\n\
-Segment\n\
-Size (bytes)\n\
-%6d\n";
-
-
- float elapsed_time;
-
- /* what we want is to have a buffer space that is at least one */
- /* recv-size greater than our recv window. this will insure that we */
- /* are never trying to re-use a buffer that may still be in the hands */
- /* of the transport. This buffer will be malloc'd after we have found */
- /* the size of the local senc socket buffer. We will want to deal */
- /* with alignment and offset concerns as well. */
-
- struct ring_elt *recv_ring;
-
- int len;
- unsigned int nummessages = 0;
- SOCKET recv_socket;
- int bytes_remaining;
- int sdp_mss = -1; /* possibly uninitialized on printf far below */
-
- /* with links like fddi, one can recv > 32 bits worth of bytes */
- /* during a test... ;-) at some point, this should probably become a */
- /* 64bit integral type, but those are not entirely common yet */
- double bytes_sent = 0.0;
- unsigned long long local_bytes_recvd = 0;
-
- float local_cpu_utilization;
- float local_service_demand;
- float remote_cpu_utilization;
- float remote_service_demand;
-
- double thruput;
-
- struct addrinfo *remote_res;
- struct addrinfo *local_res;
-
- struct sdp_maerts_request_struct *sdp_maerts_request;
- struct sdp_maerts_response_struct *sdp_maerts_response;
- struct sdp_maerts_results_struct *sdp_maerts_result;
-
- sdp_maerts_request =
- (struct sdp_maerts_request_struct *)netperf_request.content.test_specific_data;
- sdp_maerts_response =
- (struct sdp_maerts_response_struct *)netperf_response.content.test_specific_data;
- sdp_maerts_result =
- (struct sdp_maerts_results_struct *)netperf_response.content.test_specific_data;
-
-#ifdef WANT_HISTOGRAM
- if (verbosity > 1) {
- time_hist = HIST_new();
- }
-#endif /* WANT_HISTOGRAM */
- /* since we are now disconnected from the code that established the */
- /* control socket, and since we want to be able to use different */
- /* protocols and such, we are passed the name of the remote host and */
- /* must turn that into the test specific addressing information. */
-
- complete_addrinfos(&remote_res,
- &local_res,
- remote_host,
- SOCK_STREAM,
- IPPROTO_TCP,
- 0);
-
- if ( print_headers ) {
- print_top_test_header("SDP MAERTS TEST",local_res,remote_res);
- }
-
- recv_ring = NULL;
- confidence_iteration = 1;
- init_stat();
-
- /* we have a great-big while loop which controls the number of times */
- /* we run a particular test. this is for the calculation of a */
- /* confidence interval (I really should have stayed awake during */
- /* probstats :). If the user did not request confidence measurement */
- /* (no confidence is the default) then we will only go though the */
- /* loop once. the confidence stuff originates from the folks at IBM */
-
- while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
- (confidence_iteration <= iteration_min)) {
-
- /* initialize a few counters. we have to remember that we might be */
- /* going through the loop more than once. */
-
- nummessages = 0;
- bytes_sent = 0.0;
- times_up = 0;
-
- /*set up the data socket */
- /* fake things out by changing local_res->ai_family to AF_INET_SDP */
- local_res->ai_family = AF_INET_SDP;
- local_res->ai_protocol = 0;
- recv_socket = create_data_socket(local_res);
-
- if (recv_socket == INVALID_SOCKET){
- perror("netperf: send_sdp_maerts: sdp stream data socket");
- exit(1);
- }
-
- if (debug) {
- fprintf(where,"send_sdp_maerts: recv_socket obtained...\n");
- }
-
- /* at this point, we have either retrieved the socket buffer sizes, */
- /* or have tried to set them, so now, we may want to set the recv */
- /* size based on that (because the user either did not use a -m */
- /* option, or used one with an argument of 0). If the socket buffer */
- /* size is not available, we will set the recv size to 4KB - no */
- /* particular reason, just arbitrary... */
- if (recv_size == 0) {
- if (lsr_size > 0) {
- recv_size = lsr_size;
- }
- else {
- recv_size = 4096;
- }
- }
-
- /* set-up the data buffer ring with the requested alignment and offset. */
- /* note also that we have allocated a quantity */
- /* of memory that is at least one recv-size greater than our socket */
- /* buffer size. We want to be sure that there are at least two */
- /* buffers allocated - this can be a bit of a problem when the */
- /* recv_size is bigger than the socket size, so we must check... the */
- /* user may have wanted to explicitly set the "width" of our recv */
- /* buffers, we should respect that wish... */
- if (recv_width == 0) {
- recv_width = (lsr_size/recv_size) + 1;
- if (recv_width == 1) recv_width++;
- }
-
- if (recv_ring == NULL) {
- /* only allocate the recv ring once. this is a networking test, */
- /* not a memory allocation test. this way, we do not need a */
- /* deallocate_buffer_ring() routine, and I don't feel like */
- /* writing one anyway :) raj 11/94 */
- recv_ring = allocate_buffer_ring(recv_width,
- recv_size,
- local_recv_align,
- local_recv_offset);
- }
-
- /* If the user has requested cpu utilization measurements, we must */
- /* calibrate the cpu(s). We will perform this task within the tests */
- /* themselves. If the user has specified the cpu rate, then */
- /* calibrate_local_cpu will return rather quickly as it will have */
- /* nothing to do. If local_cpu_rate is zero, then we will go through */
- /* all the "normal" calibration stuff and return the rate back. */
-
- if (local_cpu_usage) {
- local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
- }
-
- if (!no_control) {
- /* Tell the remote end to do a listen. The server alters the
- socket paramters on the other side at this point, hence the
- reason for all the values being passed in the setup
- message. If the user did not specify any of the parameters,
- they will be passed as 0, which will indicate to the remote
- that no changes beyond the system's default should be
- used. Alignment is the exception, it will default to 1, which
- will be no alignment alterations. */
-
- netperf_request.content.request_type = DO_SDP_MAERTS;
- sdp_maerts_request->send_buf_size = rss_size_req;
- sdp_maerts_request->recv_buf_size = rsr_size_req;
- sdp_maerts_request->send_size = send_size;
- sdp_maerts_request->no_delay = rem_nodelay;
- sdp_maerts_request->send_alignment = remote_send_align;
- sdp_maerts_request->send_offset = remote_send_offset;
- sdp_maerts_request->measure_cpu = remote_cpu_usage;
- sdp_maerts_request->cpu_rate = remote_cpu_rate;
- if (test_time) {
- sdp_maerts_request->test_length = test_time;
- }
- else {
- sdp_maerts_request->test_length = test_bytes;
- }
- sdp_maerts_request->so_rcvavoid = rem_rcvavoid;
- sdp_maerts_request->so_sndavoid = rem_sndavoid;
-#ifdef DIRTY
- sdp_maerts_request->dirty_count = rem_dirty_count;
- sdp_maerts_request->clean_count = rem_clean_count;
-#endif /* DIRTY */
- sdp_maerts_request->port = atoi(remote_data_port);
- sdp_maerts_request->ipfamily = af_to_nf(remote_res->ai_family);
- if (debug > 1) {
- fprintf(where,
- "netperf: send_sdp_maerts: requesting SDP maerts test\n");
- }
-
- send_request();
-
- /* The response from the remote will contain all of the relevant
- socket parameters for this test type. We will put them back
- into the variables here so they can be displayed if desired.
- The remote will have calibrated CPU if necessary, and will
- have done all the needed set-up we will have calibrated the
- cpu locally before sending the request, and will grab the
- counter value right after the connect returns. The remote
- will grab the counter right after the accept call. This saves
- the hassle of extra messages being sent for the SDP
- tests. */
-
- recv_response();
-
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote listen done.\n");
- rsr_size = sdp_maerts_response->recv_buf_size;
- rss_size = sdp_maerts_response->send_buf_size;
- rem_nodelay = sdp_maerts_response->no_delay;
- remote_cpu_usage= sdp_maerts_response->measure_cpu;
- remote_cpu_rate = sdp_maerts_response->cpu_rate;
- send_size = sdp_maerts_response->send_size;
-
- /* we have to make sure that the server port number is in
- network order */
- set_port_number(remote_res,
- (short)sdp_maerts_response->data_port_number);
- rem_rcvavoid = sdp_maerts_response->so_rcvavoid;
- rem_sndavoid = sdp_maerts_response->so_sndavoid;
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- fprintf(where,
- "netperf: remote error %d",
- netperf_response.content.serv_errno);
- perror("");
- fflush(where);
-
- exit(1);
- }
- }
-
-#ifdef WANT_DEMO
- DEMO_STREAM_SETUP(lsr_size,rss_size)
-#endif
-
- /*Connect up to the remote port on the data socket */
- if (connect(recv_socket,
- remote_res->ai_addr,
- remote_res->ai_addrlen) == INVALID_SOCKET){
- perror("netperf: send_sdp_maerts: data socket connect failed");
- exit(1);
- }
-
- /* Data Socket set-up is finished. If there were problems, either */
- /* the connect would have failed, or the previous response would */
- /* have indicated a problem. I failed to see the value of the */
- /* extra message after the accept on the remote. If it failed, */
- /* we'll see it here. If it didn't, we might as well start pumping */
- /* data. */
-
- /* Set-up the test end conditions. For a maerts test, they can be */
- /* either time or byte-count based. */
-
- if (test_time) {
- /* The user wanted to end the test after a period of time. */
- times_up = 0;
- bytes_remaining = 0;
- /* in previous revisions, we had the same code repeated throught */
- /* all the test suites. this was unnecessary, and meant more */
- /* work for me when I wanted to switch to POSIX signals, so I */
- /* have abstracted this out into a routine in netlib.c. if you */
- /* are experiencing signal problems, you might want to look */
- /* there. raj 11/94 */
- if (!no_control) {
- /* this is a netperf to netserver test, netserver will close
- to tell us the test is over, so use PAD_TIME to avoid
- causing the netserver fits. */
- start_timer(test_time + PAD_TIME);
- }
- else {
- /* this is a netperf to data source test, no PAD_TIME */
- start_timer(test_time);
- }
- }
- else {
- /* The tester wanted to recv a number of bytes. we don't do that
- in a SDP_MAERTS test. sorry. raj 2002-06-21 */
- printf("netperf: send_sdp_maerts: test must be timed\n");
- exit(1);
- }
-
- /* The cpu_start routine will grab the current time and possibly */
- /* value of the idle counter for later use in measuring cpu */
- /* utilization and/or service demand and thruput. */
-
- cpu_start(local_cpu_usage);
-
-#ifdef WANT_INTERVALS
- INTERVALS_INIT();
-#endif /* WANT_INTERVALS */
-
- /* before we start, initialize a few variables */
-
-#ifdef WANT_DEMO
- if (demo_mode) {
- HIST_timestamp(demo_one_ptr);
- }
-#endif
-
- /* the test will continue until we either get a zero-byte recv()
- on the socket or our failsafe timer expires. most of the time
- we trust that we get a zero-byte recieve from the socket. raj
- 2002-06-21 */
-
-#ifdef WANT_HISTOGRAM
- if (verbosity > 1) {
- /* timestamp just before we go into recv and then again just
- after we come out raj 8/94 */
- /* but only if we are actually going to display a histogram. raj
- 2006-02-07 */
- HIST_timestamp(&time_one);
- }
-#endif /* WANT_HISTOGRAM */
-
- while ((!times_up) && (len=recv(recv_socket,
- recv_ring->buffer_ptr,
- recv_size,
- 0)) > 0 ) {
-
-#ifdef WANT_HISTOGRAM
- if (verbosity > 1) {
- /* timestamp the exit from the recv call and update the histogram */
- HIST_timestamp(&time_two);
- HIST_add(time_hist,delta_micro(&time_one,&time_two));
- }
-#endif /* WANT_HISTOGRAM */
-
-#ifdef DIRTY
- access_buffer(recv_ring->buffer_ptr,
- recv_size,
- loc_dirty_count,
- loc_clean_count);
-#endif /* DIRTY */
-
-#ifdef WANT_DEMO
- DEMO_STREAM_INTERVAL(len);
-#endif
-
-#ifdef WANT_INTERVALS
- INTERVALS_WAIT();
-#endif /* WANT_INTERVALS */
-
- /* now we want to move our pointer to the next position in the */
- /* data buffer...we may also want to wrap back to the "beginning" */
- /* of the bufferspace, so we will mod the number of messages sent */
- /* by the recv width, and use that to calculate the offset to add */
- /* to the base pointer. */
- nummessages++;
- recv_ring = recv_ring->next;
- if (bytes_remaining) {
- bytes_remaining -= len;
- }
-
- local_bytes_recvd += len;
-
-#ifdef WANT_HISTOGRAM
- if (verbosity > 1) {
- /* make sure we timestamp just before we go into recv */
- /* raj 2004-06-15 */
- HIST_timestamp(&time_one);
- }
-#endif /* WANT_HISTOGRAM */
-
- }
-
- /* an EINTR is to be expected when this is a no_control test */
- if (((len < 0) || SOCKET_EINTR(len)) && (!no_control)) {
- perror("send_sdp_maerts: data recv error");
- printf("len was %d\n",len);
- exit(1);
- }
-
- /* if we get here, it must mean we had a recv return of 0 before
- the watchdog timer expired, or the watchdog timer expired and
- this was a no_control test */
-
- /* The test is over. Flush the buffers to the remote end. We do a
- graceful release to tell the remote we have all the data. */
-
- /* but first, if the verbosity is greater than 1, find-out what */
- /* the SDP maximum segment_size was (if possible) */
- if (verbosity > 1) {
- sdp_mss = -1;
- get_sdp_info(recv_socket,&sdp_mss);
- }
-
- if (shutdown(recv_socket,SHUT_WR) == SOCKET_ERROR) {
- perror("netperf: cannot shutdown sdp maerts socket");
- exit(1);
- }
-
- stop_timer();
-
- /* this call will always give us the local elapsed time for the
- test, and will also store-away the necessaries for cpu
- utilization */
-
- cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */
- /* measured and how */
- /* long did we really */
- /* run? */
-
- /* we are finished with the socket, so close it to prevent hitting */
- /* the limit on maximum open files. */
-
- close(recv_socket);
-
- if (!no_control) {
- /* Get the statistics from the remote end. The remote will have
- calculated service demand and all those interesting
- things. If it wasn't supposed to care, it will return obvious
- values. */
-
- recv_response();
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote results obtained\n");
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- fprintf(where,
- "netperf: remote error %d",
- netperf_response.content.serv_errno);
- perror("");
- fflush(where);
-
- exit(1);
- }
-
- /* We now calculate what our thruput was for the test. In the
- future, we may want to include a calculation of the thruput
- measured by the remote, but it should be the case that for a
- SDP maerts test, that the two numbers should be *very*
- close... We calculate bytes_sent regardless of the way the
- test length was controlled. If it was time, we needed to,
- and if it was by bytes, the user may have specified a number
- of bytes that wasn't a multiple of the recv_size, so we
- really didn't recv what he asked for ;-) */
-
- bytes_sent = ntohd(sdp_maerts_result->bytes_sent);
- }
- else {
- bytes_sent = (double)local_bytes_recvd;
- }
-
-
- thruput = calc_thruput(bytes_sent);
-
- if (local_cpu_usage || remote_cpu_usage) {
- /* We must now do a little math for service demand and cpu */
- /* utilization for the system(s) */
- /* Of course, some of the information might be bogus because */
- /* there was no idle counter in the kernel(s). We need to make */
- /* a note of this for the user's benefit...*/
- if (local_cpu_usage) {
-
- local_cpu_utilization = calc_cpu_util(0.0);
- local_service_demand = calc_service_demand(bytes_sent,
- 0.0,
- 0.0,
- 0);
- }
- else {
- local_cpu_utilization = (float) -1.0;
- local_service_demand = (float) -1.0;
- }
-
- if (remote_cpu_usage) {
-
- remote_cpu_utilization = sdp_maerts_result->cpu_util;
- remote_service_demand = calc_service_demand(bytes_sent,
- 0.0,
- remote_cpu_utilization,
- sdp_maerts_result->num_cpus);
- }
- else {
- remote_cpu_utilization = (float) -1.0;
- remote_service_demand = (float) -1.0;
- }
- }
- else {
- /* we were not measuring cpu, for the confidence stuff, we */
- /* should make it -1.0 */
- local_cpu_utilization = (float) -1.0;
- local_service_demand = (float) -1.0;
- remote_cpu_utilization = (float) -1.0;
- remote_service_demand = (float) -1.0;
- }
-
- /* at this point, we want to calculate the confidence information. */
- /* if debugging is on, calculate_confidence will print-out the */
- /* parameters we pass it */
-
- calculate_confidence(confidence_iteration,
- elapsed_time,
- thruput,
- local_cpu_utilization,
- remote_cpu_utilization,
- local_service_demand,
- remote_service_demand);
-
-
- confidence_iteration++;
- }
-
- /* at this point, we have finished making all the runs that we */
- /* will be making. so, we should extract what the calcuated values */
- /* are for all the confidence stuff. we could make the values */
- /* global, but that seemed a little messy, and it did not seem worth */
- /* all the mucking with header files. so, we create a routine much */
- /* like calcualte_confidence, which just returns the mean values. */
- /* raj 11/94 */
-
- retrieve_confident_values(&elapsed_time,
- &thruput,
- &local_cpu_utilization,
- &remote_cpu_utilization,
- &local_service_demand,
- &remote_service_demand);
-
- /* We are now ready to print all the information. If the user */
- /* has specified zero-level verbosity, we will just print the */
- /* local service demand, or the remote service demand. If the */
- /* user has requested verbosity level 1, he will get the basic */
- /* "streamperf" numbers. If the user has specified a verbosity */
- /* of greater than 1, we will display a veritable plethora of */
- /* background information from outside of this block as it it */
- /* not cpu_measurement specific... */
-
- if (confidence < 0) {
- /* we did not hit confidence, but were we asked to look for it? */
- if (iteration_max > 1) {
- display_confidence();
- }
- }
-
- if (local_cpu_usage || remote_cpu_usage) {
- local_cpu_method = format_cpu_method(cpu_method);
- remote_cpu_method = format_cpu_method(sdp_maerts_result->cpu_method);
-
- switch (verbosity) {
- case 0:
- if (local_cpu_usage) {
- fprintf(where,
- cpu_fmt_0,
- local_service_demand,
- local_cpu_method,
- ((print_headers) ||
- (result_brand == NULL)) ? "" : result_brand);
- }
- else {
- fprintf(where,
- cpu_fmt_0,
- remote_service_demand,
- remote_cpu_method,
- ((print_headers) ||
- (result_brand == NULL)) ? "" : result_brand);
- }
- break;
- case 1:
- case 2:
- if (print_headers) {
- fprintf(where,
- cpu_title,
- format_units(),
- local_cpu_method,
- remote_cpu_method);
- }
-
- fprintf(where,
- cpu_fmt_1, /* the format string */
- rsr_size, /* remote recvbuf size */
- lss_size, /* local sendbuf size */
- send_size, /* how large were the recvs */
- elapsed_time, /* how long was the test */
- thruput, /* what was the xfer rate */
- local_cpu_utilization, /* local cpu */
- remote_cpu_utilization, /* remote cpu */
- local_service_demand, /* local service demand */
- remote_service_demand, /* remote service demand */
- ((print_headers) ||
- (result_brand == NULL)) ? "" : result_brand);
- break;
- }
- }
- else {
- /* The tester did not wish to measure service demand. */
-
- switch (verbosity) {
- case 0:
- fprintf(where,
- tput_fmt_0,
- thruput,
- ((print_headers) ||
- (result_brand == NULL)) ? "" : result_brand);
- break;
- case 1:
- case 2:
- if (print_headers) {
- fprintf(where,tput_title,format_units());
- }
- fprintf(where,
- tput_fmt_1, /* the format string */
- lsr_size, /* local recvbuf size */
- rss_size, /* remot sendbuf size */
- send_size, /* how large were the recvs */
- elapsed_time, /* how long did it take */
- thruput, /* how fast did it go */
- ((print_headers) ||
- (result_brand == NULL)) ? "" : result_brand);
- break;
- }
- }
-
- /* it would be a good thing to include information about some of the */
- /* other parameters that may have been set for this test, but at the */
- /* moment, I do not wish to figure-out all the formatting, so I will */
- /* just put this comment here to help remind me that it is something */
- /* that should be done at a later time. */
-
- if (verbosity > 1) {
- /* The user wanted to know it all, so we will give it to him. */
- /* This information will include as much as we can find about */
- /* SDP statistics, the alignments of the sends and receives */
- /* and all that sort of rot... */
-
- /* this stuff needs to be worked-out in the presence of confidence */
- /* intervals and multiple iterations of the test... raj 11/94 */
-
- fprintf(where,
- ksink_fmt,
- "Bytes",
- "Bytes",
- "Bytes",
- local_recv_align,
- remote_recv_align,
- local_recv_offset,
- remote_recv_offset,
- bytes_sent,
- bytes_sent / (double)nummessages,
- nummessages,
- bytes_sent / (double)sdp_maerts_result->send_calls,
- sdp_maerts_result->send_calls);
- fprintf(where,
- ksink_fmt2,
- sdp_mss);
- fflush(where);
-#ifdef WANT_HISTOGRAM
- fprintf(where,"\n\nHistogram of time spent in recv() call.\n");
- fflush(where);
- HIST_report(time_hist);
-#endif /* WANT_HISTOGRAM */
- }
-
-}
-/* This is the server-side routine for the sdp stream test. It is */
-/* implemented as one routine. I could break things-out somewhat, but */
-/* didn't feel it was necessary. */
-
-void
-recv_sdp_stream()
-{
-
- struct sockaddr_in myaddr_in, peeraddr_in;
- SOCKET s_listen,s_data;
- netperf_socklen_t addrlen;
- int len;
- unsigned int receive_calls;
- float elapsed_time;
- double bytes_received;
-
- struct ring_elt *recv_ring;
-
- struct addrinfo *local_res;
- char local_name[BUFSIZ];
- char port_buffer[PORTBUFSIZE];
-
-#ifdef DO_SELECT
- fd_set readfds;
- struct timeval timeout;
-#endif /* DO_SELECT */
-
- struct sdp_stream_request_struct *sdp_stream_request;
- struct sdp_stream_response_struct *sdp_stream_response;
- struct sdp_stream_results_struct *sdp_stream_results;
-
-#ifdef DO_SELECT
- FD_ZERO(&readfds);
- timeout.tv_sec = 1;
- timeout.tv_usec = 0;
-#endif /* DO_SELECT */
-
- sdp_stream_request =
- (struct sdp_stream_request_struct *)netperf_request.content.test_specific_data;
- sdp_stream_response =
- (struct sdp_stream_response_struct *)netperf_response.content.test_specific_data;
- sdp_stream_results =
- (struct sdp_stream_results_struct *)netperf_response.content.test_specific_data;
-
- if (debug) {
- fprintf(where,"netserver: recv_sdp_stream: entered...\n");
- fflush(where);
- }
-
- /* We want to set-up the listen socket with all the desired */
- /* parameters and then let the initiator know that all is ready. If */
- /* socket size defaults are to be used, then the initiator will have */
- /* sent us 0's. If the socket sizes cannot be changed, then we will */
- /* send-back what they are. If that information cannot be determined, */
- /* then we send-back -1's for the sizes. If things go wrong for any */
- /* reason, we will drop back ten yards and punt. */
-
- /* If anything goes wrong, we want the remote to know about it. It */
- /* would be best if the error that the remote reports to the user is */
- /* the actual error we encountered, rather than some bogus unexpected */
- /* response type message. */
-
- if (debug) {
- fprintf(where,"recv_sdp_stream: setting the response type...\n");
- fflush(where);
- }
-
- netperf_response.content.response_type = SDP_STREAM_RESPONSE;
-
- if (debug) {
- fprintf(where,"recv_sdp_stream: the response type is set...\n");
- fflush(where);
- }
-
- /* We now alter the message_ptr variable to be at the desired */
- /* alignment with the desired offset. */
-
- if (debug) {
- fprintf(where,"recv_sdp_stream: requested alignment of %d\n",
- sdp_stream_request->recv_alignment);
- fflush(where);
- }
-
- /* create_data_socket expects to find some things in the global */
- /* variables, so set the globals based on the values in the request. */
- /* once the socket has been created, we will set the response values */
- /* based on the updated value of those globals. raj 7/94 */
- lss_size_req = sdp_stream_request->send_buf_size;
- lsr_size_req = sdp_stream_request->recv_buf_size;
- loc_nodelay = sdp_stream_request->no_delay;
- loc_rcvavoid = sdp_stream_request->so_rcvavoid;
- loc_sndavoid = sdp_stream_request->so_sndavoid;
-
- set_hostname_and_port(local_name,
- port_buffer,
- nf_to_af(sdp_stream_request->ipfamily),
- sdp_stream_request->port);
-
- local_res = complete_addrinfo(local_name,
- local_name,
- port_buffer,
- nf_to_af(sdp_stream_request->ipfamily),
- SOCK_STREAM,
- IPPROTO_TCP,
- 0);
-
- /* fake things out by changing local_res->ai_family to AF_INET_SDP */
- local_res->ai_family = AF_INET_SDP;
- local_res->ai_protocol = 0;
- s_listen = create_data_socket(local_res);
-
- if (s_listen == INVALID_SOCKET) {
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
-
-#ifdef WIN32
- /* The test timer can fire during operations on the listening socket,
- so to make the start_timer below work we have to move
- it to close s_listen while we are blocked on accept. */
- win_kludge_socket2 = s_listen;
-#endif
-
- /* what sort of sizes did we end-up with? */
- if (sdp_stream_request->receive_size == 0) {
- if (lsr_size > 0) {
- recv_size = lsr_size;
- }
- else {
- recv_size = 4096;
- }
- }
- else {
- recv_size = sdp_stream_request->receive_size;
- }
-
- /* we want to set-up our recv_ring in a manner analagous to what we */
- /* do on the sending side. this is more for the sake of symmetry */
- /* than for the needs of say copy avoidance, but it might also be */
- /* more realistic - this way one could conceivably go with a */
- /* double-buffering scheme when taking the data an putting it into */
- /* the filesystem or something like that. raj 7/94 */
-
- if (recv_width == 0) {
- recv_width = (lsr_size/recv_size) + 1;
- if (recv_width == 1) recv_width++;
- }
-
- recv_ring = allocate_buffer_ring(recv_width,
- recv_size,
- sdp_stream_request->recv_alignment,
- sdp_stream_request->recv_offset);
-
- if (debug) {
- fprintf(where,"recv_sdp_stream: receive alignment and offset set...\n");
- fflush(where);
- }
-
- /* Now, let's set-up the socket to listen for connections */
- if (listen(s_listen, 5) == SOCKET_ERROR) {
- netperf_response.content.serv_errno = errno;
- close(s_listen);
- send_response();
-
- exit(1);
- }
-
-
- /* now get the port number assigned by the system */
- addrlen = sizeof(myaddr_in);
- if (getsockname(s_listen,
- (struct sockaddr *)&myaddr_in,
- &addrlen) == SOCKET_ERROR){
- netperf_response.content.serv_errno = errno;
- close(s_listen);
- send_response();
-
- exit(1);
- }
-
- /* Now myaddr_in contains the port and the internet address this is */
- /* returned to the sender also implicitly telling the sender that the */
- /* socket buffer sizing has been done. */
-
- sdp_stream_response->data_port_number = (int) ntohs(myaddr_in.sin_port);
- netperf_response.content.serv_errno = 0;
-
- /* But wait, there's more. If the initiator wanted cpu measurements, */
- /* then we must call the calibrate routine, which will return the max */
- /* rate back to the initiator. If the CPU was not to be measured, or */
- /* something went wrong with the calibration, we will return a -1 to */
- /* the initiator. */
-
- sdp_stream_response->cpu_rate = (float)0.0; /* assume no cpu */
- if (sdp_stream_request->measure_cpu) {
- sdp_stream_response->measure_cpu = 1;
- sdp_stream_response->cpu_rate =
- calibrate_local_cpu(sdp_stream_request->cpu_rate);
- }
- else {
- sdp_stream_response->measure_cpu = 0;
- }
-
- /* before we send the response back to the initiator, pull some of */
- /* the socket parms from the globals */
- sdp_stream_response->send_buf_size = lss_size;
- sdp_stream_response->recv_buf_size = lsr_size;
- sdp_stream_response->no_delay = loc_nodelay;
- sdp_stream_response->so_rcvavoid = loc_rcvavoid;
- sdp_stream_response->so_sndavoid = loc_sndavoid;
- sdp_stream_response->receive_size = recv_size;
-
- send_response();
-
- addrlen = sizeof(peeraddr_in);
-
- if ((s_data=accept(s_listen,
- (struct sockaddr *)&peeraddr_in,
- &addrlen)) == INVALID_SOCKET) {
- /* Let's just punt. The remote will be given some information */
- close(s_listen);
- exit(1);
- }
-
-#ifdef KLUDGE_SOCKET_OPTIONS
- /* this is for those systems which *INCORRECTLY* fail to pass */
- /* attributes across an accept() call. Including this goes against */
- /* my better judgement :( raj 11/95 */
-
- kludge_socket_options(s_data);
-
-#endif /* KLUDGE_SOCKET_OPTIONS */
-
- /* Now it's time to start receiving data on the connection. We will */
- /* first grab the apropriate counters and then start grabbing. */
-
- cpu_start(sdp_stream_request->measure_cpu);
-
- /* The loop will exit when the sender does a shutdown, which will */
- /* return a length of zero */
-
- /* there used to be an #ifdef DIRTY call to access_buffer() here,
- but we have switched from accessing the buffer before the recv()
- call to accessing the buffer after the recv() call. The
- accessing before was, IIRC, related to having dirty data when
- doing page-flipping copy avoidance. */
-
- bytes_received = 0;
- receive_calls = 0;
-
- while ((len = recv(s_data, recv_ring->buffer_ptr, recv_size, 0)) != 0) {
- if (len == SOCKET_ERROR )
- {
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
- bytes_received += len;
- receive_calls++;
-
-#ifdef DIRTY
- /* we access the buffer after the recv() call now, rather than before */
- access_buffer(recv_ring->buffer_ptr,
- recv_size,
- sdp_stream_request->dirty_count,
- sdp_stream_request->clean_count);
-#endif /* DIRTY */
-
-
- /* move to the next buffer in the recv_ring */
- recv_ring = recv_ring->next;
-
-#ifdef PAUSE
- sleep(1);
-#endif /* PAUSE */
-
-#ifdef DO_SELECT
- FD_SET(s_data,&readfds);
- select(s_data+1,&readfds,NULL,NULL,&timeout);
-#endif /* DO_SELECT */
-
- }
-
- /* perform a shutdown to signal the sender that */
- /* we have received all the data sent. raj 4/93 */
-
- if (shutdown(s_data,SHUT_WR) == SOCKET_ERROR) {
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
-
- cpu_stop(sdp_stream_request->measure_cpu,&elapsed_time);
-
- /* send the results to the sender */
-
- if (debug) {
- fprintf(where,
- "recv_sdp_stream: got %g bytes\n",
- bytes_received);
- fprintf(where,
- "recv_sdp_stream: got %d recvs\n",
- receive_calls);
- fflush(where);
- }
-
- sdp_stream_results->bytes_received = htond(bytes_received);
- sdp_stream_results->elapsed_time = elapsed_time;
- sdp_stream_results->recv_calls = receive_calls;
-
- sdp_stream_results->cpu_method = cpu_method;
- sdp_stream_results->num_cpus = lib_num_loc_cpus;
-
- if (sdp_stream_request->measure_cpu) {
- sdp_stream_results->cpu_util = calc_cpu_util(0.0);
- };
-
- if (debug) {
- fprintf(where,
- "recv_sdp_stream: test complete, sending results.\n");
- fprintf(where,
- " bytes_received %g receive_calls %d\n",
- bytes_received,
- receive_calls);
- fprintf(where,
- " len %d\n",
- len);
- fflush(where);
- }
-
- send_response();
-
- /* we are now done with the sockets */
- close(s_data);
- close(s_listen);
-
- }
-
-/* This is the server-side routine for the sdp maerts test. It is
- implemented as one routine. I could break things-out somewhat, but
- didn't feel it was necessary. */
-
-void
-recv_sdp_maerts()
-{
-
- struct sockaddr_in myaddr_in, peeraddr_in;
- struct addrinfo *local_res;
- char local_name[BUFSIZ];
- char port_buffer[PORTBUFSIZE];
-
- SOCKET s_listen,s_data;
- netperf_socklen_t addrlen;
- int len;
- unsigned int send_calls;
- float elapsed_time;
- double bytes_sent = 0.0 ;
-
- struct ring_elt *send_ring;
-
- struct sdp_maerts_request_struct *sdp_maerts_request;
- struct sdp_maerts_response_struct *sdp_maerts_response;
- struct sdp_maerts_results_struct *sdp_maerts_results;
-
- sdp_maerts_request =
- (struct sdp_maerts_request_struct *)netperf_request.content.test_specific_data;
- sdp_maerts_response =
- (struct sdp_maerts_response_struct *)netperf_response.content.test_specific_data;
- sdp_maerts_results =
- (struct sdp_maerts_results_struct *)netperf_response.content.test_specific_data;
-
- if (debug) {
- fprintf(where,"netserver: recv_sdp_maerts: entered...\n");
- fflush(where);
- }
-
- /* We want to set-up the listen socket with all the desired
- parameters and then let the initiator know that all is ready. If
- socket size defaults are to be used, then the initiator will have
- sent us 0's. If the socket sizes cannot be changed, then we will
- send-back what they are. If that information cannot be
- determined, then we send-back -1's for the sizes. If things go
- wrong for any reason, we will drop back ten yards and punt. */
-
- /* If anything goes wrong, we want the remote to know about it. It
- would be best if the error that the remote reports to the user is
- the actual error we encountered, rather than some bogus
- unexpected response type message. */
-
- if (debug) {
- fprintf(where,"recv_sdp_maerts: setting the response type...\n");
- fflush(where);
- }
-
- netperf_response.content.response_type = SDP_MAERTS_RESPONSE;
-
- if (debug) {
- fprintf(where,"recv_sdp_maerts: the response type is set...\n");
- fflush(where);
- }
-
- /* We now alter the message_ptr variable to be at the desired */
- /* alignment with the desired offset. */
-
- if (debug) {
- fprintf(where,"recv_sdp_maerts: requested alignment of %d\n",
- sdp_maerts_request->send_alignment);
- fflush(where);
- }
-
- /* Grab a socket to listen on, and then listen on it. */
-
- if (debug) {
- fprintf(where,"recv_sdp_maerts: grabbing a socket...\n");
- fflush(where);
- }
-
- /* create_data_socket expects to find some things in the global */
- /* variables, so set the globals based on the values in the request. */
- /* once the socket has been created, we will set the response values */
- /* based on the updated value of those globals. raj 7/94 */
- lss_size_req = sdp_maerts_request->send_buf_size;
- lsr_size_req = sdp_maerts_request->recv_buf_size;
- loc_nodelay = sdp_maerts_request->no_delay;
- loc_rcvavoid = sdp_maerts_request->so_rcvavoid;
- loc_sndavoid = sdp_maerts_request->so_sndavoid;
-
- set_hostname_and_port(local_name,
- port_buffer,
- nf_to_af(sdp_maerts_request->ipfamily),
- sdp_maerts_request->port);
-
- local_res = complete_addrinfo(local_name,
- local_name,
- port_buffer,
- nf_to_af(sdp_maerts_request->ipfamily),
- SOCK_STREAM,
- IPPROTO_TCP,
- 0);
-
- /* fake things out by changing local_res->ai_family to AF_INET_SDP */
- local_res->ai_family = AF_INET_SDP;
- local_res->ai_protocol = 0;
- s_listen = create_data_socket(local_res);
-
- if (s_listen == INVALID_SOCKET) {
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
-
-#ifdef WIN32
- /* The test timer can fire during operations on the listening socket,
- so to make the start_timer below work we have to move
- it to close s_listen while we are blocked on accept. */
- win_kludge_socket2 = s_listen;
-#endif
-
-
- /* what sort of sizes did we end-up with? */
- if (sdp_maerts_request->send_size == 0) {
- if (lss_size > 0) {
- send_size = lss_size;
- }
- else {
- send_size = 4096;
- }
- }
- else {
- send_size = sdp_maerts_request->send_size;
- }
-
- /* we want to set-up our recv_ring in a manner analagous to what we */
- /* do on the recving side. this is more for the sake of symmetry */
- /* than for the needs of say copy avoidance, but it might also be */
- /* more realistic - this way one could conceivably go with a */
- /* double-buffering scheme when taking the data an putting it into */
- /* the filesystem or something like that. raj 7/94 */
-
- if (send_width == 0) {
- send_width = (lsr_size/send_size) + 1;
- if (send_width == 1) send_width++;
- }
-
- send_ring = allocate_buffer_ring(send_width,
- send_size,
- sdp_maerts_request->send_alignment,
- sdp_maerts_request->send_offset);
-
- if (debug) {
- fprintf(where,"recv_sdp_maerts: receive alignment and offset set...\n");
- fflush(where);
- }
-
- /* Now, let's set-up the socket to listen for connections */
- if (listen(s_listen, 5) == SOCKET_ERROR) {
- netperf_response.content.serv_errno = errno;
- close(s_listen);
- send_response();
-
- exit(1);
- }
-
-
- /* now get the port number assigned by the system */
- addrlen = sizeof(myaddr_in);
- if (getsockname(s_listen,
- (struct sockaddr *)&myaddr_in,
- &addrlen) == SOCKET_ERROR){
- netperf_response.content.serv_errno = errno;
- close(s_listen);
- send_response();
-
- exit(1);
- }
-
- /* Now myaddr_in contains the port and the internet address this is */
- /* returned to the sender also implicitly telling the sender that the */
- /* socket buffer sizing has been done. */
-
- sdp_maerts_response->data_port_number = (int) ntohs(myaddr_in.sin_port);
- netperf_response.content.serv_errno = 0;
-
- /* But wait, there's more. If the initiator wanted cpu measurements, */
- /* then we must call the calibrate routine, which will return the max */
- /* rate back to the initiator. If the CPU was not to be measured, or */
- /* something went wrong with the calibration, we will return a -1 to */
- /* the initiator. */
-
- sdp_maerts_response->cpu_rate = (float)0.0; /* assume no cpu */
- if (sdp_maerts_request->measure_cpu) {
- sdp_maerts_response->measure_cpu = 1;
- sdp_maerts_response->cpu_rate =
- calibrate_local_cpu(sdp_maerts_request->cpu_rate);
- }
- else {
- sdp_maerts_response->measure_cpu = 0;
- }
-
- /* before we send the response back to the initiator, pull some of */
- /* the socket parms from the globals */
- sdp_maerts_response->send_buf_size = lss_size;
- sdp_maerts_response->recv_buf_size = lsr_size;
- sdp_maerts_response->no_delay = loc_nodelay;
- sdp_maerts_response->so_rcvavoid = loc_rcvavoid;
- sdp_maerts_response->so_sndavoid = loc_sndavoid;
- sdp_maerts_response->send_size = send_size;
-
- send_response();
-
- addrlen = sizeof(peeraddr_in);
-
- /* we will start the timer before the accept() to be somewhat
- analagous to the starting of the timer before the connect() call
- in the SDP_STREAM test. raj 2002-06-21 */
-
- start_timer(sdp_maerts_request->test_length);
-
- /* Now it's time to start receiving data on the connection. We will
- first grab the apropriate counters and then start grabbing. */
-
- cpu_start(sdp_maerts_request->measure_cpu);
-
-
- if ((s_data=accept(s_listen,
- (struct sockaddr *)&peeraddr_in,
- &addrlen)) == INVALID_SOCKET) {
- /* Let's just punt. The remote will be given some information */
- close(s_listen);
- exit(1);
- }
-
-#ifdef KLUDGE_SOCKET_OPTIONS
-
- /* this is for those systems which *INCORRECTLY* fail to pass
- attributes across an accept() call. Including this goes against
- my better judgement :( raj 11/95 */
-
- kludge_socket_options(s_data);
-
-#endif /* KLUDGE_SOCKET_OPTIONS */
-
- /* The loop will exit when the sender does a shutdown, which will */
- /* return a length of zero */
-
- bytes_sent = 0.0;
- send_calls = 0;
-
- len = 0; /* nt-lint; len is not initialized (printf far below) if
- times_up initially true.*/
- times_up = 0; /* must remember to initialize this little beauty */
- while (!times_up) {
-
-#ifdef DIRTY
- /* we want to dirty some number of consecutive integers in the buffer */
- /* we are about to send. we may also want to bring some number of */
- /* them cleanly into the cache. The clean ones will follow any dirty */
- /* ones into the cache. */
-
- access_buffer(send_ring->buffer_ptr,
- send_size,
- sdp_maerts_request->dirty_count,
- sdp_maerts_request->clean_count);
-
-#endif /* DIRTY */
-
- if((len=send(s_data,
- send_ring->buffer_ptr,
- send_size,
- 0)) != send_size) {
- if ((len >=0) || SOCKET_EINTR(len)) {
- /* the test was interrupted, must be the end of test */
- break;
- }
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
-
- bytes_sent += len;
- send_calls++;
-
- /* more to the next buffer in the send_ring */
- send_ring = send_ring->next;
-
- }
-
- /* perform a shutdown to signal the sender that */
- /* we have received all the data sent. raj 4/93 */
-
- if (shutdown(s_data,SHUT_WR) == SOCKET_ERROR) {
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
-
- /* hang a recv() off the socket to block until the remote has
- brought all the data up into the application. it will do a
- shutdown to cause a FIN to be sent our way. We will assume that
- any exit from the recv() call is good... raj 4/93 */
-
- recv(s_data, send_ring->buffer_ptr, send_size, 0);
-
-
- cpu_stop(sdp_maerts_request->measure_cpu,&elapsed_time);
-
- /* send the results to the sender */
-
- if (debug) {
- fprintf(where,
- "recv_sdp_maerts: got %g bytes\n",
- bytes_sent);
- fprintf(where,
- "recv_sdp_maerts: got %d sends\n",
- send_calls);
- fflush(where);
- }
-
- sdp_maerts_results->bytes_sent = htond(bytes_sent);
- sdp_maerts_results->elapsed_time = elapsed_time;
- sdp_maerts_results->send_calls = send_calls;
-
- if (sdp_maerts_request->measure_cpu) {
- sdp_maerts_results->cpu_util = calc_cpu_util(0.0);
- };
-
- if (debug) {
- fprintf(where,
- "recv_sdp_maerts: test complete, sending results.\n");
- fprintf(where,
- " bytes_sent %g send_calls %d\n",
- bytes_sent,
- send_calls);
- fprintf(where,
- " len %d\n",
- len);
- fflush(where);
- }
-
- sdp_maerts_results->cpu_method = cpu_method;
- sdp_maerts_results->num_cpus = lib_num_loc_cpus;
- send_response();
-
- /* we are now done with the sockets */
- close(s_data);
- close(s_listen);
-
- }
-
-
- /* this routine implements the sending (netperf) side of the SDP_RR */
- /* test. */
-
-void
-send_sdp_rr(char remote_host[])
-{
-
- char *tput_title = "\
-Local /Remote\n\
-Socket Size Request Resp. Elapsed Trans.\n\
-Send Recv Size Size Time Rate \n\
-bytes Bytes bytes bytes secs. per sec \n\n";
-
- char *tput_fmt_0 =
- "%7.2f %s\n";
-
- char *tput_fmt_1_line_1 = "\
-%-6d %-6d %-6d %-6d %-6.2f %7.2f %s\n";
- char *tput_fmt_1_line_2 = "\
-%-6d %-6d\n";
-
- char *cpu_title = "\
-Local /Remote\n\
-Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\
-Send Recv Size Size Time Rate local remote local remote\n\
-bytes bytes bytes bytes secs. per sec %% %c %% %c us/Tr us/Tr\n\n";
-
- char *cpu_fmt_0 =
- "%6.3f %c %s\n";
-
- char *cpu_fmt_1_line_1 = "\
-%-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f %s\n";
-
- char *cpu_fmt_1_line_2 = "\
-%-6d %-6d\n";
-
- char *ksink_fmt = "\
-Alignment Offset\n\
-Local Remote Local Remote\n\
-Send Recv Send Recv\n\
-%5d %5d %5d %5d\n";
-
-
- int timed_out = 0;
- float elapsed_time;
-
- int len;
- char *temp_message_ptr;
- int nummessages;
- SOCKET send_socket;
- int trans_remaining;
- double bytes_xferd;
-
- struct ring_elt *send_ring;
- struct ring_elt *recv_ring;
-
- int rsp_bytes_left;
- int rsp_bytes_recvd;
-
- float local_cpu_utilization;
- float local_service_demand;
- float remote_cpu_utilization;
- float remote_service_demand;
- double thruput;
-
- struct addrinfo *local_res;
- struct addrinfo *remote_res;
-
- struct sdp_rr_request_struct *sdp_rr_request;
- struct sdp_rr_response_struct *sdp_rr_response;
- struct sdp_rr_results_struct *sdp_rr_result;
-
-#ifdef WANT_FIRST_BURST
-#define REQUEST_CWND_INITIAL 2
- /* "in the beginning..." the WANT_FIRST_BURST stuff was like both
- Unix and the state of New Jersey - both were simple an unspoiled.
- then it was realized that some stacks are quite picky about
- initial congestion windows and a non-trivial initial burst of
- requests would not be individual segments even with TCP_NODELAY
- set. so, we have to start tracking a poor-man's congestion window
- up here in window space because we want to try to make something
- happen that frankly, we cannot guarantee with the specification
- of SDP. ain't that grand?-) raj 2006-01-30 */
- int requests_outstanding = 0;
- int request_cwnd = REQUEST_CWND_INITIAL; /* we ass-u-me that having
- three requests
- outstanding at the
- beginning of the test
- is ok with SDP stacks
- of interest. the first
- two will come from our
- first_burst loop, and
- the third from our
- regularly scheduled
- send */
-#endif
-
- sdp_rr_request =
- (struct sdp_rr_request_struct *)netperf_request.content.test_specific_data;
- sdp_rr_response=
- (struct sdp_rr_response_struct *)netperf_response.content.test_specific_data;
- sdp_rr_result =
- (struct sdp_rr_results_struct *)netperf_response.content.test_specific_data;
-
-#ifdef WANT_HISTOGRAM
- if (verbosity > 1) {
- time_hist = HIST_new();
- }
-#endif /* WANT_HISTOGRAM */
-
- /* since we are now disconnected from the code that established the */
- /* control socket, and since we want to be able to use different */
- /* protocols and such, we are passed the name of the remote host and */
- /* must turn that into the test specific addressing information. */
-
- complete_addrinfos(&remote_res,
- &local_res,
- remote_host,
- SOCK_STREAM,
- IPPROTO_TCP,
- 0);
-
- if ( print_headers ) {
- print_top_test_header("SDP REQUEST/RESPONSE TEST",local_res,remote_res);
- }
-
- /* initialize a few counters */
-
- send_ring = NULL;
- recv_ring = NULL;
- confidence_iteration = 1;
- init_stat();
-
- /* we have a great-big while loop which controls the number of times */
- /* we run a particular test. this is for the calculation of a */
- /* confidence interval (I really should have stayed awake during */
- /* probstats :). If the user did not request confidence measurement */
- /* (no confidence is the default) then we will only go though the */
- /* loop once. the confidence stuff originates from the folks at IBM */
-
- while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
- (confidence_iteration <= iteration_min)) {
-
- /* initialize a few counters. we have to remember that we might be */
- /* going through the loop more than once. */
-
- nummessages = 0;
- bytes_xferd = 0.0;
- times_up = 0;
- timed_out = 0;
- trans_remaining = 0;
-
-#ifdef WANT_FIRST_BURST
- /* we have to remember to reset the number of transactions
- outstanding and the "congestion window for each new
- iteration. raj 2006-01-31 */
- requests_outstanding = 0;
- request_cwnd = REQUEST_CWND_INITIAL;
-#endif
-
-
- /* set-up the data buffers with the requested alignment and offset. */
- /* since this is a request/response test, default the send_width and */
- /* recv_width to 1 and not two raj 7/94 */
-
- if (send_width == 0) send_width = 1;
- if (recv_width == 0) recv_width = 1;
-
- if (send_ring == NULL) {
- send_ring = allocate_buffer_ring(send_width,
- req_size,
- local_send_align,
- local_send_offset);
- }
-
- if (recv_ring == NULL) {
- recv_ring = allocate_buffer_ring(recv_width,
- rsp_size,
- local_recv_align,
- local_recv_offset);
- }
-
- /*set up the data socket */
- /* fake things out by changing local_res->ai_family to AF_INET_SDP */
- local_res->ai_family = AF_INET_SDP;
- local_res->ai_protocol = 0;
- send_socket = create_data_socket(local_res);
-
- if (send_socket == INVALID_SOCKET){
- perror("netperf: send_sdp_rr: sdp stream data socket");
- exit(1);
- }
-
- if (debug) {
- fprintf(where,"send_sdp_rr: send_socket obtained...\n");
- }
-
- /* If the user has requested cpu utilization measurements, we must */
- /* calibrate the cpu(s). We will perform this task within the tests */
- /* themselves. If the user has specified the cpu rate, then */
- /* calibrate_local_cpu will return rather quickly as it will have */
- /* nothing to do. If local_cpu_rate is zero, then we will go through */
- /* all the "normal" calibration stuff and return the rate back.*/
-
- if (local_cpu_usage) {
- local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
- }
-
- if (!no_control) {
- /* Tell the remote end to do a listen. The server alters the
- socket paramters on the other side at this point, hence the
- reason for all the values being passed in the setup
- message. If the user did not specify any of the parameters,
- they will be passed as 0, which will indicate to the remote
- that no changes beyond the system's default should be
- used. Alignment is the exception, it will default to 8, which
- will be no alignment alterations. */
-
- netperf_request.content.request_type = DO_SDP_RR;
- sdp_rr_request->recv_buf_size = rsr_size_req;
- sdp_rr_request->send_buf_size = rss_size_req;
- sdp_rr_request->recv_alignment = remote_recv_align;
- sdp_rr_request->recv_offset = remote_recv_offset;
- sdp_rr_request->send_alignment = remote_send_align;
- sdp_rr_request->send_offset = remote_send_offset;
- sdp_rr_request->request_size = req_size;
- sdp_rr_request->response_size = rsp_size;
- sdp_rr_request->no_delay = rem_nodelay;
- sdp_rr_request->measure_cpu = remote_cpu_usage;
- sdp_rr_request->cpu_rate = remote_cpu_rate;
- sdp_rr_request->so_rcvavoid = rem_rcvavoid;
- sdp_rr_request->so_sndavoid = rem_sndavoid;
- if (test_time) {
- sdp_rr_request->test_length = test_time;
- }
- else {
- sdp_rr_request->test_length = test_trans * -1;
- }
- sdp_rr_request->port = atoi(remote_data_port);
- sdp_rr_request->ipfamily = af_to_nf(remote_res->ai_family);
-
- if (debug > 1) {
- fprintf(where,"netperf: send_sdp_rr: requesting SDP rr test\n");
- }
-
- send_request();
-
- /* The response from the remote will contain all of the relevant
- socket parameters for this test type. We will put them back
- into the variables here so they can be displayed if desired.
- The remote will have calibrated CPU if necessary, and will
- have done all the needed set-up we will have calibrated the
- cpu locally before sending the request, and will grab the
- counter value right after the connect returns. The remote
- will grab the counter right after the accept call. This saves
- the hassle of extra messages being sent for the SDP
- tests. */
-
- recv_response();
-
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote listen done.\n");
- rsr_size = sdp_rr_response->recv_buf_size;
- rss_size = sdp_rr_response->send_buf_size;
- rem_nodelay = sdp_rr_response->no_delay;
- remote_cpu_usage = sdp_rr_response->measure_cpu;
- remote_cpu_rate = sdp_rr_response->cpu_rate;
- /* make sure that port numbers are in network order */
- set_port_number(remote_res,(short)sdp_rr_response->data_port_number);
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- fprintf(where,
- "netperf: remote error %d",
- netperf_response.content.serv_errno);
- perror("");
- fflush(where);
-
- exit(1);
- }
- }
-
-#ifdef WANT_DEMO
- DEMO_RR_SETUP(1000)
-#endif
-
- /*Connect up to the remote port on the data socket */
- if (connect(send_socket,
- remote_res->ai_addr,
- remote_res->ai_addrlen) == INVALID_SOCKET){
- perror("netperf: data socket connect failed");
-
- exit(1);
- }
-
- /* Data Socket set-up is finished. If there were problems, either the */
- /* connect would have failed, or the previous response would have */
- /* indicated a problem. I failed to see the value of the extra */
- /* message after the accept on the remote. If it failed, we'll see it */
- /* here. If it didn't, we might as well start pumping data. */
-
- /* Set-up the test end conditions. For a request/response test, they */
- /* can be either time or transaction based. */
-
- if (test_time) {
- /* The user wanted to end the test after a period of time. */
- times_up = 0;
- trans_remaining = 0;
- start_timer(test_time);
- }
- else {
- /* The tester wanted to send a number of bytes. */
- trans_remaining = test_bytes;
- times_up = 1;
- }
-
- /* The cpu_start routine will grab the current time and possibly */
- /* value of the idle counter for later use in measuring cpu */
- /* utilization and/or service demand and thruput. */
-
- cpu_start(local_cpu_usage);
-
-#ifdef WANT_INTERVALS
- INTERVALS_INIT();
-#endif /* WANT_INTERVALS */
-
- /* We use an "OR" to control test execution. When the test is */
- /* controlled by time, the byte count check will always return false. */
- /* When the test is controlled by byte count, the time test will */
- /* always return false. When the test is finished, the whole */
- /* expression will go false and we will stop sending data. I think I */
- /* just arbitrarily decrement trans_remaining for the timed test, but */
- /* will not do that just yet... One other question is whether or not */
- /* the send buffer and the receive buffer should be the same buffer. */
-
-#ifdef WANT_DEMO
- if (demo_mode) {
- HIST_timestamp(demo_one_ptr);
- }
-#endif
-
- while ((!times_up) || (trans_remaining > 0)) {
- /* send the request. we assume that if we use a blocking socket, */
- /* the request will be sent at one shot. */
-
-#ifdef WANT_FIRST_BURST
- /* we can inject no more than request_cwnd, which will grow with
- time, and no more than first_burst_size. we don't use <= to
- account for the "regularly scheduled" send call. of course
- that makes it more a "max_outstanding_ than a
- "first_burst_size" but for now we won't fix the names. also,
- I suspect the extra check against < first_burst_size is
- redundant since later I expect to make sure that request_cwnd
- can never get larger than first_burst_size, but just at the
- moment I'm feeling like a belt and suspenders kind of
- programmer. raj 2006-01-30 */
- while ((first_burst_size > 0) &&
- (requests_outstanding < request_cwnd) &&
- (requests_outstanding < first_burst_size)) {
- if (debug) {
- fprintf(where,
- "injecting, req_outstndng %d req_cwnd %d burst %d\n",
- requests_outstanding,
- request_cwnd,
- first_burst_size);
- }
- if ((len = send(send_socket,
- send_ring->buffer_ptr,
- req_size,
- 0)) != req_size) {
- /* we should never hit the end of the test in the first burst */
- perror("send_sdp_rr: initial burst data send error");
- exit(-1);
- }
- requests_outstanding += 1;
- }
-
-#endif /* WANT_FIRST_BURST */
-
-#ifdef WANT_HISTOGRAM
- if (verbosity > 1) {
- /* timestamp just before our call to send, and then again just
- after the receive raj 8/94 */
- /* but only if we are actually going to display one. raj
- 2007-02-07 */
-
- HIST_timestamp(&time_one);
- }
-#endif /* WANT_HISTOGRAM */
-
- if ((len = send(send_socket,
- send_ring->buffer_ptr,
- req_size,
- 0)) != req_size) {
- if (SOCKET_EINTR(len) || (errno == 0)) {
- /* we hit the end of a */
- /* timed test. */
- timed_out = 1;
- break;
- }
- perror("send_sdp_rr: data send error");
- exit(1);
- }
- send_ring = send_ring->next;
-
-#ifdef WANT_FIRST_BURST
- requests_outstanding += 1;
-#endif
-
- /* receive the response */
- rsp_bytes_left = rsp_size;
- temp_message_ptr = recv_ring->buffer_ptr;
- while(rsp_bytes_left > 0) {
- if((rsp_bytes_recvd=recv(send_socket,
- temp_message_ptr,
- rsp_bytes_left,
- 0)) == SOCKET_ERROR) {
- if ( SOCKET_EINTR(rsp_bytes_recvd) ) {
- /* We hit the end of a timed test. */
- timed_out = 1;
- break;
- }
- perror("send_sdp_rr: data recv error");
- exit(1);
- }
- rsp_bytes_left -= rsp_bytes_recvd;
- temp_message_ptr += rsp_bytes_recvd;
- }
- recv_ring = recv_ring->next;
-
-#ifdef WANT_FIRST_BURST
- /* so, since we've gotten a response back, update the
- bookkeeping accordingly. there is one less request
- outstanding and we can put one more out there than before. */
- requests_outstanding -= 1;
- if (request_cwnd < first_burst_size) {
- request_cwnd += 1;
- if (debug) {
- fprintf(where,
- "incr req_cwnd to %d first_burst %d reqs_outstndng %d\n",
- request_cwnd,
- first_burst_size,
- requests_outstanding);
- }
- }
-#endif
- if (timed_out) {
- /* we may have been in a nested while loop - we need */
- /* another call to break. */
- break;
- }
-
-#ifdef WANT_HISTOGRAM
- if (verbosity > 1) {
- HIST_timestamp(&time_two);
- HIST_add(time_hist,delta_micro(&time_one,&time_two));
- }
-#endif /* WANT_HISTOGRAM */
-
-#ifdef WANT_DEMO
- DEMO_RR_INTERVAL(1);
-#endif
-
-#ifdef WANT_INTERVALS
- INTERVALS_WAIT();
-#endif /* WANT_INTERVALS */
-
- nummessages++;
- if (trans_remaining) {
- trans_remaining--;
- }
-
- if (debug > 3) {
- if ((nummessages % 100) == 0) {
- fprintf(where,
- "Transaction %d completed\n",
- nummessages);
- fflush(where);
- }
- }
- }
-
- /* At this point we used to call shutdown on the data socket to be
- sure all the data was delivered, but this was not germane in a
- request/response test, and it was causing the tests to "hang"
- when they were being controlled by time. So, I have replaced
- this shutdown call with a call to close that can be found later
- in the procedure. */
-
- /* this call will always give us the elapsed time for the test,
- and will also store-away the necessaries for cpu utilization */
-
- cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */
- /* measured? how long */
- /* did we really run? */
-
- if (!no_control) {
- /* Get the statistics from the remote end. The remote will have
- calculated CPU utilization. If it wasn't supposed to care, it
- will return obvious values. */
-
- recv_response();
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote results obtained\n");
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- fprintf(where,"netperf: remote error %d",
- netperf_response.content.serv_errno);
- perror("");
- fflush(where);
- exit(1);
- }
- }
-
- /* We now calculate what our throughput was for the test. */
-
- bytes_xferd = (req_size * nummessages) + (rsp_size * nummessages);
- thruput = nummessages/elapsed_time;
-
- if (local_cpu_usage || remote_cpu_usage) {
- /* We must now do a little math for service demand and cpu
- utilization for the system(s) Of course, some of the
- information might be bogus because there was no idle counter in
- the kernel(s). We need to make a note of this for the user's
- benefit... */
- if (local_cpu_usage) {
- local_cpu_utilization = calc_cpu_util(0.0);
- /* since calc_service demand is doing ms/Kunit we will
- multiply the number of transaction by 1024 to get "good"
- numbers */
- local_service_demand = calc_service_demand((double) nummessages*1024,
- 0.0,
- 0.0,
- 0);
- }
- else {
- local_cpu_utilization = (float) -1.0;
- local_service_demand = (float) -1.0;
- }
-
- if (remote_cpu_usage) {
- remote_cpu_utilization = sdp_rr_result->cpu_util;
- /* since calc_service demand is doing ms/Kunit we will
- multiply the number of transaction by 1024 to get "good"
- numbers */
- remote_service_demand = calc_service_demand((double) nummessages*1024,
- 0.0,
- remote_cpu_utilization,
- sdp_rr_result->num_cpus);
- }
- else {
- remote_cpu_utilization = (float) -1.0;
- remote_service_demand = (float) -1.0;
- }
-
- }
- else {
- /* we were not measuring cpu, for the confidence stuff, we */
- /* should make it -1.0 */
- local_cpu_utilization = (float) -1.0;
- local_service_demand = (float) -1.0;
- remote_cpu_utilization = (float) -1.0;
- remote_service_demand = (float) -1.0;
- }
-
- /* at this point, we want to calculate the confidence information.
- if debugging is on, calculate_confidence will print-out the
- parameters we pass it */
-
- calculate_confidence(confidence_iteration,
- elapsed_time,
- thruput,
- local_cpu_utilization,
- remote_cpu_utilization,
- local_service_demand,
- remote_service_demand);
-
-
- confidence_iteration++;
-
- /* we are now done with the socket, so close it */
- close(send_socket);
-
- }
-
- retrieve_confident_values(&elapsed_time,
- &thruput,
- &local_cpu_utilization,
- &remote_cpu_utilization,
- &local_service_demand,
- &remote_service_demand);
-
- /* We are now ready to print all the information. If the user has
- specified zero-level verbosity, we will just print the local
- service demand, or the remote service demand. If the user has
- requested verbosity level 1, he will get the basic "streamperf"
- numbers. If the user has specified a verbosity of greater than 1,
- we will display a veritable plethora of background information
- from outside of this block as it it not cpu_measurement
- specific... */
-
- if (confidence < 0) {
- /* we did not hit confidence, but were we asked to look for it? */
- if (iteration_max > 1) {
- display_confidence();
- }
- }
-
- if (local_cpu_usage || remote_cpu_usage) {
- local_cpu_method = format_cpu_method(cpu_method);
- remote_cpu_method = format_cpu_method(sdp_rr_result->cpu_method);
-
- switch (verbosity) {
- case 0:
- if (local_cpu_usage) {
- fprintf(where,
- cpu_fmt_0,
- local_service_demand,
- local_cpu_method,
- ((print_headers) ||
- (result_brand == NULL)) ? "" : result_brand);
- }
- else {
- fprintf(where,
- cpu_fmt_0,
- remote_service_demand,
- remote_cpu_method,
- ((print_headers) ||
- (result_brand == NULL)) ? "" : result_brand);
- }
- break;
- case 1:
- case 2:
- if (print_headers) {
- fprintf(where,
- cpu_title,
- local_cpu_method,
- remote_cpu_method);
- }
-
- fprintf(where,
- cpu_fmt_1_line_1, /* the format string */
- lss_size, /* local sendbuf size */
- lsr_size,
- req_size, /* how large were the requests */
- rsp_size, /* guess */
- elapsed_time, /* how long was the test */
- thruput,
- local_cpu_utilization, /* local cpu */
- remote_cpu_utilization, /* remote cpu */
- local_service_demand, /* local service demand */
- remote_service_demand, /* remote service demand */
- ((print_headers) ||
- (result_brand == NULL)) ? "" : result_brand);
- fprintf(where,
- cpu_fmt_1_line_2,
- rss_size,
- rsr_size);
- break;
- }
- }
- else {
- /* The tester did not wish to measure service demand. */
-
- switch (verbosity) {
- case 0:
- fprintf(where,
- tput_fmt_0,
- thruput,
- ((print_headers) ||
- (result_brand == NULL)) ? "" : result_brand);
- break;
- case 1:
- case 2:
- if (print_headers) {
- fprintf(where,tput_title,format_units());
- }
-
- fprintf(where,
- tput_fmt_1_line_1, /* the format string */
- lss_size,
- lsr_size,
- req_size, /* how large were the requests */
- rsp_size, /* how large were the responses */
- elapsed_time, /* how long did it take */
- thruput,
- ((print_headers) ||
- (result_brand == NULL)) ? "" : result_brand);
- fprintf(where,
- tput_fmt_1_line_2,
- rss_size, /* remote recvbuf size */
- rsr_size);
-
- break;
- }
- }
-
- /* it would be a good thing to include information about some of the */
- /* other parameters that may have been set for this test, but at the */
- /* moment, I do not wish to figure-out all the formatting, so I will */
- /* just put this comment here to help remind me that it is something */
- /* that should be done at a later time. */
-
- /* how to handle the verbose information in the presence of */
- /* confidence intervals is yet to be determined... raj 11/94 */
- if (verbosity > 1) {
- /* The user wanted to know it all, so we will give it to him. */
- /* This information will include as much as we can find about */
- /* SDP statistics, the alignments of the sends and receives */
- /* and all that sort of rot... */
-
- fprintf(where,
- ksink_fmt,
- local_send_align,
- remote_recv_offset,
- local_send_offset,
- remote_recv_offset);
-
-#ifdef WANT_HISTOGRAM
- fprintf(where,"\nHistogram of request/response times\n");
- fflush(where);
- HIST_report(time_hist);
-#endif /* WANT_HISTOGRAM */
-
- }
-
-}
- /* this routine implements the receive (netserver) side of a SDP_RR */
- /* test */
-void
-recv_sdp_rr()
-{
-
- struct ring_elt *send_ring;
- struct ring_elt *recv_ring;
-
- struct addrinfo *local_res;
- char local_name[BUFSIZ];
- char port_buffer[PORTBUFSIZE];
-
- struct sockaddr_in myaddr_in,
- peeraddr_in;
- SOCKET s_listen,s_data;
- netperf_socklen_t addrlen;
- char *temp_message_ptr;
- int trans_received;
- int trans_remaining;
- int bytes_sent;
- int request_bytes_recvd;
- int request_bytes_remaining;
- int timed_out = 0;
- int sock_closed = 0;
- float elapsed_time;
-
- struct sdp_rr_request_struct *sdp_rr_request;
- struct sdp_rr_response_struct *sdp_rr_response;
- struct sdp_rr_results_struct *sdp_rr_results;
-
- sdp_rr_request =
- (struct sdp_rr_request_struct *)netperf_request.content.test_specific_data;
- sdp_rr_response =
- (struct sdp_rr_response_struct *)netperf_response.content.test_specific_data;
- sdp_rr_results =
- (struct sdp_rr_results_struct *)netperf_response.content.test_specific_data;
-
- if (debug) {
- fprintf(where,"netserver: recv_sdp_rr: entered...\n");
- fflush(where);
- }
-
- /* We want to set-up the listen socket with all the desired */
- /* parameters and then let the initiator know that all is ready. If */
- /* socket size defaults are to be used, then the initiator will have */
- /* sent us 0's. If the socket sizes cannot be changed, then we will */
- /* send-back what they are. If that information cannot be determined, */
- /* then we send-back -1's for the sizes. If things go wrong for any */
- /* reason, we will drop back ten yards and punt. */
-
- /* If anything goes wrong, we want the remote to know about it. It */
- /* would be best if the error that the remote reports to the user is */
- /* the actual error we encountered, rather than some bogus unexpected */
- /* response type message. */
-
- if (debug) {
- fprintf(where,"recv_sdp_rr: setting the response type...\n");
- fflush(where);
- }
-
- netperf_response.content.response_type = SDP_RR_RESPONSE;
-
- if (debug) {
- fprintf(where,"recv_sdp_rr: the response type is set...\n");
- fflush(where);
- }
-
- /* allocate the recv and send rings with the requested alignments */
- /* and offsets. raj 7/94 */
- if (debug) {
- fprintf(where,"recv_sdp_rr: requested recv alignment of %d offset %d\n",
- sdp_rr_request->recv_alignment,
- sdp_rr_request->recv_offset);
- fprintf(where,"recv_sdp_rr: requested send alignment of %d offset %d\n",
- sdp_rr_request->send_alignment,
- sdp_rr_request->send_offset);
- fflush(where);
- }
-
- /* at some point, these need to come to us from the remote system */
- if (send_width == 0) send_width = 1;
- if (recv_width == 0) recv_width = 1;
-
- send_ring = allocate_buffer_ring(send_width,
- sdp_rr_request->response_size,
- sdp_rr_request->send_alignment,
- sdp_rr_request->send_offset);
-
- recv_ring = allocate_buffer_ring(recv_width,
- sdp_rr_request->request_size,
- sdp_rr_request->recv_alignment,
- sdp_rr_request->recv_offset);
-
-
- /* Grab a socket to listen on, and then listen on it. */
-
- if (debug) {
- fprintf(where,"recv_sdp_rr: grabbing a socket...\n");
- fflush(where);
- }
-
- /* create_data_socket expects to find some things in the global */
- /* variables, so set the globals based on the values in the request. */
- /* once the socket has been created, we will set the response values */
- /* based on the updated value of those globals. raj 7/94 */
- lss_size_req = sdp_rr_request->send_buf_size;
- lsr_size_req = sdp_rr_request->recv_buf_size;
- loc_nodelay = sdp_rr_request->no_delay;
- loc_rcvavoid = sdp_rr_request->so_rcvavoid;
- loc_sndavoid = sdp_rr_request->so_sndavoid;
-
- set_hostname_and_port(local_name,
- port_buffer,
- nf_to_af(sdp_rr_request->ipfamily),
- sdp_rr_request->port);
-
- local_res = complete_addrinfo(local_name,
- local_name,
- port_buffer,
- nf_to_af(sdp_rr_request->ipfamily),
- SOCK_STREAM,
- IPPROTO_TCP,
- 0);
-
- /* fake things out by changing local_res->ai_family to AF_INET_SDP */
- local_res->ai_family = AF_INET_SDP;
- local_res->ai_protocol = 0;
- s_listen = create_data_socket(local_res);
-
- if (s_listen == INVALID_SOCKET) {
- netperf_response.content.serv_errno = errno;
- send_response();
-
- exit(1);
- }
-
-
-#ifdef WIN32
- /* The test timer can fire during operations on the listening socket,
- so to make the start_timer below work we have to move
- it to close s_listen while we are blocked on accept. */
- win_kludge_socket2 = s_listen;
-#endif
-
-
- /* Now, let's set-up the socket to listen for connections */
- if (listen(s_listen, 5) == SOCKET_ERROR) {
- netperf_response.content.serv_errno = errno;
- close(s_listen);
- send_response();
-
- exit(1);
- }
-
-
- /* now get the port number assigned by the system */
- addrlen = sizeof(myaddr_in);
- if (getsockname(s_listen,
- (struct sockaddr *)&myaddr_in,
- &addrlen) == SOCKET_ERROR) {
- netperf_response.content.serv_errno = errno;
- close(s_listen);
- send_response();
-
- exit(1);
- }
-
- /* Now myaddr_in contains the port and the internet address this is */
- /* returned to the sender also implicitly telling the sender that the */
- /* socket buffer sizing has been done. */
-
- sdp_rr_response->data_port_number = (int) ntohs(myaddr_in.sin_port);
- netperf_response.content.serv_errno = 0;
-
- /* But wait, there's more. If the initiator wanted cpu measurements, */
- /* then we must call the calibrate routine, which will return the max */
- /* rate back to the initiator. If the CPU was not to be measured, or */
- /* something went wrong with the calibration, we will return a 0.0 to */
- /* the initiator. */
-
- sdp_rr_response->cpu_rate = (float)0.0; /* assume no cpu */
- sdp_rr_response->measure_cpu = 0;
-
- if (sdp_rr_request->measure_cpu) {
- sdp_rr_response->measure_cpu = 1;
- sdp_rr_response->cpu_rate = calibrate_local_cpu(sdp_rr_request->cpu_rate);
- }
-
-
- /* before we send the response back to the initiator, pull some of */
- /* the socket parms from the globals */
- sdp_rr_response->send_buf_size = lss_size;
- sdp_rr_response->recv_buf_size = lsr_size;
- sdp_rr_response->no_delay = loc_nodelay;
- sdp_rr_response->so_rcvavoid = loc_rcvavoid;
- sdp_rr_response->so_sndavoid = loc_sndavoid;
- sdp_rr_response->test_length = sdp_rr_request->test_length;
- send_response();
-
- addrlen = sizeof(peeraddr_in);
-
- if ((s_data = accept(s_listen,
- (struct sockaddr *)&peeraddr_in,
- &addrlen)) == INVALID_SOCKET) {
- /* Let's just punt. The remote will be given some information */
- close(s_listen);
-
- exit(1);
- }
-
-#ifdef KLUDGE_SOCKET_OPTIONS
- /* this is for those systems which *INCORRECTLY* fail to pass */
- /* attributes across an accept() call. Including this goes against */
- /* my better judgement :( raj 11/95 */
-
- kludge_socket_options(s_data);
-
-#endif /* KLUDGE_SOCKET_OPTIONS */
-
-#ifdef WIN32
- /* this is used so the timer thread can close the socket out from */
- /* under us, which to date is the easiest/cleanest/least */
- /* Windows-specific way I can find to force the winsock calls to */
- /* return WSAEINTR with the test is over. anything that will run on */
- /* 95 and NT and is closer to what netperf expects from Unix signals */
- /* and such would be appreciated raj 1/96 */
- win_kludge_socket = s_data;
-#endif /* WIN32 */
-
- if (debug) {
- fprintf(where,"recv_sdp_rr: accept completes on the data connection.\n");
- fflush(where);
- }
-
- /* Now it's time to start receiving data on the connection. We will */
- /* first grab the apropriate counters and then start grabbing. */
-
- cpu_start(sdp_rr_request->measure_cpu);
-
- /* The loop will exit when we hit the end of the test time, or when */
- /* we have exchanged the requested number of transactions. */
-
- if (sdp_rr_request->test_length > 0) {
- times_up = 0;
- trans_remaining = 0;
- start_timer(sdp_rr_request->test_length + PAD_TIME);
- }
- else {
- times_up = 1;
- trans_remaining = sdp_rr_request->test_length * -1;
- }
-
- trans_received = 0;
-
- while ((!times_up) || (trans_remaining > 0)) {
- temp_message_ptr = recv_ring->buffer_ptr;
- request_bytes_remaining = sdp_rr_request->request_size;
- while(request_bytes_remaining > 0) {
- if((request_bytes_recvd=recv(s_data,
- temp_message_ptr,
- request_bytes_remaining,
- 0)) == SOCKET_ERROR) {
- if (SOCKET_EINTR(request_bytes_recvd))
- {
- timed_out = 1;
- break;
- }
-
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
- else if( request_bytes_recvd == 0 ) {
- if (debug) {
- fprintf(where,"zero is my hero\n");
- fflush(where);
- }
- sock_closed = 1;
- break;
- }
- else {
- request_bytes_remaining -= request_bytes_recvd;
- temp_message_ptr += request_bytes_recvd;
- }
- }
-
- recv_ring = recv_ring->next;
-
- if ((timed_out) || (sock_closed)) {
- /* we hit the end of the test based on time - or the socket
- closed on us along the way. bail out of here now... */
- if (debug) {
- fprintf(where,"yo5\n");
- fflush(where);
- }
- break;
- }
-
- /* Now, send the response to the remote */
- if((bytes_sent=send(s_data,
- send_ring->buffer_ptr,
- sdp_rr_request->response_size,
- 0)) == SOCKET_ERROR) {
- if (SOCKET_EINTR(bytes_sent)) {
- /* the test timer has popped */
- timed_out = 1;
- fprintf(where,"yo6\n");
- fflush(where);
- break;
- }
- netperf_response.content.serv_errno = 992;
- send_response();
- exit(1);
- }
-
- send_ring = send_ring->next;
-
- trans_received++;
- if (trans_remaining) {
- trans_remaining--;
- }
- }
-
-
- /* The loop now exits due to timeout or transaction count being */
- /* reached */
-
- cpu_stop(sdp_rr_request->measure_cpu,&elapsed_time);
-
- stop_timer();
-
- if (timed_out) {
- /* we ended the test by time, which was at least 2 seconds */
- /* longer than we wanted to run. so, we want to subtract */
- /* PAD_TIME from the elapsed_time. */
- elapsed_time -= PAD_TIME;
- }
-
- /* send the results to the sender */
-
- if (debug) {
- fprintf(where,
- "recv_sdp_rr: got %d transactions\n",
- trans_received);
- fflush(where);
- }
-
- sdp_rr_results->bytes_received = (trans_received *
- (sdp_rr_request->request_size +
- sdp_rr_request->response_size));
- sdp_rr_results->trans_received = trans_received;
- sdp_rr_results->elapsed_time = elapsed_time;
- sdp_rr_results->cpu_method = cpu_method;
- sdp_rr_results->num_cpus = lib_num_loc_cpus;
- if (sdp_rr_request->measure_cpu) {
- sdp_rr_results->cpu_util = calc_cpu_util(elapsed_time);
- }
-
- if (debug) {
- fprintf(where,
- "recv_sdp_rr: test complete, sending results.\n");
- fflush(where);
- }
-
- /* we are now done with the sockets */
- close(s_data);
- close(s_listen);
-
- send_response();
-
-}
-
-
-
-void
-print_sdp_usage()
-{
-
- printf("%s",sdp_usage);
- exit(1);
-
-}
-void
-scan_sdp_args(argc, argv)
- int argc;
- char *argv[];
-
-{
-
-#define SOCKETS_ARGS "b:DhH:I:L:m:M:P:r:s:S:V46"
-
- extern char *optarg; /* pointer to option string */
-
- int c;
-
- char
- arg1[BUFSIZ], /* argument holders */
- arg2[BUFSIZ];
-
- if (no_control) {
- fprintf(where,
- "The SDP tests do not know how to deal with no control tests\n");
- exit(-1);
- }
-
- strncpy(local_data_port,"0",sizeof(local_data_port));
- strncpy(remote_data_port,"0",sizeof(remote_data_port));
-
- /* Go through all the command line arguments and break them */
- /* out. For those options that take two parms, specifying only */
- /* the first will set both to that value. Specifying only the */
- /* second will leave the first untouched. To change only the */
- /* first, use the form "first," (see the routine break_args.. */
-
- while ((c= getopt(argc, argv, SOCKETS_ARGS)) != EOF) {
- switch (c) {
- case '?':
- case '4':
- remote_data_family = AF_INET;
- local_data_family = AF_INET;
- break;
- case '6':
-#if defined(AF_INET6)
- remote_data_family = AF_INET6;
- local_data_family = AF_INET6;
-#else
- fprintf(stderr,
- "This netperf was not compiled on an IPv6 capable host!\n");
- fflush(stderr);
- exit(-1);
-#endif
- break;
- case 'h':
- print_sdp_usage();
- exit(1);
- case 'b':
-#ifdef WANT_FIRST_BURST
- first_burst_size = atoi(optarg);
-#else /* WANT_FIRST_BURST */
- printf("Initial request burst functionality not compiled-in!\n");
-#endif /* WANT_FIRST_BURST */
- break;
- case 'D':
- /* set the nodelay flag */
- loc_nodelay = 1;
- rem_nodelay = 1;
- break;
- case 'H':
- break_args_explicit(optarg,arg1,arg2);
- if (arg1[0]) {
- /* make sure we leave room for the NULL termination boys and
- girls. raj 2005-02-82 */
- remote_data_address = malloc(strlen(arg1)+1);
- strncpy(remote_data_address,arg1,strlen(arg1));
- }
- if (arg2[0])
- remote_data_family = parse_address_family(arg2);
- break;
- case 'L':
- break_args_explicit(optarg,arg1,arg2);
- if (arg1[0]) {
- /* make sure we leave room for the NULL termination boys and
- girls. raj 2005-02-82 */
- local_data_address = malloc(strlen(arg1)+1);
- strncpy(local_data_address,arg1,strlen(arg1));
- }
- if (arg2[0])
- local_data_family = parse_address_family(arg2);
- break;
- case 'P':
- /* set the local and remote data port numbers for the tests to
- allow them to run through those blankety blank end-to-end
- breaking firewalls. raj 2004-06-15 */
- break_args(optarg,arg1,arg2);
- if (arg1[0])
- strncpy(local_data_port,arg1,sizeof(local_data_port));
- if (arg2[0])
- strncpy(remote_data_port,arg2,sizeof(remote_data_port));
- break;
- case 's':
- /* set local socket sizes */
- break_args(optarg,arg1,arg2);
- if (arg1[0])
- lss_size_req = convert(arg1);
- if (arg2[0])
- lsr_size_req = convert(arg2);
- break;
- case 'S':
- /* set remote socket sizes */
- break_args(optarg,arg1,arg2);
- if (arg1[0])
- rss_size_req = convert(arg1);
- if (arg2[0])
- rsr_size_req = convert(arg2);
- break;
- case 'r':
- /* set the request/response sizes */
- break_args(optarg,arg1,arg2);
- if (arg1[0])
- req_size = convert(arg1);
- if (arg2[0])
- rsp_size = convert(arg2);
- break;
- case 'm':
- /* set size of the buffer for each sent message */
- send_size = convert(optarg);
- break;
- case 'M':
- /* set the size of the buffer for each received message */
- recv_size = convert(optarg);
- break;
- case 't':
- /* set the test name */
- strcpy(test_name,optarg);
- break;
- case 'W':
- /* set the "width" of the user space data */
- /* buffer. This will be the number of */
- /* send_size buffers malloc'd in the */
- /* *_STREAM test. It may be enhanced to set */
- /* both send and receive "widths" but for now */
- /* it is just the sending *_STREAM. */
- send_width = convert(optarg);
- break;
- case 'V':
- /* we want to do copy avoidance and will set */
- /* it for everything, everywhere, if we really */
- /* can. of course, we don't know anything */
- /* about the remote... */
-#ifdef SO_SND_COPYAVOID
- loc_sndavoid = 1;
-#else
- loc_sndavoid = 0;
- printf("Local send copy avoidance not available.\n");
-#endif
-#ifdef SO_RCV_COPYAVOID
- loc_rcvavoid = 1;
-#else
- loc_rcvavoid = 0;
- printf("Local recv copy avoidance not available.\n");
-#endif
- rem_sndavoid = 1;
- rem_rcvavoid = 1;
- break;
- case 'N':
- /* this opton allows the user to set the number of
- * messages to send. This in effect modifies the test
- * time. If we know the message size, then the we can
- * express the test time as message_size * number_messages
- */
- msg_count = convert (optarg);
- if (msg_count > 0)
- test_time = 0;
- break;
- case 'B':
- non_block = 1;
- break;
- case 'T':
- num_associations = atoi(optarg);
- if (num_associations <= 1) {
- printf("Number of SDP associations must be >= 1\n");
- exit(1);
- }
- break;
- };
- }
-}
-
-#endif /* WANT_SDP */
diff --git a/nettest_sdp.h b/nettest_sdp.h
deleted file mode 100644
index 31d76bc..0000000
--- a/nettest_sdp.h
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- Copyright (C) 2007 Hewlett-Packard Company
-*/
-
- /* This file contains the test-specific definitions for netperf's SDP */
- /* sockets tests */
-
-/* one of these days, this should not be required */
-#ifndef AF_INET_SDP
-#define AF_INET_SDP 27
-#define PF_INET_SDP AF_INET_SDP
-#endif
-
-struct sdp_stream_request_struct {
- int send_buf_size;
- int recv_buf_size; /* how big does the client want it - the */
- /* receive socket buffer that is */
- int receive_size; /* how many bytes do we want to receive at one */
- /* time? */
- int recv_alignment; /* what is the alignment of the receive */
- /* buffer? */
- int recv_offset; /* and at what offset from that alignment? */
- int no_delay; /* do we disable the nagle algorithm for send */
- /* coalescing? */
- int measure_cpu; /* does the client want server cpu utilization */
- /* measured? */
- float cpu_rate; /* do we know how fast the cpu is already? */
- int test_length; /* how long is the test? */
- int so_rcvavoid; /* do we want the remote to avoid copies on */
- /* receives? */
- int so_sndavoid; /* do we want the remote to avoid send copies? */
- int dirty_count; /* how many integers in the receive buffer */
- /* should be made dirty before calling recv? */
- int clean_count; /* how many integers should be read from the */
- /* recv buffer before calling recv? */
- int port; /* the to port to which recv side should bind
- to allow netperf to run through firewalls */
- int ipfamily; /* address family of ipaddress */
- int non_blocking; /* run the test in non-blocking mode */
-};
-
-struct sdp_stream_response_struct {
- int recv_buf_size; /* how big does the client want it */
- int receive_size;
- int no_delay;
- int measure_cpu; /* does the client want server cpu */
- int test_length; /* how long is the test? */
- int send_buf_size;
- int data_port_number; /* connect to me here */
- float cpu_rate; /* could we measure */
- int so_rcvavoid; /* could the remote avoid receive copies? */
- int so_sndavoid; /* could the remote avoid send copies? */
- int non_blocking; /* run the test in non-blocking mode */
-};
-
-struct sdp_stream_results_struct {
- double bytes_received;
- unsigned int recv_calls;
- float elapsed_time; /* how long the test ran */
- float cpu_util; /* -1 if not measured */
- float serv_dem; /* -1 if not measured */
- int cpu_method; /* how was cpu util measured? */
- int num_cpus; /* how many CPUs had the remote? */
-};
-
-struct sdp_rr_request_struct {
- int recv_buf_size; /* how big does the client want it */
- int send_buf_size;
- int recv_alignment;
- int recv_offset;
- int send_alignment;
- int send_offset;
- int request_size;
- int response_size;
- int no_delay;
- int measure_cpu; /* does the client want server cpu */
- float cpu_rate; /* do we know how fast the cpu is? */
- int test_length; /* how long is the test? */
- int so_rcvavoid; /* do we want the remote to avoid receive */
- /* copies? */
- int so_sndavoid; /* do we want the remote to avoid send copies? */
- int port; /* the to port to which recv side should bind
- to allow netperf to run through firewalls */
- int ipfamily; /* address family of ipaddress */
- int non_blocking; /* run the test in non-blocking mode */
-};
-
-struct sdp_rr_response_struct {
- int recv_buf_size; /* how big does the client want it */
- int no_delay;
- int measure_cpu; /* does the client want server cpu */
- int test_length; /* how long is the test? */
- int send_buf_size;
- int data_port_number; /* connect to me here */
- float cpu_rate; /* could we measure */
- int so_rcvavoid; /* could the remote avoid receive copies? */
- int so_sndavoid; /* could the remote avoid send copies? */
- int non_blocking; /* run the test in non-blocking mode */
-};
-
-struct sdp_rr_results_struct {
- unsigned int bytes_received; /* ignored initially */
- unsigned int recv_calls; /* ignored initially */
- unsigned int trans_received; /* not ignored */
- float elapsed_time; /* how long the test ran */
- float cpu_util; /* -1 if not measured */
- float serv_dem; /* -1 if not measured */
- int cpu_method; /* how was cpu util measured? */
- int num_cpus; /* how many CPUs had the remote? */
-};
-
-struct sdp_maerts_request_struct {
- int send_buf_size;
- int recv_buf_size; /* how big does the client want it - the */
- /* receive socket buffer that is */
- int send_size; /* how many bytes do we want netserver to send
- at one time? */
- int send_alignment; /* what is the alignment of the send */
- /* buffer? */
- int send_offset; /* and at what offset from that alignment? */
- int no_delay; /* do we disable the nagle algorithm for send */
- /* coalescing? */
- int measure_cpu; /* does the client want server cpu utilization */
- /* measured? */
- float cpu_rate; /* do we know how fast the cpu is already? */
- int test_length; /* how long is the test? */
- int so_rcvavoid; /* do we want the remote to avoid copies on */
- /* receives? */
- int so_sndavoid; /* do we want the remote to avoid send copies? */
- int dirty_count; /* how many integers in the send buffer */
- /* should be made dirty before calling recv? */
- int clean_count; /* how many integers should be read from the */
- /* recv buffer before calling recv? */
- int port; /* the port to which the recv side should bind
- to allow netperf to run through those evil
- firewall things */
- int ipfamily;
-};
-
-struct sdp_maerts_response_struct {
- int recv_buf_size; /* how big does the client want it */
- int send_size;
- int no_delay;
- int measure_cpu; /* does the client want server cpu */
- int test_length; /* how long is the test? */
- int send_buf_size;
- int data_port_number; /* connect to me here */
- float cpu_rate; /* could we measure */
- int so_rcvavoid; /* could the remote avoid receive copies? */
- int so_sndavoid; /* could the remote avoid send copies? */
-};
-
-struct sdp_maerts_results_struct {
- double bytes_sent;
- unsigned int send_calls;
- float elapsed_time; /* how long the test ran */
- float cpu_util; /* -1 if not measured */
- float serv_dem; /* -1 if not measured */
- int cpu_method; /* how was cpu util measured? */
- int num_cpus; /* how many CPUs had the remote? */
-};
-
-extern void send_sdp_stream();
-extern void send_sdp_rr();
-
-extern void recv_sdp_stream();
-extern void recv_sdp_rr();
-
-extern void loc_cpu_rate();
-extern void rem_cpu_rate();
diff --git a/nettest_unix.c b/nettest_unix.c
deleted file mode 100644
index e4716a4..0000000
--- a/nettest_unix.c
+++ /dev/null
@@ -1,3431 +0,0 @@
-#ifdef lint
-#define WANT_UNIX
-#define DIRTY
-#define WANT_INTERVALS
-#endif /* lint */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifdef WANT_UNIX
-char nettest_unix_id[]="\
-@(#)nettest_unix.c (c) Copyright 1994-2007 Hewlett-Packard Co. Version 2.4.3";
-
-/****************************************************************/
-/* */
-/* nettest_bsd.c */
-/* */
-/* the BSD sockets parsing routine... */
-/* */
-/* scan_unix_args() */
-/* */
-/* the actual test routines... */
-/* */
-/* send_stream_stream() perform a stream stream test */
-/* recv_stream_stream() */
-/* send_stream_rr() perform a stream request/response */
-/* recv_stream_rr() */
-/* send_dg_stream() perform a dg stream test */
-/* recv_dg_stream() */
-/* send_dg_rr() perform a dg request/response */
-/* recv_dg_rr() */
-/* loc_cpu_rate() determine the local cpu maxrate */
-/* rem_cpu_rate() find the remote cpu maxrate */
-/* */
-/****************************************************************/
-
- /* at some point, I might want to go-in and see if I really need all */
- /* these includes, but for the moment, we'll let them all just sit */
- /* there. raj 8/94 */
-#include <sys/types.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#ifndef WIN32
-#include <sys/ipc.h>
-#include <sys/socket.h>
-#include <errno.h>
-#include <signal.h>
-#include <sys/un.h>
-#include <unistd.h>
-#else /* WIN32 */
-#include <process.h>
-#include <winsock2.h>
-#include <windows.h>
-#endif /* WIN32 */
-#include <string.h>
-#include <time.h>
-#include <sys/time.h>
-
-#ifdef NOSTDLIBH
-#include <malloc.h>
-#else /* NOSTDLIBH */
-#include <stdlib.h>
-#endif /* NOSTDLIBH */
-
-#include <sys/stat.h>
-
-
-#include "netlib.h"
-#include "netsh.h"
-#include "nettest_unix.h"
-
-
-
- /* these variables are specific to the UNIX sockets tests. declare */
- /* them static to make them global only to this file. */
-
-#define UNIX_PRFX "netperf."
-#define UNIX_LENGTH_MAX 0xFFFF - 28
-
-static char
- path_prefix[32];
-
-static int
- rss_size, /* remote socket send buffer size */
- rsr_size, /* remote socket recv buffer size */
- lss_size_req, /* requested local socket send buffer size */
- lsr_size_req, /* requested local socket recv buffer size */
- lss_size, /* local socket send buffer size */
- lsr_size, /* local socket recv buffer size */
- req_size = 1, /* request size */
- rsp_size = 1, /* response size */
- send_size, /* how big are individual sends */
- recv_size; /* how big are individual receives */
-
- /* different options for the sockets */
-
-
-char unix_usage[] = "\n\
-Usage: netperf [global options] -- [test options] \n\
-\n\
-STREAM/DG UNIX Sockets Test Options:\n\
- -h Display this text\n\
- -m bytes Set the send size (STREAM_STREAM, DG_STREAM)\n\
- -M bytes Set the recv size (STREAM_STREAM, DG_STREAM)\n\
- -p dir Set the directory where pipes are created\n\
- -r req,res Set request,response size (STREAM_RR, DG_RR)\n\
- -s send[,recv] Set local socket send/recv buffer sizes\n\
- -S send[,recv] Set remote socket send/recv buffer sizes\n\
-\n\
-For those options taking two parms, at least one must be specified;\n\
-specifying one value without a comma will set both parms to that\n\
-value, specifying a value with a leading comma will set just the second\n\
-parm, a value with a trailing comma will set just the first. To set\n\
-each parm to unique values, specify both and separate them with a\n\
-comma.\n";
-
- /* this routing initializes all the test specific variables */
-
-static void
-init_test_vars()
-{
- rss_size = 0;
- rsr_size = 0;
- lss_size_req = 0;
- lsr_size_req = 0;
- lss_size = 0;
- lsr_size = 0;
- req_size = 1;
- rsp_size = 1;
- send_size = 0;
- recv_size = 0;
-
- strcpy(path_prefix,"/tmp");
-
-}
-
- /* This routine will create a data (listen) socket with the apropriate */
- /* options set and return it to the caller. this replaces all the */
- /* duplicate code in each of the test routines and should help make */
- /* things a little easier to understand. since this routine can be */
- /* called by either the netperf or netserver programs, all output */
- /* should be directed towards "where." family is generally AF_UNIX, */
- /* and type will be either SOCK_STREAM or SOCK_DGRAM */
-SOCKET
-create_unix_socket(int family, int type)
-{
-
- SOCKET temp_socket;
- int sock_opt_len;
-
- /*set up the data socket */
- temp_socket = socket(family,
- type,
- 0);
-
- if (temp_socket == INVALID_SOCKET){
- fprintf(where,
- "netperf: create_unix_socket: socket: %d\n",
- errno);
- fflush(where);
- exit(1);
- }
-
- if (debug) {
- fprintf(where,"create_unix_socket: socket %d obtained...\n",temp_socket);
- fflush(where);
- }
-
- /* Modify the local socket size. The reason we alter the send buffer */
- /* size here rather than when the connection is made is to take care */
- /* of decreases in buffer size. Decreasing the window size after */
- /* connection establishment is a STREAM no-no. Also, by setting the */
- /* buffer (window) size before the connection is established, we can */
- /* control the STREAM MSS (segment size). The MSS is never more that 1/2 */
- /* the minimum receive buffer size at each half of the connection. */
- /* This is why we are altering the receive buffer size on the sending */
- /* size of a unidirectional transfer. If the user has not requested */
- /* that the socket buffers be altered, we will try to find-out what */
- /* their values are. If we cannot touch the socket buffer in any way, */
- /* we will set the values to -1 to indicate that. */
-
- set_sock_buffer(temp_socket, SEND_BUFFER, lss_size_req, &lss_size);
- set_sock_buffer(temp_socket, RECV_BUFFER, lsr_size_req, &lsr_size);
-
- return(temp_socket);
-
-}
-
-
-/* This routine implements the STREAM unidirectional data transfer test */
-/* (a.k.a. stream) for the sockets interface. It receives its */
-/* parameters via global variables from the shell and writes its */
-/* output to the standard output. */
-
-
-void
-send_stream_stream(char remote_host[])
-{
-
- char *tput_title = "\
-Recv Send Send \n\
-Socket Socket Message Elapsed \n\
-Size Size Size Time Throughput \n\
-bytes bytes bytes secs. %s/sec \n\n";
-
- char *tput_fmt_0 =
- "%7.2f\n";
-
- char *tput_fmt_1 =
- "%5d %5d %6d %-6.2f %7.2f \n";
-
- char *cpu_title = "\
-Recv Send Send Utilization Service Demand\n\
-Socket Socket Message Elapsed Send Recv Send Recv\n\
-Size Size Size Time Throughput local remote local remote\n\
-bytes bytes bytes secs. %-8.8s/s %% %% us/KB us/KB\n\n";
-
- char *cpu_fmt_0 =
- "%6.3f\n";
-
- char *cpu_fmt_1 =
- "%5d %5d %6d %-6.2f %7.2f %-6.2f %-6.2f %-6.3f %-6.3f\n";
-
- char *ksink_fmt = "\n\
-Alignment Offset %-8.8s %-8.8s Sends %-8.8s Recvs\n\
-Local Remote Local Remote Xfered Per Per\n\
-Send Recv Send Recv Send (avg) Recv (avg)\n\
-%5d %5d %5d %5d %6.4g %6.2f %6d %6.2f %6d\n";
-
-
- float elapsed_time;
-
-#ifdef WANT_INTERVALS
- int interval_count;
-#endif
-
- /* what we want is to have a buffer space that is at least one */
- /* send-size greater than our send window. this will insure that we */
- /* are never trying to re-use a buffer that may still be in the hands */
- /* of the transport. This buffer will be malloc'd after we have found */
- /* the size of the local senc socket buffer. We will want to deal */
- /* with alignment and offset concerns as well. */
-
-#ifdef DIRTY
- int *message_int_ptr;
-#endif
-#include <sys/stat.h>
-
- struct ring_elt *send_ring;
-
- int len = 0;
- int nummessages;
- SOCKET send_socket;
- int bytes_remaining;
- /* with links like fddi, one can send > 32 bits worth of bytes */
- /* during a test... ;-) */
- double bytes_sent;
-
-#ifdef DIRTY
- int i;
-#endif /* DIRTY */
-
- float local_cpu_utilization;
- float local_service_demand;
- float remote_cpu_utilization;
- float remote_service_demand;
- double thruput;
-
- struct sockaddr_un server;
-
- struct stream_stream_request_struct *stream_stream_request;
- struct stream_stream_response_struct *stream_stream_response;
- struct stream_stream_results_struct *stream_stream_result;
-
- stream_stream_request =
- (struct stream_stream_request_struct *)netperf_request.content.test_specific_data;
- stream_stream_response =
- (struct stream_stream_response_struct *)netperf_response.content.test_specific_data;
- stream_stream_result =
- (struct stream_stream_results_struct *)netperf_response.content.test_specific_data;
-
- /* since we are now disconnected from the code that established the */
- /* control socket, and since we want to be able to use different */
- /* protocols and such, we are passed the name of the remote host and */
- /* must turn that into the test specific addressing information. */
-
- bzero((char *)&server,
- sizeof(server));
- server.sun_family = AF_UNIX;
-
-
- if ( print_headers ) {
- fprintf(where,"STREAM STREAM TEST\n");
- if (local_cpu_usage || remote_cpu_usage)
- fprintf(where,cpu_title,format_units());
- else
- fprintf(where,tput_title,format_units());
- }
-
- /* initialize a few counters */
-
- nummessages = 0;
- bytes_sent = 0.0;
- times_up = 0;
-
- /*set up the data socket */
- send_socket = create_unix_socket(AF_UNIX,
- SOCK_STREAM);
-
- if (send_socket == INVALID_SOCKET){
- perror("netperf: send_stream_stream: stream stream data socket");
- exit(1);
- }
-
- if (debug) {
- fprintf(where,"send_stream_stream: send_socket obtained...\n");
- }
-
- /* at this point, we have either retrieved the socket buffer sizes, */
- /* or have tried to set them, so now, we may want to set the send */
- /* size based on that (because the user either did not use a -m */
- /* option, or used one with an argument of 0). If the socket buffer */
- /* size is not available, we will set the send size to 4KB - no */
- /* particular reason, just arbitrary... */
- if (send_size == 0) {
- if (lss_size > 0) {
- send_size = lss_size;
- }
- else {
- send_size = 4096;
- }
- }
-
- /* set-up the data buffer ring with the requested alignment and offset. */
- /* note also that we have allocated a quantity */
- /* of memory that is at least one send-size greater than our socket */
- /* buffer size. We want to be sure that there are at least two */
- /* buffers allocated - this can be a bit of a problem when the */
- /* send_size is bigger than the socket size, so we must check... the */
- /* user may have wanted to explicitly set the "width" of our send */
- /* buffers, we should respect that wish... */
- if (send_width == 0) {
- send_width = (lss_size/send_size) + 1;
- if (send_width == 1) send_width++;
- }
-
- send_ring = allocate_buffer_ring(send_width,
- send_size,
- local_send_align,
- local_send_offset);
-
- /* If the user has requested cpu utilization measurements, we must */
- /* calibrate the cpu(s). We will perform this task within the tests */
- /* themselves. If the user has specified the cpu rate, then */
- /* calibrate_local_cpu will return rather quickly as it will have */
- /* nothing to do. If local_cpu_rate is zero, then we will go through */
- /* all the "normal" calibration stuff and return the rate back.*/
-
- if (local_cpu_usage) {
- local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
- }
-
- /* Tell the remote end to do a listen. The server alters the socket */
- /* paramters on the other side at this point, hence the reason for */
- /* all the values being passed in the setup message. If the user did */
- /* not specify any of the parameters, they will be passed as 0, which */
- /* will indicate to the remote that no changes beyond the system's */
- /* default should be used. Alignment is the exception, it will */
- /* default to 1, which will be no alignment alterations. */
-
- netperf_request.content.request_type = DO_STREAM_STREAM;
- stream_stream_request->send_buf_size = rss_size;
- stream_stream_request->recv_buf_size = rsr_size;
- stream_stream_request->receive_size = recv_size;
- stream_stream_request->recv_alignment = remote_recv_align;
- stream_stream_request->recv_offset = remote_recv_offset;
- stream_stream_request->measure_cpu = remote_cpu_usage;
- stream_stream_request->cpu_rate = remote_cpu_rate;
- if (test_time) {
- stream_stream_request->test_length = test_time;
- }
- else {
- stream_stream_request->test_length = test_bytes;
- }
-#ifdef DIRTY
- stream_stream_request->dirty_count = rem_dirty_count;
- stream_stream_request->clean_count = rem_clean_count;
-#endif /* DIRTY */
-
-
- if (debug > 1) {
- fprintf(where,
- "netperf: send_stream_stream: requesting STREAM stream test\n");
- }
-
- send_request();
-
- /* The response from the remote will contain all of the relevant */
- /* socket parameters for this test type. We will put them back into */
- /* the variables here so they can be displayed if desired. The */
- /* remote will have calibrated CPU if necessary, and will have done */
- /* all the needed set-up we will have calibrated the cpu locally */
- /* before sending the request, and will grab the counter value right */
- /* after the connect returns. The remote will grab the counter right */
- /* after the accept call. This saves the hassle of extra messages */
- /* being sent for the STREAM tests. */
-
- recv_response();
-
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote listen done.\n");
- rsr_size = stream_stream_response->recv_buf_size;
- rss_size = stream_stream_response->send_buf_size;
- remote_cpu_usage = stream_stream_response->measure_cpu;
- remote_cpu_rate = stream_stream_response->cpu_rate;
- strcpy(server.sun_path,stream_stream_response->unix_path);
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- perror("netperf: send_stream_stream: remote error");
- exit(1);
- }
-
- /*Connect up to the remote port on the data socket */
- if (connect(send_socket,
- (struct sockaddr *)&server,
- sizeof(server)) == INVALID_SOCKET){
- perror("netperf: send_stream_stream: data socket connect failed");
- printf(" path: %s\n",server.sun_path);
- exit(1);
- }
-
- /* Data Socket set-up is finished. If there were problems, either the */
- /* connect would have failed, or the previous response would have */
- /* indicated a problem. I failed to see the value of the extra */
- /* message after the accept on the remote. If it failed, we'll see it */
- /* here. If it didn't, we might as well start pumping data. */
-
- /* Set-up the test end conditions. For a stream test, they can be */
- /* either time or byte-count based. */
-
- if (test_time) {
- /* The user wanted to end the test after a period of time. */
- times_up = 0;
- bytes_remaining = 0;
- start_timer(test_time);
- }
- else {
- /* The tester wanted to send a number of bytes. */
- bytes_remaining = test_bytes;
- times_up = 1;
- }
-
- /* The cpu_start routine will grab the current time and possibly */
- /* value of the idle counter for later use in measuring cpu */
- /* utilization and/or service demand and thruput. */
-
- cpu_start(local_cpu_usage);
-
- /* We use an "OR" to control test execution. When the test is */
- /* controlled by time, the byte count check will always return false. */
- /* When the test is controlled by byte count, the time test will */
- /* always return false. When the test is finished, the whole */
- /* expression will go false and we will stop sending data. */
-
-#ifdef DIRTY
- /* initialize the random number generator for putting dirty stuff */
- /* into the send buffer. raj */
- srand((int) getpid());
-#endif
-
- while ((!times_up) || (bytes_remaining > 0)) {
-
-#ifdef DIRTY
- /* we want to dirty some number of consecutive integers in the buffer */
- /* we are about to send. we may also want to bring some number of */
- /* them cleanly into the cache. The clean ones will follow any dirty */
- /* ones into the cache. at some point, we might want to replace */
- /* the rand() call with something from a table to reduce our call */
- /* overhead during the test, but it is not a high priority item. */
- message_int_ptr = (int *)(send_ring->buffer_ptr);
- for (i = 0; i < loc_dirty_count; i++) {
- *message_int_ptr = rand();
- message_int_ptr++;
- }
- for (i = 0; i < loc_clean_count; i++) {
- loc_dirty_count = *message_int_ptr;
- message_int_ptr++;
- }
-#endif /* DIRTY */
-
- if((len=send(send_socket,
- send_ring->buffer_ptr,
- send_size,
- 0)) != send_size) {
- if ((len >=0) || (errno == EINTR)) {
- /* the test was interrupted, must be the end of test */
- break;
- }
- perror("netperf: data send error");
- printf("len was %d\n",len);
- exit(1);
- }
-#ifdef WANT_INTERVALS
- for (interval_count = 0;
- interval_count < interval_wate;
- interval_count++);
-#endif
-
- /* now we want to move our pointer to the next position in the */
- /* data buffer...we may also want to wrap back to the "beginning" */
- /* of the bufferspace, so we will mod the number of messages sent */
- /* by the send width, and use that to calculate the offset to add */
- /* to the base pointer. */
- nummessages++;
- send_ring = send_ring->next;
- if (bytes_remaining) {
- bytes_remaining -= send_size;
- }
- }
-
- /* The test is over. Flush the buffers to the remote end. We do a */
- /* graceful release to insure that all data has been taken by the */
- /* remote. */
-
- if (close(send_socket) == -1) {
- perror("netperf: send_stream_stream: cannot close socket");
- exit(1);
- }
-
- /* this call will always give us the elapsed time for the test, and */
- /* will also store-away the necessaries for cpu utilization */
-
- cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */
- /* measured and how */
- /* long did we really */
- /* run? */
-
- /* Get the statistics from the remote end. The remote will have */
- /* calculated service demand and all those interesting things. If it */
- /* wasn't supposed to care, it will return obvious values. */
-
- recv_response();
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote results obtained\n");
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- perror("netperf: remote error");
-
- exit(1);
- }
-
- /* We now calculate what our thruput was for the test. In the future, */
- /* we may want to include a calculation of the thruput measured by */
- /* the remote, but it should be the case that for a STREAM stream test, */
- /* that the two numbers should be *very* close... We calculate */
- /* bytes_sent regardless of the way the test length was controlled. */
- /* If it was time, we needed to, and if it was by bytes, the user may */
- /* have specified a number of bytes that wasn't a multiple of the */
- /* send_size, so we really didn't send what he asked for ;-) */
-
- bytes_sent = ((double) send_size * (double) nummessages) + len;
- thruput = calc_thruput(bytes_sent);
-
- if (local_cpu_usage || remote_cpu_usage) {
- /* We must now do a little math for service demand and cpu */
- /* utilization for the system(s) */
- /* Of course, some of the information might be bogus because */
- /* there was no idle counter in the kernel(s). We need to make */
- /* a note of this for the user's benefit...*/
- if (local_cpu_usage) {
- if (local_cpu_rate == 0.0) {
- fprintf(where,"WARNING WARNING WARNING WARNING WARNING WARNING WARNING!\n");
- fprintf(where,"Local CPU usage numbers based on process information only!\n");
- fflush(where);
- }
- local_cpu_utilization = calc_cpu_util(0.0);
- local_service_demand = calc_service_demand(bytes_sent,
- 0.0,
- 0.0,
- 0);
- }
- else {
- local_cpu_utilization = -1.0;
- local_service_demand = -1.0;
- }
-
- if (remote_cpu_usage) {
- if (remote_cpu_rate == 0.0) {
- fprintf(where,"DANGER DANGER DANGER DANGER DANGER DANGER DANGER!\n");
- fprintf(where,"Remote CPU usage numbers based on process information only!\n");
- fflush(where);
- }
- remote_cpu_utilization = stream_stream_result->cpu_util;
- remote_service_demand = calc_service_demand(bytes_sent,
- 0.0,
- remote_cpu_utilization,
- stream_stream_result->num_cpus);
- }
- else {
- remote_cpu_utilization = -1.0;
- remote_service_demand = -1.0;
- }
-
- /* We are now ready to print all the information. If the user */
- /* has specified zero-level verbosity, we will just print the */
- /* local service demand, or the remote service demand. If the */
- /* user has requested verbosity level 1, he will get the basic */
- /* "streamperf" numbers. If the user has specified a verbosity */
- /* of greater than 1, we will display a veritable plethora of */
- /* background information from outside of this block as it it */
- /* not cpu_measurement specific... */
-
- switch (verbosity) {
- case 0:
- if (local_cpu_usage) {
- fprintf(where,
- cpu_fmt_0,
- local_service_demand);
- }
- else {
- fprintf(where,
- cpu_fmt_0,
- remote_service_demand);
- }
- break;
- case 1:
- case 2:
- fprintf(where,
- cpu_fmt_1, /* the format string */
- rsr_size, /* remote recvbuf size */
- lss_size, /* local sendbuf size */
- send_size, /* how large were the sends */
- elapsed_time, /* how long was the test */
- thruput, /* what was the xfer rate */
- local_cpu_utilization, /* local cpu */
- remote_cpu_utilization, /* remote cpu */
- local_service_demand, /* local service demand */
- remote_service_demand); /* remote service demand */
- break;
- }
- }
- else {
- /* The tester did not wish to measure service demand. */
- switch (verbosity) {
- case 0:
- fprintf(where,
- tput_fmt_0,
- thruput);
- break;
- case 1:
- case 2:
- fprintf(where,
- tput_fmt_1, /* the format string */
- rsr_size, /* remote recvbuf size */
- lss_size, /* local sendbuf size */
- send_size, /* how large were the sends */
- elapsed_time, /* how long did it take */
- thruput);/* how fast did it go */
- break;
- }
- }
-
- /* it would be a good thing to include information about some of the */
- /* other parameters that may have been set for this test, but at the */
- /* moment, I do not wish to figure-out all the formatting, so I will */
- /* just put this comment here to help remind me that it is something */
- /* that should be done at a later time. */
-
- if (verbosity > 1) {
- /* The user wanted to know it all, so we will give it to him. */
- /* This information will include as much as we can find about */
- /* STREAM statistics, the alignments of the sends and receives */
- /* and all that sort of rot... */
-
- fprintf(where,
- ksink_fmt,
- "Bytes",
- "Bytes",
- "Bytes",
- local_send_align,
- remote_recv_align,
- local_send_offset,
- remote_recv_offset,
- bytes_sent,
- bytes_sent / (double)nummessages,
- nummessages,
- bytes_sent / (double)stream_stream_result->recv_calls,
- stream_stream_result->recv_calls);
- }
-
-}
-
-
-/* This is the server-side routine for the stream stream test. It is */
-/* implemented as one routine. I could break things-out somewhat, but */
-/* didn't feel it was necessary. */
-
-void
-recv_stream_stream()
-{
-
- struct sockaddr_un myaddr_un, peeraddr_un;
- SOCKET s_listen,s_data;
- int addrlen;
- int len;
- int receive_calls = 0;
- float elapsed_time;
- int bytes_received;
-
- struct ring_elt *recv_ring;
-
-#ifdef DIRTY
- char *message_ptr;
- int *message_int_ptr;
- int dirty_count;
- int clean_count;
- int i;
-#endif
-
- struct stream_stream_request_struct *stream_stream_request;
- struct stream_stream_response_struct *stream_stream_response;
- struct stream_stream_results_struct *stream_stream_results;
-
- stream_stream_request =
- (struct stream_stream_request_struct *)netperf_request.content.test_specific_data;
- stream_stream_response =
- (struct stream_stream_response_struct *)netperf_response.content.test_specific_data;
- stream_stream_results =
- (struct stream_stream_results_struct *)netperf_response.content.test_specific_data;
-
- if (debug) {
- fprintf(where,"netserver: recv_stream_stream: entered...\n");
- fflush(where);
- }
-
- /* We want to set-up the listen socket with all the desired */
- /* parameters and then let the initiator know that all is ready. If */
- /* socket size defaults are to be used, then the initiator will have */
- /* sent us 0's. If the socket sizes cannot be changed, then we will */
- /* send-back what they are. If that information cannot be determined, */
- /* then we send-back -1's for the sizes. If things go wrong for any */
- /* reason, we will drop back ten yards and punt. */
-
- /* If anything goes wrong, we want the remote to know about it. It */
- /* would be best if the error that the remote reports to the user is */
- /* the actual error we encountered, rather than some bogus unexpected */
- /* response type message. */
-
- if (debug) {
- fprintf(where,"recv_stream_stream: setting the response type...\n");
- fflush(where);
- }
-
- netperf_response.content.response_type = STREAM_STREAM_RESPONSE;
-
- if (debug) {
- fprintf(where,"recv_stream_stream: the response type is set...\n");
- fflush(where);
- }
-
- /* We now alter the message_ptr variable to be at the desired */
- /* alignment with the desired offset. */
-
- if (debug) {
- fprintf(where,"recv_stream_stream: requested alignment of %d\n",
- stream_stream_request->recv_alignment);
- fflush(where);
- }
-
- /* Let's clear-out our sockaddr for the sake of cleanlines. Then we */
- /* can put in OUR values !-) At some point, we may want to nail this */
- /* socket to a particular network-level address, but for now, */
- /* INADDR_ANY should be just fine. */
-
- bzero((char *)&myaddr_un,
- sizeof(myaddr_un));
- myaddr_un.sun_family = AF_UNIX;
-
- /* Grab a socket to listen on, and then listen on it. */
-
- if (debug) {
- fprintf(where,"recv_stream_stream: grabbing a socket...\n");
- fflush(where);
- }
-
- /* create_unix_socket expects to find some things in the global */
- /* variables, so set the globals based on the values in the request. */
- /* once the socket has been created, we will set the response values */
- /* based on the updated value of those globals. raj 7/94 */
- lss_size_req = stream_stream_request->send_buf_size;
- lsr_size_req = stream_stream_request->recv_buf_size;
-
- s_listen = create_unix_socket(AF_UNIX,
- SOCK_STREAM);
-
- if (s_listen == INVALID_SOCKET) {
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
-
- /* Let's get an address assigned to this socket so we can tell the */
- /* initiator how to reach the data socket. There may be a desire to */
- /* nail this socket to a specific IP address in a multi-homed, */
- /* multi-connection situation, but for now, we'll ignore the issue */
- /* and concentrate on single connection testing. */
-
- strcpy(myaddr_un.sun_path,tempnam(path_prefix,"netperf."));
- if (debug) {
- fprintf(where,"selected a path of %s\n",myaddr_un.sun_path);
- fflush(where);
- }
- if (bind(s_listen,
- (struct sockaddr *)&myaddr_un,
- sizeof(myaddr_un)) == SOCKET_ERROR) {
- netperf_response.content.serv_errno = errno;
- fprintf(where,"could not bind to path\n");
- close(s_listen);
- send_response();
-
- exit(1);
- }
-
- chmod(myaddr_un.sun_path, 0666);
-
- /* what sort of sizes did we end-up with? */
- if (stream_stream_request->receive_size == 0) {
- if (lsr_size > 0) {
- recv_size = lsr_size;
- }
- else {
- recv_size = 4096;
- }
- }
- else {
- recv_size = stream_stream_request->receive_size;
- }
-
- /* we want to set-up our recv_ring in a manner analagous to what we */
- /* do on the sending side. this is more for the sake of symmetry */
- /* than for the needs of say copy avoidance, but it might also be */
- /* more realistic - this way one could conceivably go with a */
- /* double-buffering scheme when taking the data an putting it into */
- /* the filesystem or something like that. raj 7/94 */
-
- if (recv_width == 0) {
- recv_width = (lsr_size/recv_size) + 1;
- if (recv_width == 1) recv_width++;
- }
-
- recv_ring = allocate_buffer_ring(recv_width,
- recv_size,
- stream_stream_request->recv_alignment,
- stream_stream_request->recv_offset);
-
- if (debug) {
- fprintf(where,"recv_stream_stream: receive alignment and offset set...\n");
- fflush(where);
- }
-
- /* Now, let's set-up the socket to listen for connections */
- if (listen(s_listen, 5) == SOCKET_ERROR) {
- netperf_response.content.serv_errno = errno;
- close(s_listen);
- send_response();
-
- exit(1);
- }
-
- /* now get the port number assigned by the system */
- addrlen = sizeof(myaddr_un);
- if (getsockname(s_listen,
- (struct sockaddr *)&myaddr_un,
- &addrlen) == SOCKET_ERROR){
- netperf_response.content.serv_errno = errno;
- close(s_listen);
- send_response();
-
- exit(1);
- }
-
- /* Now myaddr_un contains the path */
- /* returned to the sender also implicitly telling the sender that the */
- /* socket buffer sizing has been done. */
- strcpy(stream_stream_response->unix_path,myaddr_un.sun_path);
- netperf_response.content.serv_errno = 0;
-
- /* But wait, there's more. If the initiator wanted cpu measurements, */
- /* then we must call the calibrate routine, which will return the max */
- /* rate back to the initiator. If the CPU was not to be measured, or */
- /* something went wrong with the calibration, we will return a -1 to */
- /* the initiator. */
-
- stream_stream_response->cpu_rate = 0.0; /* assume no cpu */
- if (stream_stream_request->measure_cpu) {
- stream_stream_response->measure_cpu = 1;
- stream_stream_response->cpu_rate =
- calibrate_local_cpu(stream_stream_request->cpu_rate);
- }
-
- /* before we send the response back to the initiator, pull some of */
- /* the socket parms from the globals */
- stream_stream_response->send_buf_size = lss_size;
- stream_stream_response->recv_buf_size = lsr_size;
- stream_stream_response->receive_size = recv_size;
-
- send_response();
-
- addrlen = sizeof(peeraddr_un);
-
- if ((s_data=accept(s_listen,
- (struct sockaddr *)&peeraddr_un,
- &addrlen)) == INVALID_SOCKET) {
- /* Let's just punt. The remote will be given some information */
- close(s_listen);
- exit(1);
- }
-
- /* Now it's time to start receiving data on the connection. We will */
- /* first grab the apropriate counters and then start grabbing. */
-
- cpu_start(stream_stream_request->measure_cpu);
-
- /* The loop will exit when the sender does a shutdown, which will */
- /* return a length of zero */
-
-#ifdef DIRTY
- /* we want to dirty some number of consecutive integers in the buffer */
- /* we are about to recv. we may also want to bring some number of */
- /* them cleanly into the cache. The clean ones will follow any dirty */
- /* ones into the cache. */
-
- dirty_count = stream_stream_request->dirty_count;
- clean_count = stream_stream_request->clean_count;
- message_int_ptr = (int *)recv_ring->buffer_ptr;
- for (i = 0; i < dirty_count; i++) {
- *message_int_ptr = rand();
- message_int_ptr++;
- }
- for (i = 0; i < clean_count; i++) {
- dirty_count = *message_int_ptr;
- message_int_ptr++;
- }
-#endif /* DIRTY */
- bytes_received = 0;
-
- while ((len = recv(s_data, recv_ring->buffer_ptr, recv_size, 0)) != 0) {
- if (len == SOCKET_ERROR) {
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
- bytes_received += len;
- receive_calls++;
-
- /* more to the next buffer in the recv_ring */
- recv_ring = recv_ring->next;
-
-#ifdef DIRTY
- message_int_ptr = (int *)(recv_ring->buffer_ptr);
- for (i = 0; i < dirty_count; i++) {
- *message_int_ptr = rand();
- message_int_ptr++;
- }
- for (i = 0; i < clean_count; i++) {
- dirty_count = *message_int_ptr;
- message_int_ptr++;
- }
-#endif /* DIRTY */
- }
-
- /* The loop now exits due to zero bytes received. we will have */
- /* counted one too many messages received, so decrement the */
- /* receive_calls counter by one. raj 7/94 */
- receive_calls--;
-
- /* perform a shutdown to signal the sender that */
- /* we have received all the data sent. raj 4/93 */
-
- if (shutdown(s_data,1) == SOCKET_ERROR) {
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
-
- cpu_stop(stream_stream_request->measure_cpu,&elapsed_time);
-
- /* send the results to the sender */
-
- if (debug) {
- fprintf(where,
- "recv_stream_stream: got %d bytes\n",
- bytes_received);
- fprintf(where,
- "recv_stream_stream: got %d recvs\n",
- receive_calls);
- fflush(where);
- }
-
- stream_stream_results->bytes_received = bytes_received;
- stream_stream_results->elapsed_time = elapsed_time;
- stream_stream_results->recv_calls = receive_calls;
-
- if (stream_stream_request->measure_cpu) {
- stream_stream_results->cpu_util = calc_cpu_util(0.0);
- };
-
- if (debug > 1) {
- fprintf(where,
- "recv_stream_stream: test complete, sending results.\n");
- fflush(where);
- }
-
- send_response();
- unlink(myaddr_un.sun_path);
-}
-
-
- /* this routine implements the sending (netperf) side of the STREAM_RR */
- /* test. */
-
-void
-send_stream_rr(char remote_host[])
-{
-
- char *tput_title = "\
-Local /Remote\n\
-Socket Size Request Resp. Elapsed Trans.\n\
-Send Recv Size Size Time Rate \n\
-bytes Bytes bytes bytes secs. per sec \n\n";
-
- char *tput_fmt_0 =
- "%7.2f\n";
-
- char *tput_fmt_1_line_1 = "\
-%-6d %-6d %-6d %-6d %-6.2f %7.2f \n";
- char *tput_fmt_1_line_2 = "\
-%-6d %-6d\n";
-
- char *cpu_title = "\
-Local /Remote\n\
-Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\
-Send Recv Size Size Time Rate local remote local remote\n\
-bytes bytes bytes bytes secs. per sec %% %% us/Tr us/Tr\n\n";
-
- char *cpu_fmt_0 =
- "%6.3f\n";
-
- char *cpu_fmt_1_line_1 = "\
-%-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f\n";
-
- char *cpu_fmt_1_line_2 = "\
-%-6d %-6d\n";
-
- char *ksink_fmt = "\
-Alignment Offset\n\
-Local Remote Local Remote\n\
-Send Recv Send Recv\n\
-%5d %5d %5d %5d\n";
-
-
- int timed_out = 0;
- float elapsed_time;
-
- int len;
- char *temp_message_ptr;
- int nummessages;
- SOCKET send_socket;
- int trans_remaining;
- double bytes_xferd;
-
- struct ring_elt *send_ring;
- struct ring_elt *recv_ring;
-
- int rsp_bytes_left;
- int rsp_bytes_recvd;
-
- float local_cpu_utilization;
- float local_service_demand;
- float remote_cpu_utilization;
- float remote_service_demand;
- double thruput;
-
- struct sockaddr_un server;
-
- struct stream_rr_request_struct *stream_rr_request;
- struct stream_rr_response_struct *stream_rr_response;
- struct stream_rr_results_struct *stream_rr_result;
-
- stream_rr_request =
- (struct stream_rr_request_struct *)netperf_request.content.test_specific_data;
- stream_rr_response=
- (struct stream_rr_response_struct *)netperf_response.content.test_specific_data;
- stream_rr_result =
- (struct stream_rr_results_struct *)netperf_response.content.test_specific_data;
-
- /* since we are now disconnected from the code that established the */
- /* control socket, and since we want to be able to use different */
- /* protocols and such, we are passed the name of the remote host and */
- /* must turn that into the test specific addressing information. */
-
- bzero((char *)&server,
- sizeof(server));
-
- server.sun_family = AF_UNIX;
-
-
- if ( print_headers ) {
- fprintf(where,"STREAM REQUEST/RESPONSE TEST\n");
- if (local_cpu_usage || remote_cpu_usage)
- fprintf(where,cpu_title,format_units());
- else
- fprintf(where,tput_title,format_units());
- }
-
- /* initialize a few counters */
-
- nummessages = 0;
- bytes_xferd = 0.0;
- times_up = 0;
-
- /* set-up the data buffers with the requested alignment and offset. */
- /* since this is a request/response test, default the send_width and */
- /* recv_width to 1 and not two raj 7/94 */
-
- if (send_width == 0) send_width = 1;
- if (recv_width == 0) recv_width = 1;
-
- send_ring = allocate_buffer_ring(send_width,
- req_size,
- local_send_align,
- local_send_offset);
-
- recv_ring = allocate_buffer_ring(recv_width,
- rsp_size,
- local_recv_align,
- local_recv_offset);
-
- /*set up the data socket */
- send_socket = create_unix_socket(AF_UNIX,
- SOCK_STREAM);
-
- if (send_socket == INVALID_SOCKET){
- perror("netperf: send_stream_rr: stream stream data socket");
- exit(1);
- }
-
- if (debug) {
- fprintf(where,"send_stream_rr: send_socket obtained...\n");
- }
-
- /* If the user has requested cpu utilization measurements, we must */
- /* calibrate the cpu(s). We will perform this task within the tests */
- /* themselves. If the user has specified the cpu rate, then */
- /* calibrate_local_cpu will return rather quickly as it will have */
- /* nothing to do. If local_cpu_rate is zero, then we will go through */
- /* all the "normal" calibration stuff and return the rate back.*/
-
- if (local_cpu_usage) {
- local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
- }
-
- /* Tell the remote end to do a listen. The server alters the socket */
- /* paramters on the other side at this point, hence the reason for */
- /* all the values being passed in the setup message. If the user did */
- /* not specify any of the parameters, they will be passed as 0, which */
- /* will indicate to the remote that no changes beyond the system's */
- /* default should be used. Alignment is the exception, it will */
- /* default to 8, which will be no alignment alterations. */
-
- netperf_request.content.request_type = DO_STREAM_RR;
- stream_rr_request->recv_buf_size = rsr_size;
- stream_rr_request->send_buf_size = rss_size;
- stream_rr_request->recv_alignment= remote_recv_align;
- stream_rr_request->recv_offset = remote_recv_offset;
- stream_rr_request->send_alignment= remote_send_align;
- stream_rr_request->send_offset = remote_send_offset;
- stream_rr_request->request_size = req_size;
- stream_rr_request->response_size = rsp_size;
- stream_rr_request->measure_cpu = remote_cpu_usage;
- stream_rr_request->cpu_rate = remote_cpu_rate;
- if (test_time) {
- stream_rr_request->test_length = test_time;
- }
- else {
- stream_rr_request->test_length = test_trans * -1;
- }
-
- if (debug > 1) {
- fprintf(where,"netperf: send_stream_rr: requesting STREAM rr test\n");
- }
-
- send_request();
-
- /* The response from the remote will contain all of the relevant */
- /* socket parameters for this test type. We will put them back into */
- /* the variables here so they can be displayed if desired. The */
- /* remote will have calibrated CPU if necessary, and will have done */
- /* all the needed set-up we will have calibrated the cpu locally */
- /* before sending the request, and will grab the counter value right */
- /* after the connect returns. The remote will grab the counter right */
- /* after the accept call. This saves the hassle of extra messages */
- /* being sent for the STREAM tests. */
-
- recv_response();
-
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote listen done.\n");
- rsr_size = stream_rr_response->recv_buf_size;
- rss_size = stream_rr_response->send_buf_size;
- remote_cpu_usage= stream_rr_response->measure_cpu;
- remote_cpu_rate = stream_rr_response->cpu_rate;
- /* make sure that port numbers are in network order */
- strcpy(server.sun_path,stream_rr_response->unix_path);
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- perror("netperf: remote error");
-
- exit(1);
- }
-
- /*Connect up to the remote port on the data socket */
- if (connect(send_socket,
- (struct sockaddr *)&server,
- sizeof(server)) == INVALID_SOCKET){
- perror("netperf: data socket connect failed");
-
- exit(1);
- }
-
- /* Data Socket set-up is finished. If there were problems, either the */
- /* connect would have failed, or the previous response would have */
- /* indicated a problem. I failed to see the value of the extra */
- /* message after the accept on the remote. If it failed, we'll see it */
- /* here. If it didn't, we might as well start pumping data. */
-
- /* Set-up the test end conditions. For a request/response test, they */
- /* can be either time or transaction based. */
-
- if (test_time) {
- /* The user wanted to end the test after a period of time. */
- times_up = 0;
- trans_remaining = 0;
- start_timer(test_time);
- }
- else {
- /* The tester wanted to send a number of bytes. */
- trans_remaining = test_bytes;
- times_up = 1;
- }
-
- /* The cpu_start routine will grab the current time and possibly */
- /* value of the idle counter for later use in measuring cpu */
- /* utilization and/or service demand and thruput. */
-
- cpu_start(local_cpu_usage);
-
- /* We use an "OR" to control test execution. When the test is */
- /* controlled by time, the byte count check will always return false. */
- /* When the test is controlled by byte count, the time test will */
- /* always return false. When the test is finished, the whole */
- /* expression will go false and we will stop sending data. I think I */
- /* just arbitrarily decrement trans_remaining for the timed test, but */
- /* will not do that just yet... One other question is whether or not */
- /* the send buffer and the receive buffer should be the same buffer. */
-
- while ((!times_up) || (trans_remaining > 0)) {
- /* send the request. we assume that if we use a blocking socket, */
- /* the request will be sent at one shot. */
- if((len=send(send_socket,
- send_ring->buffer_ptr,
- req_size,
- 0)) != req_size) {
- if (errno == EINTR) {
- /* we hit the end of a */
- /* timed test. */
- timed_out = 1;
- break;
- }
- perror("send_stream_rr: data send error");
- exit(1);
- }
- send_ring = send_ring->next;
-
- /* receive the response */
- rsp_bytes_left = rsp_size;
- temp_message_ptr = recv_ring->buffer_ptr;
- while(rsp_bytes_left > 0) {
- if((rsp_bytes_recvd=recv(send_socket,
- temp_message_ptr,
- rsp_bytes_left,
- 0)) == SOCKET_ERROR) {
- if (errno == EINTR) {
- /* We hit the end of a timed test. */
- timed_out = 1;
- break;
- }
- perror("send_stream_rr: data recv error");
- exit(1);
- }
- rsp_bytes_left -= rsp_bytes_recvd;
- temp_message_ptr += rsp_bytes_recvd;
- }
- recv_ring = recv_ring->next;
-
- if (timed_out) {
- /* we may have been in a nested while loop - we need */
- /* another call to break. */
- break;
- }
-
- nummessages++;
- if (trans_remaining) {
- trans_remaining--;
- }
-
- if (debug > 3) {
- fprintf(where,
- "Transaction %d completed\n",
- nummessages);
- fflush(where);
- }
- }
-
- /* At this point we used to call shutdown on the data socket to be */
- /* sure all the data was delivered, but this was not germane in a */
- /* request/response test, and it was causing the tests to "hang" when */
- /* they were being controlled by time. So, I have replaced this */
- /* shutdown call with a call to close that can be found later in the */
- /* procedure. */
-
- /* this call will always give us the elapsed time for the test, and */
- /* will also store-away the necessaries for cpu utilization */
-
- cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being measured? */
- /* how long did we really run? */
-
- /* Get the statistics from the remote end. The remote will have */
- /* calculated service demand and all those interesting things. If it */
- /* wasn't supposed to care, it will return obvious values. */
-
- recv_response();
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote results obtained\n");
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- perror("netperf: remote error");
-
- exit(1);
- }
-
- /* We now calculate what our thruput was for the test. In the future, */
- /* we may want to include a calculation of the thruput measured by */
- /* the remote, but it should be the case that for a STREAM stream test, */
- /* that the two numbers should be *very* close... We calculate */
- /* bytes_sent regardless of the way the test length was controlled. */
- /* If it was time, we needed to, and if it was by bytes, the user may */
- /* have specified a number of bytes that wasn't a multiple of the */
- /* send_size, so we really didn't send what he asked for ;-) We use */
- /* Kbytes/s as the units of thruput for a STREAM stream test, where K = */
- /* 1024. A future enhancement *might* be to choose from a couple of */
- /* unit selections. */
-
- bytes_xferd = (req_size * nummessages) + (rsp_size * nummessages);
- thruput = calc_thruput(bytes_xferd);
-
- if (local_cpu_usage || remote_cpu_usage) {
- /* We must now do a little math for service demand and cpu */
- /* utilization for the system(s) */
- /* Of course, some of the information might be bogus because */
- /* there was no idle counter in the kernel(s). We need to make */
- /* a note of this for the user's benefit...*/
- if (local_cpu_usage) {
- if (local_cpu_rate == 0.0) {
- fprintf(where,"WARNING WARNING WARNING WARNING WARNING WARNING WARNING!\n");
- fprintf(where,"Local CPU usage numbers based on process information only!\n");
- fflush(where);
- }
- local_cpu_utilization = calc_cpu_util(0.0);
- /* since calc_service demand is doing ms/Kunit we will */
- /* multiply the number of transaction by 1024 to get */
- /* "good" numbers */
- local_service_demand = calc_service_demand((double) nummessages*1024,
- 0.0,
- 0.0,
- 0);
- }
- else {
- local_cpu_utilization = -1.0;
- local_service_demand = -1.0;
- }
-
- if (remote_cpu_usage) {
- if (remote_cpu_rate == 0.0) {
- fprintf(where,"DANGER DANGER DANGER DANGER DANGER DANGER DANGER!\n");
- fprintf(where,"Remote CPU usage numbers based on process information only!\n");
- fflush(where);
- }
- remote_cpu_utilization = stream_rr_result->cpu_util;
- /* since calc_service demand is doing ms/Kunit we will */
- /* multiply the number of transaction by 1024 to get */
- /* "good" numbers */
- remote_service_demand = calc_service_demand((double) nummessages*1024,
- 0.0,
- remote_cpu_utilization,
- stream_rr_result->num_cpus);
- }
- else {
- remote_cpu_utilization = -1.0;
- remote_service_demand = -1.0;
- }
-
- /* We are now ready to print all the information. If the user */
- /* has specified zero-level verbosity, we will just print the */
- /* local service demand, or the remote service demand. If the */
- /* user has requested verbosity level 1, he will get the basic */
- /* "streamperf" numbers. If the user has specified a verbosity */
- /* of greater than 1, we will display a veritable plethora of */
- /* background information from outside of this block as it it */
- /* not cpu_measurement specific... */
-
- switch (verbosity) {
- case 0:
- if (local_cpu_usage) {
- fprintf(where,
- cpu_fmt_0,
- local_service_demand);
- }
- else {
- fprintf(where,
- cpu_fmt_0,
- remote_service_demand);
- }
- break;
- case 1:
- fprintf(where,
- cpu_fmt_1_line_1, /* the format string */
- lss_size, /* local sendbuf size */
- lsr_size,
- req_size, /* how large were the requests */
- rsp_size, /* guess */
- elapsed_time, /* how long was the test */
- nummessages/elapsed_time,
- local_cpu_utilization, /* local cpu */
- remote_cpu_utilization, /* remote cpu */
- local_service_demand, /* local service demand */
- remote_service_demand); /* remote service demand */
- fprintf(where,
- cpu_fmt_1_line_2,
- rss_size,
- rsr_size);
- break;
- }
- }
- else {
- /* The tester did not wish to measure service demand. */
- switch (verbosity) {
- case 0:
- fprintf(where,
- tput_fmt_0,
- nummessages/elapsed_time);
- break;
- case 1:
- fprintf(where,
- tput_fmt_1_line_1, /* the format string */
- lss_size,
- lsr_size,
- req_size, /* how large were the requests */
- rsp_size, /* how large were the responses */
- elapsed_time, /* how long did it take */
- nummessages/elapsed_time);
- fprintf(where,
- tput_fmt_1_line_2,
- rss_size, /* remote recvbuf size */
- rsr_size);
-
- break;
- }
- }
-
- /* it would be a good thing to include information about some of the */
- /* other parameters that may have been set for this test, but at the */
- /* moment, I do not wish to figure-out all the formatting, so I will */
- /* just put this comment here to help remind me that it is something */
- /* that should be done at a later time. */
-
- if (verbosity > 1) {
- /* The user wanted to know it all, so we will give it to him. */
- /* This information will include as much as we can find about */
- /* STREAM statistics, the alignments of the sends and receives */
- /* and all that sort of rot... */
-
- fprintf(where,
- ksink_fmt);
- }
- /* The test is over. Kill the data socket */
-
- if (close(send_socket) == -1) {
- perror("send_stream_rr: cannot shutdown stream stream socket");
- }
-
-}
-
-void
-send_dg_stream(char remote_host[])
-{
- /************************************************************************/
- /* */
- /* DG Unidirectional Send Test */
- /* */
- /************************************************************************/
- char *tput_title =
- "Socket Message Elapsed Messages \n\
-Size Size Time Okay Errors Throughput\n\
-bytes bytes secs # # %s/sec\n\n";
-
- char *tput_fmt_0 =
- "%7.2f\n";
-
- char *tput_fmt_1 =
- "%5d %5d %-7.2f %7d %6d %7.2f\n\
-%5d %-7.2f %7d %7.2f\n\n";
-
-
- char *cpu_title =
- "Socket Message Elapsed Messages CPU Service\n\
-Size Size Time Okay Errors Throughput Util Demand\n\
-bytes bytes secs # # %s/sec %% us/KB\n\n";
-
- char *cpu_fmt_0 =
- "%6.2f\n";
-
- char *cpu_fmt_1 =
- "%5d %5d %-7.2f %7d %6d %7.1f %-6.2f %-6.3f\n\
-%5d %-7.2f %7d %7.1f %-6.2f %-6.3f\n\n";
-
- int messages_recvd;
- float elapsed_time,
- local_cpu_utilization,
- remote_cpu_utilization;
-
- float local_service_demand, remote_service_demand;
- double local_thruput, remote_thruput;
- double bytes_sent;
- double bytes_recvd;
-
-
- int len;
- struct ring_elt *send_ring;
- int failed_sends;
- int failed_cows;
- int messages_sent;
- SOCKET data_socket;
-
-
-#ifdef WANT_INTERVALS
- int interval_count;
-#endif /* WANT_INTERVALS */
-#ifdef DIRTY
- int *message_int_ptr;
- int i;
-#endif /* DIRTY */
-
- struct sockaddr_un server;
-
- struct dg_stream_request_struct *dg_stream_request;
- struct dg_stream_response_struct *dg_stream_response;
- struct dg_stream_results_struct *dg_stream_results;
-
- dg_stream_request = (struct dg_stream_request_struct *)netperf_request.content.test_specific_data;
- dg_stream_response = (struct dg_stream_response_struct *)netperf_response.content.test_specific_data;
- dg_stream_results = (struct dg_stream_results_struct *)netperf_response.content.test_specific_data;
-
- /* since we are now disconnected from the code that established the */
- /* control socket, and since we want to be able to use different */
- /* protocols and such, we are passed the name of the remote host and */
- /* must turn that into the test specific addressing information. */
-
- bzero((char *)&server,
- sizeof(server));
-
- server.sun_family = AF_UNIX;
-
- if ( print_headers ) {
- printf("DG UNIDIRECTIONAL SEND TEST\n");
- if (local_cpu_usage || remote_cpu_usage)
- printf(cpu_title,format_units());
- else
- printf(tput_title,format_units());
- }
-
- failed_sends = 0;
- failed_cows = 0;
- messages_sent = 0;
- times_up = 0;
-
- /*set up the data socket */
- data_socket = create_unix_socket(AF_UNIX,
- SOCK_DGRAM);
-
- if (data_socket == INVALID_SOCKET){
- perror("dg_send: data socket");
- exit(1);
- }
-
- /* now, we want to see if we need to set the send_size */
- if (send_size == 0) {
- if (lss_size > 0) {
- send_size = (lss_size < UNIX_LENGTH_MAX ? lss_size : UNIX_LENGTH_MAX);
- }
- else {
- send_size = 4096;
- }
- }
-
-
- /* set-up the data buffer with the requested alignment and offset, */
- /* most of the numbers here are just a hack to pick something nice */
- /* and big in an attempt to never try to send a buffer a second time */
- /* before it leaves the node...unless the user set the width */
- /* explicitly. */
- if (send_width == 0) send_width = 32;
-
- send_ring = allocate_buffer_ring(send_width,
- send_size,
- local_send_align,
- local_send_offset);
-
- /* At this point, we want to do things like disable DG checksumming */
- /* and measure the cpu rate and all that so we are ready to go */
- /* immediately after the test response message is delivered. */
-
- /* if the user supplied a cpu rate, this call will complete rather */
- /* quickly, otherwise, the cpu rate will be retured to us for */
- /* possible display. The Library will keep it's own copy of this data */
- /* for use elsewhere. We will only display it. (Does that make it */
- /* "opaque" to us?) */
-
- if (local_cpu_usage)
- local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
-
- /* Tell the remote end to set up the data connection. The server */
- /* sends back the port number and alters the socket parameters there. */
- /* Of course this is a datagram service so no connection is actually */
- /* set up, the server just sets up the socket and binds it. */
-
- netperf_request.content.request_type = DO_DG_STREAM;
- dg_stream_request->recv_buf_size = rsr_size;
- dg_stream_request->message_size = send_size;
- dg_stream_request->recv_alignment = remote_recv_align;
- dg_stream_request->recv_offset = remote_recv_offset;
- dg_stream_request->measure_cpu = remote_cpu_usage;
- dg_stream_request->cpu_rate = remote_cpu_rate;
- dg_stream_request->test_length = test_time;
-
- send_request();
-
- recv_response();
-
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"send_dg_stream: remote data connection done.\n");
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- perror("send_dg_stream: error on remote");
- exit(1);
- }
-
- /* Place the port number returned by the remote into the sockaddr */
- /* structure so our sends can be sent to the correct place. Also get */
- /* some of the returned socket buffer information for user display. */
-
- /* make sure that port numbers are in the proper order */
- strcpy(server.sun_path,dg_stream_response->unix_path);
- rsr_size = dg_stream_response->recv_buf_size;
- rss_size = dg_stream_response->send_buf_size;
- remote_cpu_rate = dg_stream_response->cpu_rate;
-
- /* We "connect" up to the remote post to allow is to use the send */
- /* call instead of the sendto call. Presumeably, this is a little */
- /* simpler, and a little more efficient. I think that it also means */
- /* that we can be informed of certain things, but am not sure yet... */
-
- if (connect(data_socket,
- (struct sockaddr *)&server,
- sizeof(server)) == INVALID_SOCKET){
- perror("send_dg_stream: data socket connect failed");
- exit(1);
- }
-
- /* set up the timer to call us after test_time */
- start_timer(test_time);
-
- /* Get the start count for the idle counter and the start time */
-
- cpu_start(local_cpu_usage);
-
-#ifdef WANT_INTERVALS
- interval_count = interval_burst;
-#endif
-
- /* Send datagrams like there was no tomorrow. at somepoint it might */
- /* be nice to set this up so that a quantity of bytes could be sent, */
- /* but we still need some sort of end of test trigger on the receive */
- /* side. that could be a select with a one second timeout, but then */
- /* if there is a test where none of the data arrives for awile and */
- /* then starts again, we would end the test too soon. something to */
- /* think about... */
- while (!times_up) {
-
-#ifdef DIRTY
- /* we want to dirty some number of consecutive integers in the buffer */
- /* we are about to send. we may also want to bring some number of */
- /* them cleanly into the cache. The clean ones will follow any dirty */
- /* ones into the cache. */
- message_int_ptr = (int *)(send_ring->buffer_ptr);
- for (i = 0; i < loc_dirty_count; i++) {
- *message_int_ptr = 4;
- message_int_ptr++;
- }
- for (i = 0; i < loc_clean_count; i++) {
- loc_dirty_count = *message_int_ptr;
- message_int_ptr++;
- }
-#endif /* DIRTY */
-
- if ((len=send(data_socket,
- send_ring->buffer_ptr,
- send_size,
- 0)) != send_size) {
- if ((len >= 0) || (errno == EINTR))
- break;
- if (errno == ENOBUFS) {
- failed_sends++;
- continue;
- }
- perror("dg_send: data send error");
- exit(1);
- }
- messages_sent++;
-
- /* now we want to move our pointer to the next position in the */
- /* data buffer... */
-
- send_ring = send_ring->next;
-
-
-#ifdef WANT_INTERVALS
- /* in this case, the interval count is the count-down couter */
- /* to decide to sleep for a little bit */
- if ((interval_burst) && (--interval_count == 0)) {
- /* call the sleep routine for some milliseconds, if our */
- /* timer popped while we were in there, we want to */
- /* break out of the loop. */
- if (msec_sleep(interval_wate)) {
- break;
- }
- interval_count = interval_burst;
- }
-
-#endif
-
- }
-
- /* This is a timed test, so the remote will be returning to us after */
- /* a time. We should not need to send any "strange" messages to tell */
- /* the remote that the test is completed, unless we decide to add a */
- /* number of messages to the test. */
-
- /* the test is over, so get stats and stuff */
- cpu_stop(local_cpu_usage,
- &elapsed_time);
-
- /* Get the statistics from the remote end */
- recv_response();
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"send_dg_stream: remote results obtained\n");
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- perror("send_dg_stream: error on remote");
- exit(1);
- }
-
- bytes_sent = send_size * messages_sent;
- local_thruput = calc_thruput(bytes_sent);
-
- messages_recvd = dg_stream_results->messages_recvd;
- bytes_recvd = send_size * messages_recvd;
-
- /* we asume that the remote ran for as long as we did */
-
- remote_thruput = calc_thruput(bytes_recvd);
-
- /* print the results for this socket and message size */
-
- if (local_cpu_usage || remote_cpu_usage) {
- /* We must now do a little math for service demand and cpu */
- /* utilization for the system(s) We pass zeros for the local */
- /* cpu utilization and elapsed time to tell the routine to use */
- /* the libraries own values for those. */
- if (local_cpu_usage) {
- if (local_cpu_rate == 0.0) {
- fprintf(where,"WARNING WARNING WARNING WARNING WARNING WARNING WARNING!\n");
- fprintf(where,"Local CPU usage numbers based on process information only!\n");
- fflush(where);
- }
-
- local_cpu_utilization = calc_cpu_util(0.0);
- local_service_demand = calc_service_demand(bytes_sent,
- 0.0,
- 0.0,
- 0);
- }
- else {
- local_cpu_utilization = -1.0;
- local_service_demand = -1.0;
- }
-
- /* The local calculations could use variables being kept by */
- /* the local netlib routines. The remote calcuations need to */
- /* have a few things passed to them. */
- if (remote_cpu_usage) {
- if (remote_cpu_rate == 0.0) {
- fprintf(where,"DANGER DANGER DANGER DANGER DANGER DANGER DANGER!\n");
- fprintf(where,"REMOTE CPU usage numbers based on process information only!\n");
- fflush(where);
- }
-
- remote_cpu_utilization = dg_stream_results->cpu_util;
- remote_service_demand = calc_service_demand(bytes_recvd,
- 0.0,
- remote_cpu_utilization,
- dg_stream_results->num_cpus);
- }
- else {
- remote_cpu_utilization = -1.0;
- remote_service_demand = -1.0;
- }
-
- /* We are now ready to print all the information. If the user */
- /* has specified zero-level verbosity, we will just print the */
- /* local service demand, or the remote service demand. If the */
- /* user has requested verbosity level 1, he will get the basic */
- /* "streamperf" numbers. If the user has specified a verbosity */
- /* of greater than 1, we will display a veritable plethora of */
- /* background information from outside of this block as it it */
- /* not cpu_measurement specific... */
-
- switch (verbosity) {
- case 0:
- if (local_cpu_usage) {
- fprintf(where,
- cpu_fmt_0,
- local_service_demand);
- }
- else {
- fprintf(where,
- cpu_fmt_0,
- remote_service_demand);
- }
- break;
- case 1:
- fprintf(where,
- cpu_fmt_1, /* the format string */
- lss_size, /* local sendbuf size */
- send_size, /* how large were the sends */
- elapsed_time, /* how long was the test */
- messages_sent,
- failed_sends,
- local_thruput, /* what was the xfer rate */
- local_cpu_utilization, /* local cpu */
- local_service_demand, /* local service demand */
- rsr_size,
- elapsed_time,
- messages_recvd,
- remote_thruput,
- remote_cpu_utilization, /* remote cpu */
- remote_service_demand); /* remote service demand */
- break;
- }
- }
- else {
- /* The tester did not wish to measure service demand. */
- switch (verbosity) {
- case 0:
- fprintf(where,
- tput_fmt_0,
- local_thruput);
- break;
- case 1:
- fprintf(where,
- tput_fmt_1, /* the format string */
- lss_size, /* local sendbuf size */
- send_size, /* how large were the sends */
- elapsed_time, /* how long did it take */
- messages_sent,
- failed_sends,
- local_thruput,
- rsr_size, /* remote recvbuf size */
- elapsed_time,
- messages_recvd,
- remote_thruput
- );
- break;
- }
- }
-}
-
-
- /* this routine implements the receive side (netserver) of the */
- /* DG_STREAM performance test. */
-
-void
-recv_dg_stream()
-{
- struct ring_elt *recv_ring;
-
- struct sockaddr_un myaddr_un;
- SOCKET s_data;
- int len = 0;
- int bytes_received = 0;
- float elapsed_time;
-
- int message_size;
- int messages_recvd = 0;
-
- struct dg_stream_request_struct *dg_stream_request;
- struct dg_stream_response_struct *dg_stream_response;
- struct dg_stream_results_struct *dg_stream_results;
-
- dg_stream_request =
- (struct dg_stream_request_struct *)netperf_request.content.test_specific_data;
- dg_stream_response =
- (struct dg_stream_response_struct *)netperf_response.content.test_specific_data;
- dg_stream_results =
- (struct dg_stream_results_struct *)netperf_response.content.test_specific_data;
-
- if (debug) {
- fprintf(where,"netserver: recv_dg_stream: entered...\n");
- fflush(where);
- }
-
- /* We want to set-up the listen socket with all the desired */
- /* parameters and then let the initiator know that all is ready. If */
- /* socket size defaults are to be used, then the initiator will have */
- /* sent us 0's. If the socket sizes cannot be changed, then we will */
- /* send-back what they are. If that information cannot be determined, */
- /* then we send-back -1's for the sizes. If things go wrong for any */
- /* reason, we will drop back ten yards and punt. */
-
- /* If anything goes wrong, we want the remote to know about it. It */
- /* would be best if the error that the remote reports to the user is */
- /* the actual error we encountered, rather than some bogus unexpected */
- /* response type message. */
-
- if (debug > 1) {
- fprintf(where,"recv_dg_stream: setting the response type...\n");
- fflush(where);
- }
-
- netperf_response.content.response_type = DG_STREAM_RESPONSE;
-
- if (debug > 2) {
- fprintf(where,"recv_dg_stream: the response type is set...\n");
- fflush(where);
- }
-
- /* We now alter the message_ptr variable to be at the desired */
- /* alignment with the desired offset. */
-
- if (debug > 1) {
- fprintf(where,"recv_dg_stream: requested alignment of %d\n",
- dg_stream_request->recv_alignment);
- fflush(where);
- }
-
- if (recv_width == 0) recv_width = 1;
-
- recv_ring = allocate_buffer_ring(recv_width,
- dg_stream_request->message_size,
- dg_stream_request->recv_alignment,
- dg_stream_request->recv_offset);
-
- if (debug > 1) {
- fprintf(where,"recv_dg_stream: receive alignment and offset set...\n");
- fflush(where);
- }
-
- /* Let's clear-out our sockaddr for the sake of cleanlines. Then we */
- /* can put in OUR values !-) At some point, we may want to nail this */
- /* socket to a particular network-level address, but for now, */
- /* INADDR_ANY should be just fine. */
-
- bzero((char *)&myaddr_un,
- sizeof(myaddr_un));
- myaddr_un.sun_family = AF_UNIX;
-
- /* Grab a socket to listen on, and then listen on it. */
-
- if (debug > 1) {
- fprintf(where,"recv_dg_stream: grabbing a socket...\n");
- fflush(where);
- }
-
- /* create_unix_socket expects to find some things in the global */
- /* variables, so set the globals based on the values in the request. */
- /* once the socket has been created, we will set the response values */
- /* based on the updated value of those globals. raj 7/94 */
- lsr_size = dg_stream_request->recv_buf_size;
-
- s_data = create_unix_socket(AF_UNIX,
- SOCK_DGRAM);
-
- if (s_data == INVALID_SOCKET) {
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
-
- /* Let's get an address assigned to this socket so we can tell the */
- /* initiator how to reach the data socket. There may be a desire to */
- /* nail this socket to a specific IP address in a multi-homed, */
- /* multi-connection situation, but for now, we'll ignore the issue */
- /* and concentrate on single connection testing. */
-
- strcpy(myaddr_un.sun_path,tempnam(path_prefix,"netperf."));
- if (bind(s_data,
- (struct sockaddr *)&myaddr_un,
- sizeof(myaddr_un)) == SOCKET_ERROR) {
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
-
- chmod(myaddr_un.sun_path, 0666);
-
- dg_stream_response->test_length = dg_stream_request->test_length;
-
- /* Now myaddr_un contains the port and the internet address this is */
- /* returned to the sender also implicitly telling the sender that the */
- /* socket buffer sizing has been done. */
-
- strcpy(dg_stream_response->unix_path,myaddr_un.sun_path);
- netperf_response.content.serv_errno = 0;
-
- /* But wait, there's more. If the initiator wanted cpu measurements, */
- /* then we must call the calibrate routine, which will return the max */
- /* rate back to the initiator. If the CPU was not to be measured, or */
- /* something went wrong with the calibration, we will return a -1 to */
- /* the initiator. */
-
- dg_stream_response->cpu_rate = 0.0; /* assume no cpu */
- if (dg_stream_request->measure_cpu) {
- /* We will pass the rate into the calibration routine. If the */
- /* user did not specify one, it will be 0.0, and we will do a */
- /* "real" calibration. Otherwise, all it will really do is */
- /* store it away... */
- dg_stream_response->measure_cpu = 1;
- dg_stream_response->cpu_rate =
- calibrate_local_cpu(dg_stream_request->cpu_rate);
- }
-
- message_size = dg_stream_request->message_size;
- test_time = dg_stream_request->test_length;
-
- /* before we send the response back to the initiator, pull some of */
- /* the socket parms from the globals */
- dg_stream_response->send_buf_size = lss_size;
- dg_stream_response->recv_buf_size = lsr_size;
-
- send_response();
-
- /* Now it's time to start receiving data on the connection. We will */
- /* first grab the apropriate counters and then start grabbing. */
-
- cpu_start(dg_stream_request->measure_cpu);
-
- /* The loop will exit when the timer pops, or if we happen to recv a */
- /* message of less than send_size bytes... */
-
- times_up = 0;
- start_timer(test_time + PAD_TIME);
-
- if (debug) {
- fprintf(where,"recv_dg_stream: about to enter inner sanctum.\n");
- fflush(where);
- }
-
- while (!times_up) {
- if ((len = recv(s_data,
- recv_ring->buffer_ptr,
- message_size,
- 0)) != message_size) {
- if ((len == SOCKET_ERROR) && (errno != EINTR)) {
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
- break;
- }
- messages_recvd++;
- recv_ring = recv_ring->next;
- }
-
- if (debug) {
- fprintf(where,"recv_dg_stream: got %d messages.\n",messages_recvd);
- fflush(where);
- }
-
-
- /* The loop now exits due timer or < send_size bytes received. */
-
- cpu_stop(dg_stream_request->measure_cpu,&elapsed_time);
-
- if (times_up) {
- /* we ended on a timer, subtract the PAD_TIME */
- elapsed_time -= (float)PAD_TIME;
- }
- else {
- stop_timer();
- }
-
- if (debug) {
- fprintf(where,"recv_dg_stream: test ended in %f seconds.\n",elapsed_time);
- fflush(where);
- }
-
-
- /* We will count the "off" message that got us out of the loop */
- bytes_received = (messages_recvd * message_size) + len;
-
- /* send the results to the sender */
-
- if (debug) {
- fprintf(where,
- "recv_dg_stream: got %d bytes\n",
- bytes_received);
- fflush(where);
- }
-
- netperf_response.content.response_type = DG_STREAM_RESULTS;
- dg_stream_results->bytes_received = bytes_received;
- dg_stream_results->messages_recvd = messages_recvd;
- dg_stream_results->elapsed_time = elapsed_time;
- if (dg_stream_request->measure_cpu) {
- dg_stream_results->cpu_util = calc_cpu_util(elapsed_time);
- }
- else {
- dg_stream_results->cpu_util = -1.0;
- }
-
- if (debug > 1) {
- fprintf(where,
- "recv_dg_stream: test complete, sending results.\n");
- fflush(where);
- }
-
- send_response();
-
-}
-
-void
-send_dg_rr(char remote_host[])
-{
-
- char *tput_title = "\
-Local /Remote\n\
-Socket Size Request Resp. Elapsed Trans.\n\
-Send Recv Size Size Time Rate \n\
-bytes Bytes bytes bytes secs. per sec \n\n";
-
- char *tput_fmt_0 =
- "%7.2f\n";
-
- char *tput_fmt_1_line_1 = "\
-%-6d %-6d %-6d %-6d %-6.2f %7.2f \n";
- char *tput_fmt_1_line_2 = "\
-%-6d %-6d\n";
-
- char *cpu_title = "\
-Local /Remote\n\
-Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\
-Send Recv Size Size Time Rate local remote local remote\n\
-bytes bytes bytes bytes secs. per sec %% %% us/Tr us/Tr\n\n";
-
- char *cpu_fmt_0 =
- "%6.3f\n";
-
- char *cpu_fmt_1_line_1 = "\
-%-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f\n";
-
- char *cpu_fmt_1_line_2 = "\
-%-6d %-6d\n";
-
- float elapsed_time;
-
- /* we add MAXALIGNMENT and MAXOFFSET to insure that there is enough */
- /* space for a maximally aligned, maximally sized message. At some */
- /* point, we may want to actually make this even larger and cycle */
- /* through the thing one piece at a time.*/
-
- int len;
- char *send_message_ptr;
- char *recv_message_ptr;
- char *temp_message_ptr;
- int nummessages;
- SOCKET send_socket;
- int trans_remaining;
- int bytes_xferd;
-
- int rsp_bytes_recvd;
-
- float local_cpu_utilization;
- float local_service_demand;
- float remote_cpu_utilization;
- float remote_service_demand;
- double thruput;
-
-#ifdef WANT_INTERVALS
- /* timing stuff */
-#define MAX_KEPT_TIMES 1024
- int time_index = 0;
- int unused_buckets;
- int kept_times[MAX_KEPT_TIMES];
- int sleep_usecs;
- unsigned int total_times=0;
- struct timezone dummy_zone;
- struct timeval send_time;
- struct timeval recv_time;
- struct timeval sleep_timeval;
-#endif
-
- struct sockaddr_un server, myaddr_un;
-
- struct dg_rr_request_struct *dg_rr_request;
- struct dg_rr_response_struct *dg_rr_response;
- struct dg_rr_results_struct *dg_rr_result;
-
- dg_rr_request =
- (struct dg_rr_request_struct *)netperf_request.content.test_specific_data;
- dg_rr_response=
- (struct dg_rr_response_struct *)netperf_response.content.test_specific_data;
- dg_rr_result =
- (struct dg_rr_results_struct *)netperf_response.content.test_specific_data;
-
- /* we want to zero out the times, so we can detect unused entries. */
-#ifdef WANT_INTERVALS
- time_index = 0;
- while (time_index < MAX_KEPT_TIMES) {
- kept_times[time_index] = 0;
- time_index += 1;
- }
- time_index = 0;
-#endif
-
- /* since we are now disconnected from the code that established the */
- /* control socket, and since we want to be able to use different */
- /* protocols and such, we are passed the name of the remote host and */
- /* must turn that into the test specific addressing information. */
-
- bzero((char *)&server,
- sizeof(server));
- server.sun_family = AF_UNIX;
-
- bzero((char *)&myaddr_un,
- sizeof(myaddr_un));
- myaddr_un.sun_family = AF_UNIX;
-
- strcpy(myaddr_un.sun_path,tempnam(path_prefix,"netperf."));
-
- if ( print_headers ) {
- fprintf(where,"DG REQUEST/RESPONSE TEST\n");
- if (local_cpu_usage || remote_cpu_usage)
- fprintf(where,cpu_title,format_units());
- else
- fprintf(where,tput_title,format_units());
- }
-
- /* initialize a few counters */
-
- nummessages = 0;
- bytes_xferd = 0;
- times_up = 0;
-
- /* set-up the data buffer with the requested alignment and offset */
- temp_message_ptr = (char *)malloc(DATABUFFERLEN);
- if (temp_message_ptr == NULL) {
- printf("malloc(%d) failed!\n", DATABUFFERLEN);
- exit(1);
- }
- send_message_ptr = (char *)(( (long)temp_message_ptr +
- (long) local_send_align - 1) &
- ~((long) local_send_align - 1));
- send_message_ptr = send_message_ptr + local_send_offset;
- temp_message_ptr = (char *)malloc(DATABUFFERLEN);
- if (temp_message_ptr == NULL) {
- printf("malloc(%d) failed!\n", DATABUFFERLEN);
- exit(1);
- }
- recv_message_ptr = (char *)(( (long)temp_message_ptr +
- (long) local_recv_align - 1) &
- ~((long) local_recv_align - 1));
- recv_message_ptr = recv_message_ptr + local_recv_offset;
-
- /*set up the data socket */
- send_socket = create_unix_socket(AF_UNIX,
- SOCK_DGRAM);
-
- if (send_socket == INVALID_SOCKET){
- perror("netperf: send_dg_rr: dg rr data socket");
- exit(1);
- }
-
- if (debug) {
- fprintf(where,"send_dg_rr: send_socket obtained...\n");
- }
-
-
- /* If the user has requested cpu utilization measurements, we must */
- /* calibrate the cpu(s). We will perform this task within the tests */
- /* themselves. If the user has specified the cpu rate, then */
- /* calibrate_local_cpu will return rather quickly as it will have */
- /* nothing to do. If local_cpu_rate is zero, then we will go through */
- /* all the "normal" calibration stuff and return the rate back. If */
- /* there is no idle counter in the kernel idle loop, the */
- /* local_cpu_rate will be set to -1. */
-
- if (local_cpu_usage) {
- local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
- }
-
- /* Tell the remote end to do a listen. The server alters the socket */
- /* paramters on the other side at this point, hence the reason for */
- /* all the values being passed in the setup message. If the user did */
- /* not specify any of the parameters, they will be passed as 0, which */
- /* will indicate to the remote that no changes beyond the system's */
- /* default should be used. Alignment is the exception, it will */
- /* default to 8, which will be no alignment alterations. */
-
- netperf_request.content.request_type = DO_DG_RR;
- dg_rr_request->recv_buf_size = rsr_size;
- dg_rr_request->send_buf_size = rss_size;
- dg_rr_request->recv_alignment = remote_recv_align;
- dg_rr_request->recv_offset = remote_recv_offset;
- dg_rr_request->send_alignment = remote_send_align;
- dg_rr_request->send_offset = remote_send_offset;
- dg_rr_request->request_size = req_size;
- dg_rr_request->response_size = rsp_size;
- dg_rr_request->measure_cpu = remote_cpu_usage;
- dg_rr_request->cpu_rate = remote_cpu_rate;
- if (test_time) {
- dg_rr_request->test_length = test_time;
- }
- else {
- dg_rr_request->test_length = test_trans * -1;
- }
-
- if (debug > 1) {
- fprintf(where,"netperf: send_dg_rr: requesting DG request/response test\n");
- }
-
- send_request();
-
- /* The response from the remote will contain all of the relevant */
- /* socket parameters for this test type. We will put them back into */
- /* the variables here so they can be displayed if desired. The */
- /* remote will have calibrated CPU if necessary, and will have done */
- /* all the needed set-up we will have calibrated the cpu locally */
- /* before sending the request, and will grab the counter value right */
- /* after the connect returns. The remote will grab the counter right */
- /* after the accept call. This saves the hassle of extra messages */
- /* being sent for the DG tests. */
-
- recv_response();
-
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote listen done.\n");
- rsr_size = dg_rr_response->recv_buf_size;
- rss_size = dg_rr_response->send_buf_size;
- remote_cpu_usage= dg_rr_response->measure_cpu;
- remote_cpu_rate = dg_rr_response->cpu_rate;
- /* port numbers in proper order */
- strcpy(server.sun_path,dg_rr_response->unix_path);
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- perror("netperf: remote error");
-
- exit(1);
- }
-
- /* Connect up to the remote port on the data socket. This will set */
- /* the default destination address on this socket. we need to bind */
- /* out socket so that the remote gets something from a recvfrom */
- if (bind(send_socket,
- (struct sockaddr *)&myaddr_un,
- sizeof(myaddr_un)) == SOCKET_ERROR) {
- perror("netperf: send_dg_rr");
- unlink(myaddr_un.sun_path);
- close(send_socket);
- exit(1);
- }
-
- if (connect(send_socket,
- (struct sockaddr *)&server,
- sizeof(server)) == INVALID_SOCKET ) {
- perror("netperf: data socket connect failed");
- exit(1);
- }
-
- /* Data Socket set-up is finished. If there were problems, either the */
- /* connect would have failed, or the previous response would have */
- /* indicated a problem. I failed to see the value of the extra */
- /* message after the accept on the remote. If it failed, we'll see it */
- /* here. If it didn't, we might as well start pumping data. */
-
- /* Set-up the test end conditions. For a request/response test, they */
- /* can be either time or transaction based. */
-
- if (test_time) {
- /* The user wanted to end the test after a period of time. */
- times_up = 0;
- trans_remaining = 0;
- start_timer(test_time);
- }
- else {
- /* The tester wanted to send a number of bytes. */
- trans_remaining = test_bytes;
- times_up = 1;
- }
-
- /* The cpu_start routine will grab the current time and possibly */
- /* value of the idle counter for later use in measuring cpu */
- /* utilization and/or service demand and thruput. */
-
- cpu_start(local_cpu_usage);
-
- /* We use an "OR" to control test execution. When the test is */
- /* controlled by time, the byte count check will always return false. */
- /* When the test is controlled by byte count, the time test will */
- /* always return false. When the test is finished, the whole */
- /* expression will go false and we will stop sending data. I think I */
- /* just arbitrarily decrement trans_remaining for the timed test, but */
- /* will not do that just yet... One other question is whether or not */
- /* the send buffer and the receive buffer should be the same buffer. */
- while ((!times_up) || (trans_remaining > 0)) {
- /* send the request */
-#ifdef WANT_INTERVALS
- gettimeofday(&send_time,&dummy_zone);
-#endif
- if((len=send(send_socket,
- send_message_ptr,
- req_size,
- 0)) != req_size) {
- if (errno == EINTR) {
- /* We likely hit */
- /* test-end time. */
- break;
- }
- perror("send_dg_rr: data send error");
- exit(1);
- }
-
- /* receive the response. with DG we will get it all, or nothing */
-
- if((rsp_bytes_recvd=recv(send_socket,
- recv_message_ptr,
- rsp_size,
- 0)) != rsp_size) {
- if (errno == EINTR) {
- /* Again, we have likely hit test-end time */
- break;
- }
- perror("send_dg_rr: data recv error");
- exit(1);
- }
-#ifdef WANT_INTERVALS
- gettimeofday(&recv_time,&dummy_zone);
-
- /* now we do some arithmatic on the two timevals */
- if (recv_time.tv_usec < send_time.tv_usec) {
- /* we wrapped around a second */
- recv_time.tv_usec += 1000000;
- recv_time.tv_sec -= 1;
- }
-
- /* and store it away */
- kept_times[time_index] = (recv_time.tv_sec - send_time.tv_sec) * 1000000;
- kept_times[time_index] += (recv_time.tv_usec - send_time.tv_usec);
-
- /* at this point, we may wish to sleep for some period of */
- /* time, so we see how long that last transaction just took, */
- /* and sleep for the difference of that and the interval. We */
- /* will not sleep if the time would be less than a */
- /* millisecond. */
- if (interval_usecs > 0) {
- sleep_usecs = interval_usecs - kept_times[time_index];
- if (sleep_usecs > 1000) {
- /* we sleep */
- sleep_timeval.tv_sec = sleep_usecs / 1000000;
- sleep_timeval.tv_usec = sleep_usecs % 1000000;
- select(0,
- 0,
- 0,
- 0,
- &sleep_timeval);
- }
- }
-
- /* now up the time index */
- time_index = (time_index +1)%MAX_KEPT_TIMES;
-#endif
- nummessages++;
- if (trans_remaining) {
- trans_remaining--;
- }
-
- if (debug > 3) {
- fprintf(where,"Transaction %d completed\n",nummessages);
- fflush(where);
- }
-
- }
-
- /* The test is over. Flush the buffers to the remote end. We do a */
- /* graceful release to insure that all data has been taken by the */
- /* remote. Of course, since this was a request/response test, there */
- /* should be no data outstanding on the socket ;-) */
-
- if (shutdown(send_socket,1) == SOCKET_ERROR) {
- perror("netperf: cannot shutdown dg stream socket");
-
- exit(1);
- }
-
- /* this call will always give us the elapsed time for the test, and */
- /* will also store-away the necessaries for cpu utilization */
-
- cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being measured? */
- /* how long did we really run? */
-
- /* Get the statistics from the remote end. The remote will have */
- /* calculated service demand and all those interesting things. If it */
- /* wasn't supposed to care, it will return obvious values. */
-
- recv_response();
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote results obtained\n");
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- perror("netperf: remote error");
-
- exit(1);
- }
-
- /* We now calculate what our thruput was for the test. In the future, */
- /* we may want to include a calculation of the thruput measured by */
- /* the remote, but it should be the case that for a DG stream test, */
- /* that the two numbers should be *very* close... We calculate */
- /* bytes_sent regardless of the way the test length was controlled. */
- /* If it was time, we needed to, and if it was by bytes, the user may */
- /* have specified a number of bytes that wasn't a multiple of the */
- /* send_size, so we really didn't send what he asked for ;-) We use */
-
- bytes_xferd = (req_size * nummessages) + (rsp_size * nummessages);
- thruput = calc_thruput(bytes_xferd);
-
- if (local_cpu_usage || remote_cpu_usage) {
- /* We must now do a little math for service demand and cpu */
- /* utilization for the system(s) */
- /* Of course, some of the information might be bogus because */
- /* there was no idle counter in the kernel(s). We need to make */
- /* a note of this for the user's benefit...*/
- if (local_cpu_usage) {
- if (local_cpu_rate == 0.0) {
- fprintf(where,"WARNING WARNING WARNING WARNING WARNING WARNING WARNING!\n");
- fprintf(where,"Local CPU usage numbers based on process information only!\n");
- fflush(where);
- }
- local_cpu_utilization = calc_cpu_util(0.0);
- /* since calc_service demand is doing ms/Kunit we will */
- /* multiply the number of transaction by 1024 to get */
- /* "good" numbers */
- local_service_demand = calc_service_demand((double) nummessages*1024,
- 0.0,
- 0.0,
- 0);
- }
- else {
- local_cpu_utilization = -1.0;
- local_service_demand = -1.0;
- }
-
- if (remote_cpu_usage) {
- if (remote_cpu_rate == 0.0) {
- fprintf(where,"DANGER DANGER DANGER DANGER DANGER DANGER DANGER!\n");
- fprintf(where,"Remote CPU usage numbers based on process information only!\n");
- fflush(where);
- }
- remote_cpu_utilization = dg_rr_result->cpu_util;
- /* since calc_service demand is doing ms/Kunit we will */
- /* multiply the number of transaction by 1024 to get */
- /* "good" numbers */
- remote_service_demand = calc_service_demand((double) nummessages*1024,
- 0.0,
- remote_cpu_utilization,
- dg_rr_result->num_cpus);
- }
- else {
- remote_cpu_utilization = -1.0;
- remote_service_demand = -1.0;
- }
-
- /* We are now ready to print all the information. If the user */
- /* has specified zero-level verbosity, we will just print the */
- /* local service demand, or the remote service demand. If the */
- /* user has requested verbosity level 1, he will get the basic */
- /* "streamperf" numbers. If the user has specified a verbosity */
- /* of greater than 1, we will display a veritable plethora of */
- /* background information from outside of this block as it it */
- /* not cpu_measurement specific... */
-
- switch (verbosity) {
- case 0:
- if (local_cpu_usage) {
- fprintf(where,
- cpu_fmt_0,
- local_service_demand);
- }
- else {
- fprintf(where,
- cpu_fmt_0,
- remote_service_demand);
- }
- break;
- case 1:
- case 2:
- fprintf(where,
- cpu_fmt_1_line_1, /* the format string */
- lss_size, /* local sendbuf size */
- lsr_size,
- req_size, /* how large were the requests */
- rsp_size, /* guess */
- elapsed_time, /* how long was the test */
- nummessages/elapsed_time,
- local_cpu_utilization, /* local cpu */
- remote_cpu_utilization, /* remote cpu */
- local_service_demand, /* local service demand */
- remote_service_demand); /* remote service demand */
- fprintf(where,
- cpu_fmt_1_line_2,
- rss_size,
- rsr_size);
- break;
- }
- }
- else {
- /* The tester did not wish to measure service demand. */
- switch (verbosity) {
- case 0:
- fprintf(where,
- tput_fmt_0,
- nummessages/elapsed_time);
- break;
- case 1:
- case 2:
- fprintf(where,
- tput_fmt_1_line_1, /* the format string */
- lss_size,
- lsr_size,
- req_size, /* how large were the requests */
- rsp_size, /* how large were the responses */
- elapsed_time, /* how long did it take */
- nummessages/elapsed_time);
- fprintf(where,
- tput_fmt_1_line_2,
- rss_size, /* remote recvbuf size */
- rsr_size);
-
- break;
- }
- }
-
- /* it would be a good thing to include information about some of the */
- /* other parameters that may have been set for this test, but at the */
- /* moment, I do not wish to figure-out all the formatting, so I will */
- /* just put this comment here to help remind me that it is something */
- /* that should be done at a later time. */
-
- if (verbosity > 1) {
- /* The user wanted to know it all, so we will give it to him. */
- /* This information will include as much as we can find about */
- /* DG statistics, the alignments of the sends and receives */
- /* and all that sort of rot... */
-
-#ifdef WANT_INTERVALS
- kept_times[MAX_KEPT_TIMES] = 0;
- time_index = 0;
- while (time_index < MAX_KEPT_TIMES) {
- if (kept_times[time_index] > 0) {
- total_times += kept_times[time_index];
- }
- else
- unused_buckets++;
- time_index += 1;
- }
- total_times /= (MAX_KEPT_TIMES-unused_buckets);
- fprintf(where,
- "Average response time %d usecs\n",
- total_times);
-#endif
- }
- unlink(myaddr_un.sun_path);
-}
-
- /* this routine implements the receive side (netserver) of a DG_RR */
- /* test. */
-void
-recv_dg_rr()
-{
-
- struct ring_elt *recv_ring;
- struct ring_elt *send_ring;
-
- struct sockaddr_un myaddr_un,
- peeraddr_un;
- SOCKET s_data;
- int addrlen;
- int trans_received = 0;
- int trans_remaining;
- float elapsed_time;
-
- struct dg_rr_request_struct *dg_rr_request;
- struct dg_rr_response_struct *dg_rr_response;
- struct dg_rr_results_struct *dg_rr_results;
-
- dg_rr_request =
- (struct dg_rr_request_struct *)netperf_request.content.test_specific_data;
- dg_rr_response =
- (struct dg_rr_response_struct *)netperf_response.content.test_specific_data;
- dg_rr_results =
- (struct dg_rr_results_struct *)netperf_response.content.test_specific_data;
-
- if (debug) {
- fprintf(where,"netserver: recv_dg_rr: entered...\n");
- fflush(where);
- }
-
- /* We want to set-up the listen socket with all the desired */
- /* parameters and then let the initiator know that all is ready. If */
- /* socket size defaults are to be used, then the initiator will have */
- /* sent us 0's. If the socket sizes cannot be changed, then we will */
- /* send-back what they are. If that information cannot be determined, */
- /* then we send-back -1's for the sizes. If things go wrong for any */
- /* reason, we will drop back ten yards and punt. */
-
- /* If anything goes wrong, we want the remote to know about it. It */
- /* would be best if the error that the remote reports to the user is */
- /* the actual error we encountered, rather than some bogus unexpected */
- /* response type message. */
-
- if (debug) {
- fprintf(where,"recv_dg_rr: setting the response type...\n");
- fflush(where);
- }
-
- netperf_response.content.response_type = DG_RR_RESPONSE;
-
- if (debug) {
- fprintf(where,"recv_dg_rr: the response type is set...\n");
- fflush(where);
- }
-
- /* We now alter the message_ptr variables to be at the desired */
- /* alignments with the desired offsets. */
-
- if (debug) {
- fprintf(where,"recv_dg_rr: requested recv alignment of %d offset %d\n",
- dg_rr_request->recv_alignment,
- dg_rr_request->recv_offset);
- fprintf(where,"recv_dg_rr: requested send alignment of %d offset %d\n",
- dg_rr_request->send_alignment,
- dg_rr_request->send_offset);
- fflush(where);
- }
-
- if (send_width == 0) send_width = 1;
- if (recv_width == 0) recv_width = 1;
-
- recv_ring = allocate_buffer_ring(recv_width,
- dg_rr_request->request_size,
- dg_rr_request->recv_alignment,
- dg_rr_request->recv_offset);
-
- send_ring = allocate_buffer_ring(send_width,
- dg_rr_request->response_size,
- dg_rr_request->send_alignment,
- dg_rr_request->send_offset);
-
- if (debug) {
- fprintf(where,"recv_dg_rr: receive alignment and offset set...\n");
- fflush(where);
- }
-
- /* Let's clear-out our sockaddr for the sake of cleanlines. Then we */
- /* can put in OUR values !-) At some point, we may want to nail this */
- /* socket to a particular network-level address, but for now, */
- /* INADDR_ANY should be just fine. */
-
- bzero((char *)&myaddr_un,
- sizeof(myaddr_un));
- myaddr_un.sun_family = AF_UNIX;
-
- /* Grab a socket to listen on, and then listen on it. */
-
- if (debug) {
- fprintf(where,"recv_dg_rr: grabbing a socket...\n");
- fflush(where);
- }
-
-
- /* create_unix_socket expects to find some things in the global */
- /* variables, so set the globals based on the values in the request. */
- /* once the socket has been created, we will set the response values */
- /* based on the updated value of those globals. raj 7/94 */
- lss_size_req = dg_rr_request->send_buf_size;
- lsr_size_req = dg_rr_request->recv_buf_size;
-
- s_data = create_unix_socket(AF_UNIX,
- SOCK_DGRAM);
-
- if (s_data == INVALID_SOCKET) {
- netperf_response.content.serv_errno = errno;
- send_response();
-
- exit(1);
- }
-
- /* Let's get an address assigned to this socket so we can tell the */
- /* initiator how to reach the data socket. There may be a desire to */
- /* nail this socket to a specific IP address in a multi-homed, */
- /* multi-connection situation, but for now, we'll ignore the issue */
- /* and concentrate on single connection testing. */
-
- strcpy(myaddr_un.sun_path,tempnam(path_prefix,"netperf."));
- if (bind(s_data,
- (struct sockaddr *)&myaddr_un,
- sizeof(myaddr_un)) == SOCKET_ERROR) {
- netperf_response.content.serv_errno = errno;
- unlink(myaddr_un.sun_path);
- close(s_data);
- send_response();
-
- exit(1);
- }
-
- /* Now myaddr_un contains the port and the internet address this is */
- /* returned to the sender also implicitly telling the sender that the */
- /* socket buffer sizing has been done. */
-
- strcpy(dg_rr_response->unix_path,myaddr_un.sun_path);
- netperf_response.content.serv_errno = 0;
-
- /* But wait, there's more. If the initiator wanted cpu measurements, */
- /* then we must call the calibrate routine, which will return the max */
- /* rate back to the initiator. If the CPU was not to be measured, or */
- /* something went wrong with the calibration, we will return a 0.0 to */
- /* the initiator. */
-
- dg_rr_response->cpu_rate = 0.0; /* assume no cpu */
- if (dg_rr_request->measure_cpu) {
- dg_rr_response->measure_cpu = 1;
- dg_rr_response->cpu_rate = calibrate_local_cpu(dg_rr_request->cpu_rate);
- }
-
- /* before we send the response back to the initiator, pull some of */
- /* the socket parms from the globals */
- dg_rr_response->send_buf_size = lss_size;
- dg_rr_response->recv_buf_size = lsr_size;
-
- send_response();
-
-
- /* Now it's time to start receiving data on the connection. We will */
- /* first grab the apropriate counters and then start grabbing. */
-
- cpu_start(dg_rr_request->measure_cpu);
-
- if (dg_rr_request->test_length > 0) {
- times_up = 0;
- trans_remaining = 0;
- start_timer(dg_rr_request->test_length + PAD_TIME);
- }
- else {
- times_up = 1;
- trans_remaining = dg_rr_request->test_length * -1;
- }
-
- addrlen = sizeof(peeraddr_un);
- bzero((char *)&peeraddr_un, addrlen);
-
- while ((!times_up) || (trans_remaining > 0)) {
-
- /* receive the request from the other side */
- fprintf(where,"socket %d ptr %p size %d\n",
- s_data,
- recv_ring->buffer_ptr,
- dg_rr_request->request_size);
- fflush(where);
- if (recvfrom(s_data,
- recv_ring->buffer_ptr,
- dg_rr_request->request_size,
- 0,
- (struct sockaddr *)&peeraddr_un,
- &addrlen) != dg_rr_request->request_size) {
- if (errno == EINTR) {
- /* we must have hit the end of test time. */
- break;
- }
- netperf_response.content.serv_errno = errno;
- fprintf(where,"error on recvfrom errno %d\n",errno);
- fflush(where);
- send_response();
- unlink(myaddr_un.sun_path);
- exit(1);
- }
- recv_ring = recv_ring->next;
-
- /* Now, send the response to the remote */
- if (sendto(s_data,
- send_ring->buffer_ptr,
- dg_rr_request->response_size,
- 0,
- (struct sockaddr *)&peeraddr_un,
- addrlen) != dg_rr_request->response_size) {
- if (errno == EINTR) {
- /* we have hit end of test time. */
- break;
- }
- netperf_response.content.serv_errno = errno;
- fprintf(where,"error on recvfrom errno %d\n",errno);
- fflush(where);
- unlink(myaddr_un.sun_path);
- send_response();
- exit(1);
- }
- send_ring = send_ring->next;
-
- trans_received++;
- if (trans_remaining) {
- trans_remaining--;
- }
-
- if (debug) {
- fprintf(where,
- "recv_dg_rr: Transaction %d complete.\n",
- trans_received);
- fflush(where);
- }
-
- }
-
-
- /* The loop now exits due to timeout or transaction count being */
- /* reached */
-
- cpu_stop(dg_rr_request->measure_cpu,&elapsed_time);
-
- if (times_up) {
- /* we ended the test by time, which was at least 2 seconds */
- /* longer than we wanted to run. so, we want to subtract */
- /* PAD_TIME from the elapsed_time. */
- elapsed_time -= PAD_TIME;
- }
- /* send the results to the sender */
-
- if (debug) {
- fprintf(where,
- "recv_dg_rr: got %d transactions\n",
- trans_received);
- fflush(where);
- }
-
- dg_rr_results->bytes_received = (trans_received *
- (dg_rr_request->request_size +
- dg_rr_request->response_size));
- dg_rr_results->trans_received = trans_received;
- dg_rr_results->elapsed_time = elapsed_time;
- if (dg_rr_request->measure_cpu) {
- dg_rr_results->cpu_util = calc_cpu_util(elapsed_time);
- }
-
- if (debug) {
- fprintf(where,
- "recv_dg_rr: test complete, sending results.\n");
- fflush(where);
- }
-
- send_response();
- unlink(myaddr_un.sun_path);
-
-}
- /* this routine implements the receive (netserver) side of a STREAM_RR */
- /* test */
-
-void
-recv_stream_rr()
-{
-
- struct ring_elt *send_ring;
- struct ring_elt *recv_ring;
-
- struct sockaddr_un myaddr_un,
- peeraddr_un;
- SOCKET s_listen,s_data;
- int addrlen;
- char *temp_message_ptr;
- int trans_received = 0;
- int trans_remaining;
- int bytes_sent;
- int request_bytes_recvd;
- int request_bytes_remaining;
- int timed_out = 0;
- float elapsed_time;
-
- struct stream_rr_request_struct *stream_rr_request;
- struct stream_rr_response_struct *stream_rr_response;
- struct stream_rr_results_struct *stream_rr_results;
-
- stream_rr_request =
- (struct stream_rr_request_struct *)netperf_request.content.test_specific_data;
- stream_rr_response =
- (struct stream_rr_response_struct *)netperf_response.content.test_specific_data;
- stream_rr_results =
- (struct stream_rr_results_struct *)netperf_response.content.test_specific_data;
-
- if (debug) {
- fprintf(where,"netserver: recv_stream_rr: entered...\n");
- fflush(where);
- }
-
- /* We want to set-up the listen socket with all the desired */
- /* parameters and then let the initiator know that all is ready. If */
- /* socket size defaults are to be used, then the initiator will have */
- /* sent us 0's. If the socket sizes cannot be changed, then we will */
- /* send-back what they are. If that information cannot be determined, */
- /* then we send-back -1's for the sizes. If things go wrong for any */
- /* reason, we will drop back ten yards and punt. */
-
- /* If anything goes wrong, we want the remote to know about it. It */
- /* would be best if the error that the remote reports to the user is */
- /* the actual error we encountered, rather than some bogus unexpected */
- /* response type message. */
-
- if (debug) {
- fprintf(where,"recv_stream_rr: setting the response type...\n");
- fflush(where);
- }
-
- netperf_response.content.response_type = STREAM_RR_RESPONSE;
-
- if (debug) {
- fprintf(where,"recv_stream_rr: the response type is set...\n");
- fflush(where);
- }
-
- /* allocate the recv and send rings with the requested alignments */
- /* and offsets. raj 7/94 */
- if (debug) {
- fprintf(where,"recv_stream_rr: requested recv alignment of %d offset %d\n",
- stream_rr_request->recv_alignment,
- stream_rr_request->recv_offset);
- fprintf(where,"recv_stream_rr: requested send alignment of %d offset %d\n",
- stream_rr_request->send_alignment,
- stream_rr_request->send_offset);
- fflush(where);
- }
-
- /* at some point, these need to come to us from the remote system */
- if (send_width == 0) send_width = 1;
- if (recv_width == 0) recv_width = 1;
-
- send_ring = allocate_buffer_ring(send_width,
- stream_rr_request->response_size,
- stream_rr_request->send_alignment,
- stream_rr_request->send_offset);
-
- recv_ring = allocate_buffer_ring(recv_width,
- stream_rr_request->request_size,
- stream_rr_request->recv_alignment,
- stream_rr_request->recv_offset);
-
-
- /* Let's clear-out our sockaddr for the sake of cleanlines. Then we */
- /* can put in OUR values !-) At some point, we may want to nail this */
- /* socket to a particular network-level address, but for now, */
- /* INADDR_ANY should be just fine. */
-
- bzero((char *)&myaddr_un,
- sizeof(myaddr_un));
- myaddr_un.sun_family = AF_UNIX;
-
- /* Grab a socket to listen on, and then listen on it. */
-
- if (debug) {
- fprintf(where,"recv_stream_rr: grabbing a socket...\n");
- fflush(where);
- }
-
- /* create_unix_socket expects to find some things in the global */
- /* variables, so set the globals based on the values in the request. */
- /* once the socket has been created, we will set the response values */
- /* based on the updated value of those globals. raj 7/94 */
- lss_size_req = stream_rr_request->send_buf_size;
- lsr_size_req = stream_rr_request->recv_buf_size;
-
- s_listen = create_unix_socket(AF_UNIX,
- SOCK_STREAM);
-
- if (s_listen == INVALID_SOCKET) {
- netperf_response.content.serv_errno = errno;
- send_response();
-
- exit(1);
- }
-
- /* Let's get an address assigned to this socket so we can tell the */
- /* initiator how to reach the data socket. There may be a desire to */
- /* nail this socket to a specific IP address in a multi-homed, */
- /* multi-connection situation, but for now, we'll ignore the issue */
- /* and concentrate on single connection testing. */
-
- strcpy(myaddr_un.sun_path,tempnam(path_prefix,"netperf."));
- if (bind(s_listen,
- (struct sockaddr *)&myaddr_un,
- sizeof(myaddr_un)) == SOCKET_ERROR) {
- netperf_response.content.serv_errno = errno;
- unlink(myaddr_un.sun_path);
- close(s_listen);
- send_response();
-
- exit(1);
- }
-
- /* Now, let's set-up the socket to listen for connections */
- if (listen(s_listen, 5) == SOCKET_ERROR) {
- netperf_response.content.serv_errno = errno;
- close(s_listen);
- send_response();
-
- exit(1);
- }
-
- /* Now myaddr_un contains the port and the internet address this is */
- /* returned to the sender also implicitly telling the sender that the */
- /* socket buffer sizing has been done. */
-
- strcpy(stream_rr_response->unix_path,myaddr_un.sun_path);
- netperf_response.content.serv_errno = 0;
-
- /* But wait, there's more. If the initiator wanted cpu measurements, */
- /* then we must call the calibrate routine, which will return the max */
- /* rate back to the initiator. If the CPU was not to be measured, or */
- /* something went wrong with the calibration, we will return a 0.0 to */
- /* the initiator. */
-
- stream_rr_response->cpu_rate = 0.0; /* assume no cpu */
- if (stream_rr_request->measure_cpu) {
- stream_rr_response->measure_cpu = 1;
- stream_rr_response->cpu_rate = calibrate_local_cpu(stream_rr_request->cpu_rate);
- }
-
-
- /* before we send the response back to the initiator, pull some of */
- /* the socket parms from the globals */
- stream_rr_response->send_buf_size = lss_size;
- stream_rr_response->recv_buf_size = lsr_size;
-
- send_response();
-
- addrlen = sizeof(peeraddr_un);
-
- if ((s_data = accept(s_listen,
- (struct sockaddr *)&peeraddr_un,
- &addrlen)) == INVALID_SOCKET) {
- /* Let's just punt. The remote will be given some information */
- close(s_listen);
-
- exit(1);
- }
-
- if (debug) {
- fprintf(where,"recv_stream_rr: accept completes on the data connection.\n");
- fflush(where);
- }
-
- /* Now it's time to start receiving data on the connection. We will */
- /* first grab the apropriate counters and then start grabbing. */
-
- cpu_start(stream_rr_request->measure_cpu);
-
- /* The loop will exit when the sender does a shutdown, which will */
- /* return a length of zero */
-
- if (stream_rr_request->test_length > 0) {
- times_up = 0;
- trans_remaining = 0;
- start_timer(stream_rr_request->test_length + PAD_TIME);
- }
- else {
- times_up = 1;
- trans_remaining = stream_rr_request->test_length * -1;
- }
-
- while ((!times_up) || (trans_remaining > 0)) {
- temp_message_ptr = recv_ring->buffer_ptr;
- request_bytes_remaining = stream_rr_request->request_size;
-
- /* receive the request from the other side */
- if (debug) {
- fprintf(where,"about to receive for trans %d\n",trans_received);
- fprintf(where,"temp_message_ptr is %p\n",temp_message_ptr);
- fflush(where);
- }
- while(request_bytes_remaining > 0) {
- if((request_bytes_recvd=recv(s_data,
- temp_message_ptr,
- request_bytes_remaining,
- 0)) == SOCKET_ERROR) {
- if (errno == EINTR) {
- /* the timer popped */
- timed_out = 1;
- break;
- }
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
- else {
- request_bytes_remaining -= request_bytes_recvd;
- temp_message_ptr += request_bytes_recvd;
- }
- if (debug) {
- fprintf(where,"just received for trans %d\n",trans_received);
- fflush(where);
- }
- }
-
- recv_ring = recv_ring->next;
-
- if (timed_out) {
- /* we hit the end of the test based on time - lets */
- /* bail out of here now... */
- fprintf(where,"yo5\n");
- fflush(where);
- break;
- }
-
- /* Now, send the response to the remote */
- if (debug) {
- fprintf(where,"about to send for trans %d\n",trans_received);
- fflush(where);
- }
- if((bytes_sent=send(s_data,
- send_ring->buffer_ptr,
- stream_rr_request->response_size,
- 0)) == SOCKET_ERROR) {
- if (errno == EINTR) {
- /* the test timer has popped */
- timed_out = 1;
- fprintf(where,"yo6\n");
- fflush(where);
- break;
- }
- netperf_response.content.serv_errno = 997;
- send_response();
- exit(1);
- }
-
- send_ring = send_ring->next;
-
- trans_received++;
- if (trans_remaining) {
- trans_remaining--;
- }
-
- if (debug) {
- fprintf(where,
- "recv_stream_rr: Transaction %d complete\n",
- trans_received);
- fflush(where);
- }
- }
-
-
- /* The loop now exits due to timeout or transaction count being */
- /* reached */
-
- cpu_stop(stream_rr_request->measure_cpu,&elapsed_time);
-
- if (timed_out) {
- /* we ended the test by time, which was at least 2 seconds */
- /* longer than we wanted to run. so, we want to subtract */
- /* PAD_TIME from the elapsed_time. */
- elapsed_time -= PAD_TIME;
- }
- /* send the results to the sender */
-
- if (debug) {
- fprintf(where,
- "recv_stream_rr: got %d transactions\n",
- trans_received);
- fflush(where);
- }
-
- stream_rr_results->bytes_received = (trans_received *
- (stream_rr_request->request_size +
- stream_rr_request->response_size));
- stream_rr_results->trans_received = trans_received;
- stream_rr_results->elapsed_time = elapsed_time;
- if (stream_rr_request->measure_cpu) {
- stream_rr_results->cpu_util = calc_cpu_util(elapsed_time);
- }
-
- if (debug) {
- fprintf(where,
- "recv_stream_rr: test complete, sending results.\n");
- fflush(where);
- }
-
- send_response();
- unlink(myaddr_un.sun_path);
-}
-
-void
-print_unix_usage()
-{
-
- fwrite(unix_usage, sizeof(char), strlen(unix_usage), stdout);
- exit(1);
-
-}
-void
-scan_unix_args(int argc, char *argv[])
-{
-#define UNIX_ARGS "hm:M:p:r:s:S:"
- extern char *optarg; /* pointer to option string */
-
- int c;
-
- char
- arg1[BUFSIZ], /* argument holders */
- arg2[BUFSIZ];
-
- init_test_vars();
-
- if (no_control) {
- fprintf(where,
- "The UNIX tests do not know how to run with no control connection\n");
- exit(-1);
- }
-
- /* Go through all the command line arguments and break them */
- /* out. For those options that take two parms, specifying only */
- /* the first will set both to that value. Specifying only the */
- /* second will leave the first untouched. To change only the */
- /* first, use the form "first," (see the routine break_args.. */
-
- while ((c= getopt(argc, argv, UNIX_ARGS)) != EOF) {
- switch (c) {
- case '?':
- case 'h':
- print_unix_usage();
- exit(1);
- case 'p':
- /* set the path prefix (directory) that should be used for the */
- /* pipes. at some point, there should be some error checking. */
- strcpy(path_prefix,optarg);
- break;
- case 's':
- /* set local socket sizes */
- break_args(optarg,arg1,arg2);
- if (arg1[0])
- lss_size_req = atoi(arg1);
- if (arg2[0])
- lsr_size_req = atoi(arg2);
- break;
- case 'S':
- /* set remote socket sizes */
- break_args(optarg,arg1,arg2);
- if (arg1[0])
- rss_size = atoi(arg1);
- if (arg2[0])
- rsr_size = atoi(arg2);
- break;
- case 'r':
- /* set the request/response sizes */
- break_args(optarg,arg1,arg2);
- if (arg1[0])
- req_size = atoi(arg1);
- if (arg2[0])
- rsp_size = atoi(arg2);
- break;
- case 'm':
- /* set the send size */
- send_size = atoi(optarg);
- break;
- case 'M':
- /* set the recv size */
- recv_size = atoi(optarg);
- break;
- };
- }
-}
-#endif /* WANT_UNIX */
diff --git a/nettest_unix.h b/nettest_unix.h
deleted file mode 100644
index 8eb393b..0000000
--- a/nettest_unix.h
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- Copyright (C) 1993-2004 Hewlett-Packard Company
-*/
-
- /* This file contains the test-specific definitions for netperf's */
- /* DLPI tests */
-
-struct stream_stream_request_struct {
- int recv_buf_size;
- int send_buf_size;
- int receive_size; /* how many bytes do we want to */
- /* receive at one time? */
- int recv_alignment; /* what is the alignment of the */
- /* receive buffer? */
- int recv_offset; /* and at what offset from that */
- /* alignment? */
- int so_rcvavoid; /* do we want the remote to avoid receive copies? */
- int so_sndavoid; /* do we want the remote to avoid send copies? */
- int measure_cpu; /* does the client want server cpu */
- /* utilization measured? */
- float cpu_rate; /* do we know how fast the cpu is */
- /* already? */
- int test_length; /* how long is the test? */
- int dirty_count; /* how many integers in the receive buffer */
- /* should be made dirty before calling recv? */
- int clean_count; /* how many integers should be read from the */
- /* recv buffer before calling recv? */
- int path_name_len; /* the length of the device name string. this */
- /* is used to put it into the proper order on */
- /* @#$% byte-swapped boxes... */
- char unix_path[32]; /* the path */
-};
-
-struct stream_stream_response_struct {
- int recv_buf_size; /* how big does the client want it */
- int send_buf_size;
- int receive_size;
- int so_rcvavoid; /* do we want the remote to avoid receive copies? */
- int so_sndavoid; /* do we want the remote to avoid send copies? */
- int measure_cpu; /* does the client want server cpu */
- int test_length; /* how long is the test? */
- int data_port_number; /* connect to me here */
- float cpu_rate; /* could we measure */
- int path_name_len; /* the length of the device name string. this */
- /* is used to put it into the proper order on */
- /* @#$% byte-swapped boxes... */
- char unix_path[32]; /* the path */
-};
-
-struct stream_stream_results_struct {
- int bytes_received; /* ignored initially */
- int recv_calls; /* ignored initially */
- float elapsed_time; /* how long the test ran */
- float cpu_util; /* -1 if not measured */
- float serv_dem; /* -1 if not measured */
- int num_cpus;
-};
-
-struct stream_rr_request_struct {
- int recv_buf_size; /* how big does the client want it */
- int send_buf_size;
- int recv_alignment;
- int recv_offset;
- int send_alignment;
- int send_offset;
- int request_size;
- int response_size;
- int so_rcvavoid; /* do we want the remote to avoid receive copies? */
- int so_sndavoid; /* do we want the remote to avoid send copies? */
- int measure_cpu; /* does the client want server cpu */
- float cpu_rate; /* do we know how fast the cpu is? */
- int test_length; /* how long is the test? */
- int path_name_len; /* the length of the device name string. this */
- /* is used to put it into the proper order on */
- /* @#$% byte-swapped boxes... */
- char unix_path[32]; /* the path */
-};
-
-struct stream_rr_response_struct {
- int recv_buf_size; /* how big does the client want it */
- int send_buf_size;
- int so_rcvavoid; /* do we want the remote to avoid receive copies? */
- int so_sndavoid; /* do we want the remote to avoid send copies? */
- int measure_cpu; /* does the client want server cpu */
- int test_length; /* how long is the test? */
- float cpu_rate; /* could we measure */
- int path_name_len; /* the length of the device name string. this */
- /* is used to put it into the proper order on */
- /* @#$% byte-swapped boxes... */
- char unix_path[32]; /* the path to the dlpi device */
-};
-
-struct stream_rr_results_struct {
- int bytes_received; /* ignored initially */
- int recv_calls; /* ignored initially */
- int trans_received; /* not ignored */
- float elapsed_time; /* how long the test ran */
- float cpu_util; /* -1 if not measured */
- float serv_dem; /* -1 if not measured */
- int num_cpus;
-};
-
-struct dg_stream_request_struct {
- int recv_buf_size;
- int message_size;
- int recv_alignment;
- int recv_offset;
- int measure_cpu;
- float cpu_rate;
- int test_length;
- int so_rcvavoid; /* do we want the remote to avoid receive copies? */
- int so_sndavoid; /* do we want the remote to avoid send copies? */
- int path_name_len; /* the length of the device name string. this */
- /* is used to put it into the proper order on */
- /* @#$% byte-swapped boxes... */
- char unix_path[32]; /* the path */
-};
-
-struct dg_stream_response_struct {
- int recv_buf_size;
- int send_buf_size;
- int measure_cpu;
- int test_length;
- float cpu_rate;
- int so_rcvavoid; /* could the remote avoid receive copies? */
- int so_sndavoid; /* could the remote avoid send copies? */
- int path_name_len; /* the length of the device name string. this */
- /* is used to put it into the proper order on */
- /* @#$% byte-swapped boxes... */
- char unix_path[32]; /* the path */
-};
-
-struct dg_stream_results_struct {
- int messages_recvd;
- int bytes_received;
- float elapsed_time;
- float cpu_util;
- int num_cpus;
-};
-
-
-struct dg_rr_request_struct {
- int recv_buf_size; /* how big does the client want it */
- int send_buf_size;
- int recv_alignment;
- int recv_offset;
- int send_alignment;
- int send_offset;
- int request_size;
- int response_size;
- int measure_cpu; /* does the client want server cpu */
- float cpu_rate; /* do we know how fast the cpu is? */
- int test_length; /* how long is the test? */
- int so_rcvavoid; /* do we want the remote to avoid receive */
- /* copies? */
- int so_sndavoid; /* do we want the remote to avoid send copies? */
- int path_name_len; /* the length of the device name string. this */
- /* is used to put it into the proper order on */
- /* @#$% byte-swapped boxes... */
- char unix_path[32]; /* the path */
-};
-
-struct dg_rr_response_struct {
- int recv_buf_size; /* how big does the client want it */
- int send_buf_size;
- int no_delay;
- int measure_cpu; /* does the client want server cpu */
- int test_length; /* how long is the test? */
- float cpu_rate; /* could we measure */
- int so_rcvavoid; /* could the remote avoid receive copies? */
- int so_sndavoid; /* could the remote avoid send copies? */
- int path_name_len; /* the length of the device name string. this */
- /* is used to put it into the proper order on */
- /* @#$% byte-swapped boxes... */
- char unix_path[32]; /* the path */
-};
-
-struct dg_rr_results_struct {
- int bytes_received; /* ignored initially */
- int recv_calls; /* ignored initially */
- int trans_received; /* not ignored */
- float elapsed_time; /* how long the test ran */
- float cpu_util; /* -1 if not measured */
- float serv_dem; /* -1 if not measured */
- int num_cpus;
-};
-
-extern void scan_unix_args(int argc, char *argv[]);
-
-extern void send_stream_stream(char remote_host[]);
-extern void send_stream_rr(char remote_host[]);
-extern void send_dg_stream(char remote_host[]);
-extern void send_dg_rr(char remote_host[]);
-
-extern void recv_stream_stream();
-extern void recv_stream_rr();
-extern void recv_dg_stream();
-extern void recv_dg_rr();
diff --git a/nettest_xti.c b/nettest_xti.c
deleted file mode 100644
index 9d27f25..0000000
--- a/nettest_xti.c
+++ /dev/null
@@ -1,6026 +0,0 @@
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifdef WANT_XTI
-#ifndef lint
-char nettest_xti_id[]="\
-@(#)nettest_xti.c (c) Copyright 1995-2007 Hewlett-Packard Co. Version 2.4.3";
-#else
-#define DIRTY
-#define WANT_HISTOGRAM
-#define WANT_INTERVALS
-#endif /* lint */
-/****************************************************************/
-/* */
-/* nettest_xti.c */
-/* */
-/* the XTI args parsing routine... */
-/* */
-/* scan_xti_args() */
-/* */
-/* the actual test routines... */
-/* */
-/* send_xti_tcp_stream() perform a tcp stream test */
-/* recv_xti_tcp_stream() */
-/* send_xti_tcp_rr() perform a tcp request/response */
-/* recv_xti_tcp_rr() */
-/* send_xti_tcp_conn_rr() an RR test including connect */
-/* recv_xti_tcp_conn_rr() */
-/* send_xti_udp_stream() perform a udp stream test */
-/* recv_xti_udp_stream() */
-/* send_xti_udp_rr() perform a udp request/response */
-/* recv_xti_udp_rr() */
-/* */
-/****************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <sys/types.h>
-#include <fcntl.h>
-#ifndef WIN32
-#include <sys/ipc.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include <errno.h>
-#include <signal.h>
-#else /* WIN32 */
-#include <process.h>
-#include <winsock2.h>
-#include <windows.h>
-#endif /* WIN32 */
-#include <stdio.h>
-#include <time.h>
-#include <malloc.h>
- /* xti.h should be included *after* in.h because there are name */
- /* conflicts!( Silly standards people... raj 2/95 fortuenately, the */
- /* confilcts are on IP_TOP and IP_TTL, whcih netperf does not yet use */
-#include <xti.h>
-
-#include "netlib.h"
-#include "netsh.h"
-#include "nettest_xti.h"
-
-#ifdef WANT_HISTOGRAM
-#ifdef __sgi
-#include <sys/time.h>
-#endif /* __sgi */
-#include "hist.h"
-#endif /* WANT_HISTOGRAM */
-
-
-
- /* these variables are specific to the XTI sockets tests. declare */
- /* them static to make them global only to this file. */
-
-static int
- rss_size, /* remote socket send buffer size */
- rsr_size, /* remote socket recv buffer size */
- lss_size, /* local socket send buffer size */
- lsr_size, /* local socket recv buffer size */
- req_size = 1, /* request size */
- rsp_size = 1, /* response size */
- send_size, /* how big are individual sends */
- recv_size; /* how big are individual receives */
-
-static int confidence_iteration;
-static char local_cpu_method;
-static char remote_cpu_method;
-
- /* different options for the xti */
-
-static int
- loc_nodelay, /* don't/do use NODELAY locally */
- rem_nodelay, /* don't/do use NODELAY remotely */
- loc_sndavoid, /* avoid send copies locally */
- loc_rcvavoid, /* avoid recv copies locally */
- rem_sndavoid, /* avoid send copies remotely */
- rem_rcvavoid; /* avoid recv_copies remotely */
-
-static struct t_info info_struct;
-
-#ifdef WANT_HISTOGRAM
-#ifdef HAVE_GETHRTIME
-hrtime_t time_one;
-hrtime_t time_two;
-#else
-static struct timeval time_one;
-static struct timeval time_two;
-#endif /* HAVE_GETHRTIME */
-static HIST time_hist;
-#endif /* WANT_HISTOGRAM */
-
-static char loc_xti_device[32] = "/dev/tcp";
-static char rem_xti_device[32] = "/dev/tcp";
-
-static int xti_flags = 0;
-
-char xti_usage[] = "\n\
-Usage: netperf [global options] -- [test options] \n\
-\n\
-TCP/UDP XTI API Test Options:\n\
- -D [L][,R] Set XTI_TCP_NODELAY locally and/or remotely (XTI_TCP_*)\n\
- -h Display this text\n\
- -m bytes Set the send size (XTI_TCP_STREAM, XTI_UDP_STREAM)\n\
- -M bytes Set the recv size (XTI_TCP_STREAM, XTI_UDP_STREAM)\n\
- -r bytes Set request size (XTI_TCP_RR, XTI_UDP_RR)\n\
- -R bytes Set response size (XTI_TCP_RR, XTI_UDP_RR)\n\
- -s send[,recv] Set local socket send/recv buffer sizes\n\
- -S send[,recv] Set remote socket send/recv buffer sizes\n\
- -X dev[,dev] Set the local/remote XTI device file name\n\
-\n\
-For those options taking two parms, at least one must be specified;\n\
-specifying one value without a comma will set both parms to that\n\
-value, specifying a value with a leading comma will set just the second\n\
-parm, a value with a trailing comma will set just the first. To set\n\
-each parm to unique values, specify both and separate them with a\n\
-comma.\n";
-
-
- /* This routine is intended to retrieve interesting aspects of tcp */
- /* for the data connection. at first, it attempts to retrieve the */
- /* maximum segment size. later, it might be modified to retrieve */
- /* other information, but it must be information that can be */
- /* retrieved quickly as it is called during the timing of the test. */
- /* for that reason, a second routine may be created that can be */
- /* called outside of the timing loop */
-void
-get_xti_info(socket, info_struct)
- int socket;
- struct t_info *info_struct;
-{
-
-}
-
-
- /* This routine will create a data (listen) socket with the apropriate */
- /* options set and return it to the caller. this replaces all the */
- /* duplicate code in each of the test routines and should help make */
- /* things a little easier to understand. since this routine can be */
- /* called by either the netperf or netserver programs, all output */
- /* should be directed towards "where." family is generally AF_INET, */
- /* and type will be either SOCK_STREAM or SOCK_DGRAM */
-SOCKET
-create_xti_endpoint(char *name)
-{
-
- SOCKET temp_socket;
-
- struct t_optmgmt *opt_req; /* we request an option */
- struct t_optmgmt *opt_ret; /* it tells us what we got */
-
- /* we use this to pass-in BSD-like socket options through t_optmgmt. */
- /* it ends up being about as clear as mud. raj 2/95 */
- struct sock_option {
- struct t_opthdr myopthdr;
- long value;
- } *sock_option;
-
- if (debug) {
- fprintf(where,"create_xti_endpoint: attempting to open %s\n",
- name);
- fflush(where);
- }
-
- /*set up the data socket */
- temp_socket = t_open(name,O_RDWR,NULL);
-
- if (temp_socket == INVALID_SOCKET){
- fprintf(where,
- "netperf: create_xti_endpoint: t_open %s: errno %d t_errno %d\n",
- name,
- errno,
- t_errno);
- fflush(where);
- exit(1);
- }
-
- if (debug) {
- fprintf(where,"create_xti_endpoint: socket %d obtained...\n",temp_socket);
- fflush(where);
- }
-
- /* allocate what we need for option mgmt */
- if ((opt_req = (struct t_optmgmt *)t_alloc(temp_socket,T_OPTMGMT,T_ALL)) ==
- NULL) {
- fprintf(where,
- "netperf: create_xti_endpoint: t_alloc: opt_req errno %d\n",
- errno);
- fflush(where);
- exit(1);
- }
-
- if (debug) {
- fprintf(where,
- "create_xti_endpoint: opt_req->opt.buf %x maxlen %d len %d\n",
- opt_req->opt.buf,
- opt_req->opt.maxlen,
- opt_req->opt.len);
-
- fflush(where);
- }
-
- if ((opt_ret = (struct t_optmgmt *) t_alloc(temp_socket,T_OPTMGMT,T_ALL)) ==
- NULL) {
- fprintf(where,
- "netperf: create_xti_endpoint: t_alloc: opt_ret errno %d\n",
- errno);
- fflush(where);
- exit(1);
- }
-
- if (debug) {
- fprintf(where,
- "create_xti_endpoint: opt_ret->opt.buf %x maxlen %d len %d\n",
- opt_ret->opt.buf,
- opt_ret->opt.maxlen,
- opt_ret->opt.len);
- fflush(where);
- }
-
- /* Modify the local socket size. The reason we alter the send buffer */
- /* size here rather than when the connection is made is to take care */
- /* of decreases in buffer size. Decreasing the window size after */
- /* connection establishment is a TCP no-no. Also, by setting the */
- /* buffer (window) size before the connection is established, we can */
- /* control the TCP MSS (segment size). The MSS is never more that 1/2 */
- /* the minimum receive buffer size at each half of the connection. */
- /* This is why we are altering the receive buffer size on the sending */
- /* size of a unidirectional transfer. If the user has not requested */
- /* that the socket buffers be altered, we will try to find-out what */
- /* their values are. If we cannot touch the socket buffer in any way, */
- /* we will set the values to -1 to indicate that. */
-
-#ifdef XTI_SNDBUF
- if (lss_size > 0) {
- /* we want to "negotiate" the option */
- opt_req->flags = T_NEGOTIATE;
- }
- else {
- /* we want to accept the default, and know what it is. I assume */
- /* that when nothing has been changed, that T_CURRENT will return */
- /* the same as T_DEFAULT raj 3/95 */
- opt_req->flags = T_CURRENT;
- }
-
- /* the first part is for the netbuf that holds the option we want */
- /* to negotiate or check */
- /* the buffer of the netbuf points at the socket options structure */
-
- /* we assume that the t_alloc call allocated a buffer that started */
- /* on a proper alignment */
- sock_option = (struct sock_option *)opt_req->opt.buf;
-
- /* and next, set the fields in the sock_option structure */
- sock_option->myopthdr.level = XTI_GENERIC;
- sock_option->myopthdr.name = XTI_SNDBUF;
- sock_option->myopthdr.len = sizeof(struct t_opthdr) + sizeof(long);
- sock_option->value = lss_size;
-
- opt_req->opt.len = sizeof(struct t_opthdr) + sizeof(long);
-
- /* now, set-up the stuff to return the value in the end */
- /* we assume that the t_alloc call allocated a buffer that started */
- /* on a proper alignment */
- sock_option = (struct sock_option *)opt_ret->opt.buf;
-
- /* finally, call t_optmgmt. clear as mud. */
- if (t_optmgmt(temp_socket,opt_req,opt_ret) == -1) {
- fprintf(where,
- "netperf: create_xti_endpoint: XTI_SNDBUF option: t_errno %d\n",
- t_errno);
- fflush(where);
- exit(1);
- }
-
- if (sock_option->myopthdr.status == T_SUCCESS) {
- lss_size = sock_option->value;
- }
- else {
- fprintf(where,"create_xti_endpoint: XTI_SNDBUF option status 0x%.4x",
- sock_option->myopthdr.status);
- fprintf(where," value %d\n",
- sock_option->value);
- fflush(where);
- lss_size = -1;
- }
-
- if (lsr_size > 0) {
- /* we want to "negotiate" the option */
- opt_req->flags = T_NEGOTIATE;
- }
- else {
- /* we want to accept the default, and know what it is. I assume */
- /* that when nothing has been changed, that T_CURRENT will return */
- /* the same as T_DEFAULT raj 3/95 */
- opt_req->flags = T_CURRENT;
- }
-
- /* the first part is for the netbuf that holds the option we want */
- /* to negotiate or check */
- /* the buffer of the netbuf points at the socket options structure */
-
- /* we assume that the t_alloc call allocated a buffer that started */
- /* on a proper alignment */
- sock_option = (struct sock_option *)opt_req->opt.buf;
-
- /* and next, set the fields in the sock_option structure */
- sock_option->myopthdr.level = XTI_GENERIC;
- sock_option->myopthdr.name = XTI_RCVBUF;
- sock_option->myopthdr.len = sizeof(struct t_opthdr) + sizeof(long);
- sock_option->value = lsr_size;
-
- opt_req->opt.len = sizeof(struct t_opthdr) + sizeof(long);
-
- /* now, set-up the stuff to return the value in the end */
- /* we assume that the t_alloc call allocated a buffer that started */
- /* on a proper alignment */
- sock_option = (struct sock_option *)opt_ret->opt.buf;
-
- /* finally, call t_optmgmt. clear as mud. */
- if (t_optmgmt(temp_socket,opt_req,opt_ret) == -1) {
- fprintf(where,
- "netperf: create_xti_endpoint: XTI_RCVBUF option: t_errno %d\n",
- t_errno);
- fflush(where);
- exit(1);
- }
- lsr_size = sock_option->value;
-
- /* this needs code */
-
- if (debug) {
- fprintf(where,"netperf: create_xti_endpoint: socket sizes determined...\n");
- fprintf(where," send: %d recv: %d\n",
- lss_size,lsr_size);
- fflush(where);
- }
-
-#else /* XTI_SNDBUF */
-
- lss_size = -1;
- lsr_size = -1;
-
-#endif /* XTI_SNDBUF */
-
- /* now, we may wish to enable the copy avoidance features on the */
- /* local system. of course, this may not be possible... */
-
- if (loc_rcvavoid) {
- fprintf(where,
- "netperf: create_xti_endpoint: Could not enable receive copy avoidance");
- fflush(where);
- loc_rcvavoid = 0;
- }
-
- if (loc_sndavoid) {
- fprintf(where,
- "netperf: create_xti_endpoint: Could not enable send copy avoidance");
- fflush(where);
- loc_sndavoid = 0;
- }
-
- /* Now, we will see about setting the TCP_NODELAY flag on the local */
- /* socket. We will only do this for those systems that actually */
- /* support the option. If it fails, note the fact, but keep going. */
- /* If the user tries to enable TCP_NODELAY on a UDP socket, this */
- /* will cause an error to be displayed */
-
-#ifdef TCP_NODELAY
- if ((strcmp(test_name,"XTI_TCP_STREAM") == 0) ||
- (strcmp(test_name,"XTI_TCP_RR") == 0) ||
- (strcmp(test_name,"XTI_TCP_CRR") == 0)) {
- if (loc_nodelay) {
- /* we want to "negotiate" the option */
- opt_req->flags = T_NEGOTIATE;
- }
- else {
- /* we want to accept the default, and know what it is. I assume */
- /* that when nothing has been changed, that T_CURRENT will return */
- /* the same as T_DEFAULT raj 3/95 */
- opt_req->flags = T_CURRENT;
- }
-
- /* the first part is for the netbuf that holds the option we want */
- /* to negotiate or check the buffer of the netbuf points at the */
- /* socket options structure */
-
- /* we assume that the t_alloc call allocated a buffer that started */
- /* on a proper alignment */
- sock_option = (struct sock_option *)opt_req->opt.buf;
-
- /* and next, set the fields in the sock_option structure */
- sock_option->myopthdr.level = INET_TCP;
- sock_option->myopthdr.name = TCP_NODELAY;
- sock_option->myopthdr.len = sizeof(struct t_opthdr) + sizeof(long);
- sock_option->value = T_YES;
-
- opt_req->opt.len = sizeof(struct t_opthdr) + sizeof(long);
-
- /* now, set-up the stuff to return the value in the end */
- /* we assume that the t_alloc call allocated a buffer that started */
- /* on a proper alignment */
- sock_option = (struct sock_option *)opt_ret->opt.buf;
-
- /* finally, call t_optmgmt. clear as mud. */
- if (t_optmgmt(temp_socket,opt_req,opt_ret) == -1) {
- fprintf(where,
- "create_xti_endpoint: TCP_NODELAY option: errno %d t_errno %d\n",
- errno,
- t_errno);
- fflush(where);
- exit(1);
- }
- loc_nodelay = sock_option->value;
- }
-#else /* TCP_NODELAY */
-
- loc_nodelay = 0;
-
-#endif /* TCP_NODELAY */
-
- return(temp_socket);
-
-}
-
-
-/* This routine implements the TCP unidirectional data transfer test */
-/* (a.k.a. stream) for the xti interface. It receives its */
-/* parameters via global variables from the shell and writes its */
-/* output to the standard output. */
-
-
-void
-send_xti_tcp_stream(char remote_host[])
-{
-
- char *tput_title = "\
-Recv Send Send \n\
-Socket Socket Message Elapsed \n\
-Size Size Size Time Throughput \n\
-bytes bytes bytes secs. %s/sec \n\n";
-
- char *tput_fmt_0 =
- "%7.2f\n";
-
- char *tput_fmt_1 =
- "%6d %6d %6d %-6.2f %7.2f \n";
-
- char *cpu_title = "\
-Recv Send Send Utilization Service Demand\n\
-Socket Socket Message Elapsed Send Recv Send Recv\n\
-Size Size Size Time Throughput local remote local remote\n\
-bytes bytes bytes secs. %-8.8s/s %% %c %% %c us/KB us/KB\n\n";
-
- char *cpu_fmt_0 =
- "%6.3f %c\n";
-
- char *cpu_fmt_1 =
- "%6d %6d %6d %-6.2f %7.2f %-6.2f %-6.2f %-6.3f %-6.3f\n";
-
- char *ksink_fmt = "\n\
-Alignment Offset %-8.8s %-8.8s Sends %-8.8s Recvs\n\
-Local Remote Local Remote Xfered Per Per\n\
-Send Recv Send Recv Send (avg) Recv (avg)\n\
-%5d %5d %5d %5d %6.4g %6.2f %6d %6.2f %6d\n";
-
- char *ksink_fmt2 = "\n\
-Maximum\n\
-Segment\n\
-Size (bytes)\n\
-%6d\n";
-
-
- float elapsed_time;
-
-#ifdef WANT_INTERVALS
- int interval_count;
- sigset_t signal_set;
-#endif
-
- /* what we want is to have a buffer space that is at least one */
- /* send-size greater than our send window. this will insure that we */
- /* are never trying to re-use a buffer that may still be in the hands */
- /* of the transport. This buffer will be malloc'd after we have found */
- /* the size of the local senc socket buffer. We will want to deal */
- /* with alignment and offset concerns as well. */
-
- int *message_int_ptr;
-
- struct ring_elt *send_ring;
-
- int len;
- unsigned int nummessages;
- SOCKET send_socket;
- int bytes_remaining;
- int tcp_mss = -1; /* possibly uninitialized on printf far below */
-
- /* with links like fddi, one can send > 32 bits worth of bytes */
- /* during a test... ;-) at some point, this should probably become a */
- /* 64bit integral type, but those are not entirely common yet */
-
- double bytes_sent;
-
- float local_cpu_utilization;
- float local_service_demand;
- float remote_cpu_utilization;
- float remote_service_demand;
-
- double thruput;
-
- /* some addressing information */
- struct hostent *hp;
- struct sockaddr_in server;
- unsigned int addr;
-
- struct t_call server_call;
-
- struct xti_tcp_stream_request_struct *xti_tcp_stream_request;
- struct xti_tcp_stream_response_struct *xti_tcp_stream_response;
- struct xti_tcp_stream_results_struct *xti_tcp_stream_result;
-
- xti_tcp_stream_request =
- (struct xti_tcp_stream_request_struct *)netperf_request.content.test_specific_data;
- xti_tcp_stream_response =
- (struct xti_tcp_stream_response_struct *)netperf_response.content.test_specific_data;
- xti_tcp_stream_result =
- (struct xti_tcp_stream_results_struct *)netperf_response.content.test_specific_data;
-
-#ifdef WANT_HISTOGRAM
- time_hist = HIST_new();
-#endif /* WANT_HISTOGRAM */
- /* since we are now disconnected from the code that established the */
- /* control socket, and since we want to be able to use different */
- /* protocols and such, we are passed the name of the remote host and */
- /* must turn that into the test specific addressing information. */
-
- bzero((char *)&server,
- sizeof(server));
-
- /* it would seem that while HP-UX will allow an IP address (as a */
- /* string) in a call to gethostbyname, other, less enlightened */
- /* systems do not. fix from awjacks@ca.sandia.gov raj 10/95 */
- /* order changed to check for IP address first. raj 7/96 */
-
- if ((addr = inet_addr(remote_host)) == SOCKET_ERROR) {
- /* it was not an IP address, try it as a name */
- if ((hp = gethostbyname(remote_host)) == NULL) {
- /* we have no idea what it is */
- fprintf(where,
- "establish_control: could not resolve the destination %s\n",
- remote_host);
- fflush(where);
- exit(1);
- }
- else {
- /* it was a valid remote_host */
- bcopy(hp->h_addr,
- (char *)&server.sin_addr,
- hp->h_length);
- server.sin_family = hp->h_addrtype;
- }
- }
- else {
- /* it was a valid IP address */
- server.sin_addr.s_addr = addr;
- server.sin_family = AF_INET;
- }
-
- if ( print_headers ) {
- /* we want to have some additional, interesting information in */
- /* the headers. we know some of it here, but not all, so we will */
- /* only print the test title here and will print the results */
- /* titles after the test is finished */
- fprintf(where,"XTI TCP STREAM TEST");
- fprintf(where," to %s", remote_host);
- if (iteration_max > 1) {
- fprintf(where,
- " : +/-%3.1f%% @ %2d%% conf.",
- interval/0.02,
- confidence_level);
- }
- if (loc_nodelay || rem_nodelay) {
- fprintf(where," : nodelay");
- }
- if (loc_sndavoid ||
- loc_rcvavoid ||
- rem_sndavoid ||
- rem_rcvavoid) {
- fprintf(where," : copy avoidance");
- }
-#ifdef WANT_HISTOGRAM
- fprintf(where," : histogram");
-#endif /* WANT_HISTOGRAM */
-#ifdef WANT_INTERVALS
- fprintf(where," : interval");
-#endif /* WANT_INTERVALS */
-#ifdef DIRTY
- fprintf(where," : dirty data");
-#endif /* DIRTY */
- fprintf(where,"\n");
- }
-
- send_ring = NULL;
- confidence_iteration = 1;
- init_stat();
-
- /* we have a great-big while loop which controls the number of times */
- /* we run a particular test. this is for the calculation of a */
- /* confidence interval (I really should have stayed awake during */
- /* probstats :). If the user did not request confidence measurement */
- /* (no confidence is the default) then we will only go though the */
- /* loop once. the confidence stuff originates from the folks at IBM */
-
- while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
- (confidence_iteration <= iteration_min)) {
-
- /* initialize a few counters. we have to remember that we might be */
- /* going through the loop more than once. */
-
- nummessages = 0;
- bytes_sent = 0.0;
- times_up = 0;
-
- /*set up the data socket */
- send_socket = create_xti_endpoint(loc_xti_device);
-
- if (send_socket == INVALID_SOCKET) {
- perror("netperf: send_xti_tcp_stream: tcp stream data socket");
- exit(1);
- }
-
- if (debug) {
- fprintf(where,"send_xti_tcp_stream: send_socket obtained...\n");
- }
-
- /* it would seem that with XTI, there is no implicit bind on a */
- /* connect, so we have to make a call to t_bind. this is not */
- /* terribly convenient, but I suppose that "standard is better */
- /* than better" :) raj 2/95 */
-
- if (t_bind(send_socket, NULL, NULL) == SOCKET_ERROR) {
- t_error("send_xti_tcp_stream: t_bind");
- exit(1);
- }
-
- /* at this point, we have either retrieved the socket buffer sizes, */
- /* or have tried to set them, so now, we may want to set the send */
- /* size based on that (because the user either did not use a -m */
- /* option, or used one with an argument of 0). If the socket buffer */
- /* size is not available, we will set the send size to 4KB - no */
- /* particular reason, just arbitrary... */
- if (send_size == 0) {
- if (lss_size > 0) {
- send_size = lss_size;
- }
- else {
- send_size = 4096;
- }
- }
-
- /* set-up the data buffer ring with the requested alignment and offset. */
- /* note also that we have allocated a quantity */
- /* of memory that is at least one send-size greater than our socket */
- /* buffer size. We want to be sure that there are at least two */
- /* buffers allocated - this can be a bit of a problem when the */
- /* send_size is bigger than the socket size, so we must check... the */
- /* user may have wanted to explicitly set the "width" of our send */
- /* buffers, we should respect that wish... */
-
- if (send_width == 0) {
- send_width = (lss_size/send_size) + 1;
- if (send_width == 1) send_width++;
- }
-
- if (send_ring == NULL) {
- /* only allocate the send ring once. this is a networking test, */
- /* not a memory allocation test. this way, we do not need a */
- /* deallocate_buffer_ring() routine, and I don't feel like */
- /* writing one anyway :) raj 11/94 */
- send_ring = allocate_buffer_ring(send_width,
- send_size,
- local_send_align,
- local_send_offset);
- }
-
- /* If the user has requested cpu utilization measurements, we must */
- /* calibrate the cpu(s). We will perform this task within the tests */
- /* themselves. If the user has specified the cpu rate, then */
- /* calibrate_local_cpu will return rather quickly as it will have */
- /* nothing to do. If local_cpu_rate is zero, then we will go through */
- /* all the "normal" calibration stuff and return the rate back. */
-
- if (local_cpu_usage) {
- local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
- }
-
- /* Tell the remote end to do a listen. The server alters the socket */
- /* paramters on the other side at this point, hence the reason for */
- /* all the values being passed in the setup message. If the user did */
- /* not specify any of the parameters, they will be passed as 0, which */
- /* will indicate to the remote that no changes beyond the system's */
- /* default should be used. Alignment is the exception, it will */
- /* default to 1, which will be no alignment alterations. */
-
- netperf_request.content.request_type = DO_XTI_TCP_STREAM;
- xti_tcp_stream_request->send_buf_size = rss_size;
- xti_tcp_stream_request->recv_buf_size = rsr_size;
- xti_tcp_stream_request->receive_size = recv_size;
- xti_tcp_stream_request->no_delay = rem_nodelay;
- xti_tcp_stream_request->recv_alignment = remote_recv_align;
- xti_tcp_stream_request->recv_offset = remote_recv_offset;
- xti_tcp_stream_request->measure_cpu = remote_cpu_usage;
- xti_tcp_stream_request->cpu_rate = remote_cpu_rate;
- if (test_time) {
- xti_tcp_stream_request->test_length = test_time;
- }
- else {
- xti_tcp_stream_request->test_length = test_bytes;
- }
- xti_tcp_stream_request->so_rcvavoid = rem_rcvavoid;
- xti_tcp_stream_request->so_sndavoid = rem_sndavoid;
-
- strcpy(xti_tcp_stream_request->xti_device, rem_xti_device);
-
-#ifdef __alpha
-
- /* ok - even on a DEC box, strings are strings. I didn't really want */
- /* to ntohl the words of a string. since I don't want to teach the */
- /* send_ and recv_ _request and _response routines about the types, */
- /* I will put "anti-ntohl" calls here. I imagine that the "pure" */
- /* solution would be to use XDR, but I am still leary of being able */
- /* to find XDR libs on all platforms I want running netperf. raj */
- {
- int *charword;
- int *initword;
- int *lastword;
-
- initword = (int *) xti_tcp_stream_request->xti_device;
- lastword = initword + ((strlen(rem_xti_device) + 3) / 4);
-
- for (charword = initword;
- charword < lastword;
- charword++) {
-
- *charword = ntohl(*charword);
- }
- }
-#endif /* __alpha */
-
-#ifdef DIRTY
- xti_tcp_stream_request->dirty_count = rem_dirty_count;
- xti_tcp_stream_request->clean_count = rem_clean_count;
-#endif /* DIRTY */
-
-
- if (debug > 1) {
- fprintf(where,
- "netperf: send_xti_tcp_stream: requesting TCP stream test\n");
- }
-
- send_request();
-
- /* The response from the remote will contain all of the relevant */
- /* socket parameters for this test type. We will put them back into */
- /* the variables here so they can be displayed if desired. The */
- /* remote will have calibrated CPU if necessary, and will have done */
- /* all the needed set-up we will have calibrated the cpu locally */
- /* before sending the request, and will grab the counter value right*/
- /* after the connect returns. The remote will grab the counter right*/
- /* after the accept call. This saves the hassle of extra messages */
- /* being sent for the TCP tests. */
-
- recv_response();
-
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote listen done.\n");
- rsr_size = xti_tcp_stream_response->recv_buf_size;
- rss_size = xti_tcp_stream_response->send_buf_size;
- rem_nodelay = xti_tcp_stream_response->no_delay;
- remote_cpu_usage = xti_tcp_stream_response->measure_cpu;
- remote_cpu_rate = xti_tcp_stream_response->cpu_rate;
-
- /* we have to make sure that the server port number is in */
- /* network order */
- server.sin_port = (short)xti_tcp_stream_response->data_port_number;
- server.sin_port = htons(server.sin_port);
- rem_rcvavoid = xti_tcp_stream_response->so_rcvavoid;
- rem_sndavoid = xti_tcp_stream_response->so_sndavoid;
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- perror("netperf: remote error");
-
- exit(1);
- }
-
- /*Connect up to the remote port on the data socket */
- memset (&server_call, 0, sizeof(server_call));
- server_call.addr.maxlen = sizeof(struct sockaddr_in);
- server_call.addr.len = sizeof(struct sockaddr_in);
- server_call.addr.buf = (char *)&server;
-
- if (t_connect(send_socket,
- &server_call,
- NULL) == INVALID_SOCKET){
- t_error("netperf: send_xti_tcp_stream: data socket connect failed");
- printf(" port: %d\n",ntohs(server.sin_port));
- exit(1);
- }
-
- /* Data Socket set-up is finished. If there were problems, either */
- /* the connect would have failed, or the previous response would */
- /* have indicated a problem. I failed to see the value of the */
- /* extra message after the accept on the remote. If it failed, */
- /* we'll see it here. If it didn't, we might as well start pumping */
- /* data. */
-
- /* Set-up the test end conditions. For a stream test, they can be */
- /* either time or byte-count based. */
-
- if (test_time) {
- /* The user wanted to end the test after a period of time. */
- times_up = 0;
- bytes_remaining = 0;
- /* in previous revisions, we had the same code repeated throught */
- /* all the test suites. this was unnecessary, and meant more */
- /* work for me when I wanted to switch to POSIX signals, so I */
- /* have abstracted this out into a routine in netlib.c. if you */
- /* are experiencing signal problems, you might want to look */
- /* there. raj 11/94 */
- start_timer(test_time);
- }
- else {
- /* The tester wanted to send a number of bytes. */
- bytes_remaining = test_bytes;
- times_up = 1;
- }
-
- /* The cpu_start routine will grab the current time and possibly */
- /* value of the idle counter for later use in measuring cpu */
- /* utilization and/or service demand and thruput. */
-
- cpu_start(local_cpu_usage);
-
-#ifdef WANT_INTERVALS
- if ((interval_burst) || (demo_mode)) {
- /* zero means that we never pause, so we never should need the */
- /* interval timer, unless we are in demo_mode */
- start_itimer(interval_wate);
- }
- interval_count = interval_burst;
- /* get the signal set for the call to sigsuspend */
- if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &signal_set) != 0) {
- fprintf(where,
- "send_xti_tcp_stream: unable to get sigmask errno %d\n",
- errno);
- fflush(where);
- exit(1);
- }
-#endif /* WANT_INTERVALS */
-
- /* before we start, initialize a few variables */
-
- /* We use an "OR" to control test execution. When the test is */
- /* controlled by time, the byte count check will always return false. */
- /* When the test is controlled by byte count, the time test will */
- /* always return false. When the test is finished, the whole */
- /* expression will go false and we will stop sending data. */
-
- while ((!times_up) || (bytes_remaining > 0)) {
-
-#ifdef DIRTY
- /* we want to dirty some number of consecutive integers in the buffer */
- /* we are about to send. we may also want to bring some number of */
- /* them cleanly into the cache. The clean ones will follow any dirty */
- /* ones into the cache. at some point, we might want to replace */
- /* the rand() call with something from a table to reduce our call */
- /* overhead during the test, but it is not a high priority item. */
- access_buffer(send_ring->buffer_ptr,
- send_size,
- loc_dirty_count,
- loc_clean_count);
-#endif /* DIRTY */
-
-#ifdef WANT_HISTOGRAM
- /* timestamp just before we go into send and then again just after */
- /* we come out raj 8/94 */
- HIST_timestamp(&time_one);
-#endif /* WANT_HISTOGRAM */
-
- if((len=t_snd(send_socket,
- send_ring->buffer_ptr,
- send_size,
- 0)) != send_size) {
- if ((len >=0) || (errno == EINTR)) {
- /* the test was interrupted, must be the end of test */
- break;
- }
- fprintf(where,
- "send_xti_tcp_stream: t_snd: errno %d t_errno %d t_look 0x%.4x\n",
- errno,
- t_errno,
- t_look(send_socket));
- fflush(where);
- exit(1);
- }
-
-#ifdef WANT_HISTOGRAM
- /* timestamp the exit from the send call and update the histogram */
- HIST_timestamp(&time_two);
- HIST_add(time_hist,delta_micro(&time_one,&time_two));
-#endif /* WANT_HISTOGRAM */
-
-#ifdef WANT_INTERVALS
- if (demo_mode) {
- units_this_tick += send_size;
- }
- /* in this case, the interval count is the count-down couter */
- /* to decide to sleep for a little bit */
- if ((interval_burst) && (--interval_count == 0)) {
- /* call sigsuspend and wait for the interval timer to get us */
- /* out */
- if (debug) {
- fprintf(where,"about to suspend\n");
- fflush(where);
- }
- if (sigsuspend(&signal_set) == EFAULT) {
- fprintf(where,
- "send_xti_tcp_stream: fault with signal set!\n");
- fflush(where);
- exit(1);
- }
- interval_count = interval_burst;
- }
-#endif /* WANT_INTERVALS */
-
- /* now we want to move our pointer to the next position in the */
- /* data buffer...we may also want to wrap back to the "beginning" */
- /* of the bufferspace, so we will mod the number of messages sent */
- /* by the send width, and use that to calculate the offset to add */
- /* to the base pointer. */
- nummessages++;
- send_ring = send_ring->next;
- if (bytes_remaining) {
- bytes_remaining -= send_size;
- }
- }
-
- /* The test is over. Flush the buffers to the remote end. We do a */
- /* graceful release to insure that all data has been taken by the */
- /* remote. */
-
- /* but first, if the verbosity is greater than 1, find-out what */
- /* the TCP maximum segment_size was (if possible) */
- if (verbosity > 1) {
- tcp_mss = -1;
- get_xti_info(send_socket,info_struct);
- }
-
- if (t_sndrel(send_socket) == -1) {
- t_error("netperf: cannot shutdown tcp stream socket");
- exit(1);
- }
-
- /* hang a t_rcvrel() off the socket to block until the remote has */
- /* brought all the data up into the application. it will do a */
- /* t_sedrel to cause a FIN to be sent our way. We will assume that */
- /* any exit from the t_rcvrel() call is good... raj 2/95 */
-
- if (debug > 1) {
- fprintf(where,"about to hang a receive for graceful release.\n");
- fflush(where);
- }
-
- t_rcvrel(send_socket);
-
- /* this call will always give us the elapsed time for the test, and */
- /* will also store-away the necessaries for cpu utilization */
-
- cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */
- /* measured and how */
- /* long did we really */
- /* run? */
-
- /* Get the statistics from the remote end. The remote will have */
- /* calculated service demand and all those interesting things. If it */
- /* wasn't supposed to care, it will return obvious values. */
-
- recv_response();
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote results obtained\n");
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- perror("netperf: remote error");
-
- exit(1);
- }
-
- /* We now calculate what our thruput was for the test. In the future, */
- /* we may want to include a calculation of the thruput measured by */
- /* the remote, but it should be the case that for a TCP stream test, */
- /* that the two numbers should be *very* close... We calculate */
- /* bytes_sent regardless of the way the test length was controlled. */
- /* If it was time, we needed to, and if it was by bytes, the user may */
- /* have specified a number of bytes that wasn't a multiple of the */
- /* send_size, so we really didn't send what he asked for ;-) */
-
- bytes_sent = xti_tcp_stream_result->bytes_received;
-
- thruput = calc_thruput(bytes_sent);
-
- if (local_cpu_usage || remote_cpu_usage) {
- /* We must now do a little math for service demand and cpu */
- /* utilization for the system(s) */
- /* Of course, some of the information might be bogus because */
- /* there was no idle counter in the kernel(s). We need to make */
- /* a note of this for the user's benefit...*/
- if (local_cpu_usage) {
-
- local_cpu_utilization = calc_cpu_util(0.0);
- local_service_demand = calc_service_demand(bytes_sent,
- 0.0,
- 0.0,
- 0);
- }
- else {
- local_cpu_utilization = -1.0;
- local_service_demand = -1.0;
- }
-
- if (remote_cpu_usage) {
-
- remote_cpu_utilization = xti_tcp_stream_result->cpu_util;
- remote_service_demand = calc_service_demand(bytes_sent,
- 0.0,
- remote_cpu_utilization,
- xti_tcp_stream_result->num_cpus);
- }
- else {
- remote_cpu_utilization = -1.0;
- remote_service_demand = -1.0;
- }
- }
- else {
- /* we were not measuring cpu, for the confidence stuff, we */
- /* should make it -1.0 */
- local_cpu_utilization = -1.0;
- local_service_demand = -1.0;
- remote_cpu_utilization = -1.0;
- remote_service_demand = -1.0;
- }
-
- /* at this point, we want to calculate the confidence information. */
- /* if debugging is on, calculate_confidence will print-out the */
- /* parameters we pass it */
-
- calculate_confidence(confidence_iteration,
- elapsed_time,
- thruput,
- local_cpu_utilization,
- remote_cpu_utilization,
- local_service_demand,
- remote_service_demand);
-
-
- confidence_iteration++;
- }
-
- /* at this point, we have finished making all the runs that we */
- /* will be making. so, we should extract what the calcuated values */
- /* are for all the confidence stuff. we could make the values */
- /* global, but that seemed a little messy, and it did not seem worth */
- /* all the mucking with header files. so, we create a routine much */
- /* like calcualte_confidence, which just returns the mean values. */
- /* raj 11/94 */
-
- retrieve_confident_values(&elapsed_time,
- &thruput,
- &local_cpu_utilization,
- &remote_cpu_utilization,
- &local_service_demand,
- &remote_service_demand);
-
- /* We are now ready to print all the information. If the user */
- /* has specified zero-level verbosity, we will just print the */
- /* local service demand, or the remote service demand. If the */
- /* user has requested verbosity level 1, he will get the basic */
- /* "streamperf" numbers. If the user has specified a verbosity */
- /* of greater than 1, we will display a veritable plethora of */
- /* background information from outside of this block as it it */
- /* not cpu_measurement specific... */
-
- if (confidence < 0) {
- /* we did not hit confidence, but were we asked to look for it? */
- if (iteration_max > 1) {
- display_confidence();
- }
- }
-
- if (local_cpu_usage || remote_cpu_usage) {
- local_cpu_method = format_cpu_method(cpu_method);
- remote_cpu_method = format_cpu_method(xti_tcp_stream_result->cpu_method);
-
- switch (verbosity) {
- case 0:
- if (local_cpu_usage) {
- fprintf(where,
- cpu_fmt_0,
- local_service_demand,
- local_cpu_method);
- }
- else {
- fprintf(where,
- cpu_fmt_0,
- remote_service_demand,
- remote_cpu_method);
- }
- break;
- case 1:
- case 2:
- if (print_headers) {
- fprintf(where,
- cpu_title,
- format_units(),
- local_cpu_method,
- remote_cpu_method);
- }
-
- fprintf(where,
- cpu_fmt_1, /* the format string */
- rsr_size, /* remote recvbuf size */
- lss_size, /* local sendbuf size */
- send_size, /* how large were the sends */
- elapsed_time, /* how long was the test */
- thruput, /* what was the xfer rate */
- local_cpu_utilization, /* local cpu */
- remote_cpu_utilization, /* remote cpu */
- local_service_demand, /* local service demand */
- remote_service_demand); /* remote service demand */
- break;
- }
- }
- else {
- /* The tester did not wish to measure service demand. */
-
- switch (verbosity) {
- case 0:
- fprintf(where,
- tput_fmt_0,
- thruput);
- break;
- case 1:
- case 2:
- if (print_headers) {
- fprintf(where,tput_title,format_units());
- }
- fprintf(where,
- tput_fmt_1, /* the format string */
- rsr_size, /* remote recvbuf size */
- lss_size, /* local sendbuf size */
- send_size, /* how large were the sends */
- elapsed_time, /* how long did it take */
- thruput);/* how fast did it go */
- break;
- }
- }
-
- /* it would be a good thing to include information about some of the */
- /* other parameters that may have been set for this test, but at the */
- /* moment, I do not wish to figure-out all the formatting, so I will */
- /* just put this comment here to help remind me that it is something */
- /* that should be done at a later time. */
-
- if (verbosity > 1) {
- /* The user wanted to know it all, so we will give it to him. */
- /* This information will include as much as we can find about */
- /* TCP statistics, the alignments of the sends and receives */
- /* and all that sort of rot... */
-
- /* this stuff needs to be worked-out in the presence of confidence */
- /* intervals and multiple iterations of the test... raj 11/94 */
-
- fprintf(where,
- ksink_fmt,
- "Bytes",
- "Bytes",
- "Bytes",
- local_send_align,
- remote_recv_align,
- local_send_offset,
- remote_recv_offset,
- bytes_sent,
- bytes_sent / (double)nummessages,
- nummessages,
- bytes_sent / (double)xti_tcp_stream_result->recv_calls,
- xti_tcp_stream_result->recv_calls);
- fprintf(where,
- ksink_fmt2,
- tcp_mss);
- fflush(where);
-#ifdef WANT_HISTOGRAM
- fprintf(where,"\n\nHistogram of time spent in send() call.\n");
- fflush(where);
- HIST_report(time_hist);
-#endif /* WANT_HISTOGRAM */
- }
-
-}
-
-
-/* This is the server-side routine for the tcp stream test. It is */
-/* implemented as one routine. I could break things-out somewhat, but */
-/* didn't feel it was necessary. */
-
-void
-recv_xti_tcp_stream()
-{
-
- struct sockaddr_in myaddr_in, peeraddr_in;
- struct t_bind bind_req, bind_resp;
- struct t_call call_req;
-
- SOCKET s_listen,s_data;
- int addrlen;
- int len;
- unsigned int receive_calls;
- float elapsed_time;
- double bytes_received;
-
- struct ring_elt *recv_ring;
-
- int *message_int_ptr;
- int i;
-
- struct xti_tcp_stream_request_struct *xti_tcp_stream_request;
- struct xti_tcp_stream_response_struct *xti_tcp_stream_response;
- struct xti_tcp_stream_results_struct *xti_tcp_stream_results;
-
- xti_tcp_stream_request =
- (struct xti_tcp_stream_request_struct *)netperf_request.content.test_specific_data;
- xti_tcp_stream_response =
- (struct xti_tcp_stream_response_struct *)netperf_response.content.test_specific_data;
- xti_tcp_stream_results =
- (struct xti_tcp_stream_results_struct *)netperf_response.content.test_specific_data;
-
- if (debug) {
- fprintf(where,"netserver: recv_xti_tcp_stream: entered...\n");
- fflush(where);
- }
-
- /* We want to set-up the listen socket with all the desired */
- /* parameters and then let the initiator know that all is ready. If */
- /* socket size defaults are to be used, then the initiator will have */
- /* sent us 0's. If the socket sizes cannot be changed, then we will */
- /* send-back what they are. If that information cannot be determined, */
- /* then we send-back -1's for the sizes. If things go wrong for any */
- /* reason, we will drop back ten yards and punt. */
-
- /* If anything goes wrong, we want the remote to know about it. It */
- /* would be best if the error that the remote reports to the user is */
- /* the actual error we encountered, rather than some bogus unexpected */
- /* response type message. */
-
- if (debug) {
- fprintf(where,"recv_xti_tcp_stream: setting the response type...\n");
- fflush(where);
- }
-
- netperf_response.content.response_type = XTI_TCP_STREAM_RESPONSE;
-
- if (debug) {
- fprintf(where,"recv_xti_tcp_stream: the response type is set...\n");
- fflush(where);
- }
-
- /* We now alter the message_ptr variable to be at the desired */
- /* alignment with the desired offset. */
-
- if (debug) {
- fprintf(where,"recv_xti_tcp_stream: requested alignment of %d\n",
- xti_tcp_stream_request->recv_alignment);
- fflush(where);
- }
-
- /* Let's clear-out our sockaddr for the sake of cleanlines. Then we */
- /* can put in OUR values !-) At some point, we may want to nail this */
- /* socket to a particular network-level address, but for now, */
- /* INADDR_ANY should be just fine. */
-
- bzero((char *)&myaddr_in,
- sizeof(myaddr_in));
- myaddr_in.sin_family = AF_INET;
- myaddr_in.sin_addr.s_addr = INADDR_ANY;
- myaddr_in.sin_port = 0;
-
- /* Grab a socket to listen on, and then listen on it. */
-
- if (debug) {
- fprintf(where,"recv_xti_tcp_stream: grabbing a socket...\n");
- fflush(where);
- }
-
- /* create_xti_endpoint expects to find some things in the global */
- /* variables, so set the globals based on the values in the request. */
- /* once the socket has been created, we will set the response values */
- /* based on the updated value of those globals. raj 7/94 */
- lss_size = xti_tcp_stream_request->send_buf_size;
- lsr_size = xti_tcp_stream_request->recv_buf_size;
- loc_nodelay = xti_tcp_stream_request->no_delay;
- loc_rcvavoid = xti_tcp_stream_request->so_rcvavoid;
- loc_sndavoid = xti_tcp_stream_request->so_sndavoid;
-
-#ifdef __alpha
-
- /* ok - even on a DEC box, strings are strings. I din't really want */
- /* to ntohl the words of a string. since I don't want to teach the */
- /* send_ and recv_ _request and _response routines about the types, */
- /* I will put "anti-ntohl" calls here. I imagine that the "pure" */
- /* solution would be to use XDR, but I am still leary of being able */
- /* to find XDR libs on all platforms I want running netperf. raj */
- {
- int *charword;
- int *initword;
- int *lastword;
-
- initword = (int *) xti_tcp_stream_request->xti_device;
- lastword = initword + ((xti_tcp_stream_request->dev_name_len + 3) / 4);
-
- for (charword = initword;
- charword < lastword;
- charword++) {
-
- *charword = htonl(*charword);
- }
- }
-
-#endif /* __alpha */
-
- s_listen = create_xti_endpoint(xti_tcp_stream_request->xti_device);
-
- if (s_listen == INVALID_SOCKET) {
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
-
- /* Let's get an address assigned to this socket so we can tell the */
- /* initiator how to reach the data socket. There may be a desire to */
- /* nail this socket to a specific IP address in a multi-homed, */
- /* multi-connection situation, but for now, we'll ignore the issue */
- /* and concentrate on single connection testing. */
-
- bind_req.addr.maxlen = sizeof(struct sockaddr_in);
- bind_req.addr.len = sizeof(struct sockaddr_in);
- bind_req.addr.buf = (char *)&myaddr_in;
- bind_req.qlen = 1;
-
- bind_resp.addr.maxlen = sizeof(struct sockaddr_in);
- bind_resp.addr.len = sizeof(struct sockaddr_in);
- bind_resp.addr.buf = (char *)&myaddr_in;
- bind_resp.qlen = 1;
-
- if (t_bind(s_listen,
- &bind_req,
- &bind_resp) == SOCKET_ERROR) {
- netperf_response.content.serv_errno = t_errno;
- close(s_listen);
- send_response();
-
- exit(1);
- }
-
- if (debug) {
- fprintf(where,
- "recv_xti_tcp_stream: t_bind complete port %d\n",
- ntohs(myaddr_in.sin_port));
- fflush(where);
- }
-
- /* what sort of sizes did we end-up with? */
- if (xti_tcp_stream_request->receive_size == 0) {
- if (lsr_size > 0) {
- recv_size = lsr_size;
- }
- else {
- recv_size = 4096;
- }
- }
- else {
- recv_size = xti_tcp_stream_request->receive_size;
- }
-
- /* we want to set-up our recv_ring in a manner analagous to what we */
- /* do on the sending side. this is more for the sake of symmetry */
- /* than for the needs of say copy avoidance, but it might also be */
- /* more realistic - this way one could conceivably go with a */
- /* double-buffering scheme when taking the data an putting it into */
- /* the filesystem or something like that. raj 7/94 */
-
- if (recv_width == 0) {
- recv_width = (lsr_size/recv_size) + 1;
- if (recv_width == 1) recv_width++;
- }
-
- recv_ring = allocate_buffer_ring(recv_width,
- recv_size,
- xti_tcp_stream_request->recv_alignment,
- xti_tcp_stream_request->recv_offset);
-
- if (debug) {
- fprintf(where,"recv_xti_tcp_stream: recv alignment and offset set...\n");
- fflush(where);
- }
-
- /* Now myaddr_in contains the port and the internet address this is */
- /* returned to the sender also implicitly telling the sender that the */
- /* socket buffer sizing has been done. */
-
- xti_tcp_stream_response->data_port_number =
- (int) ntohs(myaddr_in.sin_port);
- netperf_response.content.serv_errno = 0;
-
- /* But wait, there's more. If the initiator wanted cpu measurements, */
- /* then we must call the calibrate routine, which will return the max */
- /* rate back to the initiator. If the CPU was not to be measured, or */
- /* something went wrong with the calibration, we will return a -1 to */
- /* the initiator. */
-
- xti_tcp_stream_response->cpu_rate = 0.0; /* assume no cpu */
- if (xti_tcp_stream_request->measure_cpu) {
- xti_tcp_stream_response->measure_cpu = 1;
- xti_tcp_stream_response->cpu_rate =
- calibrate_local_cpu(xti_tcp_stream_request->cpu_rate);
- }
- else {
- xti_tcp_stream_response->measure_cpu = 0;
- }
-
- /* before we send the response back to the initiator, pull some of */
- /* the socket parms from the globals */
- xti_tcp_stream_response->send_buf_size = lss_size;
- xti_tcp_stream_response->recv_buf_size = lsr_size;
- xti_tcp_stream_response->no_delay = loc_nodelay;
- xti_tcp_stream_response->so_rcvavoid = loc_rcvavoid;
- xti_tcp_stream_response->so_sndavoid = loc_sndavoid;
- xti_tcp_stream_response->receive_size = recv_size;
-
- send_response();
-
- /* Now, let's set-up the socket to listen for connections. for xti, */
- /* the t_listen call is blocking by default - this is different */
- /* semantics from BSD - probably has to do with being able to reject */
- /* a call before an accept */
- call_req.addr.maxlen = sizeof(struct sockaddr_in);
- call_req.addr.len = sizeof(struct sockaddr_in);
- call_req.addr.buf = (char *)&peeraddr_in;
- call_req.opt.maxlen = 0;
- call_req.opt.len = 0;
- call_req.opt.buf = NULL;
- call_req.udata.maxlen= 0;
- call_req.udata.len = 0;
- call_req.udata.buf = 0;
-
- if (t_listen(s_listen, &call_req) == -1) {
- fprintf(where,
- "recv_xti_tcp_stream: t_listen: errno %d t_errno %d\n",
- errno,
- t_errno);
- fflush(where);
- netperf_response.content.serv_errno = t_errno;
- close(s_listen);
- send_response();
- exit(1);
- }
-
- if (debug) {
- fprintf(where,
- "recv_xti_tcp_stream: t_listen complete t_look 0x%.4x\n",
- t_look(s_listen));
- fflush(where);
- }
-
- /* now just rubber stamp the thing. we want to use the same fd? so */
- /* we will just equate s_data with s_listen. this seems a little */
- /* hokey to me, but then I'm a BSD biggot still. raj 2/95 */
- s_data = s_listen;
- if (t_accept(s_listen,
- s_data,
- &call_req) == -1) {
- fprintf(where,
- "recv_xti_tcp_stream: t_accept: errno %d t_errno %d\n",
- errno,
- t_errno);
- fflush(where);
- close(s_listen);
- exit(1);
- }
-
- if (debug) {
- fprintf(where,
- "recv_xti_tcp_stream: t_accept complete t_look 0x%.4x\n",
- t_look(s_data));
- fprintf(where,
- " remote is %s port %d\n",
- inet_ntoa(*(struct in_addr *)&peeraddr_in.sin_addr),
- ntohs(peeraddr_in.sin_port));
- fflush(where);
- }
-
- /* Now it's time to start receiving data on the connection. We will */
- /* first grab the apropriate counters and then start grabbing. */
-
- cpu_start(xti_tcp_stream_request->measure_cpu);
-
- /* The loop will exit when the sender does a t_sndrel, which will */
- /* return T_LOOK error from the t_recv */
-
-#ifdef DIRTY
- /* we want to dirty some number of consecutive integers in the buffer */
- /* we are about to recv. we may also want to bring some number of */
- /* them cleanly into the cache. The clean ones will follow any dirty */
- /* ones into the cache. */
-
- access_buffer(recv_ring->buffer_ptr,
- recv_size,
- xti_tcp_stream_request->dirty_count,
- xti_tcp_stream_request->clean_count);
-
-#endif /* DIRTY */
-
- bytes_received = 0;
- receive_calls = 0;
-
- while ((len = t_rcv(s_data,
- recv_ring->buffer_ptr,
- recv_size,
- &xti_flags)) != -1) {
- bytes_received += len;
- receive_calls++;
-
- /* more to the next buffer in the recv_ring */
- recv_ring = recv_ring->next;
-
-#ifdef DIRTY
-
- access_buffer(recv_ring->buffer_ptr,
- recv_size,
- xti_tcp_stream_request->dirty_count,
- xti_tcp_stream_request->clean_count);
-
-#endif /* DIRTY */
- }
-
- if (t_look(s_data) == T_ORDREL) {
- /* this is a normal exit path */
- if (debug) {
- fprintf(where,
- "recv_xti_tcp_stream: t_rcv T_ORDREL indicated\n");
- fflush(where);
- }
- }
- else {
- /* something went wrong */
- fprintf(where,
- "recv_xti_tcp_stream: t_rcv: errno %d t_errno %d len %d",
- errno,
- t_errno,
- len);
- fprintf(where,
- " t_look 0x%.4x",
- t_look(s_data));
- fflush(where);
- netperf_response.content.serv_errno = t_errno;
- send_response();
- exit(1);
- }
-
- /* receive the release and let the initiator know that we have */
- /* received all the data. raj 3/95 */
-
- if (t_rcvrel(s_data) == -1) {
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
-
- if (debug) {
- fprintf(where,
- "recv_xti_tcp_stream: t_rcvrel complete\n");
- fflush(where);
- }
-
- if (t_sndrel(s_data) == -1) {
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
-
- if (debug) {
- fprintf(where,
- "recv_xti_tcp_stream: t_sndrel complete\n");
- fflush(where);
- }
-
- cpu_stop(xti_tcp_stream_request->measure_cpu,&elapsed_time);
-
- /* send the results to the sender */
-
- if (debug) {
- fprintf(where,
- "recv_xti_tcp_stream: got %g bytes\n",
- bytes_received);
- fprintf(where,
- "recv_xti_tcp_stream: got %d recvs\n",
- receive_calls);
- fflush(where);
- }
-
- xti_tcp_stream_results->bytes_received = bytes_received;
- xti_tcp_stream_results->elapsed_time = elapsed_time;
- xti_tcp_stream_results->recv_calls = receive_calls;
-
- if (xti_tcp_stream_request->measure_cpu) {
- xti_tcp_stream_results->cpu_util = calc_cpu_util(0.0);
- };
-
- if (debug) {
- fprintf(where,
- "recv_xti_tcp_stream: test complete, sending results.\n");
- fprintf(where,
- " bytes_received %g receive_calls %d\n",
- bytes_received,
- receive_calls);
- fprintf(where,
- " len %d\n",
- len);
- fflush(where);
- }
-
- xti_tcp_stream_results->cpu_method = cpu_method;
- send_response();
-
- /* we are now done with the socket */
- t_close(s_data);
-
-}
-
-
- /* this routine implements the sending (netperf) side of the XTI_TCP_RR */
- /* test. */
-
-void
-send_xti_tcp_rr(char remote_host[])
-{
-
- char *tput_title = "\
-Local /Remote\n\
-Socket Size Request Resp. Elapsed Trans.\n\
-Send Recv Size Size Time Rate \n\
-bytes Bytes bytes bytes secs. per sec \n\n";
-
- char *tput_fmt_0 =
- "%7.2f\n";
-
- char *tput_fmt_1_line_1 = "\
-%-6d %-6d %-6d %-6d %-6.2f %7.2f \n";
- char *tput_fmt_1_line_2 = "\
-%-6d %-6d\n";
-
- char *cpu_title = "\
-Local /Remote\n\
-Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\
-Send Recv Size Size Time Rate local remote local remote\n\
-bytes bytes bytes bytes secs. per sec %% %c %% %c us/Tr us/Tr\n\n";
-
- char *cpu_fmt_0 =
- "%6.3f %c\n";
-
- char *cpu_fmt_1_line_1 = "\
-%-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f\n";
-
- char *cpu_fmt_1_line_2 = "\
-%-6d %-6d\n";
-
- char *ksink_fmt = "\
-Alignment Offset\n\
-Local Remote Local Remote\n\
-Send Recv Send Recv\n\
-%5d %5d %5d %5d\n";
-
-
- int timed_out = 0;
- float elapsed_time;
-
- int len;
- char *temp_message_ptr;
- int nummessages;
- SOCKET send_socket;
- int trans_remaining;
- double bytes_xferd;
-
- struct ring_elt *send_ring;
- struct ring_elt *recv_ring;
-
- int rsp_bytes_left;
- int rsp_bytes_recvd;
-
- float local_cpu_utilization;
- float local_service_demand;
- float remote_cpu_utilization;
- float remote_service_demand;
- double thruput;
-
- struct hostent *hp;
- struct sockaddr_in server;
- unsigned int addr;
-
- struct t_call server_call;
-
- struct xti_tcp_rr_request_struct *xti_tcp_rr_request;
- struct xti_tcp_rr_response_struct *xti_tcp_rr_response;
- struct xti_tcp_rr_results_struct *xti_tcp_rr_result;
-
-#ifdef WANT_INTERVALS
- int interval_count;
- sigset_t signal_set;
-#endif /* WANT_INTERVALS */
-
- xti_tcp_rr_request =
- (struct xti_tcp_rr_request_struct *)netperf_request.content.test_specific_data;
- xti_tcp_rr_response=
- (struct xti_tcp_rr_response_struct *)netperf_response.content.test_specific_data;
- xti_tcp_rr_result =
- (struct xti_tcp_rr_results_struct *)netperf_response.content.test_specific_data;
-
-#ifdef WANT_HISTOGRAM
- time_hist = HIST_new();
-#endif /* WANT_HISTOGRAM */
-
- /* since we are now disconnected from the code that established the */
- /* control socket, and since we want to be able to use different */
- /* protocols and such, we are passed the name of the remote host and */
- /* must turn that into the test specific addressing information. */
-
- bzero((char *)&server,
- sizeof(server));
-
- /* it would seem that while HP-UX will allow an IP address (as a */
- /* string) in a call to gethostbyname, other, less enlightened */
- /* systems do not. fix from awjacks@ca.sandia.gov raj 10/95 */
- /* order changed to check for IP address first. raj 7/96 */
-
- if ((addr = inet_addr(remote_host)) == SOCKET_ERROR) {
- /* it was not an IP address, try it as a name */
- if ((hp = gethostbyname(remote_host)) == NULL) {
- /* we have no idea what it is */
- fprintf(where,
- "establish_control: could not resolve the destination %s\n",
- remote_host);
- fflush(where);
- exit(1);
- }
- else {
- /* it was a valid remote_host */
- bcopy(hp->h_addr,
- (char *)&server.sin_addr,
- hp->h_length);
- server.sin_family = hp->h_addrtype;
- }
- }
- else {
- /* it was a valid IP address */
- server.sin_addr.s_addr = addr;
- server.sin_family = AF_INET;
- }
-
- if ( print_headers ) {
- fprintf(where,"XTI TCP REQUEST/RESPONSE TEST");
- fprintf(where," to %s", remote_host);
- if (iteration_max > 1) {
- fprintf(where,
- " : +/-%3.1f%% @ %2d%% conf.",
- interval/0.02,
- confidence_level);
- }
- if (loc_nodelay || rem_nodelay) {
- fprintf(where," : nodelay");
- }
- if (loc_sndavoid ||
- loc_rcvavoid ||
- rem_sndavoid ||
- rem_rcvavoid) {
- fprintf(where," : copy avoidance");
- }
-#ifdef WANT_HISTOGRAM
- fprintf(where," : histogram");
-#endif /* WANT_HISTOGRAM */
-#ifdef WANT_INTERVALS
- fprintf(where," : interval");
-#endif /* WANT_INTERVALS */
-#ifdef DIRTY
- fprintf(where," : dirty data");
-#endif /* DIRTY */
- fprintf(where,"\n");
- }
-
- /* initialize a few counters */
-
- send_ring = NULL;
- recv_ring = NULL;
- confidence_iteration = 1;
- init_stat();
-
- /* we have a great-big while loop which controls the number of times */
- /* we run a particular test. this is for the calculation of a */
- /* confidence interval (I really should have stayed awake during */
- /* probstats :). If the user did not request confidence measurement */
- /* (no confidence is the default) then we will only go though the */
- /* loop once. the confidence stuff originates from the folks at IBM */
-
- while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
- (confidence_iteration <= iteration_min)) {
-
- /* initialize a few counters. we have to remember that we might be */
- /* going through the loop more than once. */
-
- nummessages = 0;
- bytes_xferd = 0.0;
- times_up = 0;
- timed_out = 0;
- trans_remaining = 0;
-
- /* set-up the data buffers with the requested alignment and offset. */
- /* since this is a request/response test, default the send_width and */
- /* recv_width to 1 and not two raj 7/94 */
-
- if (send_width == 0) send_width = 1;
- if (recv_width == 0) recv_width = 1;
-
- if (send_ring == NULL) {
- send_ring = allocate_buffer_ring(send_width,
- req_size,
- local_send_align,
- local_send_offset);
- }
-
- if (recv_ring == NULL) {
- recv_ring = allocate_buffer_ring(recv_width,
- rsp_size,
- local_recv_align,
- local_recv_offset);
- }
-
- /*set up the data socket */
- send_socket = create_xti_endpoint(loc_xti_device);
-
- if (send_socket == INVALID_SOCKET){
- perror("netperf: send_xti_tcp_rr: tcp stream data socket");
- exit(1);
- }
-
- if (debug) {
- fprintf(where,"send_xti_tcp_rr: send_socket obtained...\n");
- }
-
- /* it would seem that with XTI, there is no implicit bind on a */
- /* connect, so we have to make a call to t_bind. this is not */
- /* terribly convenient, but I suppose that "standard is better */
- /* than better" :) raj 2/95 */
-
- if (t_bind(send_socket, NULL, NULL) == SOCKET_ERROR) {
- t_error("send_xti_tcp_stream: t_bind");
- exit(1);
- }
-
- /* If the user has requested cpu utilization measurements, we must */
- /* calibrate the cpu(s). We will perform this task within the tests */
- /* themselves. If the user has specified the cpu rate, then */
- /* calibrate_local_cpu will return rather quickly as it will have */
- /* nothing to do. If local_cpu_rate is zero, then we will go through */
- /* all the "normal" calibration stuff and return the rate back.*/
-
- if (local_cpu_usage) {
- local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
- }
-
- /* Tell the remote end to do a listen. The server alters the socket */
- /* paramters on the other side at this point, hence the reason for */
- /* all the values being passed in the setup message. If the user did */
- /* not specify any of the parameters, they will be passed as 0, which */
- /* will indicate to the remote that no changes beyond the system's */
- /* default should be used. Alignment is the exception, it will */
- /* default to 8, which will be no alignment alterations. */
-
- netperf_request.content.request_type = DO_XTI_TCP_RR;
- xti_tcp_rr_request->recv_buf_size = rsr_size;
- xti_tcp_rr_request->send_buf_size = rss_size;
- xti_tcp_rr_request->recv_alignment = remote_recv_align;
- xti_tcp_rr_request->recv_offset = remote_recv_offset;
- xti_tcp_rr_request->send_alignment = remote_send_align;
- xti_tcp_rr_request->send_offset = remote_send_offset;
- xti_tcp_rr_request->request_size = req_size;
- xti_tcp_rr_request->response_size = rsp_size;
- xti_tcp_rr_request->no_delay = rem_nodelay;
- xti_tcp_rr_request->measure_cpu = remote_cpu_usage;
- xti_tcp_rr_request->cpu_rate = remote_cpu_rate;
- xti_tcp_rr_request->so_rcvavoid = rem_rcvavoid;
- xti_tcp_rr_request->so_sndavoid = rem_sndavoid;
- if (test_time) {
- xti_tcp_rr_request->test_length = test_time;
- }
- else {
- xti_tcp_rr_request->test_length = test_trans * -1;
- }
-
- strcpy(xti_tcp_rr_request->xti_device, rem_xti_device);
-
-#ifdef __alpha
-
- /* ok - even on a DEC box, strings are strings. I didn't really want */
- /* to ntohl the words of a string. since I don't want to teach the */
- /* send_ and recv_ _request and _response routines about the types, */
- /* I will put "anti-ntohl" calls here. I imagine that the "pure" */
- /* solution would be to use XDR, but I am still leary of being able */
- /* to find XDR libs on all platforms I want running netperf. raj */
- {
- int *charword;
- int *initword;
- int *lastword;
-
- initword = (int *) xti_tcp_rr_request->xti_device;
- lastword = initword + ((strlen(rem_xti_device) + 3) / 4);
-
- for (charword = initword;
- charword < lastword;
- charword++) {
-
- *charword = ntohl(*charword);
- }
- }
-#endif /* __alpha */
-
- if (debug > 1) {
- fprintf(where,"netperf: send_xti_tcp_rr: requesting TCP rr test\n");
- }
-
- send_request();
-
- /* The response from the remote will contain all of the relevant */
- /* socket parameters for this test type. We will put them back into */
- /* the variables here so they can be displayed if desired. The */
- /* remote will have calibrated CPU if necessary, and will have done */
- /* all the needed set-up we will have calibrated the cpu locally */
- /* before sending the request, and will grab the counter value right*/
- /* after the connect returns. The remote will grab the counter right*/
- /* after the accept call. This saves the hassle of extra messages */
- /* being sent for the TCP tests. */
-
- recv_response();
-
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote listen done.\n");
- rsr_size = xti_tcp_rr_response->recv_buf_size;
- rss_size = xti_tcp_rr_response->send_buf_size;
- rem_nodelay = xti_tcp_rr_response->no_delay;
- remote_cpu_usage = xti_tcp_rr_response->measure_cpu;
- remote_cpu_rate = xti_tcp_rr_response->cpu_rate;
- /* make sure that port numbers are in network order */
- server.sin_port = (short)xti_tcp_rr_response->data_port_number;
- server.sin_port = htons(server.sin_port);
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- perror("netperf: remote error");
-
- exit(1);
- }
-
- /*Connect up to the remote port on the data socket */
- memset (&server_call, 0, sizeof(server_call));
- server_call.addr.maxlen = sizeof(struct sockaddr_in);
- server_call.addr.len = sizeof(struct sockaddr_in);
- server_call.addr.buf = (char *)&server;
-
- if (t_connect(send_socket,
- &server_call,
- NULL) == INVALID_SOCKET){
- t_error("netperf: send_xti_tcp_rr: data socket connect failed");
- printf(" port: %d\n",ntohs(server.sin_port));
- exit(1);
- }
-
- /* Data Socket set-up is finished. If there were problems, either the */
- /* connect would have failed, or the previous response would have */
- /* indicated a problem. I failed to see the value of the extra */
- /* message after the accept on the remote. If it failed, we'll see it */
- /* here. If it didn't, we might as well start pumping data. */
-
- /* Set-up the test end conditions. For a request/response test, they */
- /* can be either time or transaction based. */
-
- if (test_time) {
- /* The user wanted to end the test after a period of time. */
- times_up = 0;
- trans_remaining = 0;
- start_timer(test_time);
- }
- else {
- /* The tester wanted to send a number of bytes. */
- trans_remaining = test_bytes;
- times_up = 1;
- }
-
- /* The cpu_start routine will grab the current time and possibly */
- /* value of the idle counter for later use in measuring cpu */
- /* utilization and/or service demand and thruput. */
-
- cpu_start(local_cpu_usage);
-
-#ifdef WANT_INTERVALS
- if ((interval_burst) || (demo_mode)) {
- /* zero means that we never pause, so we never should need the */
- /* interval timer, unless we are in demo_mode */
- start_itimer(interval_wate);
- }
- interval_count = interval_burst;
- /* get the signal set for the call to sigsuspend */
- if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &signal_set) != 0) {
- fprintf(where,
- "send_xti_tcp_rr: unable to get sigmask errno %d\n",
- errno);
- fflush(where);
- exit(1);
- }
-#endif /* WANT_INTERVALS */
-
- /* We use an "OR" to control test execution. When the test is */
- /* controlled by time, the byte count check will always return false. */
- /* When the test is controlled by byte count, the time test will */
- /* always return false. When the test is finished, the whole */
- /* expression will go false and we will stop sending data. I think I */
- /* just arbitrarily decrement trans_remaining for the timed test, but */
- /* will not do that just yet... One other question is whether or not */
- /* the send buffer and the receive buffer should be the same buffer. */
-
- while ((!times_up) || (trans_remaining > 0)) {
- /* send the request. we assume that if we use a blocking socket, */
- /* the request will be sent at one shot. */
-
-#ifdef WANT_HISTOGRAM
- /* timestamp just before our call to send, and then again just */
- /* after the receive raj 8/94 */
- HIST_timestamp(&time_one);
-#endif /* WANT_HISTOGRAM */
-
- if((len=t_snd(send_socket,
- send_ring->buffer_ptr,
- req_size,
- 0)) != req_size) {
- if ((errno == EINTR) || (errno == 0)) {
- /* we hit the end of a */
- /* timed test. */
- timed_out = 1;
- break;
- }
- fprintf(where,
- "send_xti_tcp_rr: t_snd: errno %d t_errno %d t_look 0x%.4x\n",
- errno,
- t_errno,
- t_look(send_socket));
- fflush(where);
- exit(1);
- }
- send_ring = send_ring->next;
-
- /* receive the response */
- rsp_bytes_left = rsp_size;
- temp_message_ptr = recv_ring->buffer_ptr;
- while(rsp_bytes_left > 0) {
- if((rsp_bytes_recvd=t_rcv(send_socket,
- temp_message_ptr,
- rsp_bytes_left,
- &xti_flags)) == SOCKET_ERROR) {
- if (errno == EINTR) {
- /* We hit the end of a timed test. */
- timed_out = 1;
- break;
- }
- fprintf(where,
- "send_xti_tcp_rr: t_rcv: errno %d t_errno %d t_look 0x%x\n",
- errno,
- t_errno,
- t_look(send_socket));
- fflush(where);
- exit(1);
- }
- rsp_bytes_left -= rsp_bytes_recvd;
- temp_message_ptr += rsp_bytes_recvd;
- }
- recv_ring = recv_ring->next;
-
- if (timed_out) {
- /* we may have been in a nested while loop - we need */
- /* another call to break. */
- break;
- }
-
-#ifdef WANT_HISTOGRAM
- HIST_timestamp(&time_two);
- HIST_add(time_hist,delta_micro(&time_one,&time_two));
-#endif /* WANT_HISTOGRAM */
-#ifdef WANT_INTERVALS
- if (demo_mode) {
- units_this_tick += 1;
- }
- /* in this case, the interval count is the count-down couter */
- /* to decide to sleep for a little bit */
- if ((interval_burst) && (--interval_count == 0)) {
- /* call sigsuspend and wait for the interval timer to get us */
- /* out */
- if (debug) {
- fprintf(where,"about to suspend\n");
- fflush(where);
- }
- if (sigsuspend(&signal_set) == EFAULT) {
- fprintf(where,
- "send_xti_udp_rr: fault with signal set!\n");
- fflush(where);
- exit(1);
- }
- interval_count = interval_burst;
- }
-#endif /* WANT_INTERVALS */
-
- nummessages++;
- if (trans_remaining) {
- trans_remaining--;
- }
-
- if (debug > 3) {
- if ((nummessages % 100) == 0) {
- fprintf(where,
- "Transaction %d completed\n",
- nummessages);
- fflush(where);
- }
- }
- }
-
-
- /* this call will always give us the elapsed time for the test, and */
- /* will also store-away the necessaries for cpu utilization */
-
- cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */
- /* measured? how long */
- /* did we really run? */
-
- /* Get the statistics from the remote end. The remote will have */
- /* calculated service demand and all those interesting things. If it */
- /* wasn't supposed to care, it will return obvious values. */
-
- recv_response();
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote results obtained\n");
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- perror("netperf: remote error");
-
- exit(1);
- }
-
- /* We now calculate what our thruput was for the test. */
-
- bytes_xferd = (req_size * nummessages) + (rsp_size * nummessages);
- thruput = nummessages/elapsed_time;
-
- if (local_cpu_usage || remote_cpu_usage) {
- /* We must now do a little math for service demand and cpu */
- /* utilization for the system(s) */
- /* Of course, some of the information might be bogus because */
- /* there was no idle counter in the kernel(s). We need to make */
- /* a note of this for the user's benefit...*/
- if (local_cpu_usage) {
- local_cpu_utilization = calc_cpu_util(0.0);
- /* since calc_service demand is doing ms/Kunit we will */
- /* multiply the number of transaction by 1024 to get */
- /* "good" numbers */
- local_service_demand = calc_service_demand((double) nummessages*1024,
- 0.0,
- 0.0,
- 0);
- }
- else {
- local_cpu_utilization = -1.0;
- local_service_demand = -1.0;
- }
-
- if (remote_cpu_usage) {
- remote_cpu_utilization = xti_tcp_rr_result->cpu_util;
- /* since calc_service demand is doing ms/Kunit we will */
- /* multiply the number of transaction by 1024 to get */
- /* "good" numbers */
- remote_service_demand = calc_service_demand((double) nummessages*1024,
- 0.0,
- remote_cpu_utilization,
- xti_tcp_rr_result->num_cpus);
- }
- else {
- remote_cpu_utilization = -1.0;
- remote_service_demand = -1.0;
- }
-
- }
- else {
- /* we were not measuring cpu, for the confidence stuff, we */
- /* should make it -1.0 */
- local_cpu_utilization = -1.0;
- local_service_demand = -1.0;
- remote_cpu_utilization = -1.0;
- remote_service_demand = -1.0;
- }
-
- /* at this point, we want to calculate the confidence information. */
- /* if debugging is on, calculate_confidence will print-out the */
- /* parameters we pass it */
-
- calculate_confidence(confidence_iteration,
- elapsed_time,
- thruput,
- local_cpu_utilization,
- remote_cpu_utilization,
- local_service_demand,
- remote_service_demand);
-
-
- confidence_iteration++;
-
- /* we are now done with the socket, so close it */
- t_close(send_socket);
-
- }
-
- retrieve_confident_values(&elapsed_time,
- &thruput,
- &local_cpu_utilization,
- &remote_cpu_utilization,
- &local_service_demand,
- &remote_service_demand);
-
- /* We are now ready to print all the information. If the user */
- /* has specified zero-level verbosity, we will just print the */
- /* local service demand, or the remote service demand. If the */
- /* user has requested verbosity level 1, he will get the basic */
- /* "streamperf" numbers. If the user has specified a verbosity */
- /* of greater than 1, we will display a veritable plethora of */
- /* background information from outside of this block as it it */
- /* not cpu_measurement specific... */
-
- if (confidence < 0) {
- /* we did not hit confidence, but were we asked to look for it? */
- if (iteration_max > 1) {
- display_confidence();
- }
- }
-
- if (local_cpu_usage || remote_cpu_usage) {
- local_cpu_method = format_cpu_method(cpu_method);
- remote_cpu_method = format_cpu_method(xti_tcp_rr_result->cpu_method);
-
- switch (verbosity) {
- case 0:
- if (local_cpu_usage) {
- fprintf(where,
- cpu_fmt_0,
- local_service_demand,
- local_cpu_method);
- }
- else {
- fprintf(where,
- cpu_fmt_0,
- remote_service_demand,
- remote_cpu_method);
- }
- break;
- case 1:
- case 2:
- if (print_headers) {
- fprintf(where,
- cpu_title,
- local_cpu_method,
- remote_cpu_method);
- }
-
- fprintf(where,
- cpu_fmt_1_line_1, /* the format string */
- lss_size, /* local sendbuf size */
- lsr_size,
- req_size, /* how large were the requests */
- rsp_size, /* guess */
- elapsed_time, /* how long was the test */
- thruput,
- local_cpu_utilization, /* local cpu */
- remote_cpu_utilization, /* remote cpu */
- local_service_demand, /* local service demand */
- remote_service_demand); /* remote service demand */
- fprintf(where,
- cpu_fmt_1_line_2,
- rss_size,
- rsr_size);
- break;
- }
- }
- else {
- /* The tester did not wish to measure service demand. */
-
- switch (verbosity) {
- case 0:
- fprintf(where,
- tput_fmt_0,
- thruput);
- break;
- case 1:
- case 2:
- if (print_headers) {
- fprintf(where,tput_title,format_units());
- }
-
- fprintf(where,
- tput_fmt_1_line_1, /* the format string */
- lss_size,
- lsr_size,
- req_size, /* how large were the requests */
- rsp_size, /* how large were the responses */
- elapsed_time, /* how long did it take */
- thruput);
- fprintf(where,
- tput_fmt_1_line_2,
- rss_size, /* remote recvbuf size */
- rsr_size);
-
- break;
- }
- }
-
- /* it would be a good thing to include information about some of the */
- /* other parameters that may have been set for this test, but at the */
- /* moment, I do not wish to figure-out all the formatting, so I will */
- /* just put this comment here to help remind me that it is something */
- /* that should be done at a later time. */
-
- /* how to handle the verbose information in the presence of */
- /* confidence intervals is yet to be determined... raj 11/94 */
- if (verbosity > 1) {
- /* The user wanted to know it all, so we will give it to him. */
- /* This information will include as much as we can find about */
- /* TCP statistics, the alignments of the sends and receives */
- /* and all that sort of rot... */
-
- fprintf(where,
- ksink_fmt,
- local_send_align,
- remote_recv_offset,
- local_send_offset,
- remote_recv_offset);
-
-#ifdef WANT_HISTOGRAM
- fprintf(where,"\nHistogram of request/response times\n");
- fflush(where);
- HIST_report(time_hist);
-#endif /* WANT_HISTOGRAM */
-
- }
-
-}
-
-void
-send_xti_udp_stream(char remote_host[])
-{
- /**********************************************************************/
- /* */
- /* UDP Unidirectional Send Test */
- /* */
- /**********************************************************************/
- char *tput_title = "\
-Socket Message Elapsed Messages \n\
-Size Size Time Okay Errors Throughput\n\
-bytes bytes secs # # %s/sec\n\n";
-
- char *tput_fmt_0 =
- "%7.2f\n";
-
- char *tput_fmt_1 = "\
-%6d %6d %-7.2f %7d %6d %7.2f\n\
-%6d %-7.2f %7d %7.2f\n\n";
-
-
- char *cpu_title = "\
-Socket Message Elapsed Messages CPU Service\n\
-Size Size Time Okay Errors Throughput Util Demand\n\
-bytes bytes secs # # %s/sec %% %c%c us/KB\n\n";
-
- char *cpu_fmt_0 =
- "%6.2f %c\n";
-
- char *cpu_fmt_1 = "\
-%6d %6d %-7.2f %7d %6d %7.1f %-6.2f %-6.3f\n\
-%6d %-7.2f %7d %7.1f %-6.2f %-6.3f\n\n";
-
- unsigned int messages_recvd;
- unsigned int messages_sent;
- unsigned int failed_sends;
-
- float elapsed_time,
- recv_elapsed,
- local_cpu_utilization,
- remote_cpu_utilization;
-
- float local_service_demand, remote_service_demand;
- double local_thruput, remote_thruput;
- double bytes_sent;
- double bytes_recvd;
-
-
- int len;
- int *message_int_ptr;
- struct ring_elt *send_ring;
- SOCKET data_socket;
-
- unsigned int sum_messages_sent;
- unsigned int sum_messages_recvd;
- unsigned int sum_failed_sends;
- double sum_local_thruput;
-
-#ifdef WANT_INTERVALS
- int interval_count;
- sigset_t signal_set;
-#endif /* WANT_INTERVALS */
-
- struct hostent *hp;
- struct sockaddr_in server;
- unsigned int addr;
-
- struct t_unitdata unitdata;
-
- struct xti_udp_stream_request_struct *xti_udp_stream_request;
- struct xti_udp_stream_response_struct *xti_udp_stream_response;
- struct xti_udp_stream_results_struct *xti_udp_stream_results;
-
- xti_udp_stream_request =
- (struct xti_udp_stream_request_struct *)netperf_request.content.test_specific_data;
- xti_udp_stream_response =
- (struct xti_udp_stream_response_struct *)netperf_response.content.test_specific_data;
- xti_udp_stream_results =
- (struct xti_udp_stream_results_struct *)netperf_response.content.test_specific_data;
-
-#ifdef WANT_HISTOGRAM
- time_hist = HIST_new();
-#endif /* WANT_HISTOGRAM */
-
- /* since we are now disconnected from the code that established the */
- /* control socket, and since we want to be able to use different */
- /* protocols and such, we are passed the name of the remote host and */
- /* must turn that into the test specific addressing information. */
-
- bzero((char *)&server,
- sizeof(server));
-
- /* it would seem that while HP-UX will allow an IP address (as a */
- /* string) in a call to gethostbyname, other, less enlightened */
- /* systems do not. fix from awjacks@ca.sandia.gov raj 10/95 */
- /* order changed to check for IP address first. raj 7/96 */
-
- if ((addr = inet_addr(remote_host)) == SOCKET_ERROR) {
- /* it was not an IP address, try it as a name */
- if ((hp = gethostbyname(remote_host)) == NULL) {
- /* we have no idea what it is */
- fprintf(where,
- "establish_control: could not resolve the destination %s\n",
- remote_host);
- fflush(where);
- exit(1);
- }
- else {
- /* it was a valid remote_host */
- bcopy(hp->h_addr,
- (char *)&server.sin_addr,
- hp->h_length);
- server.sin_family = hp->h_addrtype;
- }
- }
- else {
- /* it was a valid IP address */
- server.sin_addr.s_addr = addr;
- server.sin_family = AF_INET;
- }
-
- if ( print_headers ) {
- fprintf(where,"UDP UNIDIRECTIONAL SEND TEST");
- fprintf(where," to %s", remote_host);
- if (iteration_max > 1) {
- fprintf(where,
- " : +/-%3.1f%% @ %2d%% conf.",
- interval/0.02,
- confidence_level);
- }
- if (loc_sndavoid ||
- loc_rcvavoid ||
- rem_sndavoid ||
- rem_rcvavoid) {
- fprintf(where," : copy avoidance");
- }
-#ifdef WANT_HISTOGRAM
- fprintf(where," : histogram");
-#endif /* WANT_HISTOGRAM */
-#ifdef WANT_INTERVALS
- fprintf(where," : interval");
-#endif /* WANT_INTERVALS */
-#ifdef DIRTY
- fprintf(where," : dirty data");
-#endif /* DIRTY */
- fprintf(where,"\n");
- }
-
- send_ring = NULL;
- confidence_iteration = 1;
- init_stat();
- sum_messages_sent = 0;
- sum_messages_recvd = 0;
- sum_failed_sends = 0;
- sum_local_thruput = 0.0;
-
- /* we have a great-big while loop which controls the number of times */
- /* we run a particular test. this is for the calculation of a */
- /* confidence interval (I really should have stayed awake during */
- /* probstats :). If the user did not request confidence measurement */
- /* (no confidence is the default) then we will only go though the */
- /* loop once. the confidence stuff originates from the folks at IBM */
-
- while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
- (confidence_iteration <= iteration_min)) {
-
- /* initialize a few counters. we have to remember that we might be */
- /* going through the loop more than once. */
- messages_sent = 0;
- messages_recvd = 0;
- failed_sends = 0;
- times_up = 0;
-
- /*set up the data socket */
- data_socket = create_xti_endpoint(loc_xti_device);
-
- if (data_socket == INVALID_SOCKET) {
- perror("send_xti_udp_stream: create_xti_endpoint");
- exit(1);
- }
-
- if (t_bind(data_socket, NULL, NULL) == SOCKET_ERROR) {
- t_error("send_xti_udp_stream: t_bind");
- exit(1);
- }
-
- /* now, we want to see if we need to set the send_size */
- if (send_size == 0) {
- if (lss_size > 0) {
- send_size = lss_size;
- }
- else {
- send_size = 4096;
- }
- }
-
- /* set-up the data buffer with the requested alignment and offset, */
- /* most of the numbers here are just a hack to pick something nice */
- /* and big in an attempt to never try to send a buffer a second time */
- /* before it leaves the node...unless the user set the width */
- /* explicitly. */
- if (send_width == 0) send_width = 32;
-
- if (send_ring == NULL ) {
- send_ring = allocate_buffer_ring(send_width,
- send_size,
- local_send_align,
- local_send_offset);
- }
-
-
- /* if the user supplied a cpu rate, this call will complete rather */
- /* quickly, otherwise, the cpu rate will be retured to us for */
- /* possible display. The Library will keep it's own copy of this data */
- /* for use elsewhere. We will only display it. (Does that make it */
- /* "opaque" to us?) */
-
- if (local_cpu_usage)
- local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
-
- /* Tell the remote end to set up the data connection. The server */
- /* sends back the port number and alters the socket parameters there. */
- /* Of course this is a datagram service so no connection is actually */
- /* set up, the server just sets up the socket and binds it. */
-
- netperf_request.content.request_type = DO_XTI_UDP_STREAM;
- xti_udp_stream_request->recv_buf_size = rsr_size;
- xti_udp_stream_request->message_size = send_size;
- xti_udp_stream_request->recv_alignment = remote_recv_align;
- xti_udp_stream_request->recv_offset = remote_recv_offset;
- xti_udp_stream_request->measure_cpu = remote_cpu_usage;
- xti_udp_stream_request->cpu_rate = remote_cpu_rate;
- xti_udp_stream_request->test_length = test_time;
- xti_udp_stream_request->so_rcvavoid = rem_rcvavoid;
- xti_udp_stream_request->so_sndavoid = rem_sndavoid;
-
- strcpy(xti_udp_stream_request->xti_device, rem_xti_device);
-
-#ifdef __alpha
-
- /* ok - even on a DEC box, strings are strings. I didn't really want */
- /* to ntohl the words of a string. since I don't want to teach the */
- /* send_ and recv_ _request and _response routines about the types, */
- /* I will put "anti-ntohl" calls here. I imagine that the "pure" */
- /* solution would be to use XDR, but I am still leary of being able */
- /* to find XDR libs on all platforms I want running netperf. raj */
- {
- int *charword;
- int *initword;
- int *lastword;
-
- initword = (int *) xti_udp_stream_request->xti_device;
- lastword = initword + ((strlen(rem_xti_device) + 3) / 4);
-
- for (charword = initword;
- charword < lastword;
- charword++) {
-
- *charword = ntohl(*charword);
- }
- }
-#endif /* __alpha */
-
- send_request();
-
- recv_response();
-
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"send_xti_udp_stream: remote data connection done.\n");
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- perror("send_xti_udp_stream: error on remote");
- exit(1);
- }
-
- /* Place the port number returned by the remote into the sockaddr */
- /* structure so our sends can be sent to the correct place. Also get */
- /* some of the returned socket buffer information for user display. */
-
- /* make sure that port numbers are in the proper order */
- server.sin_port = (short)xti_udp_stream_response->data_port_number;
- server.sin_port = htons(server.sin_port);
- rsr_size = xti_udp_stream_response->recv_buf_size;
- rss_size = xti_udp_stream_response->send_buf_size;
- remote_cpu_rate = xti_udp_stream_response->cpu_rate;
-
- /* it would seem that XTI does not allow the expedient of */
- /* "connecting" a UDP end-point the way BSD does. so, we will do */
- /* everything with t_sndudata and t_rcvudata. Our "virtual" */
- /* connect here will be to assign the destination portion of the */
- /* t_unitdata struct here, where we would have otherwise called */
- /* t_connect() raj 3/95 */
-
- memset (&unitdata, 0, sizeof(unitdata));
- unitdata.addr.maxlen = sizeof(struct sockaddr_in);
- unitdata.addr.len = sizeof(struct sockaddr_in);
- unitdata.addr.buf = (char *)&server;
-
- /* we don't use any options, so might as well set that part here */
- /* too */
-
- unitdata.opt.maxlen = 0;
- unitdata.opt.len = 0;
- unitdata.opt.buf = NULL;
-
- /* we need to initialize the send buffer for the first time as */
- /* well since we move to the next pointer after the send call. */
-
- unitdata.udata.maxlen = send_size;
- unitdata.udata.len = send_size;
- unitdata.udata.buf = send_ring->buffer_ptr;
-
- /* set up the timer to call us after test_time. one of these days, */
- /* it might be nice to figure-out a nice reliable way to have the */
- /* test controlled by a byte count as well, but since UDP is not */
- /* reliable, that could prove difficult. so, in the meantime, we */
- /* only allow a XTI_UDP_STREAM test to be a timed test. */
-
- if (test_time) {
- times_up = 0;
- start_timer(test_time);
- }
- else {
- fprintf(where,"Sorry, XTI_UDP_STREAM tests must be timed.\n");
- fflush(where);
- exit(1);
- }
-
- /* Get the start count for the idle counter and the start time */
-
- cpu_start(local_cpu_usage);
-
-#ifdef WANT_INTERVALS
- if ((interval_burst) || (demo_mode)) {
- /* zero means that we never pause, so we never should need the */
- /* interval timer, unless we are in demo_mode */
- start_itimer(interval_wate);
- }
- interval_count = interval_burst;
- /* get the signal set for the call to sigsuspend */
- if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &signal_set) != 0) {
- fprintf(where,
- "send_xti_udp_stream: unable to get sigmask errno %d\n",
- errno);
- fflush(where);
- exit(1);
- }
-#endif /* WANT_INTERVALS */
-
- /* Send datagrams like there was no tomorrow. at somepoint it might */
- /* be nice to set this up so that a quantity of bytes could be sent, */
- /* but we still need some sort of end of test trigger on the receive */
- /* side. that could be a select with a one second timeout, but then */
- /* if there is a test where none of the data arrives for awile and */
- /* then starts again, we would end the test too soon. something to */
- /* think about... */
- while (!times_up) {
-
-#ifdef DIRTY
- /* we want to dirty some number of consecutive integers in the buffer */
- /* we are about to send. we may also want to bring some number of */
- /* them cleanly into the cache. The clean ones will follow any dirty */
- /* ones into the cache. */
-
- access_buffer(send_ring->buffer_ptr,
- send_size,
- loc_dirty_count,
- loc_clean_count);
-
-#endif /* DIRTY */
-
-#ifdef WANT_HISTOGRAM
- HIST_timestamp(&time_one);
-#endif /* WANT_HISTOGRAM */
-
- if ((t_sndudata(data_socket,
- &unitdata)) != 0) {
- if (errno == EINTR)
- break;
- if (errno == ENOBUFS) {
- failed_sends++;
- continue;
- }
- perror("xti_udp_send: data send error");
- t_error("xti_udp_send: data send error");
- exit(1);
- }
- messages_sent++;
-
- /* now we want to move our pointer to the next position in the */
- /* data buffer...and update the unitdata structure */
-
- send_ring = send_ring->next;
- unitdata.udata.buf = send_ring->buffer_ptr;
-
-#ifdef WANT_HISTOGRAM
- /* get the second timestamp */
- HIST_timestamp(&time_two);
- HIST_add(time_hist,delta_micro(&time_one,&time_two));
-#endif /* WANT_HISTOGRAM */
-#ifdef WANT_INTERVALS
- if (demo_mode) {
- units_this_tick += send_size;
- }
- /* in this case, the interval count is the count-down couter */
- /* to decide to sleep for a little bit */
- if ((interval_burst) && (--interval_count == 0)) {
- /* call sigsuspend and wait for the interval timer to get us */
- /* out */
- if (debug) {
- fprintf(where,"about to suspend\n");
- fflush(where);
- }
- if (sigsuspend(&signal_set) == EFAULT) {
- fprintf(where,
- "send_xti_udp_stream: fault with signal set!\n");
- fflush(where);
- exit(1);
- }
- interval_count = interval_burst;
- }
-#endif /* WANT_INTERVALS */
-
- }
-
- /* This is a timed test, so the remote will be returning to us after */
- /* a time. We should not need to send any "strange" messages to tell */
- /* the remote that the test is completed, unless we decide to add a */
- /* number of messages to the test. */
-
- /* the test is over, so get stats and stuff */
- cpu_stop(local_cpu_usage,
- &elapsed_time);
-
- /* Get the statistics from the remote end */
- recv_response();
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"send_xti_udp_stream: remote results obtained\n");
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- perror("send_xti_udp_stream: error on remote");
- exit(1);
- }
-
- bytes_sent = (double) send_size * (double) messages_sent;
- local_thruput = calc_thruput(bytes_sent);
-
- messages_recvd = xti_udp_stream_results->messages_recvd;
- bytes_recvd = (double) send_size * (double) messages_recvd;
-
- /* we asume that the remote ran for as long as we did */
-
- remote_thruput = calc_thruput(bytes_recvd);
-
- /* print the results for this socket and message size */
-
- if (local_cpu_usage || remote_cpu_usage) {
- /* We must now do a little math for service demand and cpu */
- /* utilization for the system(s) We pass zeros for the local */
- /* cpu utilization and elapsed time to tell the routine to use */
- /* the libraries own values for those. */
- if (local_cpu_usage) {
- local_cpu_utilization = calc_cpu_util(0.0);
- /* shouldn't this really be based on bytes_recvd, since that is */
- /* the effective throughput of the test? I think that it should, */
- /* so will make the change raj 11/94 */
- local_service_demand = calc_service_demand(bytes_recvd,
- 0.0,
- 0.0,
- 0);
- }
- else {
- local_cpu_utilization = -1.0;
- local_service_demand = -1.0;
- }
-
- /* The local calculations could use variables being kept by */
- /* the local netlib routines. The remote calcuations need to */
- /* have a few things passed to them. */
- if (remote_cpu_usage) {
- remote_cpu_utilization = xti_udp_stream_results->cpu_util;
- remote_service_demand = calc_service_demand(bytes_recvd,
- 0.0,
- remote_cpu_utilization,
- xti_udp_stream_results->num_cpus);
- }
- else {
- remote_cpu_utilization = -1.0;
- remote_service_demand = -1.0;
- }
- }
- else {
- /* we were not measuring cpu, for the confidence stuff, we */
- /* should make it -1.0 */
- local_cpu_utilization = -1.0;
- local_service_demand = -1.0;
- remote_cpu_utilization = -1.0;
- remote_service_demand = -1.0;
- }
-
- /* at this point, we want to calculate the confidence information. */
- /* if debugging is on, calculate_confidence will print-out the */
- /* parameters we pass it */
-
- calculate_confidence(confidence_iteration,
- elapsed_time,
- remote_thruput,
- local_cpu_utilization,
- remote_cpu_utilization,
- local_service_demand,
- remote_service_demand);
-
- /* since the routine calculate_confidence is rather generic, and */
- /* we have a few other parms of interest, we will do a little work */
- /* here to caclulate their average. */
- sum_messages_sent += messages_sent;
- sum_messages_recvd += messages_recvd;
- sum_failed_sends += failed_sends;
- sum_local_thruput += local_thruput;
-
- confidence_iteration++;
-
- /* this datapoint is done, so we don't need the socket any longer */
- close(data_socket);
-
- }
-
- /* we should reach this point once the test is finished */
-
- retrieve_confident_values(&elapsed_time,
- &remote_thruput,
- &local_cpu_utilization,
- &remote_cpu_utilization,
- &local_service_demand,
- &remote_service_demand);
-
- /* some of the interesting values aren't covered by the generic */
- /* confidence routine */
- messages_sent = sum_messages_sent / (confidence_iteration -1);
- messages_recvd = sum_messages_recvd / (confidence_iteration -1);
- failed_sends = sum_failed_sends / (confidence_iteration -1);
- local_thruput = sum_local_thruput / (confidence_iteration -1);
-
- /* We are now ready to print all the information. If the user */
- /* has specified zero-level verbosity, we will just print the */
- /* local service demand, or the remote service demand. If the */
- /* user has requested verbosity level 1, he will get the basic */
- /* "streamperf" numbers. If the user has specified a verbosity */
- /* of greater than 1, we will display a veritable plethora of */
- /* background information from outside of this block as it it */
- /* not cpu_measurement specific... */
-
-
- if (confidence < 0) {
- /* we did not hit confidence, but were we asked to look for it? */
- if (iteration_max > 1) {
- display_confidence();
- }
- }
-
- if (local_cpu_usage || remote_cpu_usage) {
- local_cpu_method = format_cpu_method(cpu_method);
- remote_cpu_method = format_cpu_method(xti_udp_stream_results->cpu_method);
-
- switch (verbosity) {
- case 0:
- if (local_cpu_usage) {
- fprintf(where,
- cpu_fmt_0,
- local_service_demand,
- local_cpu_method);
- }
- else {
- fprintf(where,
- cpu_fmt_0,
- remote_service_demand,
- local_cpu_method);
- }
- break;
- case 1:
- case 2:
- if (print_headers) {
- fprintf(where,
- cpu_title,
- format_units(),
- local_cpu_method,
- remote_cpu_method);
- }
-
- fprintf(where,
- cpu_fmt_1, /* the format string */
- lss_size, /* local sendbuf size */
- send_size, /* how large were the sends */
- elapsed_time, /* how long was the test */
- messages_sent,
- failed_sends,
- local_thruput, /* what was the xfer rate */
- local_cpu_utilization, /* local cpu */
- local_service_demand, /* local service demand */
- rsr_size,
- elapsed_time,
- messages_recvd,
- remote_thruput,
- remote_cpu_utilization, /* remote cpu */
- remote_service_demand); /* remote service demand */
- break;
- }
- }
- else {
- /* The tester did not wish to measure service demand. */
- switch (verbosity) {
- case 0:
- fprintf(where,
- tput_fmt_0,
- local_thruput);
- break;
- case 1:
- case 2:
- if (print_headers) {
- fprintf(where,tput_title,format_units());
- }
- fprintf(where,
- tput_fmt_1, /* the format string */
- lss_size, /* local sendbuf size */
- send_size, /* how large were the sends */
- elapsed_time, /* how long did it take */
- messages_sent,
- failed_sends,
- local_thruput,
- rsr_size, /* remote recvbuf size */
- elapsed_time,
- messages_recvd,
- remote_thruput);
- break;
- }
- }
-
- fflush(where);
-#ifdef WANT_HISTOGRAM
- if (verbosity > 1) {
- fprintf(where,"\nHistogram of time spent in send() call\n");
- fflush(where);
- HIST_report(time_hist);
- }
-#endif /* WANT_HISTOGRAM */
-
-}
-
-
- /* this routine implements the receive side (netserver) of the */
- /* XTI_UDP_STREAM performance test. */
-
-void
-recv_xti_udp_stream()
-{
- struct ring_elt *recv_ring;
-
- struct t_bind bind_req, bind_resp;
- struct t_unitdata unitdata;
- int flags = 0;
-
- struct sockaddr_in myaddr_in;
- struct sockaddr_in fromaddr_in;
-
- SOCKET s_data;
- int addrlen;
- unsigned int bytes_received = 0;
- float elapsed_time;
-
- unsigned int message_size;
- unsigned int messages_recvd = 0;
-
- struct xti_udp_stream_request_struct *xti_udp_stream_request;
- struct xti_udp_stream_response_struct *xti_udp_stream_response;
- struct xti_udp_stream_results_struct *xti_udp_stream_results;
-
- xti_udp_stream_request =
- (struct xti_udp_stream_request_struct *)netperf_request.content.test_specific_data;
- xti_udp_stream_response =
- (struct xti_udp_stream_response_struct *)netperf_response.content.test_specific_data;
- xti_udp_stream_results =
- (struct xti_udp_stream_results_struct *)netperf_response.content.test_specific_data;
-
- if (debug) {
- fprintf(where,"netserver: recv_xti_udp_stream: entered...\n");
- fflush(where);
- }
-
- /* We want to set-up the listen socket with all the desired */
- /* parameters and then let the initiator know that all is ready. If */
- /* socket size defaults are to be used, then the initiator will have */
- /* sent us 0's. If the socket sizes cannot be changed, then we will */
- /* send-back what they are. If that information cannot be determined, */
- /* then we send-back -1's for the sizes. If things go wrong for any */
- /* reason, we will drop back ten yards and punt. */
-
- /* If anything goes wrong, we want the remote to know about it. It */
- /* would be best if the error that the remote reports to the user is */
- /* the actual error we encountered, rather than some bogus unexpected */
- /* response type message. */
-
- if (debug > 1) {
- fprintf(where,"recv_xti_udp_stream: setting the response type...\n");
- fflush(where);
- }
-
- netperf_response.content.response_type = XTI_UDP_STREAM_RESPONSE;
-
- if (debug > 2) {
- fprintf(where,"recv_xti_udp_stream: the response type is set...\n");
- fflush(where);
- }
-
- /* We now alter the message_ptr variable to be at the desired */
- /* alignment with the desired offset. */
-
- if (debug > 1) {
- fprintf(where,"recv_xti_udp_stream: requested alignment of %d\n",
- xti_udp_stream_request->recv_alignment);
- fflush(where);
- }
-
- if (recv_width == 0) recv_width = 1;
-
- recv_ring = allocate_buffer_ring(recv_width,
- xti_udp_stream_request->message_size,
- xti_udp_stream_request->recv_alignment,
- xti_udp_stream_request->recv_offset);
-
- if (debug > 1) {
- fprintf(where,"recv_xti_udp_stream: receive alignment and offset set...\n");
- fflush(where);
- }
-
- /* Let's clear-out our sockaddr for the sake of cleanlines. Then we */
- /* can put in OUR values !-) At some point, we may want to nail this */
- /* socket to a particular network-level address, but for now, */
- /* INADDR_ANY should be just fine. */
-
- bzero((char *)&myaddr_in,
- sizeof(myaddr_in));
- myaddr_in.sin_family = AF_INET;
- myaddr_in.sin_addr.s_addr = INADDR_ANY;
- myaddr_in.sin_port = 0;
-
- /* Grab a socket to listen on, and then listen on it. */
-
- if (debug > 1) {
- fprintf(where,"recv_xti_udp_stream: grabbing a socket...\n");
- fflush(where);
- }
-
- /* create_xti_endpoint expects to find some things in the global */
- /* variables, so set the globals based on the values in the request. */
- /* once the socket has been created, we will set the response values */
- /* based on the updated value of those globals. raj 7/94 */
- lsr_size = xti_udp_stream_request->recv_buf_size;
- loc_rcvavoid = xti_udp_stream_request->so_rcvavoid;
- loc_sndavoid = xti_udp_stream_request->so_sndavoid;
-
-#ifdef __alpha
-
- /* ok - even on a DEC box, strings are strings. I din't really want */
- /* to ntohl the words of a string. since I don't want to teach the */
- /* send_ and recv_ _request and _response routines about the types, */
- /* I will put "anti-ntohl" calls here. I imagine that the "pure" */
- /* solution would be to use XDR, but I am still leary of being able */
- /* to find XDR libs on all platforms I want running netperf. raj */
- {
- int *charword;
- int *initword;
- int *lastword;
-
- initword = (int *) xti_udp_stream_request->xti_device;
- lastword = initword + ((xti_udp_stream_request->dev_name_len + 3) / 4);
-
- for (charword = initword;
- charword < lastword;
- charword++) {
-
- *charword = htonl(*charword);
- }
- }
-
-#endif /* __alpha */
-
- s_data = create_xti_endpoint(xti_udp_stream_request->xti_device);
-
- if (s_data == INVALID_SOCKET) {
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
-
- /* Let's get an address assigned to this socket so we can tell the */
- /* initiator how to reach the data socket. There may be a desire to */
- /* nail this socket to a specific IP address in a multi-homed, */
- /* multi-connection situation, but for now, we'll ignore the issue */
- /* and concentrate on single connection testing. */
-
- bind_req.addr.maxlen = sizeof(struct sockaddr_in);
- bind_req.addr.len = sizeof(struct sockaddr_in);
- bind_req.addr.buf = (char *)&myaddr_in;
- bind_req.qlen = 1;
-
- bind_resp.addr.maxlen = sizeof(struct sockaddr_in);
- bind_resp.addr.len = sizeof(struct sockaddr_in);
- bind_resp.addr.buf = (char *)&myaddr_in;
- bind_resp.qlen = 1;
-
- if (t_bind(s_data,
- &bind_req,
- &bind_resp) == SOCKET_ERROR) {
- netperf_response.content.serv_errno = t_errno;
- send_response();
-
- exit(1);
- }
-
- xti_udp_stream_response->test_length =
- xti_udp_stream_request->test_length;
-
- /* Now myaddr_in contains the port and the internet address this is */
- /* returned to the sender also implicitly telling the sender that the */
- /* socket buffer sizing has been done. */
-
- xti_udp_stream_response->data_port_number =
- (int) ntohs(myaddr_in.sin_port);
- netperf_response.content.serv_errno = 0;
-
- /* But wait, there's more. If the initiator wanted cpu measurements, */
- /* then we must call the calibrate routine, which will return the max */
- /* rate back to the initiator. If the CPU was not to be measured, or */
- /* something went wrong with the calibration, we will return a -1 to */
- /* the initiator. */
-
- xti_udp_stream_response->cpu_rate = 0.0; /* assume no cpu */
- xti_udp_stream_response->measure_cpu = 0;
- if (xti_udp_stream_request->measure_cpu) {
- /* We will pass the rate into the calibration routine. If the */
- /* user did not specify one, it will be 0.0, and we will do a */
- /* "real" calibration. Otherwise, all it will really do is */
- /* store it away... */
- xti_udp_stream_response->measure_cpu = 1;
- xti_udp_stream_response->cpu_rate =
- calibrate_local_cpu(xti_udp_stream_request->cpu_rate);
- }
-
- message_size = xti_udp_stream_request->message_size;
- test_time = xti_udp_stream_request->test_length;
-
- /* before we send the response back to the initiator, pull some of */
- /* the socket parms from the globals */
- xti_udp_stream_response->send_buf_size = lss_size;
- xti_udp_stream_response->recv_buf_size = lsr_size;
- xti_udp_stream_response->so_rcvavoid = loc_rcvavoid;
- xti_udp_stream_response->so_sndavoid = loc_sndavoid;
-
- /* since we are going to call t_rcvudata() instead of t_rcv() we */
- /* need to init the unitdata structure raj 3/95 */
-
- unitdata.addr.maxlen = sizeof(fromaddr_in);
- unitdata.addr.len = sizeof(fromaddr_in);
- unitdata.addr.buf = (char *)&fromaddr_in;
-
- unitdata.opt.maxlen = 0;
- unitdata.opt.len = 0;
- unitdata.opt.buf = NULL;
-
- unitdata.udata.maxlen = xti_udp_stream_request->message_size;
- unitdata.udata.len = xti_udp_stream_request->message_size;
- unitdata.udata.buf = recv_ring->buffer_ptr;
-
- send_response();
-
- /* Now it's time to start receiving data on the connection. We will */
- /* first grab the apropriate counters and then start grabbing. */
-
- cpu_start(xti_udp_stream_request->measure_cpu);
-
- /* The loop will exit when the timer pops, or if we happen to recv a */
- /* message of less than send_size bytes... */
-
- times_up = 0;
- start_timer(test_time + PAD_TIME);
-
- if (debug) {
- fprintf(where,"recv_xti_udp_stream: about to enter inner sanctum.\n");
- fflush(where);
- }
-
- while (!times_up) {
-#ifdef RAJ_DEBUG
- if (debug) {
- fprintf(where,"t_rcvudata, errno %d, t_errno %d",
- errno,
- t_errno);
- fprintf(where," after %d messages\n",messages_recvd);
- fprintf(where,"addrmax %d addrlen %d addrbuf %x\n",
- unitdata.addr.maxlen,
- unitdata.addr.len,
- unitdata.addr.buf);
- fprintf(where,"optmax %d optlen %d optbuf %x\n",
- unitdata.opt.maxlen,
- unitdata.opt.len,
- unitdata.opt.buf);
- fprintf(where,"udatamax %d udatalen %d udatabuf %x\n",
- unitdata.udata.maxlen,
- unitdata.udata.len,
- unitdata.udata.buf);
- fflush(where);
- }
-#endif /* RAJ_DEBUG */
- if (t_rcvudata(s_data,
- &unitdata,
- &flags) != 0) {
- if (errno == TNODATA) {
- continue;
- }
- if (errno != EINTR) {
- netperf_response.content.serv_errno = t_errno;
- send_response();
- exit(1);
- }
- break;
- }
- messages_recvd++;
- recv_ring = recv_ring->next;
- unitdata.udata.buf = recv_ring->buffer_ptr;
- }
-
- if (debug) {
- fprintf(where,"recv_xti_udp_stream: got %d messages.\n",messages_recvd);
- fflush(where);
- }
-
-
- /* The loop now exits due timer or < send_size bytes received. */
-
- cpu_stop(xti_udp_stream_request->measure_cpu,&elapsed_time);
-
- if (times_up) {
- /* we ended on a timer, subtract the PAD_TIME */
- elapsed_time -= (float)PAD_TIME;
- }
- else {
- stop_timer();
- }
-
- if (debug) {
- fprintf(where,"recv_xti_udp_stream: test ended in %f seconds.\n",elapsed_time);
- fflush(where);
- }
-
- bytes_received = (messages_recvd * message_size);
-
- /* send the results to the sender */
-
- if (debug) {
- fprintf(where,
- "recv_xti_udp_stream: got %d bytes\n",
- bytes_received);
- fflush(where);
- }
-
- netperf_response.content.response_type = XTI_UDP_STREAM_RESULTS;
- xti_udp_stream_results->bytes_received = bytes_received;
- xti_udp_stream_results->messages_recvd = messages_recvd;
- xti_udp_stream_results->elapsed_time = elapsed_time;
- xti_udp_stream_results->cpu_method = cpu_method;
- if (xti_udp_stream_request->measure_cpu) {
- xti_udp_stream_results->cpu_util = calc_cpu_util(elapsed_time);
- }
- else {
- xti_udp_stream_results->cpu_util = -1.0;
- }
-
- if (debug > 1) {
- fprintf(where,
- "recv_xti_udp_stream: test complete, sending results.\n");
- fflush(where);
- }
-
- send_response();
-
-}
-
-void send_xti_udp_rr(char remote_host[])
-{
-
- char *tput_title = "\
-Local /Remote\n\
-Socket Size Request Resp. Elapsed Trans.\n\
-Send Recv Size Size Time Rate \n\
-bytes Bytes bytes bytes secs. per sec \n\n";
-
- char *tput_fmt_0 =
- "%7.2f\n";
-
- char *tput_fmt_1_line_1 = "\
-%-6d %-6d %-6d %-6d %-6.2f %7.2f \n";
- char *tput_fmt_1_line_2 = "\
-%-6d %-6d\n";
-
- char *cpu_title = "\
-Local /Remote\n\
-Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\
-Send Recv Size Size Time Rate local remote local remote\n\
-bytes bytes bytes bytes secs. per sec %% %c %% %c us/Tr us/Tr\n\n";
-
- char *cpu_fmt_0 =
- "%6.3f %c\n";
-
- char *cpu_fmt_1_line_1 = "\
-%-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f\n";
-
- char *cpu_fmt_1_line_2 = "\
-%-6d %-6d\n";
-
- char *ksink_fmt = "\
-Alignment Offset\n\
-Local Remote Local Remote\n\
-Send Recv Send Recv\n\
-%5d %5d %5d %5d\n";
-
-
- float elapsed_time;
-
- struct ring_elt *send_ring;
- struct ring_elt *recv_ring;
-
- struct t_bind bind_req, bind_resp;
- struct t_unitdata unitdata;
- struct t_unitdata send_unitdata;
- struct t_unitdata recv_unitdata;
- int flags = 0;
-
- int len;
- int nummessages;
- SOCKET send_socket;
- int trans_remaining;
- int bytes_xferd;
-
- int rsp_bytes_recvd;
-
- float local_cpu_utilization;
- float local_service_demand;
- float remote_cpu_utilization;
- float remote_service_demand;
- double thruput;
-
- struct hostent *hp;
- struct sockaddr_in server, myaddr_in;
- unsigned int addr;
- int addrlen;
-
- struct xti_udp_rr_request_struct *xti_udp_rr_request;
- struct xti_udp_rr_response_struct *xti_udp_rr_response;
- struct xti_udp_rr_results_struct *xti_udp_rr_result;
-
-#ifdef WANT_INTERVALS
- int interval_count;
- sigset_t signal_set;
-#endif /* WANT_INTERVALS */
-
- xti_udp_rr_request =
- (struct xti_udp_rr_request_struct *)netperf_request.content.test_specific_data;
- xti_udp_rr_response =
- (struct xti_udp_rr_response_struct *)netperf_response.content.test_specific_data;
- xti_udp_rr_result =
- (struct xti_udp_rr_results_struct *)netperf_response.content.test_specific_data;
-
-#ifdef WANT_HISTOGRAM
- time_hist = HIST_new();
-#endif
-
- /* since we are now disconnected from the code that established the */
- /* control socket, and since we want to be able to use different */
- /* protocols and such, we are passed the name of the remote host and */
- /* must turn that into the test specific addressing information. */
-
- bzero((char *)&server,
- sizeof(server));
-
- /* it would seem that while HP-UX will allow an IP address (as a */
- /* string) in a call to gethostbyname, other, less enlightened */
- /* systems do not. fix from awjacks@ca.sandia.gov raj 10/95 */
- /* order changed to check for IP address first. raj 7/96 */
-
- if ((addr = inet_addr(remote_host)) == SOCKET_ERROR) {
- /* it was not an IP address, try it as a name */
- if ((hp = gethostbyname(remote_host)) == NULL) {
- /* we have no idea what it is */
- fprintf(where,
- "establish_control: could not resolve the destination %s\n",
- remote_host);
- fflush(where);
- exit(1);
- }
- else {
- /* it was a valid remote_host */
- bcopy(hp->h_addr,
- (char *)&server.sin_addr,
- hp->h_length);
- server.sin_family = hp->h_addrtype;
- }
- }
- else {
- /* it was a valid IP address */
- server.sin_addr.s_addr = addr;
- server.sin_family = AF_INET;
- }
-
- if ( print_headers ) {
- fprintf(where,"XTI UDP REQUEST/RESPONSE TEST");
- fprintf(where," to %s", remote_host);
- if (iteration_max > 1) {
- fprintf(where,
- " : +/-%3.1f%% @ %2d%% conf.",
- interval/0.02,
- confidence_level);
- }
- if (loc_sndavoid ||
- loc_rcvavoid ||
- rem_sndavoid ||
- rem_rcvavoid) {
- fprintf(where," : copy avoidance");
- }
-#ifdef WANT_HISTOGRAM
- fprintf(where," : histogram");
-#endif /* WANT_HISTOGRAM */
-#ifdef WANT_INTERVALS
- fprintf(where," : interval");
-#endif /* WANT_INTERVALS */
-#ifdef DIRTY
- fprintf(where," : dirty data");
-#endif /* DIRTY */
- fprintf(where,"\n");
- }
-
- /* initialize a few counters */
-
- send_ring = NULL;
- recv_ring = NULL;
- nummessages = 0;
- bytes_xferd = 0;
- times_up = 0;
- confidence_iteration = 1;
- init_stat();
-
-
- /* we have a great-big while loop which controls the number of times */
- /* we run a particular test. this is for the calculation of a */
- /* confidence interval (I really should have stayed awake during */
- /* probstats :). If the user did not request confidence measurement */
- /* (no confidence is the default) then we will only go though the */
- /* loop once. the confidence stuff originates from the folks at IBM */
-
- while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
- (confidence_iteration <= iteration_min)) {
-
- nummessages = 0;
- bytes_xferd = 0.0;
- times_up = 0;
- trans_remaining = 0;
-
- /* set-up the data buffers with the requested alignment and offset */
-
- if (send_width == 0) send_width = 1;
- if (recv_width == 0) recv_width = 1;
-
- if (send_ring == NULL) {
- send_ring = allocate_buffer_ring(send_width,
- req_size,
- local_send_align,
- local_send_offset);
- }
-
- if (recv_ring == NULL) {
- recv_ring = allocate_buffer_ring(recv_width,
- rsp_size,
- local_recv_align,
- local_recv_offset);
- }
-
- /* since we are going to call t_rcvudata() instead of t_rcv() we */
- /* need to init the unitdata structure raj 8/95 */
-
- memset (&recv_unitdata, 0, sizeof(recv_unitdata));
- recv_unitdata.addr.maxlen = sizeof(struct sockaddr_in);
- recv_unitdata.addr.len = sizeof(struct sockaddr_in);
- recv_unitdata.addr.buf = (char *)&server;
-
- recv_unitdata.opt.maxlen = 0;
- recv_unitdata.opt.len = 0;
- recv_unitdata.opt.buf = NULL;
-
- recv_unitdata.udata.maxlen = rsp_size;
- recv_unitdata.udata.len = rsp_size;
- recv_unitdata.udata.buf = recv_ring->buffer_ptr;
-
- /* since we are going to call t_sndudata() instead of t_snd() we */
- /* need to init the unitdata structure raj 8/95 */
-
- memset (&send_unitdata, 0, sizeof(send_unitdata));
- send_unitdata.addr.maxlen = sizeof(struct sockaddr_in);
- send_unitdata.addr.len = sizeof(struct sockaddr_in);
- send_unitdata.addr.buf = (char *)&server;
-
- send_unitdata.opt.maxlen = 0;
- send_unitdata.opt.len = 0;
- send_unitdata.opt.buf = NULL;
-
- send_unitdata.udata.maxlen = req_size;
- send_unitdata.udata.len = req_size;
- send_unitdata.udata.buf = send_ring->buffer_ptr;
-
- /*set up the data socket */
- send_socket = create_xti_endpoint(loc_xti_device);
-
- if (send_socket == INVALID_SOCKET){
- perror("netperf: send_xti_udp_rr: udp rr data socket");
- exit(1);
- }
-
- if (debug) {
- fprintf(where,"send_xti_udp_rr: send_socket obtained...\n");
- }
-
- /* it would seem that with XTI, there is no implicit bind */
- /* so we have to make a call to t_bind. this is not */
- /* terribly convenient, but I suppose that "standard is better */
- /* than better" :) raj 2/95 */
-
- if (t_bind(send_socket, NULL, NULL) == SOCKET_ERROR) {
- t_error("send_xti_tcp_stream: t_bind");
- exit(1);
- }
-
- /* If the user has requested cpu utilization measurements, we must */
- /* calibrate the cpu(s). We will perform this task within the tests */
- /* themselves. If the user has specified the cpu rate, then */
- /* calibrate_local_cpu will return rather quickly as it will have */
- /* nothing to do. If local_cpu_rate is zero, then we will go through */
- /* all the "normal" calibration stuff and return the rate back. If */
- /* there is no idle counter in the kernel idle loop, the */
- /* local_cpu_rate will be set to -1. */
-
- if (local_cpu_usage) {
- local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
- }
-
- /* Tell the remote end to do a listen. The server alters the socket */
- /* paramters on the other side at this point, hence the reason for */
- /* all the values being passed in the setup message. If the user did */
- /* not specify any of the parameters, they will be passed as 0, which */
- /* will indicate to the remote that no changes beyond the system's */
- /* default should be used. Alignment is the exception, it will */
- /* default to 8, which will be no alignment alterations. */
-
- netperf_request.content.request_type = DO_XTI_UDP_RR;
- xti_udp_rr_request->recv_buf_size = rsr_size;
- xti_udp_rr_request->send_buf_size = rss_size;
- xti_udp_rr_request->recv_alignment = remote_recv_align;
- xti_udp_rr_request->recv_offset = remote_recv_offset;
- xti_udp_rr_request->send_alignment = remote_send_align;
- xti_udp_rr_request->send_offset = remote_send_offset;
- xti_udp_rr_request->request_size = req_size;
- xti_udp_rr_request->response_size = rsp_size;
- xti_udp_rr_request->measure_cpu = remote_cpu_usage;
- xti_udp_rr_request->cpu_rate = remote_cpu_rate;
- xti_udp_rr_request->so_rcvavoid = rem_rcvavoid;
- xti_udp_rr_request->so_sndavoid = rem_sndavoid;
- if (test_time) {
- xti_udp_rr_request->test_length = test_time;
- }
- else {
- xti_udp_rr_request->test_length = test_trans * -1;
- }
-
- strcpy(xti_udp_rr_request->xti_device, rem_xti_device);
-
-#ifdef __alpha
-
- /* ok - even on a DEC box, strings are strings. I didn't really want */
- /* to ntohl the words of a string. since I don't want to teach the */
- /* send_ and recv_ _request and _response routines about the types, */
- /* I will put "anti-ntohl" calls here. I imagine that the "pure" */
- /* solution would be to use XDR, but I am still leary of being able */
- /* to find XDR libs on all platforms I want running netperf. raj */
- {
- int *charword;
- int *initword;
- int *lastword;
-
- initword = (int *) xti_udp_rr_request->xti_device;
- lastword = initword + ((strlen(rem_xti_device) + 3) / 4);
-
- for (charword = initword;
- charword < lastword;
- charword++) {
-
- *charword = ntohl(*charword);
- }
- }
-#endif /* __alpha */
-
- if (debug > 1) {
- fprintf(where,"netperf: send_xti_udp_rr: requesting UDP r/r test\n");
- }
-
- send_request();
-
- /* The response from the remote will contain all of the relevant */
- /* socket parameters for this test type. We will put them back into */
- /* the variables here so they can be displayed if desired. The */
- /* remote will have calibrated CPU if necessary, and will have done */
- /* all the needed set-up we will have calibrated the cpu locally */
- /* before sending the request, and will grab the counter value right*/
- /* after the connect returns. The remote will grab the counter right*/
- /* after the accept call. This saves the hassle of extra messages */
- /* being sent for the UDP tests. */
-
- recv_response();
-
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote listen done.\n");
- rsr_size = xti_udp_rr_response->recv_buf_size;
- rss_size = xti_udp_rr_response->send_buf_size;
- remote_cpu_usage = xti_udp_rr_response->measure_cpu;
- remote_cpu_rate = xti_udp_rr_response->cpu_rate;
- /* port numbers in proper order */
- server.sin_port = (short)xti_udp_rr_response->data_port_number;
- server.sin_port = htons(server.sin_port);
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- perror("netperf: remote error");
-
- exit(1);
- }
-
- /* Data Socket set-up is finished. If there were problems, either the */
- /* connect would have failed, or the previous response would have */
- /* indicated a problem. I failed to see the value of the extra */
- /* message after the accept on the remote. If it failed, we'll see it */
- /* here. If it didn't, we might as well start pumping data. */
-
- /* Set-up the test end conditions. For a request/response test, they */
- /* can be either time or transaction based. */
-
- if (test_time) {
- /* The user wanted to end the test after a period of time. */
- times_up = 0;
- trans_remaining = 0;
- start_timer(test_time);
- }
- else {
- /* The tester wanted to send a number of bytes. */
- trans_remaining = test_bytes;
- times_up = 1;
- }
-
- /* The cpu_start routine will grab the current time and possibly */
- /* value of the idle counter for later use in measuring cpu */
- /* utilization and/or service demand and thruput. */
-
- cpu_start(local_cpu_usage);
-
-#ifdef WANT_INTERVALS
- if ((interval_burst) || (demo_mode)) {
- /* zero means that we never pause, so we never should need the */
- /* interval timer, unless we are in demo_mode */
- start_itimer(interval_wate);
- }
- interval_count = interval_burst;
- /* get the signal set for the call to sigsuspend */
- if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &signal_set) != 0) {
- fprintf(where,
- "send_xti_udp_rr: unable to get sigmask errno %d\n",
- errno);
- fflush(where);
- exit(1);
- }
-#endif /* WANT_INTERVALS */
-
- /* We use an "OR" to control test execution. When the test is */
- /* controlled by time, the byte count check will always return */
- /* false. When the test is controlled by byte count, the time test */
- /* will always return false. When the test is finished, the whole */
- /* expression will go false and we will stop sending data. I think */
- /* I just arbitrarily decrement trans_remaining for the timed */
- /* test, but will not do that just yet... One other question is */
- /* whether or not the send buffer and the receive buffer should be */
- /* the same buffer. */
-
- while ((!times_up) || (trans_remaining > 0)) {
- /* send the request */
-#ifdef WANT_HISTOGRAM
- HIST_timestamp(&time_one);
-#endif
- if((t_sndudata(send_socket,
- &send_unitdata)) != 0) {
- if (errno == EINTR) {
- /* We likely hit */
- /* test-end time. */
- break;
- }
- fprintf(where,
- "send_xti_udp_rr: t_sndudata: errno %d t_errno %d t_look 0x%.4x\n",
- errno,
- t_errno,
- t_look(send_socket));
- fflush(where);
- exit(1);
- }
- send_ring = send_ring->next;
-
- /* receive the response. with UDP we will get it all, or nothing */
-
- if((t_rcvudata(send_socket,
- &recv_unitdata,
- &flags)) != 0) {
- if (errno == TNODATA) {
- continue;
- }
- if (errno == EINTR) {
- /* Again, we have likely hit test-end time */
- break;
- }
- fprintf(where,
- "send_xti_udp_rr: t_rcvudata: errno %d t_errno %d t_look 0x%x\n",
- errno,
- t_errno,
- t_look(send_socket));
- fprintf(where,
- "recv_unitdata.udata.buf %x\n",recv_unitdata.udata.buf);
- fprintf(where,
- "recv_unitdata.udata.maxlen %x\n",recv_unitdata.udata.maxlen);
- fprintf(where,
- "recv_unitdata.udata.len %x\n",recv_unitdata.udata.len);
- fprintf(where,
- "recv_unitdata.addr.buf %x\n",recv_unitdata.addr.buf);
- fprintf(where,
- "recv_unitdata.addr.maxlen %x\n",recv_unitdata.addr.maxlen);
- fprintf(where,
- "recv_unitdata.addr.len %x\n",recv_unitdata.addr.len);
- fflush(where);
- exit(1);
- }
- recv_ring = recv_ring->next;
-
-#ifdef WANT_HISTOGRAM
- HIST_timestamp(&time_two);
- HIST_add(time_hist,delta_micro(&time_one,&time_two));
-
- /* at this point, we may wish to sleep for some period of */
- /* time, so we see how long that last transaction just took, */
- /* and sleep for the difference of that and the interval. We */
- /* will not sleep if the time would be less than a */
- /* millisecond. */
-#endif
-#ifdef WANT_INTERVALS
- if (demo_mode) {
- units_this_tick += 1;
- }
- /* in this case, the interval count is the count-down couter */
- /* to decide to sleep for a little bit */
- if ((interval_burst) && (--interval_count == 0)) {
- /* call sigsuspend and wait for the interval timer to get us */
- /* out */
- if (debug) {
- fprintf(where,"about to suspend\n");
- fflush(where);
- }
- if (sigsuspend(&signal_set) == EFAULT) {
- fprintf(where,
- "send_xti_udp_rr: fault with signal set!\n");
- fflush(where);
- exit(1);
- }
- interval_count = interval_burst;
- }
-#endif /* WANT_INTERVALS */
-
- nummessages++;
- if (trans_remaining) {
- trans_remaining--;
- }
-
- if (debug > 3) {
- if ((nummessages % 100) == 0) {
- fprintf(where,"Transaction %d completed\n",nummessages);
- fflush(where);
- }
- }
-
- }
-
- /* this call will always give us the elapsed time for the test, and */
- /* will also store-away the necessaries for cpu utilization */
-
- cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */
- /* measured? how long */
- /* did we really run? */
-
- /* Get the statistics from the remote end. The remote will have */
- /* calculated service demand and all those interesting things. If */
- /* it wasn't supposed to care, it will return obvious values. */
-
- recv_response();
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote results obtained\n");
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- perror("netperf: remote error");
-
- exit(1);
- }
-
- /* We now calculate what our thruput was for the test. In the */
- /* future, we may want to include a calculation of the thruput */
- /* measured by the remote, but it should be the case that for a */
- /* UDP rr test, that the two numbers should be *very* close... */
- /* We calculate bytes_sent regardless of the way the test length */
- /* was controlled. */
-
- bytes_xferd = (req_size * nummessages) + (rsp_size * nummessages);
- thruput = nummessages / elapsed_time;
-
- if (local_cpu_usage || remote_cpu_usage) {
-
- /* We must now do a little math for service demand and cpu */
- /* utilization for the system(s) Of course, some of the */
- /* information might be bogus because there was no idle counter */
- /* in the kernel(s). We need to make a note of this for the */
- /* user's benefit by placing a code for the metod used in the */
- /* test banner */
-
- if (local_cpu_usage) {
- local_cpu_utilization = calc_cpu_util(0.0);
-
- /* since calc_service demand is doing ms/Kunit we will */
- /* multiply the number of transaction by 1024 to get */
- /* "good" numbers */
-
- local_service_demand = calc_service_demand((double) nummessages*1024,
- 0.0,
- 0.0,
- 0);
- }
- else {
- local_cpu_utilization = -1.0;
- local_service_demand = -1.0;
- }
-
- if (remote_cpu_usage) {
- remote_cpu_utilization = xti_udp_rr_result->cpu_util;
-
- /* since calc_service demand is doing ms/Kunit we will */
- /* multiply the number of transaction by 1024 to get */
- /* "good" numbers */
-
- remote_service_demand = calc_service_demand((double) nummessages*1024,
- 0.0,
- remote_cpu_utilization,
- xti_udp_rr_result->num_cpus);
- }
- else {
- remote_cpu_utilization = -1.0;
- remote_service_demand = -1.0;
- }
- }
- else {
- /* we were not measuring cpu, for the confidence stuff, we */
- /* should make it -1.0 */
- local_cpu_utilization = -1.0;
- local_service_demand = -1.0;
- remote_cpu_utilization = -1.0;
- remote_service_demand = -1.0;
- }
-
- /* at this point, we want to calculate the confidence information. */
- /* if debugging is on, calculate_confidence will print-out the */
- /* parameters we pass it */
-
- calculate_confidence(confidence_iteration,
- elapsed_time,
- thruput,
- local_cpu_utilization,
- remote_cpu_utilization,
- local_service_demand,
- remote_service_demand);
-
-
- confidence_iteration++;
-
- /* we are done with the socket */
- t_close(send_socket);
- }
-
- /* at this point, we have made all the iterations we are going to */
- /* make. */
- retrieve_confident_values(&elapsed_time,
- &thruput,
- &local_cpu_utilization,
- &remote_cpu_utilization,
- &local_service_demand,
- &remote_service_demand);
-
- /* We are now ready to print all the information. If the user */
- /* has specified zero-level verbosity, we will just print the */
- /* local service demand, or the remote service demand. If the */
- /* user has requested verbosity level 1, he will get the basic */
- /* "streamperf" numbers. If the user has specified a verbosity */
- /* of greater than 1, we will display a veritable plethora of */
- /* background information from outside of this block as it it */
- /* not cpu_measurement specific... */
-
- if (confidence < 0) {
- /* we did not hit confidence, but were we asked to look for it? */
- if (iteration_max > 1) {
- display_confidence();
- }
- }
-
- if (local_cpu_usage || remote_cpu_usage) {
- local_cpu_method = format_cpu_method(cpu_method);
- remote_cpu_method = format_cpu_method(xti_udp_rr_result->cpu_method);
-
- switch (verbosity) {
- case 0:
- if (local_cpu_usage) {
- fprintf(where,
- cpu_fmt_0,
- local_service_demand,
- local_cpu_method);
- }
- else {
- fprintf(where,
- cpu_fmt_0,
- remote_service_demand,
- remote_cpu_method);
- }
- break;
- case 1:
- case 2:
- if (print_headers) {
- fprintf(where,
- cpu_title,
- local_cpu_method,
- remote_cpu_method);
- }
-
- fprintf(where,
- cpu_fmt_1_line_1, /* the format string */
- lss_size, /* local sendbuf size */
- lsr_size,
- req_size, /* how large were the requests */
- rsp_size, /* guess */
- elapsed_time, /* how long was the test */
- nummessages/elapsed_time,
- local_cpu_utilization, /* local cpu */
- remote_cpu_utilization, /* remote cpu */
- local_service_demand, /* local service demand */
- remote_service_demand); /* remote service demand */
- fprintf(where,
- cpu_fmt_1_line_2,
- rss_size,
- rsr_size);
- break;
- }
- }
- else {
- /* The tester did not wish to measure service demand. */
- switch (verbosity) {
- case 0:
- fprintf(where,
- tput_fmt_0,
- nummessages/elapsed_time);
- break;
- case 1:
- case 2:
- if (print_headers) {
- fprintf(where,tput_title,format_units());
- }
-
- fprintf(where,
- tput_fmt_1_line_1, /* the format string */
- lss_size,
- lsr_size,
- req_size, /* how large were the requests */
- rsp_size, /* how large were the responses */
- elapsed_time, /* how long did it take */
- nummessages/elapsed_time);
- fprintf(where,
- tput_fmt_1_line_2,
- rss_size, /* remote recvbuf size */
- rsr_size);
-
- break;
- }
- }
- fflush(where);
-
- /* it would be a good thing to include information about some of the */
- /* other parameters that may have been set for this test, but at the */
- /* moment, I do not wish to figure-out all the formatting, so I will */
- /* just put this comment here to help remind me that it is something */
- /* that should be done at a later time. */
-
- /* how to handle the verbose information in the presence of */
- /* confidence intervals is yet to be determined... raj 11/94 */
-
- if (verbosity > 1) {
- /* The user wanted to know it all, so we will give it to him. */
- /* This information will include as much as we can find about */
- /* UDP statistics, the alignments of the sends and receives */
- /* and all that sort of rot... */
-
-#ifdef WANT_HISTOGRAM
- fprintf(where,"\nHistogram of request/reponse times.\n");
- fflush(where);
- HIST_report(time_hist);
-#endif /* WANT_HISTOGRAM */
- }
-}
-
- /* this routine implements the receive side (netserver) of a XTI_UDP_RR */
- /* test. */
-void
- recv_xti_udp_rr()
-{
-
- struct ring_elt *recv_ring;
- struct ring_elt *send_ring;
-
- struct t_bind bind_req, bind_resp;
- struct t_unitdata send_unitdata;
- struct t_unitdata recv_unitdata;
- int flags = 0;
-
- struct sockaddr_in myaddr_in, peeraddr_in;
- SOCKET s_data;
- int addrlen;
- int trans_received;
- int trans_remaining;
- float elapsed_time;
-
- struct xti_udp_rr_request_struct *xti_udp_rr_request;
- struct xti_udp_rr_response_struct *xti_udp_rr_response;
- struct xti_udp_rr_results_struct *xti_udp_rr_results;
-
-
- /* a little variable initialization */
- memset (&myaddr_in, 0, sizeof(struct sockaddr_in));
- myaddr_in.sin_family = AF_INET;
- myaddr_in.sin_addr.s_addr = INADDR_ANY;
- myaddr_in.sin_port = 0;
- memset (&peeraddr_in, 0, sizeof(struct sockaddr_in));
-
- /* and some not so paranoid :) */
- xti_udp_rr_request =
- (struct xti_udp_rr_request_struct *)netperf_request.content.test_specific_data;
- xti_udp_rr_response =
- (struct xti_udp_rr_response_struct *)netperf_response.content.test_specific_data;
- xti_udp_rr_results =
- (struct xti_udp_rr_results_struct *)netperf_response.content.test_specific_data;
-
- if (debug) {
- fprintf(where,"netserver: recv_xti_udp_rr: entered...\n");
- fflush(where);
- }
-
- /* We want to set-up the listen socket with all the desired */
- /* parameters and then let the initiator know that all is ready. If */
- /* socket size defaults are to be used, then the initiator will have */
- /* sent us 0's. If the socket sizes cannot be changed, then we will */
- /* send-back what they are. If that information cannot be determined, */
- /* then we send-back -1's for the sizes. If things go wrong for any */
- /* reason, we will drop back ten yards and punt. */
-
- /* If anything goes wrong, we want the remote to know about it. It */
- /* would be best if the error that the remote reports to the user is */
- /* the actual error we encountered, rather than some bogus unexpected */
- /* response type message. */
-
- if (debug) {
- fprintf(where,"recv_xti_udp_rr: setting the response type...\n");
- fflush(where);
- }
-
- netperf_response.content.response_type = XTI_UDP_RR_RESPONSE;
-
- if (debug) {
- fprintf(where,"recv_xti_udp_rr: the response type is set...\n");
- fflush(where);
- }
-
- /* We now alter the message_ptr variables to be at the desired */
- /* alignments with the desired offsets. */
-
- if (debug) {
- fprintf(where,"recv_xti_udp_rr: requested recv alignment of %d offset %d\n",
- xti_udp_rr_request->recv_alignment,
- xti_udp_rr_request->recv_offset);
- fprintf(where,"recv_xti_udp_rr: requested send alignment of %d offset %d\n",
- xti_udp_rr_request->send_alignment,
- xti_udp_rr_request->send_offset);
- fflush(where);
- }
-
- if (send_width == 0) send_width = 1;
- if (recv_width == 0) recv_width = 1;
-
- recv_ring = allocate_buffer_ring(recv_width,
- xti_udp_rr_request->request_size,
- xti_udp_rr_request->recv_alignment,
- xti_udp_rr_request->recv_offset);
-
- send_ring = allocate_buffer_ring(send_width,
- xti_udp_rr_request->response_size,
- xti_udp_rr_request->send_alignment,
- xti_udp_rr_request->send_offset);
-
- if (debug) {
- fprintf(where,"recv_xti_udp_rr: receive alignment and offset set...\n");
- fflush(where);
- }
-
- /* create_xti_endpoint expects to find some things in the global */
- /* variables, so set the globals based on the values in the request. */
- /* once the socket has been created, we will set the response values */
- /* based on the updated value of those globals. raj 7/94 */
- lss_size = xti_udp_rr_request->send_buf_size;
- lsr_size = xti_udp_rr_request->recv_buf_size;
- loc_rcvavoid = xti_udp_rr_request->so_rcvavoid;
- loc_sndavoid = xti_udp_rr_request->so_sndavoid;
-
-#ifdef __alpha
-
- /* ok - even on a DEC box, strings are strings. I din't really want */
- /* to ntohl the words of a string. since I don't want to teach the */
- /* send_ and recv_ _request and _response routines about the types, */
- /* I will put "anti-ntohl" calls here. I imagine that the "pure" */
- /* solution would be to use XDR, but I am still leary of being able */
- /* to find XDR libs on all platforms I want running netperf. raj */
- {
- int *charword;
- int *initword;
- int *lastword;
-
- initword = (int *) xti_udp_rr_request->xti_device;
- lastword = initword + ((xti_udp_rr_request->dev_name_len + 3) / 4);
-
- for (charword = initword;
- charword < lastword;
- charword++) {
-
- *charword = htonl(*charword);
- }
- }
-
-#endif /* __alpha */
-
- s_data = create_xti_endpoint(xti_udp_rr_request->xti_device);
-
- if (s_data == INVALID_SOCKET) {
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
-
- if (debug) {
- fprintf(where,"recv_xti_udp_rr: endpoint created...\n");
- fflush(where);
- }
-
- /* Let's get an address assigned to this socket so we can tell the */
- /* initiator how to reach the data socket. There may be a desire to */
- /* nail this socket to a specific IP address in a multi-homed, */
- /* multi-connection situation, but for now, we'll ignore the issue */
- /* and concentrate on single connection testing. */
-
- bind_req.addr.maxlen = sizeof(struct sockaddr_in);
- bind_req.addr.len = sizeof(struct sockaddr_in);
- bind_req.addr.buf = (char *)&myaddr_in;
- bind_req.qlen = 1;
-
- bind_resp.addr.maxlen = sizeof(struct sockaddr_in);
- bind_resp.addr.len = sizeof(struct sockaddr_in);
- bind_resp.addr.buf = (char *)&myaddr_in;
- bind_resp.qlen = 1;
-
- if (t_bind(s_data,
- &bind_req,
- &bind_resp) == SOCKET_ERROR) {
- if (debug) {
- fprintf(where,
- "recv_xti_udp_rr: t_bind failed, t_errno %d errno %d\n",
- t_errno,
- errno);
- fflush(where);
- }
-
- netperf_response.content.serv_errno = t_errno;
- send_response();
-
- exit(1);
- }
-
- if (debug) {
- fprintf(where,
- "recv_xti_udp_rr: endpoint bound to port %d...\n",
- ntohs(myaddr_in.sin_port));
- fflush(where);
- }
-
- xti_udp_rr_response->test_length =
- xti_udp_rr_request->test_length;
-
-
- /* Now myaddr_in contains the port and the internet address this is */
- /* returned to the sender also implicitly telling the sender that the */
- /* socket buffer sizing has been done. */
-
- xti_udp_rr_response->data_port_number = (int) ntohs(myaddr_in.sin_port);
- netperf_response.content.serv_errno = 0;
-
- fprintf(where,"recv port number %d\n",myaddr_in.sin_port);
- fflush(where);
-
- /* But wait, there's more. If the initiator wanted cpu measurements, */
- /* then we must call the calibrate routine, which will return the max */
- /* rate back to the initiator. If the CPU was not to be measured, or */
- /* something went wrong with the calibration, we will return a 0.0 to */
- /* the initiator. */
-
- xti_udp_rr_response->cpu_rate = 0.0; /* assume no cpu */
- xti_udp_rr_response->measure_cpu = 0;
- if (xti_udp_rr_request->measure_cpu) {
- xti_udp_rr_response->measure_cpu = 1;
- xti_udp_rr_response->cpu_rate =
- calibrate_local_cpu(xti_udp_rr_request->cpu_rate);
- }
-
- /* before we send the response back to the initiator, pull some of */
- /* the socket parms from the globals */
- xti_udp_rr_response->send_buf_size = lss_size;
- xti_udp_rr_response->recv_buf_size = lsr_size;
- xti_udp_rr_response->so_rcvavoid = loc_rcvavoid;
- xti_udp_rr_response->so_sndavoid = loc_sndavoid;
-
- /* since we are going to call t_rcvudata() instead of t_rcv() we */
- /* need to init the unitdata structure raj 3/95 */
-
- memset (&recv_unitdata, 0, sizeof(recv_unitdata));
- recv_unitdata.addr.maxlen = sizeof(struct sockaddr_in);
- recv_unitdata.addr.len = sizeof(struct sockaddr_in);
- recv_unitdata.addr.buf = (char *)&peeraddr_in;
-
- recv_unitdata.opt.maxlen = 0;
- recv_unitdata.opt.len = 0;
- recv_unitdata.opt.buf = NULL;
-
- recv_unitdata.udata.maxlen = xti_udp_rr_request->request_size;
- recv_unitdata.udata.len = xti_udp_rr_request->request_size;
- recv_unitdata.udata.buf = recv_ring->buffer_ptr;
-
- /* since we are going to call t_sndudata() instead of t_snd() we */
- /* need to init the unitdata structure raj 8/95 */
-
- memset (&send_unitdata, 0, sizeof(send_unitdata));
- send_unitdata.addr.maxlen = sizeof(struct sockaddr_in);
- send_unitdata.addr.len = sizeof(struct sockaddr_in);
- send_unitdata.addr.buf = (char *)&peeraddr_in;
-
- send_unitdata.opt.maxlen = 0;
- send_unitdata.opt.len = 0;
- send_unitdata.opt.buf = NULL;
-
- send_unitdata.udata.maxlen = xti_udp_rr_request->response_size;
- send_unitdata.udata.len = xti_udp_rr_request->response_size;
- send_unitdata.udata.buf = send_ring->buffer_ptr;
-
- send_response();
-
-
- /* Now it's time to start receiving data on the connection. We will */
- /* first grab the apropriate counters and then start grabbing. */
-
- cpu_start(xti_udp_rr_request->measure_cpu);
-
- if (xti_udp_rr_request->test_length > 0) {
- times_up = 0;
- trans_remaining = 0;
- start_timer(xti_udp_rr_request->test_length + PAD_TIME);
- }
- else {
- times_up = 1;
- trans_remaining = xti_udp_rr_request->test_length * -1;
- }
-
- addrlen = sizeof(peeraddr_in);
- bzero((char *)&peeraddr_in, addrlen);
-
- trans_received = 0;
-
- while ((!times_up) || (trans_remaining > 0)) {
-
- /* receive the request from the other side */
- if (t_rcvudata(s_data,
- &recv_unitdata,
- &flags) != 0) {
- if (errno == TNODATA) {
- continue;
- }
- if (errno == EINTR) {
- /* we must have hit the end of test time. */
- break;
- }
- if (debug) {
- fprintf(where,
- "recv_xti_udp_rr: t_rcvudata failed, t_errno %d errno %d\n",
- t_errno,
- errno);
- fflush(where);
- }
- netperf_response.content.serv_errno = t_errno;
- send_response();
- exit(1);
- }
- recv_ring = recv_ring->next;
- recv_unitdata.udata.buf = recv_ring->buffer_ptr;
-
- /* Now, send the response to the remote */
- if (t_sndudata(s_data,
- &send_unitdata) != 0) {
- if (errno == EINTR) {
- /* we have hit end of test time. */
- break;
- }
- if (debug) {
- fprintf(where,
- "recv_xti_udp_rr: t_sndudata failed, t_errno %d errno %d\n",
- t_errno,
- errno);
- fflush(where);
- }
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
- send_ring = send_ring->next;
- send_unitdata.udata.buf = send_ring->buffer_ptr;
-
- trans_received++;
- if (trans_remaining) {
- trans_remaining--;
- }
-
- if (debug) {
- fprintf(where,
- "recv_xti_udp_rr: Transaction %d complete.\n",
- trans_received);
- fflush(where);
- }
-
- }
-
-
- /* The loop now exits due to timeout or transaction count being */
- /* reached */
-
- cpu_stop(xti_udp_rr_request->measure_cpu,&elapsed_time);
-
- if (times_up) {
- /* we ended the test by time, which was at least 2 seconds */
- /* longer than we wanted to run. so, we want to subtract */
- /* PAD_TIME from the elapsed_time. */
- elapsed_time -= PAD_TIME;
- }
- /* send the results to the sender */
-
- if (debug) {
- fprintf(where,
- "recv_xti_udp_rr: got %d transactions\n",
- trans_received);
- fflush(where);
- }
-
- xti_udp_rr_results->bytes_received = (trans_received *
- (xti_udp_rr_request->request_size +
- xti_udp_rr_request->response_size));
- xti_udp_rr_results->trans_received = trans_received;
- xti_udp_rr_results->elapsed_time = elapsed_time;
- xti_udp_rr_results->cpu_method = cpu_method;
- if (xti_udp_rr_request->measure_cpu) {
- xti_udp_rr_results->cpu_util = calc_cpu_util(elapsed_time);
- }
-
- if (debug) {
- fprintf(where,
- "recv_xti_udp_rr: test complete, sending results.\n");
- fflush(where);
- }
-
- send_response();
-
- /* we are done with the socket now */
- close(s_data);
-
-}
-
- /* this routine implements the receive (netserver) side of a XTI_TCP_RR */
- /* test */
-void
-recv_xti_tcp_rr()
-{
-
- struct ring_elt *send_ring;
- struct ring_elt *recv_ring;
-
- struct sockaddr_in myaddr_in, peeraddr_in;
- struct t_bind bind_req, bind_resp;
- struct t_call call_req;
-
- SOCKET s_listen,s_data;
- int addrlen;
- char *temp_message_ptr;
- int trans_received;
- int trans_remaining;
- int bytes_sent;
- int request_bytes_recvd;
- int request_bytes_remaining;
- int timed_out = 0;
- float elapsed_time;
-
- struct xti_tcp_rr_request_struct *xti_tcp_rr_request;
- struct xti_tcp_rr_response_struct *xti_tcp_rr_response;
- struct xti_tcp_rr_results_struct *xti_tcp_rr_results;
-
- xti_tcp_rr_request =
- (struct xti_tcp_rr_request_struct *)netperf_request.content.test_specific_data;
- xti_tcp_rr_response =
- (struct xti_tcp_rr_response_struct *)netperf_response.content.test_specific_data;
- xti_tcp_rr_results =
- (struct xti_tcp_rr_results_struct *)netperf_response.content.test_specific_data;
-
- if (debug) {
- fprintf(where,"netserver: recv_xti_tcp_rr: entered...\n");
- fflush(where);
- }
-
- /* We want to set-up the listen socket with all the desired */
- /* parameters and then let the initiator know that all is ready. If */
- /* socket size defaults are to be used, then the initiator will have */
- /* sent us 0's. If the socket sizes cannot be changed, then we will */
- /* send-back what they are. If that information cannot be determined, */
- /* then we send-back -1's for the sizes. If things go wrong for any */
- /* reason, we will drop back ten yards and punt. */
-
- /* If anything goes wrong, we want the remote to know about it. It */
- /* would be best if the error that the remote reports to the user is */
- /* the actual error we encountered, rather than some bogus unexpected */
- /* response type message. */
-
- if (debug) {
- fprintf(where,"recv_xti_tcp_rr: setting the response type...\n");
- fflush(where);
- }
-
- netperf_response.content.response_type = XTI_TCP_RR_RESPONSE;
-
- if (debug) {
- fprintf(where,"recv_xti_tcp_rr: the response type is set...\n");
- fflush(where);
- }
-
- /* allocate the recv and send rings with the requested alignments */
- /* and offsets. raj 7/94 */
- if (debug) {
- fprintf(where,"recv_xti_tcp_rr: requested recv alignment of %d offset %d\n",
- xti_tcp_rr_request->recv_alignment,
- xti_tcp_rr_request->recv_offset);
- fprintf(where,"recv_xti_tcp_rr: requested send alignment of %d offset %d\n",
- xti_tcp_rr_request->send_alignment,
- xti_tcp_rr_request->send_offset);
- fflush(where);
- }
-
- /* at some point, these need to come to us from the remote system */
- if (send_width == 0) send_width = 1;
- if (recv_width == 0) recv_width = 1;
-
- send_ring = allocate_buffer_ring(send_width,
- xti_tcp_rr_request->response_size,
- xti_tcp_rr_request->send_alignment,
- xti_tcp_rr_request->send_offset);
-
- recv_ring = allocate_buffer_ring(recv_width,
- xti_tcp_rr_request->request_size,
- xti_tcp_rr_request->recv_alignment,
- xti_tcp_rr_request->recv_offset);
-
-
- /* Let's clear-out our sockaddr for the sake of cleanlines. Then we */
- /* can put in OUR values !-) At some point, we may want to nail this */
- /* socket to a particular network-level address, but for now, */
- /* INADDR_ANY should be just fine. */
-
- bzero((char *)&myaddr_in,
- sizeof(myaddr_in));
- myaddr_in.sin_family = AF_INET;
- myaddr_in.sin_addr.s_addr = INADDR_ANY;
- myaddr_in.sin_port = 0;
-
- /* Grab a socket to listen on, and then listen on it. */
-
- if (debug) {
- fprintf(where,"recv_xti_tcp_rr: grabbing a socket...\n");
- fflush(where);
- }
-
- /* create_xti_endpoint expects to find some things in the global */
- /* variables, so set the globals based on the values in the request. */
- /* once the socket has been created, we will set the response values */
- /* based on the updated value of those globals. raj 7/94 */
- lss_size = xti_tcp_rr_request->send_buf_size;
- lsr_size = xti_tcp_rr_request->recv_buf_size;
- loc_nodelay = xti_tcp_rr_request->no_delay;
- loc_rcvavoid = xti_tcp_rr_request->so_rcvavoid;
- loc_sndavoid = xti_tcp_rr_request->so_sndavoid;
-
-#ifdef __alpha
-
- /* ok - even on a DEC box, strings are strings. I din't really want */
- /* to ntohl the words of a string. since I don't want to teach the */
- /* send_ and recv_ _request and _response routines about the types, */
- /* I will put "anti-ntohl" calls here. I imagine that the "pure" */
- /* solution would be to use XDR, but I am still leary of being able */
- /* to find XDR libs on all platforms I want running netperf. raj */
- {
- int *charword;
- int *initword;
- int *lastword;
-
- initword = (int *) xti_tcp_rr_request->xti_device;
- lastword = initword + ((xti_tcp_rr_request->dev_name_len + 3) / 4);
-
- for (charword = initword;
- charword < lastword;
- charword++) {
-
- *charword = htonl(*charword);
- }
- }
-
-#endif /* __alpha */
-
- s_listen = create_xti_endpoint(xti_tcp_rr_request->xti_device);
-
- if (s_listen == INVALID_SOCKET) {
- netperf_response.content.serv_errno = errno;
- send_response();
-
- exit(1);
- }
-
- /* Let's get an address assigned to this socket so we can tell the */
- /* initiator how to reach the data socket. There may be a desire to */
- /* nail this socket to a specific IP address in a multi-homed, */
- /* multi-connection situation, but for now, we'll ignore the issue */
- /* and concentrate on single connection testing. */
-
- bind_req.addr.maxlen = sizeof(struct sockaddr_in);
- bind_req.addr.len = sizeof(struct sockaddr_in);
- bind_req.addr.buf = (char *)&myaddr_in;
- bind_req.qlen = 1;
-
- bind_resp.addr.maxlen = sizeof(struct sockaddr_in);
- bind_resp.addr.len = sizeof(struct sockaddr_in);
- bind_resp.addr.buf = (char *)&myaddr_in;
- bind_resp.qlen = 1;
-
- if (t_bind(s_listen,
- &bind_req,
- &bind_resp) == SOCKET_ERROR) {
- netperf_response.content.serv_errno = t_errno;
- close(s_listen);
- send_response();
-
- exit(1);
- }
-
- if (debug) {
- fprintf(where,
- "recv_xti_tcp_rr: t_bind complete port %d\n",
- ntohs(myaddr_in.sin_port));
- fflush(where);
- }
-
- /* Now myaddr_in contains the port and the internet address this is */
- /* returned to the sender also implicitly telling the sender that the */
- /* socket buffer sizing has been done. */
-
- xti_tcp_rr_response->data_port_number = (int) ntohs(myaddr_in.sin_port);
- netperf_response.content.serv_errno = 0;
-
- /* But wait, there's more. If the initiator wanted cpu measurements, */
- /* then we must call the calibrate routine, which will return the max */
- /* rate back to the initiator. If the CPU was not to be measured, or */
- /* something went wrong with the calibration, we will return a 0.0 to */
- /* the initiator. */
-
- xti_tcp_rr_response->cpu_rate = 0.0; /* assume no cpu */
- xti_tcp_rr_response->measure_cpu = 0;
-
- if (xti_tcp_rr_request->measure_cpu) {
- xti_tcp_rr_response->measure_cpu = 1;
- xti_tcp_rr_response->cpu_rate = calibrate_local_cpu(xti_tcp_rr_request->cpu_rate);
- }
-
-
- /* before we send the response back to the initiator, pull some of */
- /* the socket parms from the globals */
- xti_tcp_rr_response->send_buf_size = lss_size;
- xti_tcp_rr_response->recv_buf_size = lsr_size;
- xti_tcp_rr_response->no_delay = loc_nodelay;
- xti_tcp_rr_response->so_rcvavoid = loc_rcvavoid;
- xti_tcp_rr_response->so_sndavoid = loc_sndavoid;
- xti_tcp_rr_response->test_length = xti_tcp_rr_request->test_length;
- send_response();
-
- /* Now, let's set-up the socket to listen for connections. for xti, */
- /* the t_listen call is blocking by default - this is different */
- /* semantics from BSD - probably has to do with being able to reject */
- /* a call before an accept */
- call_req.addr.maxlen = sizeof(struct sockaddr_in);
- call_req.addr.len = sizeof(struct sockaddr_in);
- call_req.addr.buf = (char *)&peeraddr_in;
- call_req.opt.maxlen = 0;
- call_req.opt.len = 0;
- call_req.opt.buf = NULL;
- call_req.udata.maxlen= 0;
- call_req.udata.len = 0;
- call_req.udata.buf = 0;
-
- if (t_listen(s_listen, &call_req) == -1) {
- fprintf(where,
- "recv_xti_tcp_rr: t_listen: errno %d t_errno %d\n",
- errno,
- t_errno);
- fflush(where);
- netperf_response.content.serv_errno = t_errno;
- close(s_listen);
- send_response();
- exit(1);
- }
-
- if (debug) {
- fprintf(where,
- "recv_xti_tcp_rr: t_listen complete t_look 0x%.4x\n",
- t_look(s_listen));
- fflush(where);
- }
-
- /* now just rubber stamp the thing. we want to use the same fd? so */
- /* we will just equate s_data with s_listen. this seems a little */
- /* hokey to me, but then I'm a BSD biggot still. raj 2/95 */
- s_data = s_listen;
- if (t_accept(s_listen,
- s_data,
- &call_req) == -1) {
- fprintf(where,
- "recv_xti_tcp_rr: t_accept: errno %d t_errno %d\n",
- errno,
- t_errno);
- fflush(where);
- close(s_listen);
- exit(1);
- }
-
- if (debug) {
- fprintf(where,
- "recv_xti_tcp_rr: t_accept complete t_look 0x%.4x",
- t_look(s_data));
- fprintf(where,
- " remote is %s port %d\n",
- inet_ntoa(*(struct in_addr *)&peeraddr_in.sin_addr),
- ntohs(peeraddr_in.sin_port));
- fflush(where);
- }
-
- /* Now it's time to start receiving data on the connection. We will */
- /* first grab the apropriate counters and then start grabbing. */
-
- cpu_start(xti_tcp_rr_request->measure_cpu);
-
- if (xti_tcp_rr_request->test_length > 0) {
- times_up = 0;
- trans_remaining = 0;
- start_timer(xti_tcp_rr_request->test_length + PAD_TIME);
- }
- else {
- times_up = 1;
- trans_remaining = xti_tcp_rr_request->test_length * -1;
- }
-
- trans_received = 0;
-
- while ((!times_up) || (trans_remaining > 0)) {
- temp_message_ptr = recv_ring->buffer_ptr;
- request_bytes_remaining = xti_tcp_rr_request->request_size;
- while(request_bytes_remaining > 0) {
- if((request_bytes_recvd=t_rcv(s_data,
- temp_message_ptr,
- request_bytes_remaining,
- &xti_flags)) == SOCKET_ERROR) {
- if (errno == EINTR) {
- /* the timer popped */
- timed_out = 1;
- break;
- }
- fprintf(where,
- "recv_xti_tcp_rr: t_rcv: errno %d t_errno %d len %d",
- errno,
- t_errno,
- request_bytes_recvd);
- fprintf(where,
- " t_look 0x%x",
- t_look(s_data));
- fflush(where);
- netperf_response.content.serv_errno = t_errno;
- send_response();
- exit(1);
- }
- else {
- request_bytes_remaining -= request_bytes_recvd;
- temp_message_ptr += request_bytes_recvd;
- }
- }
-
- recv_ring = recv_ring->next;
-
- if (timed_out) {
- /* we hit the end of the test based on time - lets */
- /* bail out of here now... */
- if (debug) {
- fprintf(where,"yo5\n");
- fflush(where);
- }
- break;
- }
-
- /* Now, send the response to the remote */
- if((bytes_sent=t_snd(s_data,
- send_ring->buffer_ptr,
- xti_tcp_rr_request->response_size,
- 0)) == -1) {
- if (errno == EINTR) {
- /* the test timer has popped */
- timed_out = 1;
- if (debug) {
- fprintf(where,"yo6\n");
- fflush(where);
- }
- break;
- }
- fprintf(where,
- "recv_xti_tcp_rr: t_rcv: errno %d t_errno %d len %d",
- errno,
- t_errno,
- bytes_sent);
- fprintf(where,
- " t_look 0x%x",
- t_look(s_data));
- fflush(where);
- netperf_response.content.serv_errno = t_errno;
- send_response();
- exit(1);
- }
-
- send_ring = send_ring->next;
-
- trans_received++;
- if (trans_remaining) {
- trans_remaining--;
- }
- }
-
-
- /* The loop now exits due to timeout or transaction count being */
- /* reached */
-
- cpu_stop(xti_tcp_rr_request->measure_cpu,&elapsed_time);
-
- stop_timer(); /* this is probably unnecessary, but it shouldn't hurt */
-
- if (timed_out) {
- /* we ended the test by time, which was at least 2 seconds */
- /* longer than we wanted to run. so, we want to subtract */
- /* PAD_TIME from the elapsed_time. */
- elapsed_time -= PAD_TIME;
- }
-
- /* send the results to the sender */
-
- if (debug) {
- fprintf(where,
- "recv_xti_tcp_rr: got %d transactions\n",
- trans_received);
- fflush(where);
- }
-
- xti_tcp_rr_results->bytes_received = (trans_received *
- (xti_tcp_rr_request->request_size +
- xti_tcp_rr_request->response_size));
- xti_tcp_rr_results->trans_received = trans_received;
- xti_tcp_rr_results->elapsed_time = elapsed_time;
- xti_tcp_rr_results->cpu_method = cpu_method;
- if (xti_tcp_rr_request->measure_cpu) {
- xti_tcp_rr_results->cpu_util = calc_cpu_util(elapsed_time);
- }
-
- if (debug) {
- fprintf(where,
- "recv_xti_tcp_rr: test complete, sending results.\n");
- fflush(where);
- }
-
- /* we are done with the socket, free it */
- t_close(s_data);
-
- send_response();
-
-}
-
-
-
- /* this test is intended to test the performance of establishing a */
- /* connection, exchanging a request/response pair, and repeating. it */
- /* is expected that this would be a good starting-point for */
- /* comparision of T/TCP with classic TCP for transactional workloads. */
- /* it will also look (can look) much like the communication pattern */
- /* of http for www access. */
-
-void
-send_xti_tcp_conn_rr(char remote_host[])
-{
-
- char *tput_title = "\
-Local /Remote\n\
-Socket Size Request Resp. Elapsed Trans.\n\
-Send Recv Size Size Time Rate \n\
-bytes Bytes bytes bytes secs. per sec \n\n";
-
- char *tput_fmt_0 =
- "%7.2f\n";
-
- char *tput_fmt_1_line_1 = "\
-%-6d %-6d %-6d %-6d %-6.2f %7.2f \n";
- char *tput_fmt_1_line_2 = "\
-%-6d %-6d\n";
-
- char *cpu_title = "\
-Local /Remote\n\
-Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\
-Send Recv Size Size Time Rate local remote local remote\n\
-bytes bytes bytes bytes secs. per sec %% %% us/Tr us/Tr\n\n";
-
- char *cpu_fmt_0 =
- "%6.3f\n";
-
- char *cpu_fmt_1_line_1 = "\
-%-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f\n";
-
- char *cpu_fmt_1_line_2 = "\
-%-6d %-6d\n";
-
- char *ksink_fmt = "\
-Alignment Offset\n\
-Local Remote Local Remote\n\
-Send Recv Send Recv\n\
-%5d %5d %5d %5d\n";
-
-
- int one = 1;
- int timed_out = 0;
- float elapsed_time;
-
- int len;
- struct ring_elt *send_ring;
- struct ring_elt *recv_ring;
- char *temp_message_ptr;
- int nummessages;
- SOCKET send_socket;
- int trans_remaining;
- double bytes_xferd;
- int sock_opt_len = sizeof(int);
- int rsp_bytes_left;
- int rsp_bytes_recvd;
-
- float local_cpu_utilization;
- float local_service_demand;
- float remote_cpu_utilization;
- float remote_service_demand;
- double thruput;
-
- struct hostent *hp;
- struct sockaddr_in server;
- struct sockaddr_in *myaddr;
- unsigned int addr;
- int myport;
-
- struct xti_tcp_conn_rr_request_struct *xti_tcp_conn_rr_request;
- struct xti_tcp_conn_rr_response_struct *xti_tcp_conn_rr_response;
- struct xti_tcp_conn_rr_results_struct *xti_tcp_conn_rr_result;
-
- xti_tcp_conn_rr_request =
- (struct xti_tcp_conn_rr_request_struct *)netperf_request.content.test_specific_data;
- xti_tcp_conn_rr_response =
- (struct xti_tcp_conn_rr_response_struct *)netperf_response.content.test_specific_data;
- xti_tcp_conn_rr_result =
- (struct xti_tcp_conn_rr_results_struct *)netperf_response.content.test_specific_data;
-
- /* since we are now disconnected from the code that established the */
- /* control socket, and since we want to be able to use different */
- /* protocols and such, we are passed the name of the remote host and */
- /* must turn that into the test specific addressing information. */
-
- myaddr = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in));
- if (myaddr == NULL) {
- printf("malloc(%d) failed!\n", sizeof(struct sockaddr_in));
- exit(1);
- }
-
- bzero((char *)&server,
- sizeof(server));
- bzero((char *)myaddr,
- sizeof(struct sockaddr_in));
- myaddr->sin_family = AF_INET;
-
- /* it would seem that while HP-UX will allow an IP address (as a */
- /* string) in a call to gethostbyname, other, less enlightened */
- /* systems do not. fix from awjacks@ca.sandia.gov raj 10/95 */
- /* order changed to check for IP address first. raj 7/96 */
-
- if ((addr = inet_addr(remote_host)) == SOCKET_ERROR) {
- /* it was not an IP address, try it as a name */
- if ((hp = gethostbyname(remote_host)) == NULL) {
- /* we have no idea what it is */
- fprintf(where,
- "establish_control: could not resolve the destination %s\n",
- remote_host);
- fflush(where);
- exit(1);
- }
- else {
- /* it was a valid remote_host */
- bcopy(hp->h_addr,
- (char *)&server.sin_addr,
- hp->h_length);
- server.sin_family = hp->h_addrtype;
- }
- }
- else {
- /* it was a valid IP address */
- server.sin_addr.s_addr = addr;
- server.sin_family = AF_INET;
- }
-
- if ( print_headers ) {
- fprintf(where,"TCP Connect/Request/Response Test\n");
- if (local_cpu_usage || remote_cpu_usage)
- fprintf(where,cpu_title,format_units());
- else
- fprintf(where,tput_title,format_units());
- }
-
- /* initialize a few counters */
-
- nummessages = 0;
- bytes_xferd = 0.0;
- times_up = 0;
-
- /* set-up the data buffers with the requested alignment and offset */
- if (send_width == 0) send_width = 1;
- if (recv_width == 0) recv_width = 1;
-
- send_ring = allocate_buffer_ring(send_width,
- req_size,
- local_send_align,
- local_send_offset);
-
- recv_ring = allocate_buffer_ring(recv_width,
- rsp_size,
- local_recv_align,
- local_recv_offset);
-
-
- if (debug) {
- fprintf(where,"send_xti_tcp_conn_rr: send_socket obtained...\n");
- }
-
- /* If the user has requested cpu utilization measurements, we must */
- /* calibrate the cpu(s). We will perform this task within the tests */
- /* themselves. If the user has specified the cpu rate, then */
- /* calibrate_local_cpu will return rather quickly as it will have */
- /* nothing to do. If local_cpu_rate is zero, then we will go through */
- /* all the "normal" calibration stuff and return the rate back.*/
-
- if (local_cpu_usage) {
- local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
- }
-
- /* Tell the remote end to do a listen. The server alters the socket */
- /* paramters on the other side at this point, hence the reason for */
- /* all the values being passed in the setup message. If the user did */
- /* not specify any of the parameters, they will be passed as 0, which */
- /* will indicate to the remote that no changes beyond the system's */
- /* default should be used. Alignment is the exception, it will */
- /* default to 8, which will be no alignment alterations. */
-
- netperf_request.content.request_type = DO_XTI_TCP_CRR;
- xti_tcp_conn_rr_request->recv_buf_size = rsr_size;
- xti_tcp_conn_rr_request->send_buf_size = rss_size;
- xti_tcp_conn_rr_request->recv_alignment = remote_recv_align;
- xti_tcp_conn_rr_request->recv_offset = remote_recv_offset;
- xti_tcp_conn_rr_request->send_alignment = remote_send_align;
- xti_tcp_conn_rr_request->send_offset = remote_send_offset;
- xti_tcp_conn_rr_request->request_size = req_size;
- xti_tcp_conn_rr_request->response_size = rsp_size;
- xti_tcp_conn_rr_request->no_delay = rem_nodelay;
- xti_tcp_conn_rr_request->measure_cpu = remote_cpu_usage;
- xti_tcp_conn_rr_request->cpu_rate = remote_cpu_rate;
- xti_tcp_conn_rr_request->so_rcvavoid = rem_rcvavoid;
- xti_tcp_conn_rr_request->so_sndavoid = rem_sndavoid;
- if (test_time) {
- xti_tcp_conn_rr_request->test_length = test_time;
- }
- else {
- xti_tcp_conn_rr_request->test_length = test_trans * -1;
- }
-
- if (debug > 1) {
- fprintf(where,"netperf: send_xti_tcp_conn_rr: requesting TCP crr test\n");
- }
-
- send_request();
-
- /* The response from the remote will contain all of the relevant */
- /* socket parameters for this test type. We will put them back into */
- /* the variables here so they can be displayed if desired. The */
- /* remote will have calibrated CPU if necessary, and will have done */
- /* all the needed set-up we will have calibrated the cpu locally */
- /* before sending the request, and will grab the counter value right */
- /* after the connect returns. The remote will grab the counter right */
- /* after the accept call. This saves the hassle of extra messages */
- /* being sent for the TCP tests. */
-
- recv_response();
-
- if (!netperf_response.content.serv_errno) {
- rsr_size = xti_tcp_conn_rr_response->recv_buf_size;
- rss_size = xti_tcp_conn_rr_response->send_buf_size;
- rem_nodelay = xti_tcp_conn_rr_response->no_delay;
- remote_cpu_usage= xti_tcp_conn_rr_response->measure_cpu;
- remote_cpu_rate = xti_tcp_conn_rr_response->cpu_rate;
- /* make sure that port numbers are in network order */
- server.sin_port = (short)xti_tcp_conn_rr_response->data_port_number;
- server.sin_port = htons(server.sin_port);
- if (debug) {
- fprintf(where,"remote listen done.\n");
- fprintf(where,"remote port is %d\n",ntohs(server.sin_port));
- fflush(where);
- }
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- perror("netperf: remote error");
-
- exit(1);
- }
-
- /* Set-up the test end conditions. For a request/response test, they */
- /* can be either time or transaction based. */
-
- if (test_time) {
- /* The user wanted to end the test after a period of time. */
- times_up = 0;
- trans_remaining = 0;
- start_timer(test_time);
- }
- else {
- /* The tester wanted to send a number of bytes. */
- trans_remaining = test_bytes;
- times_up = 1;
- }
-
- /* The cpu_start routine will grab the current time and possibly */
- /* value of the idle counter for later use in measuring cpu */
- /* utilization and/or service demand and thruput. */
-
- cpu_start(local_cpu_usage);
-
- /* We use an "OR" to control test execution. When the test is */
- /* controlled by time, the byte count check will always return false. */
- /* When the test is controlled by byte count, the time test will */
- /* always return false. When the test is finished, the whole */
- /* expression will go false and we will stop sending data. I think I */
- /* just arbitrarily decrement trans_remaining for the timed test, but */
- /* will not do that just yet... One other question is whether or not */
- /* the send buffer and the receive buffer should be the same buffer. */
-
- /* just for grins, start the port numbers at 65530. this should */
- /* quickly flush-out those broken implementations of TCP which treat */
- /* the port number as a signed 16 bit quantity. */
- myport = 65530;
- myaddr->sin_port = htons(myport);
-
- while ((!times_up) || (trans_remaining > 0)) {
-
- /* set up the data socket */
- send_socket = create_xti_endpoint(loc_xti_device);
-
- if (send_socket == INVALID_SOCKET) {
- perror("netperf: send_xti_tcp_conn_rr: tcp stream data socket");
- exit(1);
- }
-
- /* we set SO_REUSEADDR on the premis that no unreserved port */
- /* number on the local system is going to be already connected to */
- /* the remote netserver's port number. we might still have a */
- /* problem if there is a port in the unconnected state. In that */
- /* case, we might want to throw-in a goto to the point where we */
- /* increment the port number by one and try again. of course, this */
- /* could lead to a big load of spinning. one thing that I might */
- /* try later is to have the remote actually allocate a couple of */
- /* port numbers and cycle through those as well. depends on if we */
- /* can get through all the unreserved port numbers in less than */
- /* the length of the TIME_WAIT state raj 8/94 */
- one = 1;
- if(setsockopt(send_socket, SOL_SOCKET, SO_REUSEADDR,
- (char *)&one, sock_opt_len) == SOCKET_ERROR) {
- perror("netperf: send_xti_tcp_conn_rr: so_reuseaddr");
- exit(1);
- }
-
- /* we want to bind our socket to a particular port number. */
- if (bind(send_socket,
- (struct sockaddr *)myaddr,
- sizeof(struct sockaddr_in)) == SOCKET_ERROR) {
- printf("netperf: send_xti_tcp_conn_rr: tried to bind to port %d\n",
- ntohs(myaddr->sin_port));
- perror("netperf: send_xti_tcp_conn_rr: bind");
- exit(1);
- }
-
- /* Connect up to the remote port on the data socket */
- if (connect(send_socket,
- (struct sockaddr *)&server,
- sizeof(server)) == INVALID_SOCKET){
- if (errno == EINTR) {
- /* we hit the end of a */
- /* timed test. */
- timed_out = 1;
- break;
- }
- perror("netperf: data socket connect failed");
- printf("\tattempted to connect on socket %d to port %d",
- send_socket,
- ntohs(server.sin_port));
- printf(" from port %d \n",ntohs(myaddr->sin_port));
- exit(1);
- }
-
- /* send the request */
- if((len=send(send_socket,
- send_ring->buffer_ptr,
- req_size,
- 0)) != req_size) {
- if (errno == EINTR) {
- /* we hit the end of a */
- /* timed test. */
- timed_out = 1;
- break;
- }
- perror("send_xti_tcp_conn_rr: data send error");
- exit(1);
- }
- send_ring = send_ring->next;
-
- /* receive the response */
- rsp_bytes_left = rsp_size;
- temp_message_ptr = recv_ring->buffer_ptr;
- while(rsp_bytes_left > 0) {
- if((rsp_bytes_recvd=recv(send_socket,
- temp_message_ptr,
- rsp_bytes_left,
- 0)) == SOCKET_ERROR) {
- if (errno == EINTR) {
- /* We hit the end of a timed test. */
- timed_out = 1;
- break;
- }
- perror("send_xti_tcp_conn_rr: data recv error");
- exit(1);
- }
- rsp_bytes_left -= rsp_bytes_recvd;
- temp_message_ptr += rsp_bytes_recvd;
- }
- recv_ring = recv_ring->next;
-
- if (timed_out) {
- /* we may have been in a nested while loop - we need */
- /* another call to break. */
- break;
- }
-
- close(send_socket);
-
- nummessages++;
- if (trans_remaining) {
- trans_remaining--;
- }
-
- if (debug > 3) {
- fprintf(where,
- "Transaction %d completed on local port %d\n",
- nummessages,
- ntohs(myaddr->sin_port));
- fflush(where);
- }
-
-newport:
- /* pick a new port number */
- myport = ntohs(myaddr->sin_port);
- myport++;
- /* we do not want to use the port number that the server is */
- /* sitting at - this would cause us to fail in a loopback test */
-
- if (myport == ntohs(server.sin_port)) myport++;
-
- /* wrap the port number when we get to 65535. NOTE, some broken */
- /* TCP's might treat the port number as a signed 16 bit quantity. */
- /* we aren't interested in testing such broekn implementations :) */
- /* raj 8/94 */
- if (myport == 65535) {
- myport = 5000;
- }
- myaddr->sin_port = htons(myport);
-
- if (debug) {
- if ((myport % 1000) == 0) {
- printf("port %d\n",myport);
- }
- }
-
- }
-
- /* this call will always give us the elapsed time for the test, and */
- /* will also store-away the necessaries for cpu utilization */
-
- cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being measured? */
- /* how long did we really run? */
-
- /* Get the statistics from the remote end. The remote will have */
- /* calculated service demand and all those interesting things. If it */
- /* wasn't supposed to care, it will return obvious values. */
-
- recv_response();
- if (!netperf_response.content.serv_errno) {
- if (debug)
- fprintf(where,"remote results obtained\n");
- }
- else {
- Set_errno(netperf_response.content.serv_errno);
- perror("netperf: remote error");
-
- exit(1);
- }
-
- /* We now calculate what our thruput was for the test. In the future, */
- /* we may want to include a calculation of the thruput measured by */
- /* the remote, but it should be the case that for a TCP stream test, */
- /* that the two numbers should be *very* close... We calculate */
- /* bytes_sent regardless of the way the test length was controlled. */
- /* If it was time, we needed to, and if it was by bytes, the user may */
- /* have specified a number of bytes that wasn't a multiple of the */
- /* send_size, so we really didn't send what he asked for ;-) We use */
- /* Kbytes/s as the units of thruput for a TCP stream test, where K = */
- /* 1024. A future enhancement *might* be to choose from a couple of */
- /* unit selections. */
-
- bytes_xferd = (req_size * nummessages) + (rsp_size * nummessages);
- thruput = calc_thruput(bytes_xferd);
-
- if (local_cpu_usage || remote_cpu_usage) {
- /* We must now do a little math for service demand and cpu */
- /* utilization for the system(s) */
- /* Of course, some of the information might be bogus because */
- /* there was no idle counter in the kernel(s). We need to make */
- /* a note of this for the user's benefit...*/
- if (local_cpu_usage) {
- if (local_cpu_rate == 0.0) {
- fprintf(where,"WARNING WARNING WARNING WARNING WARNING WARNING WARNING!\n");
- fprintf(where,"Local CPU usage numbers based on process information only!\n");
- fflush(where);
- }
- local_cpu_utilization = calc_cpu_util(0.0);
- /* since calc_service demand is doing ms/Kunit we will */
- /* multiply the number of transaction by 1024 to get */
- /* "good" numbers */
- local_service_demand = calc_service_demand((double) nummessages*1024,
- 0.0,
- 0.0,
- 0);
- }
- else {
- local_cpu_utilization = -1.0;
- local_service_demand = -1.0;
- }
-
- if (remote_cpu_usage) {
- if (remote_cpu_rate == 0.0) {
- fprintf(where,"DANGER DANGER DANGER DANGER DANGER DANGER DANGER!\n");
- fprintf(where,"Remote CPU usage numbers based on process information only!\n");
- fflush(where);
- }
- remote_cpu_utilization = xti_tcp_conn_rr_result->cpu_util;
- /* since calc_service demand is doing ms/Kunit we will */
- /* multiply the number of transaction by 1024 to get */
- /* "good" numbers */
- remote_service_demand = calc_service_demand((double) nummessages*1024,
- 0.0,
- remote_cpu_utilization,
- xti_tcp_conn_rr_result->num_cpus);
- }
- else {
- remote_cpu_utilization = -1.0;
- remote_service_demand = -1.0;
- }
-
- /* We are now ready to print all the information. If the user */
- /* has specified zero-level verbosity, we will just print the */
- /* local service demand, or the remote service demand. If the */
- /* user has requested verbosity level 1, he will get the basic */
- /* "streamperf" numbers. If the user has specified a verbosity */
- /* of greater than 1, we will display a veritable plethora of */
- /* background information from outside of this block as it it */
- /* not cpu_measurement specific... */
-
- switch (verbosity) {
- case 0:
- if (local_cpu_usage) {
- fprintf(where,
- cpu_fmt_0,
- local_service_demand);
- }
- else {
- fprintf(where,
- cpu_fmt_0,
- remote_service_demand);
- }
- break;
- case 1:
- fprintf(where,
- cpu_fmt_1_line_1, /* the format string */
- lss_size, /* local sendbuf size */
- lsr_size,
- req_size, /* how large were the requests */
- rsp_size, /* guess */
- elapsed_time, /* how long was the test */
- nummessages/elapsed_time,
- local_cpu_utilization, /* local cpu */
- remote_cpu_utilization, /* remote cpu */
- local_service_demand, /* local service demand */
- remote_service_demand); /* remote service demand */
- fprintf(where,
- cpu_fmt_1_line_2,
- rss_size,
- rsr_size);
- break;
- }
- }
- else {
- /* The tester did not wish to measure service demand. */
- switch (verbosity) {
- case 0:
- fprintf(where,
- tput_fmt_0,
- nummessages/elapsed_time);
- break;
- case 1:
- fprintf(where,
- tput_fmt_1_line_1, /* the format string */
- lss_size,
- lsr_size,
- req_size, /* how large were the requests */
- rsp_size, /* how large were the responses */
- elapsed_time, /* how long did it take */
- nummessages/elapsed_time);
- fprintf(where,
- tput_fmt_1_line_2,
- rss_size, /* remote recvbuf size */
- rsr_size);
-
- break;
- }
- }
-
- /* it would be a good thing to include information about some of the */
- /* other parameters that may have been set for this test, but at the */
- /* moment, I do not wish to figure-out all the formatting, so I will */
- /* just put this comment here to help remind me that it is something */
- /* that should be done at a later time. */
-
- if (verbosity > 1) {
- /* The user wanted to know it all, so we will give it to him. */
- /* This information will include as much as we can find about */
- /* TCP statistics, the alignments of the sends and receives */
- /* and all that sort of rot... */
-
- fprintf(where,
- ksink_fmt);
- }
-
-}
-
-
-void
-recv_xti_tcp_conn_rr()
-{
-
- char *message;
- struct sockaddr_in myaddr_in,
- peeraddr_in;
- SOCKET s_listen,s_data;
- int addrlen;
- char *recv_message_ptr;
- char *send_message_ptr;
- char *temp_message_ptr;
- int trans_received;
- int trans_remaining;
- int bytes_sent;
- int request_bytes_recvd;
- int request_bytes_remaining;
- int timed_out = 0;
- float elapsed_time;
-
- struct xti_tcp_conn_rr_request_struct *xti_tcp_conn_rr_request;
- struct xti_tcp_conn_rr_response_struct *xti_tcp_conn_rr_response;
- struct xti_tcp_conn_rr_results_struct *xti_tcp_conn_rr_results;
-
- xti_tcp_conn_rr_request =
- (struct xti_tcp_conn_rr_request_struct *)netperf_request.content.test_specific_data;
- xti_tcp_conn_rr_response =
- (struct xti_tcp_conn_rr_response_struct *)netperf_response.content.test_specific_data;
- xti_tcp_conn_rr_results =
- (struct xti_tcp_conn_rr_results_struct *)netperf_response.content.test_specific_data;
-
- if (debug) {
- fprintf(where,"netserver: recv_xti_tcp_conn_rr: entered...\n");
- fflush(where);
- }
-
- /* We want to set-up the listen socket with all the desired */
- /* parameters and then let the initiator know that all is ready. If */
- /* socket size defaults are to be used, then the initiator will have */
- /* sent us 0's. If the socket sizes cannot be changed, then we will */
- /* send-back what they are. If that information cannot be determined, */
- /* then we send-back -1's for the sizes. If things go wrong for any */
- /* reason, we will drop back ten yards and punt. */
-
- /* If anything goes wrong, we want the remote to know about it. It */
- /* would be best if the error that the remote reports to the user is */
- /* the actual error we encountered, rather than some bogus unexpected */
- /* response type message. */
-
- if (debug) {
- fprintf(where,"recv_xti_tcp_conn_rr: setting the response type...\n");
- fflush(where);
- }
-
- netperf_response.content.response_type = XTI_TCP_CRR_RESPONSE;
-
- if (debug) {
- fprintf(where,"recv_xti_tcp_conn_rr: the response type is set...\n");
- fflush(where);
- }
-
- /* set-up the data buffer with the requested alignment and offset */
- message = (char *)malloc(DATABUFFERLEN);
- if (message == NULL) {
- printf("malloc(%d) failed!\n", DATABUFFERLEN);
- exit(1);
- }
-
- /* We now alter the message_ptr variables to be at the desired */
- /* alignments with the desired offsets. */
-
- if (debug) {
- fprintf(where,
- "recv_xti_tcp_conn_rr: requested recv alignment of %d offset %d\n",
- xti_tcp_conn_rr_request->recv_alignment,
- xti_tcp_conn_rr_request->recv_offset);
- fprintf(where,
- "recv_xti_tcp_conn_rr: requested send alignment of %d offset %d\n",
- xti_tcp_conn_rr_request->send_alignment,
- xti_tcp_conn_rr_request->send_offset);
- fflush(where);
- }
-
- recv_message_ptr = ALIGN_BUFFER(message, xti_tcp_conn_rr_request->recv_alignment, xti_tcp_conn_rr_request->recv_offset);
-
- send_message_ptr = ALIGN_BUFFER(message, xti_tcp_conn_rr_request->send_alignment, xti_tcp_conn_rr_request->send_offset);
-
- if (debug) {
- fprintf(where,"recv_xti_tcp_conn_rr: receive alignment and offset set...\n");
- fflush(where);
- }
-
- /* Let's clear-out our sockaddr for the sake of cleanlines. Then we */
- /* can put in OUR values !-) At some point, we may want to nail this */
- /* socket to a particular network-level address, but for now, */
- /* INADDR_ANY should be just fine. */
-
- bzero((char *)&myaddr_in,
- sizeof(myaddr_in));
- myaddr_in.sin_family = AF_INET;
- myaddr_in.sin_addr.s_addr = INADDR_ANY;
- myaddr_in.sin_port = 0;
-
- /* Grab a socket to listen on, and then listen on it. */
-
- if (debug) {
- fprintf(where,"recv_xti_tcp_conn_rr: grabbing a socket...\n");
- fflush(where);
- }
-
- /* create_xti_endpoint expects to find some things in the global */
- /* variables, so set the globals based on the values in the request. */
- /* once the socket has been created, we will set the response values */
- /* based on the updated value of those globals. raj 7/94 */
- lss_size = xti_tcp_conn_rr_request->send_buf_size;
- lsr_size = xti_tcp_conn_rr_request->recv_buf_size;
- loc_nodelay = xti_tcp_conn_rr_request->no_delay;
- loc_rcvavoid = xti_tcp_conn_rr_request->so_rcvavoid;
- loc_sndavoid = xti_tcp_conn_rr_request->so_sndavoid;
-
- s_listen = create_xti_endpoint(loc_xti_device);
-
- if (s_listen == INVALID_SOCKET) {
- netperf_response.content.serv_errno = errno;
- send_response();
- if (debug) {
- fprintf(where,"could not create data socket\n");
- fflush(where);
- }
- exit(1);
- }
-
- /* Let's get an address assigned to this socket so we can tell the */
- /* initiator how to reach the data socket. There may be a desire to */
- /* nail this socket to a specific IP address in a multi-homed, */
- /* multi-connection situation, but for now, we'll ignore the issue */
- /* and concentrate on single connection testing. */
-
- if (bind(s_listen,
- (struct sockaddr *)&myaddr_in,
- sizeof(myaddr_in)) == SOCKET_ERROR) {
- netperf_response.content.serv_errno = errno;
- close(s_listen);
- send_response();
- if (debug) {
- fprintf(where,"could not bind\n");
- fflush(where);
- }
- exit(1);
- }
-
- /* Now, let's set-up the socket to listen for connections */
- if (listen(s_listen, 5) == SOCKET_ERROR) {
- netperf_response.content.serv_errno = errno;
- close(s_listen);
- send_response();
- if (debug) {
- fprintf(where,"could not listen\n");
- fflush(where);
- }
- exit(1);
- }
-
- /* now get the port number assigned by the system */
- addrlen = sizeof(myaddr_in);
- if (getsockname(s_listen,
- (struct sockaddr *)&myaddr_in,
- &addrlen) == SOCKET_ERROR){
- netperf_response.content.serv_errno = errno;
- close(s_listen);
- send_response();
- if (debug) {
- fprintf(where,"could not geetsockname\n");
- fflush(where);
- }
- exit(1);
- }
-
- /* Now myaddr_in contains the port and the internet address this is */
- /* returned to the sender also implicitly telling the sender that the */
- /* socket buffer sizing has been done. */
-
- xti_tcp_conn_rr_response->data_port_number = (int) ntohs(myaddr_in.sin_port);
- if (debug) {
- fprintf(where,"telling the remote to call me at %d\n",
- xti_tcp_conn_rr_response->data_port_number);
- fflush(where);
- }
- netperf_response.content.serv_errno = 0;
-
- /* But wait, there's more. If the initiator wanted cpu measurements, */
- /* then we must call the calibrate routine, which will return the max */
- /* rate back to the initiator. If the CPU was not to be measured, or */
- /* something went wrong with the calibration, we will return a 0.0 to */
- /* the initiator. */
-
- xti_tcp_conn_rr_response->cpu_rate = 0.0; /* assume no cpu */
- if (xti_tcp_conn_rr_request->measure_cpu) {
- xti_tcp_conn_rr_response->measure_cpu = 1;
- xti_tcp_conn_rr_response->cpu_rate =
- calibrate_local_cpu(xti_tcp_conn_rr_request->cpu_rate);
- }
-
-
-
- /* before we send the response back to the initiator, pull some of */
- /* the socket parms from the globals */
- xti_tcp_conn_rr_response->send_buf_size = lss_size;
- xti_tcp_conn_rr_response->recv_buf_size = lsr_size;
- xti_tcp_conn_rr_response->no_delay = loc_nodelay;
- xti_tcp_conn_rr_response->so_rcvavoid = loc_rcvavoid;
- xti_tcp_conn_rr_response->so_sndavoid = loc_sndavoid;
-
- send_response();
-
- addrlen = sizeof(peeraddr_in);
-
- /* Now it's time to start receiving data on the connection. We will */
- /* first grab the apropriate counters and then start grabbing. */
-
- cpu_start(xti_tcp_conn_rr_request->measure_cpu);
-
- /* The loop will exit when the sender does a shutdown, which will */
- /* return a length of zero */
-
- if (xti_tcp_conn_rr_request->test_length > 0) {
- times_up = 0;
- trans_remaining = 0;
- start_timer(xti_tcp_conn_rr_request->test_length + PAD_TIME);
- }
- else {
- times_up = 1;
- trans_remaining = xti_tcp_conn_rr_request->test_length * -1;
- }
-
- trans_received = 0;
-
- while ((!times_up) || (trans_remaining > 0)) {
-
- /* accept a connection from the remote */
- if ((s_data=accept(s_listen,
- (struct sockaddr *)&peeraddr_in,
- &addrlen)) == INVALID_SOCKET) {
- if (errno == EINTR) {
- /* the timer popped */
- timed_out = 1;
- break;
- }
- fprintf(where,"recv_xti_tcp_conn_rr: accept: errno = %d\n",errno);
- fflush(where);
- close(s_listen);
-
- exit(1);
- }
-
- if (debug) {
- fprintf(where,"recv_xti_tcp_conn_rr: accepted data connection.\n");
- fflush(where);
- }
-
- temp_message_ptr = recv_message_ptr;
- request_bytes_remaining = xti_tcp_conn_rr_request->request_size;
-
- /* receive the request from the other side */
- while(request_bytes_remaining > 0) {
- if((request_bytes_recvd=recv(s_data,
- temp_message_ptr,
- request_bytes_remaining,
- 0)) == SOCKET_ERROR) {
- if (errno == EINTR) {
- /* the timer popped */
- timed_out = 1;
- break;
- }
- netperf_response.content.serv_errno = errno;
- send_response();
- exit(1);
- }
- else {
- request_bytes_remaining -= request_bytes_recvd;
- temp_message_ptr += request_bytes_recvd;
- }
- }
-
- if (timed_out) {
- /* we hit the end of the test based on time - lets */
- /* bail out of here now... */
- fprintf(where,"yo5\n");
- fflush(where);
- break;
- }
-
- /* Now, send the response to the remote */
- if((bytes_sent=send(s_data,
- send_message_ptr,
- xti_tcp_conn_rr_request->response_size,
- 0)) == SOCKET_ERROR) {
- if (errno == EINTR) {
- /* the test timer has popped */
- timed_out = 1;
- fprintf(where,"yo6\n");
- fflush(where);
- break;
- }
- netperf_response.content.serv_errno = 99;
- send_response();
- exit(1);
- }
-
- trans_received++;
- if (trans_remaining) {
- trans_remaining--;
- }
-
- if (debug) {
- fprintf(where,
- "recv_xti_tcp_conn_rr: Transaction %d complete\n",
- trans_received);
- fflush(where);
- }
-
- /* close the connection */
- close(s_data);
-
- }
-
-
- /* The loop now exits due to timeout or transaction count being */
- /* reached */
-
- cpu_stop(xti_tcp_conn_rr_request->measure_cpu,&elapsed_time);
-
- if (timed_out) {
- /* we ended the test by time, which was at least 2 seconds */
- /* longer than we wanted to run. so, we want to subtract */
- /* PAD_TIME from the elapsed_time. */
- elapsed_time -= PAD_TIME;
- }
- /* send the results to the sender */
-
- if (debug) {
- fprintf(where,
- "recv_xti_tcp_conn_rr: got %d transactions\n",
- trans_received);
- fflush(where);
- }
-
- xti_tcp_conn_rr_results->bytes_received = (trans_received *
- (xti_tcp_conn_rr_request->request_size +
- xti_tcp_conn_rr_request->response_size));
- xti_tcp_conn_rr_results->trans_received = trans_received;
- xti_tcp_conn_rr_results->elapsed_time = elapsed_time;
- if (xti_tcp_conn_rr_request->measure_cpu) {
- xti_tcp_conn_rr_results->cpu_util = calc_cpu_util(elapsed_time);
- }
-
- if (debug) {
- fprintf(where,
- "recv_xti_tcp_conn_rr: test complete, sending results.\n");
- fflush(where);
- }
-
- send_response();
-
-}
-
-void
-print_xti_usage()
-{
-
- fwrite(xti_usage, sizeof(char), strlen(xti_usage), stdout);
- exit(1);
-
-}
-
-void
-scan_xti_args(int argc, char *argv[])
-{
-#define XTI_ARGS "Dhm:M:r:s:S:Vw:W:X:"
- extern int optind, opterrs; /* index of first unused arg */
- extern char *optarg; /* pointer to option string */
-
- int c;
-
- char
- arg1[BUFSIZ], /* argument holders */
- arg2[BUFSIZ];
-
- if (no_control) {
- fprintf(where,
- "The XTI tests do not know how to run with no control connection\n");
- exit(-1);
- }
-
- /* Go through all the command line arguments and break them */
- /* out. For those options that take two parms, specifying only */
- /* the first will set both to that value. Specifying only the */
- /* second will leave the first untouched. To change only the */
- /* first, use the form "first," (see the routine break_args.. */
-
- while ((c= getopt(argc, argv, XTI_ARGS)) != EOF) {
- switch (c) {
- case '?':
- case 'h':
- print_xti_usage();
- exit(1);
- case 'D':
- /* set the TCP nodelay flag */
- loc_nodelay = 1;
- rem_nodelay = 1;
- break;
- case 's':
- /* set local socket sizes */
- break_args(optarg,arg1,arg2);
- if (arg1[0])
- lss_size = convert(arg1);
- if (arg2[0])
- lsr_size = convert(arg2);
- break;
- case 'S':
- /* set remote socket sizes */
- break_args(optarg,arg1,arg2);
- if (arg1[0])
- rss_size = convert(arg1);
- if (arg2[0])
- rsr_size = convert(arg2);
- break;
- case 'r':
- /* set the request/response sizes */
- break_args(optarg,arg1,arg2);
- if (arg1[0])
- req_size = convert(arg1);
- if (arg2[0])
- rsp_size = convert(arg2);
- break;
- case 'm':
- /* set the send size */
- send_size = convert(optarg);
- break;
- case 'M':
- /* set the recv size */
- recv_size = convert(optarg);
- break;
- case 'W':
- /* set the "width" of the user space data */
- /* buffer. This will be the number of */
- /* send_size buffers malloc'd in the */
- /* *_STREAM test. It may be enhanced to set */
- /* both send and receive "widths" but for now */
- /* it is just the sending *_STREAM. */
- send_width = convert(optarg);
- break;
- case 'V' :
- /* we want to do copy avoidance and will set */
- /* it for everything, everywhere, if we really */
- /* can. of course, we don't know anything */
- /* about the remote... */
-#ifdef SO_SND_COPYAVOID
- loc_sndavoid = 1;
-#else
- loc_sndavoid = 0;
- printf("Local send copy avoidance not available.\n");
-#endif
-#ifdef SO_RCV_COPYAVOID
- loc_rcvavoid = 1;
-#else
- loc_rcvavoid = 0;
- printf("Local recv copy avoidance not available.\n");
-#endif
- rem_sndavoid = 1;
- rem_rcvavoid = 1;
- break;
- case 'X':
- /* set the xti device file name(s) */
- break_args(optarg,arg1,arg2);
- if (arg1[0])
- strcpy(loc_xti_device,arg1);
- if (arg2[0])
- strcpy(rem_xti_device,arg2);
- break;
- };
- }
-}
-#endif /* WANT_XTI */
diff --git a/nettest_xti.h b/nettest_xti.h
deleted file mode 100644
index 3bf9968..0000000
--- a/nettest_xti.h
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- * Copyright (C) 1995,2004 Hewlett-Packard Company
- */
-
- /* This file contains the test-specific definitions for netperf's BSD */
- /* sockets tests */
-
-struct xti_tcp_stream_request_struct {
- int send_buf_size;
- int recv_buf_size; /* how big does the client want it - the */
- /* receive socket buffer that is */
- int receive_size; /* how many bytes do we want to receive at one */
- /* time? */
- int recv_alignment; /* what is the alignment of the receive */
- /* buffer? */
- int recv_offset; /* and at what offset from that alignment? */
- int no_delay; /* do we disable the nagle algorithm for send */
- /* coalescing? */
- int measure_cpu; /* does the client want server cpu utilization */
- /* measured? */
- float cpu_rate; /* do we know how fast the cpu is already? */
- int test_length; /* how long is the test? */
- int so_rcvavoid; /* do we want the remote to avoid copies on */
- /* receives? */
- int so_sndavoid; /* do we want the remote to avoid send copies? */
- int dirty_count; /* how many integers in the receive buffer */
- /* should be made dirty before calling recv? */
- int clean_count; /* how many integers should be read from the */
- /* recv buffer before calling recv? */
- int dev_name_len; /* the length of the device name string. this */
- /* is used to put it into the proper order on */
- /* @#$% byte-swapped boxes... */
- char xti_device[32]; /* the path to the dlpi device */
-};
-
-struct xti_tcp_stream_response_struct {
- int recv_buf_size; /* how big does the client want it */
- int receive_size;
- int no_delay;
- int measure_cpu; /* does the client want server cpu */
- int test_length; /* how long is the test? */
- int send_buf_size;
- int data_port_number; /* connect to me here */
- float cpu_rate; /* could we measure */
- int so_rcvavoid; /* could the remote avoid receive copies? */
- int so_sndavoid; /* could the remote avoid send copies? */
-};
-
-struct xti_tcp_stream_results_struct {
- double bytes_received;
- unsigned int recv_calls;
- float elapsed_time; /* how long the test ran */
- float cpu_util; /* -1 if not measured */
- float serv_dem; /* -1 if not measured */
- int cpu_method; /* how was cpu util measured? */
- int num_cpus; /* how many CPUs were there */
-};
-
-struct xti_tcp_rr_request_struct {
- int recv_buf_size; /* how big does the client want it */
- int send_buf_size;
- int recv_alignment;
- int recv_offset;
- int send_alignment;
- int send_offset;
- int request_size;
- int response_size;
- int no_delay;
- int measure_cpu; /* does the client want server cpu */
- float cpu_rate; /* do we know how fast the cpu is? */
- int test_length; /* how long is the test? */
- int so_rcvavoid; /* do we want the remote to avoid receive */
- /* copies? */
- int so_sndavoid; /* do we want the remote to avoid send copies? */
- int dev_name_len; /* the length of the device name string. this */
- /* is used to put it into the proper order on */
- /* @#$% byte-swapped boxes... */
- char xti_device[32]; /* the path to the dlpi device */
-};
-
-struct xti_tcp_rr_response_struct {
- int recv_buf_size; /* how big does the client want it */
- int no_delay;
- int measure_cpu; /* does the client want server cpu */
- int test_length; /* how long is the test? */
- int send_buf_size;
- int data_port_number; /* connect to me here */
- float cpu_rate; /* could we measure */
- int so_rcvavoid; /* could the remote avoid receive copies? */
- int so_sndavoid; /* could the remote avoid send copies? */
-};
-
-struct xti_tcp_rr_results_struct {
- unsigned int bytes_received; /* ignored initially */
- unsigned int recv_calls; /* ignored initially */
- unsigned int trans_received; /* not ignored */
- float elapsed_time; /* how long the test ran */
- float cpu_util; /* -1 if not measured */
- float serv_dem; /* -1 if not measured */
- int cpu_method; /* how was cpu util measured? */
- int num_cpus; /* how many CPUs were there */
-};
-
-struct xti_tcp_conn_rr_request_struct {
- int recv_buf_size; /* how big does the client want it */
- int send_buf_size;
- int recv_alignment;
- int recv_offset;
- int send_alignment;
- int send_offset;
- int request_size;
- int response_size;
- int no_delay;
- int measure_cpu; /* does the client want server cpu */
- float cpu_rate; /* do we know how fast the cpu is? */
- int test_length; /* how long is the test? */
- int so_rcvavoid; /* do we want the remote to avoid receive */
- /* copies? */
- int so_sndavoid; /* do we want the remote to avoid send copies? */
- int dev_name_len; /* the length of the device name string. this */
- /* is used to put it into the proper order on */
- /* @#$% byte-swapped boxes... */
- char xti_device[32]; /* the path to the dlpi device */
-};
-
-
-struct xti_tcp_conn_rr_response_struct {
- int recv_buf_size; /* how big does the client want it */
- int no_delay;
- int measure_cpu; /* does the client want server cpu */
- int test_length; /* how long is the test? */
- int send_buf_size;
- int data_port_number; /* connect to me here */
- float cpu_rate; /* could we measure */
- int so_rcvavoid; /* could the remote avoid receive copies? */
- int so_sndavoid; /* could the remote avoid send copies? */
-};
-
-struct xti_tcp_conn_rr_results_struct {
- unsigned int bytes_received; /* ignored initially */
- unsigned int recv_calls; /* ignored initially */
- unsigned int trans_received; /* not ignored */
- float elapsed_time; /* how long the test ran */
- float cpu_util; /* -1 if not measured */
- float serv_dem; /* -1 if not measured */
- int cpu_method; /* how was cpu util measured? */
- int num_cpus; /* how many CPUs were there */
-};
-
-struct xti_udp_stream_request_struct {
- int recv_buf_size;
- int message_size;
- int recv_alignment;
- int recv_offset;
- int checksum_off; /* not used. left in for compatibility */
- int measure_cpu;
- float cpu_rate;
- int test_length;
- int so_rcvavoid; /* do we want the remote to avoid receive */
- /* copies? */
- int so_sndavoid; /* do we want the remote to avoid send copies? */
- int dev_name_len; /* the length of the device name string. this */
- /* is used to put it into the proper order on */
- /* @#$% byte-swapped boxes... */
- char xti_device[32]; /* the path to the dlpi device */
-};
-
-struct xti_udp_stream_response_struct {
- int recv_buf_size;
- int send_buf_size;
- int measure_cpu;
- int test_length;
- int data_port_number;
- float cpu_rate;
- int so_rcvavoid; /* could the remote avoid receive copies? */
- int so_sndavoid; /* could the remote avoid send copies? */
-};
-
-struct xti_udp_stream_results_struct {
- unsigned int messages_recvd;
- unsigned int bytes_received;
- float elapsed_time;
- float cpu_util;
- int cpu_method; /* how was cpu util measured? */
- int num_cpus; /* how many CPUs were there */
-};
-
-
-struct xti_udp_rr_request_struct {
- int recv_buf_size; /* how big does the client want it */
- int send_buf_size;
- int recv_alignment;
- int recv_offset;
- int send_alignment;
- int send_offset;
- int request_size;
- int response_size;
- int no_delay;
- int measure_cpu; /* does the client want server cpu */
- float cpu_rate; /* do we know how fast the cpu is? */
- int test_length; /* how long is the test? */
- int so_rcvavoid; /* do we want the remote to avoid receive */
- /* copies? */
- int so_sndavoid; /* do we want the remote to avoid send copies? */
- int dev_name_len; /* the length of the device name string. this */
- /* is used to put it into the proper order on */
- /* @#$% byte-swapped boxes... */
- char xti_device[32]; /* the path to the dlpi device */
-};
-
-struct xti_udp_rr_response_struct {
- int recv_buf_size; /* how big does the client want it */
- int no_delay;
- int measure_cpu; /* does the client want server cpu */
- int test_length; /* how long is the test? */
- int send_buf_size;
- int data_port_number; /* connect to me here */
- float cpu_rate; /* could we measure */
- int so_rcvavoid; /* could the remote avoid receive copies? */
- int so_sndavoid; /* could the remote avoid send copies? */
-};
-
-struct xti_udp_rr_results_struct {
- unsigned int bytes_received; /* ignored initially */
- unsigned int recv_calls; /* ignored initially */
- unsigned int trans_received; /* not ignored */
- float elapsed_time; /* how long the test ran */
- float cpu_util; /* -1 if not measured */
- float serv_dem; /* -1 if not measured */
- int cpu_method; /* how was cpu util measured? */
- int num_cpus; /* how many CPUs were there */
-};
-
-extern void send_xti_tcp_stream(char remote_host[]);
-
-extern void recv_xti_tcp_stream();
-
-extern void send_xti_tcp_rr(char remote_host[]);
-
-extern void send_xti_udp_stream(char remote_host[]);
-
-extern void recv_xti_udp_stream();
-
-extern void send_xti_udp_rr(char remote_host[]);
-
-extern void recv_xti_udp_rr();
-
-extern void recv_xti_tcp_rr();
-
-extern void send_xti_tcp_conn_rr(char remote_host[]);
-
-extern void recv_xti_tcp_conn_rr();
-
-extern void scan_xti_args(int argc, char *argv[]);
-
-
-
-
-
-
-
-
-
-