/*
Copyright (C) 1993-2012 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 162 /* 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 PASSPHRASE 6
#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_OMNI 97
#define OMNI_RESPONSE 98
#define OMNI_RESULTS 99
#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
#define DO_SYSINFO 600
#define SYSINFO_RESPONSE 601
#if HAVE_INTTYPES_H
# include <inttypes.h>
#else
# if HAVE_STDINT_H
# include <stdint.h>
#else
# ifdef WIN32
# include "missing\inttypes.h"
# endif
# endif
#endif
enum sock_buffer{
SEND_BUFFER,
RECV_BUFFER
};
enum netperf_output_modes {
HUMAN = 0,
CSV,
KEYVAL,
};
/* some defines for security types, perhaps these would be better
elsewhere but for now here they are */
#define NSEC_UNKNOWN -1
#define NSEC_DISABLED 0
#define NSEC_PERMISSIVE 1
#define NSEC_ENFORCING 2
#define NSEC_TYPE_UNKNOWN -1
#define NSEC_TYPE_SELINUX 1
#define NETFW_UNKNOWN -1
#define NETFW_IPTABLES 1
/* 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 */
void *completion_ptr; /* a pointer to information for async completion */
/* these are for sendfile calls and at some point we should consider
using a union but it isn't really all that much extra space */
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. */
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 */
int fildes; /* the file descriptor of the source
file */
int flags; /* the flags to pass to sendfile() -
presently unused and should be
set to zero when the ring is
setup. */
};
/* everything in percent except otherwise stated */
struct cpu_stats_struct {
float cpu_util; /* mandatory = 100% - %idle */
/* The following are optional, dependent upon netcpu implementation */
float cpu_user;
float cpu_system;
float cpu_iowait;
float cpu_irq;
float cpu_swintr;
/* mandatory */
float peak_cpu_util;
int peak_cpu_id; /* ID of most loaded CPU */
};
/* +*+ 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_ECONNREFUSED(return_value) (errno == ECONNREFUSED)
#define SOCKET_EADDRINUSE(return_value) (errno == EADDRINUSE)
#define SOCKET_EADDRNOTAVAIL(return_value) (errno == EADDRNOTAVAIL)
#define SOCKET_EAGAIN(return_value) (errno == EAGAIN)
#define SOCKET_EWOULDBLOCK(return_value) (errno == EWOULDBLOCK)
#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) || \
(errno == ENOTSOCK) ))
#define SOCKET_EADDRINUSE(return_value) \
(((return_value) == SOCKET_ERROR) && \
((errno == WSAEADDRINUSE) ))
#define SOCKET_EADDRNOTAVAIL(return_value) \
(((return_value) == SOCKET_ERROR) && \
((errno == WSAEADDRNOTAVAIL) ))
/* guessing here, and equating for one that doesn't exist */
#define SOCKET_EAGAIN(return_value) \
(((return_value) == SOCKET_ERROR) && (errno == WSAEWOULDBLOCK))
#define SOCKET_EWOULDBLOCK(return_value) \
(((return_value) == SOCKET_ERROR) && (errno == WSAEWOULDBLOCK))
#endif
#ifdef HAVE_SENDFILE
#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 char *local_sysname, *remote_sysname;
extern char *local_release, *remote_release;
extern char *local_version, *remote_version;
extern char *local_machine, *remote_machine;
extern int local_data_family;
extern int remote_data_family;
extern int control_family;
extern union netperf_request_struct netperf_request;
extern union netperf_response_struct netperf_response;
extern struct cpu_stats_struct lib_local_cpu_stats;
extern struct cpu_stats_struct lib_remote_cpu_stats;
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 enum netperf_output_modes netperf_output_mode;
#if defined(WANT_INTERVALS) || defined(WANT_DEMO)
extern int demo_mode;
extern double demo_interval;
extern double demo_units;
extern double units_this_tick;
#if defined(WANT_DEMO)
extern void demo_rr_interval(uint32_t units);
extern void demo_rr_setup(uint32_t units);
extern void demo_stream_interval(uint32_t units);
extern void demo_interval_tick(uint32_t units);
extern void demo_interval_final();
#endif
#endif
extern void netlib_init();
extern int netlib_get_page_size();
extern void install_signal_catchers();
extern struct addrinfo *resolve_host(char hostname[],
char port[],
int af);
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 int recv_request();
extern int recv_request_timed_n(int n, int seconds);
extern void send_request_n(int n); /* convert only the first N ints */
extern void recv_response_n(int n); /* of the test-specific data via */
extern void send_response_n(int n); /* htonl/ntonl as required */
extern int recv_request_n(int n);
extern void fixup_request_n(int n);
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 double get_result_confid();
extern double get_loc_cpu_confid();
extern double get_rem_cpu_confid();
extern void display_confidence();
extern void get_sock_buffer(SOCKET sd,
enum sock_buffer which,
int *effective_sizep);
extern void set_sock_buffer(SOCKET sd,
enum sock_buffer which,
int requested_size,
int *effective_sizep);
extern char *format_units();
extern void get_remote_system_info();
extern char *inet_ftos(int family);
extern char *inet_ttos(int type);
extern char *inet_ptos(int protocol);
extern char *nsec_enabled_to_str(int enabled);
extern char *nsec_type_to_str(int type);
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 random_ip_address(struct addrinfo *res, int mask_len);
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);
extern char *find_egress_interface(struct sockaddr *source, struct sockaddr *dest);
extern char *find_interface_slot(char *interface_name);
extern void find_interface_ids(char *interface_name, int *vendor, int *device, int *sub_vend, int *sub_dev);
extern void find_driver_info(char *ifname, char *driver, char *version, char *firmware, char *bus, int len);
extern void find_system_info(char **system_model, char **cpu_model, int *cpu_frequency);
extern int HIST_get_percentile();
extern void HIST_get_stats();
extern void HIST_purge();
extern void find_security_info(int *enabled, int *type, char **specific);
extern void demo_first_timestamp();
extern void demo_reset();
extern void demo_stream_setup(uint32_t a, uint32_t b);
#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);
/* this one determines the unit divisor based on libfmt */
extern float calc_service_demand_fmt(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 ring_elt *alloc_sendfile_buf_ring();
extern int netperf_sendfile(SOCKET send_socket, struct ring_elt *send_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);
extern void stop_itimer(void);
#endif
/* these are all for the confidence interval stuff */
extern double confidence;
extern double result_confid;
extern double loc_cpu_confid;
extern double rem_cpu_confid;
extern int lib_cpu_map[];
#endif
#ifdef WIN32
#define close(x) closesocket(x)
#define strcasecmp(a,b) _stricmp(a,b)
#define getpid() ((int)GetCurrentProcessId())
#endif
#ifdef WIN32
extern HANDLE WinTimer;
#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
#define strdup _strdup
#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