/* 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