Home | History | Annotate | Download | only in netperf
      1 char    netlib_id[]="\
      2 @(#)netlib.c (c) Copyright 1993-2007 Hewlett-Packard Company. Version 2.4.3";
      3 
      4 
      5 /****************************************************************/
      6 /*                                                              */
      7 /*      netlib.c                                                */
      8 /*                                                              */
      9 /*      the common utility routines available to all...         */
     10 /*                                                              */
     11 /*      establish_control()     establish the control socket    */
     12 /*      calibrate_local_cpu()   do local cpu calibration        */
     13 /*      calibrate_remote_cpu()  do remote cpu calibration       */
     14 /*      send_request()          send a request to the remote    */
     15 /*      recv_response()         receive a response from remote  */
     16 /*      send_response()         send a response to the remote   */
     17 /*      recv_request()          recv a request from the remote  */
     18 /*      dump_request()          dump request contents           */
     19 /*      dump_response()         dump response contents          */
     20 /*      cpu_start()             start measuring cpu             */
     21 /*      cpu_stop()              stop measuring cpu              */
     22 /*      calc_cpu_util()         calculate the cpu utilization   */
     23 /*      calc_service_demand()   calculate the service demand    */
     24 /*      calc_thruput()          calulate the tput in units      */
     25 /*      calibrate()             really calibrate local cpu      */
     26 /*      identify_local()        print local host information    */
     27 /*      identify_remote()       print remote host information   */
     28 /*      format_number()         format the number (KB, MB,etc)  */
     29 /*      format_units()          return the format in english    */
     30 /*      msec_sleep()            sleep for some msecs            */
     31 /*      start_timer()           start a timer                   */
     32 /*                                                              */
     33 /*      the routines you get when WANT_DLPI is defined...         */
     34 /*                                                              */
     35 /*      dl_open()               open a file descriptor and      */
     36 /*                              attach to the card              */
     37 /*      dl_mtu()                find the MTU of the card        */
     38 /*      dl_bind()               bind the sap do the card        */
     39 /*      dl_connect()            sender's have of connect        */
     40 /*      dl_accpet()             receiver's half of connect      */
     41 /*      dl_set_window()         set the window size             */
     42 /*      dl_stats()              retrieve statistics             */
     43 /*      dl_send_disc()          initiate disconnect (sender)    */
     44 /*      dl_recv_disc()          accept disconnect (receiver)    */
     45 /****************************************************************/
     46 
     47 /****************************************************************/
     48 /*                                                              */
     49 /*      Global include files                                    */
     50 /*                                                              */
     51 /****************************************************************/
     52 
     53 #ifdef HAVE_CONFIG_H
     54 #include <config.h>
     55 #endif
     56 
     57  /* It would seem that most of the includes being done here from */
     58  /* "sys/" actually have higher-level wrappers at just /usr/include. */
     59  /* This is based on a spot-check of a couple systems at my disposal. */
     60  /* If you have trouble compiling you may want to add "sys/" raj 10/95 */
     61 #include <limits.h>
     62 #include <signal.h>
     63 #ifdef MPE
     64 #  define NSIG _NSIG
     65 #endif /* MPE */
     66 #include <sys/types.h>
     67 #include <fcntl.h>
     68 #include <stdio.h>
     69 #include <stdlib.h>
     70 #include <math.h>
     71 #include <string.h>
     72 #include <assert.h>
     73 #ifdef HAVE_ENDIAN_H
     74 #include <endian.h>
     75 #endif
     76 
     77 
     78 #ifndef WIN32
     79  /* at some point, I would like to get rid of all these "sys/" */
     80  /* includes where appropriate. if you have a system that requires */
     81  /* them, speak now, or your system may not comile later revisions of */
     82  /* netperf. raj 1/96 */
     83 #include <unistd.h>
     84 #include <sys/stat.h>
     85 #include <sys/times.h>
     86 #ifndef MPE
     87 #include <time.h>
     88 #include <sys/time.h>
     89 #endif /* MPE */
     90 #include <sys/socket.h>
     91 #include <netinet/in.h>
     92 #include <arpa/inet.h>
     93 #include <netdb.h>
     94 #include <errno.h>
     95 #include <sys/utsname.h>
     96 #if !defined(MPE) && !defined(__VMS)
     97 #include <sys/param.h>
     98 #endif /* MPE */
     99 
    100 #else /* WIN32 */
    101 
    102 #include <process.h>
    103 #include <time.h>
    104 #include <winsock2.h>
    105 #define netperf_socklen_t socklen_t
    106 #include <windows.h>
    107 
    108 /* the only time someone should need to define DONT_IPV6 in the
    109    "sources" file is if they are trying to compile on Windows 2000 or
    110    NT4 and I suspect this may not be their only problem :) */
    111 #ifndef DONT_IPV6
    112 #include <ws2tcpip.h>
    113 #endif
    114 
    115 #include <windows.h>
    116 
    117 #define SIGALRM (14)
    118 #define sleep(x) Sleep((x)*1000)
    119 
    120 #endif /* WIN32 */
    121 
    122 #ifdef _AIX
    123 #include <sys/select.h>
    124 #include <sys/sched.h>
    125 #include <sys/pri.h>
    126 #define PRIORITY PRI_LOW
    127 #else/* _AIX */
    128 #ifdef __sgi
    129 #include <sys/prctl.h>
    130 #include <sys/schedctl.h>
    131 #define PRIORITY NDPLOMIN
    132 #endif /* __sgi */
    133 #endif /* _AIX */
    134 
    135 #ifdef WANT_DLPI
    136 #include <sys/stream.h>
    137 #include <sys/stropts.h>
    138 #include <sys/poll.h>
    139 #ifdef __osf__
    140 #include <sys/dlpihdr.h>
    141 #else /* __osf__ */
    142 #include <sys/dlpi.h>
    143 #ifdef __hpux
    144 #include <sys/dlpi_ext.h>
    145 #endif /* __hpux */
    146 #endif /* __osf__ */
    147 #endif /* WANT_DLPI */
    148 
    149 #ifdef HAVE_MPCTL
    150 #include <sys/mpctl.h>
    151 #endif
    152 
    153 #if !defined(HAVE_GETADDRINFO) || !defined(HAVE_GETNAMEINFO)
    154 # include "missing/getaddrinfo.h"
    155 #endif
    156 
    157 
    158 #ifdef WANT_HISTOGRAM
    159 #include "hist.h"
    160 #endif /* WANT_HISTOGRAM */
    161 /****************************************************************/
    162 /*                                                              */
    163 /*      Local Include Files                                     */
    164 /*                                                              */
    165 /****************************************************************/
    166 #define NETLIB
    167 #include "netlib.h"
    168 #include "netsh.h"
    169 #include "netcpu.h"
    170 
    171 /****************************************************************/
    172 /*                                                              */
    173 /*      Global constants, macros and variables                  */
    174 /*                                                              */
    175 /****************************************************************/
    176 
    177 #if defined(WIN32) || defined(__VMS)
    178 struct  timezone {
    179         int     dummy ;
    180         } ;
    181 #ifndef __VMS
    182 SOCKET     win_kludge_socket = INVALID_SOCKET;
    183 SOCKET     win_kludge_socket2 = INVALID_SOCKET;
    184 #endif /* __VMS */
    185 #endif /* WIN32 || __VMS */
    186 
    187 #ifndef LONG_LONG_MAX
    188 #define LONG_LONG_MAX 9223372036854775807LL
    189 #endif /* LONG_LONG_MAX */
    190 
    191  /* older versions of netperf knew about the HP kernel IDLE counter. */
    192  /* this is now obsolete - in favor of either pstat(), times, or a */
    193  /* process-level looper process. we also now require support for the */
    194  /* "long" integer type. raj 4/95.  */
    195 
    196 int
    197   lib_num_loc_cpus,    /* the number of cpus in the system */
    198   lib_num_rem_cpus;    /* how many we think are in the remote */
    199 
    200 #define PAGES_PER_CHILD 2
    201 
    202 int     lib_use_idle;
    203 int     cpu_method;
    204 
    205 struct  timeval         time1, time2;
    206 struct  timezone        tz;
    207 float   lib_elapsed,
    208         lib_local_maxrate,
    209         lib_remote_maxrate,
    210         lib_local_cpu_util,
    211         lib_remote_cpu_util;
    212 
    213 float   lib_local_per_cpu_util[MAXCPUS];
    214 int     lib_cpu_map[MAXCPUS];
    215 
    216 int     *request_array;
    217 int     *response_array;
    218 
    219 /* INVALID_SOCKET == INVALID_HANDLE_VALUE == (unsigned int)(~0) == -1 */
    220 SOCKET  netlib_control = INVALID_SOCKET;
    221 SOCKET  server_sock = INVALID_SOCKET;
    222 
    223 /* global variables to hold the value for processor affinity */
    224 int     local_proc_affinity,remote_proc_affinity = -1;
    225 
    226 /* these are to allow netperf to be run easily through those evil,
    227    end-to-end breaking things known as firewalls */
    228 char local_data_port[10];
    229 char remote_data_port[10];
    230 
    231 char *local_data_address=NULL;
    232 char *remote_data_address=NULL;
    233 
    234 int local_data_family=AF_UNSPEC;
    235 int remote_data_family=AF_UNSPEC;
    236 
    237  /* in the past, I was overlaying a structure on an array of ints. now */
    238  /* I am going to have a "real" structure, and point an array of ints */
    239  /* at it. the real structure will be forced to the same alignment as */
    240  /* the type "double." this change will mean that pre-2.1 netperfs */
    241  /* cannot be mixed with 2.1 and later. raj 11/95 */
    242 
    243 union   netperf_request_struct  netperf_request;
    244 union   netperf_response_struct netperf_response;
    245 
    246 FILE    *where;
    247 
    248 char    libfmt = '?';
    249 
    250 #ifdef WANT_DLPI
    251 /* some stuff for DLPI control messages */
    252 #define DLPI_DATA_SIZE 2048
    253 
    254 unsigned long control_data[DLPI_DATA_SIZE];
    255 struct strbuf control_message = {DLPI_DATA_SIZE, 0, (char *)control_data};
    256 
    257 #endif /* WANT_DLPI */
    258 
    259 #ifdef WIN32
    260 HANDLE hAlarm = INVALID_HANDLE_VALUE;
    261 #endif
    262 
    263 int     times_up;
    264 
    265 #ifdef WIN32
    266  /* we use a getopt implementation from net.sources */
    267 /*
    268  * get option letter from argument vector
    269  */
    270 int
    271         opterr = 1,             /* should error messages be printed? */
    272         optind = 1,             /* index into parent argv vector */
    273         optopt;                 /* character checked for validity */
    274 char
    275         *optarg;                /* argument associated with option */
    276 
    277 #define EMSG    ""
    278 
    279 #endif /* WIN32 */
    280 
    281 static int measuring_cpu;
    282 int
    283 netlib_get_page_size(void) {
    284 
    285  /* not all systems seem to have the sysconf for page size. for
    286     those  which do not, we will assume that the page size is 8192
    287     bytes.  this should be more than enough to be sure that there is
    288     no page  or cache thrashing by looper processes on MP
    289     systems. otherwise  that's really just too bad - such systems
    290     should define  _SC_PAGE_SIZE - raj 4/95 */
    291 
    292 #ifndef _SC_PAGE_SIZE
    293 #ifdef WIN32
    294 
    295 SYSTEM_INFO SystemInfo;
    296 
    297  GetSystemInfo(&SystemInfo);
    298 
    299  return SystemInfo.dwPageSize;
    300 #else
    301  return(8192L);
    302 #endif  /* WIN32 */
    303 #else
    304  return(sysconf(_SC_PAGE_SIZE));
    305 #endif /* _SC_PAGE_SIZE */
    306 
    307 }
    308 
    309 
    310 #ifdef WANT_INTERVALS
    312 static unsigned int usec_per_itvl;
    313 
    314 
    315 void
    316 stop_itimer()
    317 
    318 {
    319 
    320   struct itimerval new_interval;
    321   struct itimerval old_interval;
    322 
    323   new_interval.it_interval.tv_sec = 0;
    324   new_interval.it_interval.tv_usec = 0;
    325   new_interval.it_value.tv_sec = 0;
    326   new_interval.it_value.tv_usec = 0;
    327   if (setitimer(ITIMER_REAL,&new_interval,&old_interval) != 0) {
    328     /* there was a problem arming the interval timer */
    329     perror("netperf: setitimer");
    330     exit(1);
    331   }
    332   return;
    333 }
    334 #endif /* WANT_INTERVALS */
    335 
    336 
    338 
    339 #ifdef WIN32
    341 static void
    342 error(char *pch)
    343 {
    344   if (!opterr) {
    345     return;             /* without printing */
    346     }
    347   fprintf(stderr, "%s: %s: %c\n",
    348           (NULL != program) ? program : "getopt", pch, optopt);
    349 }
    350 
    351 int
    352 getopt(int argc, char **argv, char *ostr)
    353 {
    354   static char *place = EMSG;    /* option letter processing */
    355   register char *oli;                   /* option letter list index */
    356 
    357   if (!*place) {
    358     /* update scanning pointer */
    359       if (optind >= argc || *(place = argv[optind]) != '-' || !*++place) {
    360         return EOF;
    361       }
    362     if (*place == '-') {
    363       /* found "--" */
    364         ++optind;
    365       place = EMSG ;    /* Added by shiva for Netperf */
    366         return EOF;
    367     }
    368   }
    369 
    370   /* option letter okay? */
    371   if ((optopt = (int)*place++) == (int)':'
    372       || !(oli = strchr(ostr, optopt))) {
    373     if (!*place) {
    374       ++optind;
    375     }
    376     error("illegal option");
    377     return BADCH;
    378   }
    379   if (*++oli != ':') {
    380     /* don't need argument */
    381     optarg = NULL;
    382     if (!*place)
    383       ++optind;
    384   } else {
    385     /* need an argument */
    386     if (*place) {
    387       optarg = place;           /* no white space */
    388     } else  if (argc <= ++optind) {
    389       /* no arg */
    390       place = EMSG;
    391       error("option requires an argument");
    392       return BADCH;
    393     } else {
    394       optarg = argv[optind];            /* white space */
    395     }
    396     place = EMSG;
    397     ++optind;
    398   }
    399   return optopt;                        /* return option letter */
    400 }
    401 #endif /* WIN32 */
    402 
    403 /*----------------------------------------------------------------------------
    404  * WIN32 implementation of perror, does not deal very well with WSA errors
    405  * The stdlib.h version of perror only deals with the ancient XENIX error codes.
    406  *
    407  * +*+SAF Why can't all WSA errors go through GetLastError?  Most seem to...
    408  *--------------------------------------------------------------------------*/
    409 
    410 #ifdef WIN32
    411 void PrintWin32Error(FILE *stream, LPSTR text)
    412 {
    413     LPSTR    szTemp;
    414     DWORD    dwResult;
    415     DWORD    dwError;
    416 
    417     dwError = GetLastError();
    418     dwResult = FormatMessage(
    419         FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ARGUMENT_ARRAY,
    420         NULL,
    421         dwError,
    422         LANG_NEUTRAL,
    423         (LPTSTR)&szTemp,
    424         0,
    425         NULL );
    426 
    427     if (dwResult)
    428         fprintf(stream, "%s: %s\n", text, szTemp);
    429     else
    430         fprintf(stream, "%s: error 0x%x\n", text, dwError);
    431 	fflush(stream);
    432 
    433     if (szTemp)
    434         LocalFree((HLOCAL)szTemp);
    435 }
    436 #endif /* WIN32 */
    437 
    438 
    439 char *
    441 inet_ttos(int type)
    442 {
    443   switch (type) {
    444   case SOCK_DGRAM:
    445     return("SOCK_DGRAM");
    446     break;
    447   case SOCK_STREAM:
    448     return("SOCK_STREAM");
    449     break;
    450   default:
    451     return("SOCK_UNKNOWN");
    452   }
    453 }
    454 
    455 
    456 
    457 char unknown[32];
    459 
    460 char *
    461 inet_ptos(int protocol) {
    462   switch (protocol) {
    463   case IPPROTO_TCP:
    464     return("IPPROTO_TCP");
    465     break;
    466   case IPPROTO_UDP:
    467     return("IPPROTO_UDP");
    468     break;
    469 #if defined(IPPROTO_SCTP)
    470   case IPPROTO_SCTP:
    471     return("IPPROTO_SCTP");
    472     break;
    473 #endif
    474   default:
    475     snprintf(unknown,sizeof(unknown),"IPPROTO_UNKNOWN(%d)",protocol);
    476     return(unknown);
    477   }
    478 }
    479 
    480 /* one of these days, this should not be required */
    481 #ifndef AF_INET_SDP
    482 #define AF_INET_SDP 27
    483 #define PF_INET_SDP AF_INET_SDP
    484 #endif
    485 
    486 char *
    487 inet_ftos(int family)
    488 {
    489   switch(family) {
    490   case AF_INET:
    491     return("AF_INET");
    492     break;
    493 #if defined(AF_INET6)
    494   case AF_INET6:
    495     return("AF_INET6");
    496     break;
    497 #endif
    498 #if defined(AF_INET_SDP)
    499   case AF_INET_SDP:
    500     return("AF_INET_SDP");
    501     break;
    502 #endif
    503   default:
    504     return("AF_UNSPEC");
    505   }
    506 }
    507 
    508 int
    509 inet_nton(int af, const void *src, char *dst, int cnt)
    510 
    511 {
    512 
    513   switch (af) {
    514   case AF_INET:
    515     /* magic constants again... :) */
    516     if (cnt >= 4) {
    517       memcpy(dst,src,4);
    518       return 4;
    519     }
    520     else {
    521       Set_errno(ENOSPC);
    522       return(-1);
    523     }
    524     break;
    525 #if defined(AF_INET6)
    526   case AF_INET6:
    527     if (cnt >= 16) {
    528       memcpy(dst,src,16);
    529       return(16);
    530     }
    531     else {
    532       Set_errno(ENOSPC);
    533       return(-1);
    534     }
    535     break;
    536 #endif
    537   default:
    538     Set_errno(EAFNOSUPPORT);
    539     return(-1);
    540   }
    541 }
    542 
    543 double
    544 ntohd(double net_double)
    545 
    546 {
    547   /* we rely on things being nicely packed */
    548   union {
    549     double whole_thing;
    550     unsigned int words[2];
    551     unsigned char bytes[8];
    552   } conv_rec;
    553 
    554   unsigned char scratch;
    555   int i;
    556 
    557   /* on those systems where ntohl is a no-op, we want to return the */
    558   /* original value, unchanged */
    559 
    560   if (ntohl(1L) == 1L) {
    561     return(net_double);
    562   }
    563 
    564   conv_rec.whole_thing = net_double;
    565 
    566   /* we know that in the message passing routines that ntohl will have */
    567   /* been called on the 32 bit quantities. we need to put those back */
    568   /* the way they belong before we swap */
    569   conv_rec.words[0] = htonl(conv_rec.words[0]);
    570   conv_rec.words[1] = htonl(conv_rec.words[1]);
    571 
    572   /* now swap */
    573   for (i=0; i<= 3; i++) {
    574     scratch = conv_rec.bytes[i];
    575     conv_rec.bytes[i] = conv_rec.bytes[7-i];
    576     conv_rec.bytes[7-i] = scratch;
    577   }
    578 
    579 #if defined(__FLOAT_WORD_ORDER) && defined(__BYTE_ORDER)
    580   if (__FLOAT_WORD_ORDER != __BYTE_ORDER) {
    581     /* Fixup mixed endian floating point machines */
    582     unsigned int scratch = conv_rec.words[0];
    583     conv_rec.words[0] = conv_rec.words[1];
    584     conv_rec.words[1] = scratch;
    585   }
    586 #endif
    587 
    588   return(conv_rec.whole_thing);
    589 
    590 }
    591 
    592 double
    593 htond(double host_double)
    594 
    595 {
    596   /* we rely on things being nicely packed */
    597   union {
    598     double whole_thing;
    599     unsigned int words[2];
    600     unsigned char bytes[8];
    601   } conv_rec;
    602 
    603   unsigned char scratch;
    604   int i;
    605 
    606   /* on those systems where ntohl is a no-op, we want to return the */
    607   /* original value, unchanged */
    608 
    609   if (ntohl(1L) == 1L) {
    610     return(host_double);
    611   }
    612 
    613   conv_rec.whole_thing = host_double;
    614 
    615   /* now swap */
    616   for (i=0; i<= 3; i++) {
    617     scratch = conv_rec.bytes[i];
    618     conv_rec.bytes[i] = conv_rec.bytes[7-i];
    619     conv_rec.bytes[7-i] = scratch;
    620   }
    621 
    622 #if defined(__FLOAT_WORD_ORDER) && defined(__BYTE_ORDER)
    623   if (__FLOAT_WORD_ORDER != __BYTE_ORDER) {
    624     /* Fixup mixed endian floating point machines */
    625     unsigned int scratch = conv_rec.words[0];
    626     conv_rec.words[0] = conv_rec.words[1];
    627     conv_rec.words[1] = scratch;
    628   }
    629 #endif
    630 
    631   /* we know that in the message passing routines htonl will */
    632   /* be called on the 32 bit quantities. we need to set things up so */
    633   /* that when this happens, the proper order will go out on the */
    634   /* network */
    635   conv_rec.words[0] = htonl(conv_rec.words[0]);
    636   conv_rec.words[1] = htonl(conv_rec.words[1]);
    637 
    638   return(conv_rec.whole_thing);
    639 
    640 }
    641 
    642 
    644 /* one of these days, this should be abstracted-out just like the CPU
    645    util stuff.  raj 2005-01-27 */
    646 int
    647 get_num_cpus()
    648 
    649 {
    650 
    651   /* on HP-UX, even when we use the looper procs we need the pstat */
    652   /* call */
    653 
    654   int temp_cpus;
    655 
    656 #ifdef __hpux
    657 #include <sys/pstat.h>
    658 
    659   struct pst_dynamic psd;
    660 
    661   if (pstat_getdynamic((struct pst_dynamic *)&psd,
    662                        (size_t)sizeof(psd), (size_t)1, 0) != -1) {
    663     temp_cpus = psd.psd_proc_cnt;
    664   }
    665   else {
    666     temp_cpus = 1;
    667   }
    668 
    669 #else
    670   /* MW: <unistd.h> was included for non-Windows systems above. */
    671   /* Thus if _SC_NPROC_ONLN is defined, we should be able to use sysconf. */
    672 #ifdef _SC_NPROCESSORS_ONLN
    673   temp_cpus = sysconf(_SC_NPROCESSORS_ONLN);
    674 
    675 #ifdef USE_PERFSTAT
    676   temp_cpus = perfstat_cpu(NULL,NULL, sizeof(perfstat_cpu_t), 0);
    677 #endif /* USE_PERFSTAT */
    678 
    679 #else /* no _SC_NPROCESSORS_ONLN */
    680 
    681 #ifdef WIN32
    682   SYSTEM_INFO SystemInfo;
    683   GetSystemInfo(&SystemInfo);
    684 
    685   temp_cpus = SystemInfo.dwNumberOfProcessors;
    686 #else
    687   /* we need to know some other ways to do this, or just fall-back on */
    688   /* a global command line option - raj 4/95 */
    689   temp_cpus = shell_num_cpus;
    690 #endif  /* WIN32 */
    691 #endif /* _SC_NPROCESSORS_ONLN */
    692 #endif /*  __hpux */
    693 
    694   if (temp_cpus > MAXCPUS) {
    695     fprintf(where,
    696             "Sorry, this system has more CPUs (%d) than I can handle (%d).\n",
    697             temp_cpus,
    698             MAXCPUS);
    699     fprintf(where,
    700             "Please alter MAXCPUS in netlib.h and recompile.\n");
    701     fflush(where);
    702     exit(1);
    703   }
    704 
    705   return(temp_cpus);
    706 
    707 }
    708 
    709 #ifdef WIN32
    710 #ifdef __GNUC__
    711   #define S64_SUFFIX(x) x##LL
    712 #else
    713   #define S64_SUFFIX(x) x##i64
    714 #endif
    715 
    716 /*
    717  * Number of 100 nanosecond units from 1/1/1601 to 1/1/1970
    718  */
    719 #define EPOCH_BIAS  S64_SUFFIX(116444736000000000)
    720 
    721 /*
    722  * Union to facilitate converting from FILETIME to unsigned __int64
    723  */
    724 typedef union {
    725         unsigned __int64 ft_scalar;
    726         FILETIME ft_struct;
    727 } FT;
    728 
    729 void
    730 gettimeofday( struct timeval *tv , struct timezone *not_used )
    731 {
    732         FT nt_time;
    733         __int64 UnixTime;  /* microseconds since 1/1/1970 */
    734 
    735         GetSystemTimeAsFileTime( &(nt_time.ft_struct) );
    736 
    737         UnixTime = ((nt_time.ft_scalar - EPOCH_BIAS) / S64_SUFFIX(10));
    738         tv->tv_sec = (long)(time_t)(UnixTime / S64_SUFFIX(1000000));
    739         tv->tv_usec = (unsigned long)(UnixTime % S64_SUFFIX(1000000));
    740 }
    741 #endif /* WIN32 */
    742 
    743 
    744 
    746 /************************************************************************/
    747 /*                                                                      */
    748 /*      signal catcher                                                  */
    749 /*                                                                      */
    750 /************************************************************************/
    751 
    752 void
    753 #if defined(__hpux)
    754 catcher(sig, code, scp)
    755      int sig;
    756      int code;
    757      struct sigcontext *scp;
    758 #else
    759 catcher(int sig)
    760 #endif /* __hpux || __VMS */
    761 {
    762 
    763 #ifdef __hpux
    764   if (debug > 2) {
    765     fprintf(where,"caught signal %d ",sig);
    766     if (scp) {
    767       fprintf(where,"while in syscall %d\n",
    768               scp->sc_syscall);
    769     }
    770     else {
    771       fprintf(where,"null scp\n");
    772     }
    773     fflush(where);
    774   }
    775 #endif /* RAJ_DEBUG */
    776 
    777   switch(sig) {
    778 
    779   case SIGINT:
    780     fprintf(where,"netperf: caught SIGINT\n");
    781     fflush(where);
    782     exit(1);
    783     break;
    784   case SIGALRM:
    785    if (--test_len_ticks == 0) {
    786       /* the test is over */
    787       if (times_up != 0) {
    788         fprintf(where,"catcher: timer popped with times_up != 0\n");
    789         fflush(where);
    790       }
    791       times_up = 1;
    792 #if defined(WANT_INTERVALS) && !defined(WANT_SPIN)
    793       stop_itimer();
    794 #endif /* WANT_INTERVALS */
    795       break;
    796     }
    797     else {
    798 #ifdef WANT_INTERVALS
    799 #ifdef __hpux
    800       /* the test is not over yet and we must have been using the */
    801       /* interval timer. if we were in SYS_SIGSUSPEND we want to */
    802       /* re-start the system call. Otherwise, we want to get out of */
    803       /* the sigsuspend call. I NEED TO KNOW HOW TO DO THIS FOR OTHER */
    804       /* OPERATING SYSTEMS. If you know how, please let me know. rick */
    805       /* jones <raj (at) cup.hp.com> */
    806       if (scp->sc_syscall != SYS_SIGSUSPEND) {
    807         if (debug > 2) {
    808           fprintf(where,
    809                   "catcher: Time to send burst > interval!\n");
    810           fflush(where);
    811         }
    812         scp->sc_syscall_action = SIG_RESTART;
    813       }
    814 #endif /* __hpux */
    815 #else /* WANT_INTERVALS */
    816       fprintf(where,
    817               "catcher: interval timer running unexpectedly!\n");
    818       fflush(where);
    819       times_up = 1;
    820 #endif /* WANT_INTERVALS */
    821       break;
    822     }
    823   }
    824   return;
    825 }
    826 
    827 
    828 void
    829 install_signal_catchers()
    830 
    831 {
    832   /* just a simple little routine to catch a bunch of signals */
    833 
    834 #ifndef WIN32
    835   struct sigaction action;
    836   int i;
    837 
    838   fprintf(where,"installing catcher for all signals\n");
    839   fflush(where);
    840 
    841   sigemptyset(&(action.sa_mask));
    842   action.sa_handler = catcher;
    843 
    844 #ifdef SA_INTERRUPT
    845   action.sa_flags = SA_INTERRUPT;
    846 #else /* SA_INTERRUPT */
    847   action.sa_flags = 0;
    848 #endif /* SA_INTERRUPT */
    849 
    850 
    851   for (i = 1; i <= NSIG; i++) {
    852     if (i != SIGALRM) {
    853       if (sigaction(i,&action,NULL) != 0) {
    854         fprintf(where,
    855                 "Could not install signal catcher for sig %d, errno %d\n",
    856                 i,
    857                 errno);
    858         fflush(where);
    859 
    860       }
    861     }
    862   }
    863 #else
    864   return;
    865 #endif /* WIN32 */
    866 }
    867 
    868 
    870 #ifdef WIN32
    871 #define SIGALRM (14)
    872 void
    873 emulate_alarm( int seconds )
    874 {
    875 	DWORD ErrorCode;
    876 
    877 	/* Wait on this event for parm seconds. */
    878 
    879 	ErrorCode = WaitForSingleObject(hAlarm, seconds*1000);
    880 	if (ErrorCode == WAIT_FAILED)
    881 	{
    882 		perror("WaitForSingleObject failed");
    883 		exit(1);
    884 	}
    885 
    886 	if (ErrorCode == WAIT_TIMEOUT)
    887 	{
    888 	  /* WaitForSingleObject timed out; this means the timer
    889 	     wasn't canceled. */
    890 
    891         times_up = 1;
    892 
    893         /* We have yet to find a good way to fully emulate the effects */
    894         /* of signals and getting EINTR from system calls under */
    895         /* winsock, so what we do here is close the socket out from */
    896         /* under the other thread.  It is rather kludgy, but should be */
    897         /* sufficient to get this puppy shipped.  The concept can be */
    898         /* attributed/blamed :) on Robin raj 1/96 */
    899 
    900         if (win_kludge_socket != INVALID_SOCKET) {
    901           closesocket(win_kludge_socket);
    902         }
    903         if (win_kludge_socket2 != INVALID_SOCKET) {
    904           closesocket(win_kludge_socket2);
    905         }
    906 	}
    907 }
    908 
    909 #endif /* WIN32 */
    910 
    911 void
    912 start_timer(int time)
    913 {
    914 
    915 #ifdef WIN32
    916 	/*+*+SAF What if StartTimer is called twice without the first timer */
    917 	/*+*+SAF expiring? */
    918 
    919 	DWORD  thread_id ;
    920 	HANDLE tHandle;
    921 
    922 	if (hAlarm == (HANDLE) INVALID_HANDLE_VALUE)
    923 	{
    924 		/* Create the Alarm event object */
    925 		hAlarm = CreateEvent(
    926 			(LPSECURITY_ATTRIBUTES) NULL,	  /* no security */
    927 			FALSE,	 /* auto reset event */
    928 			FALSE,   /* init. state = reset */
    929 			(void *)NULL);  /* unnamed event object */
    930 		if (hAlarm == (HANDLE) INVALID_HANDLE_VALUE)
    931 		{
    932 			perror("CreateEvent failure");
    933 			exit(1);
    934 		}
    935 	}
    936 	else
    937 	{
    938 		ResetEvent(hAlarm);
    939 	}
    940 
    941 
    942 	tHandle = CreateThread(0,
    943 					       0,
    944 						   (LPTHREAD_START_ROUTINE)emulate_alarm,
    945 						   (LPVOID)(ULONG_PTR)time,
    946 						   0,
    947 						   &thread_id ) ;
    948 	CloseHandle(tHandle);
    949 
    950 #else /* not WIN32 */
    951 
    952 struct sigaction action;
    953 
    954 if (debug) {
    955   fprintf(where,"About to start a timer for %d seconds.\n",time);
    956   fflush(where);
    957 }
    958 
    959   action.sa_handler = catcher;
    960   sigemptyset(&(action.sa_mask));
    961   sigaddset(&(action.sa_mask),SIGALRM);
    962 
    963 #ifdef SA_INTERRUPT
    964   /* on some systems (SunOS 4.blah), system calls are restarted. we do */
    965   /* not want that */
    966   action.sa_flags = SA_INTERRUPT;
    967 #else /* SA_INTERRUPT */
    968   action.sa_flags = 0;
    969 #endif /* SA_INTERRUPT */
    970 
    971   if (sigaction(SIGALRM, &action, NULL) < 0) {
    972     fprintf(where,"start_timer: error installing alarm handler ");
    973     fprintf(where,"errno %d\n",errno);
    974     fflush(where);
    975     exit(1);
    976   }
    977 
    978   /* this is the easy case - just set the timer for so many seconds */
    979   if (alarm(time) != 0) {
    980     fprintf(where,
    981             "error starting alarm timer, errno %d\n",
    982             errno);
    983     fflush(where);
    984   }
    985 #endif /* WIN32 */
    986 
    987   test_len_ticks = 1;
    988 
    989 }
    990 
    991 
    992  /* this routine will disable any running timer */
    994 void
    995 stop_timer()
    996 {
    997 #ifndef WIN32
    998   alarm(0);
    999 #else
   1000   /* at some point we may need some win32 equivalent */
   1001   	if (hAlarm != (HANDLE) INVALID_HANDLE_VALUE)
   1002 	{
   1003 		SetEvent(hAlarm);
   1004 	}
   1005 #endif /* WIN32 */
   1006 
   1007 }
   1008 
   1009 
   1010 #ifdef WANT_INTERVALS
   1012  /* this routine will enable the interval timer and set things up so */
   1013  /* that for a timed test the test will end at the proper time. it */
   1014  /* should detect the presence of POSIX.4 timer_* routines one of */
   1015  /* these days */
   1016 void
   1017 start_itimer(unsigned int interval_len_msec )
   1018 {
   1019 
   1020   unsigned int ticks_per_itvl;
   1021 
   1022   struct itimerval new_interval;
   1023   struct itimerval old_interval;
   1024 
   1025   /* if -DWANT_INTERVALS was used, we will use the ticking of the itimer to */
   1026   /* tell us when the test is over. while the user will be specifying */
   1027   /* some number of milliseconds, we know that the interval timer is */
   1028   /* really in units of 1/HZ. so, to prevent the test from running */
   1029   /* "long" it would be necessary to keep this in mind when calculating */
   1030   /* the number of itimer events */
   1031 
   1032   ticks_per_itvl = ((interval_wate * sysconf(_SC_CLK_TCK) * 1000) /
   1033                     1000000);
   1034 
   1035   if (ticks_per_itvl == 0) ticks_per_itvl = 1;
   1036 
   1037   /* how many usecs in each interval? */
   1038   usec_per_itvl = ticks_per_itvl * (1000000 / sysconf(_SC_CLK_TCK));
   1039 
   1040   /* how many times will the timer pop before the test is over? */
   1041   if (test_time > 0) {
   1042     /* this was a timed test */
   1043     test_len_ticks = (test_time * 1000000) / usec_per_itvl;
   1044   }
   1045   else {
   1046     /* this was not a timed test, use MAXINT */
   1047     test_len_ticks = INT_MAX;
   1048   }
   1049 
   1050   if (debug) {
   1051     fprintf(where,"setting the interval timer to %d sec %d usec ",
   1052             usec_per_itvl / 1000000,
   1053             usec_per_itvl % 1000000);
   1054     fprintf(where,"test len %d ticks\n",
   1055             test_len_ticks);
   1056     fflush(where);
   1057   }
   1058 
   1059   /* if this was not a timed test, then we really aught to enable the */
   1060   /* signal catcher raj 2/95 */
   1061 
   1062   new_interval.it_interval.tv_sec = usec_per_itvl / 1000000;
   1063   new_interval.it_interval.tv_usec = usec_per_itvl % 1000000;
   1064   new_interval.it_value.tv_sec = usec_per_itvl / 1000000;
   1065   new_interval.it_value.tv_usec = usec_per_itvl % 1000000;
   1066   if (setitimer(ITIMER_REAL,&new_interval,&old_interval) != 0) {
   1067     /* there was a problem arming the interval timer */
   1068     perror("netperf: setitimer");
   1069     exit(1);
   1070   }
   1071 }
   1072 #endif /* WANT_INTERVALS */
   1073 
   1074 void
   1075 netlib_init_cpu_map() {
   1076 
   1077   int i;
   1078 #ifdef HAVE_MPCTL
   1079   int num;
   1080   i = 0;
   1081   /* I go back and forth on whether this should be the system-wide set
   1082      of calls, or if the processor set versions (sans the _SYS) should
   1083      be used.  at the moment I believe that the system-wide version
   1084      should be used. raj 2006-04-03 */
   1085   num = mpctl(MPC_GETNUMSPUS_SYS,0,0);
   1086   lib_cpu_map[i] = mpctl(MPC_GETFIRSTSPU_SYS,0,0);
   1087   for (i = 1;((i < num) && (i < MAXCPUS)); i++) {
   1088     lib_cpu_map[i] = mpctl(MPC_GETNEXTSPU_SYS,lib_cpu_map[i-1],0);
   1089   }
   1090   /* from here, we set them all to -1 because if we launch more
   1091      loopers than actual CPUs, well, I'm not sure why :) */
   1092   for (; i < MAXCPUS; i++) {
   1093     lib_cpu_map[i] = -1;
   1094   }
   1095 
   1096 #else
   1097   /* we assume that there is indeed a contiguous mapping */
   1098   for (i = 0; i < MAXCPUS; i++) {
   1099     lib_cpu_map[i] = i;
   1100   }
   1101 #endif
   1102 }
   1103 
   1104 
   1105 /****************************************************************/
   1107 /*                                                              */
   1108 /*      netlib_init()                                           */
   1109 /*                                                              */
   1110 /*      initialize the performance library...                   */
   1111 /*                                                              */
   1112 /****************************************************************/
   1113 
   1114 void
   1115 netlib_init()
   1116 {
   1117   int i;
   1118 
   1119   where            = stdout;
   1120 
   1121   request_array = (int *)(&netperf_request);
   1122   response_array = (int *)(&netperf_response);
   1123 
   1124   for (i = 0; i < MAXCPUS; i++) {
   1125     lib_local_per_cpu_util[i] = 0.0;
   1126   }
   1127 
   1128   /* on those systems where we know that CPU numbers may not start at
   1129      zero and be contiguous, we provide a way to map from a
   1130      contiguous, starting from 0 CPU id space to the actual CPU ids.
   1131      at present this is only used for the netcpu_looper stuff because
   1132      we ass-u-me that someone setting processor affinity from the
   1133      netperf commandline will provide a "proper" CPU identifier. raj
   1134      2006-04-03 */
   1135 
   1136   netlib_init_cpu_map();
   1137 
   1138   if (debug) {
   1139     fprintf(where,
   1140             "netlib_init: request_array at %p\n",
   1141             request_array);
   1142     fprintf(where,
   1143             "netlib_init: response_array at %p\n",
   1144             response_array);
   1145 
   1146     fflush(where);
   1147   }
   1148 
   1149 }
   1150 
   1151  /* this routine will conver the string into an unsigned integer. it */
   1153  /* is used primarily for the command-line options taking a number */
   1154  /* (such as the socket size) which could be rather large. If someone */
   1155  /* enters 32M, then the number will be converted to 32 * 1024 * 1024. */
   1156  /* If they inter 32m, the number will be converted to 32 * 1000 * */
   1157  /* 1000 */
   1158 unsigned int
   1159 convert(char *string)
   1160 
   1161 {
   1162   unsigned int base;
   1163   base = atoi(string);
   1164   if (strstr(string,"K")) {
   1165     base *= 1024;
   1166   }
   1167   if (strstr(string,"M")) {
   1168     base *= (1024 * 1024);
   1169   }
   1170   if (strstr(string,"G")) {
   1171     base *= (1024 * 1024 * 1024);
   1172   }
   1173   if (strstr(string,"k")) {
   1174     base *= (1000);
   1175   }
   1176   if (strstr(string,"m")) {
   1177     base *= (1000 * 1000);
   1178   }
   1179   if (strstr(string,"g")) {
   1180     base *= (1000 * 1000 * 1000);
   1181   }
   1182   return(base);
   1183 }
   1184 
   1185 /* this routine is like convert, but it is used for an interval time
   1186    specification instead of stuff like socket buffer or send sizes.
   1187    it converts everything to microseconds for internal use.  if there
   1188    is an 'm' at the end it assumes the user provided milliseconds, s
   1189    will imply seconds, u will imply microseconds.  in the future n
   1190    will imply nanoseconds but for now it will be ignored. if there is
   1191    no suffix or an unrecognized suffix, it will be assumed the user
   1192    provided milliseconds, which was the long-time netperf default. one
   1193    of these days, we should probably revisit that nanosecond business
   1194    wrt the return value being just an int rather than a uint64_t or
   1195    something.  raj 2006-02-06 */
   1196 
   1197 unsigned int
   1198 convert_timespec(char *string) {
   1199 
   1200   unsigned int base;
   1201   base = atoi(string);
   1202   if (strstr(string,"m")) {
   1203     base *= 1000;
   1204   }
   1205   else if (strstr(string,"u")) {
   1206     base *= (1);
   1207   }
   1208   else if (strstr(string,"s")) {
   1209     base *= (1000 * 1000);
   1210   }
   1211   else {
   1212     base *= (1000);
   1213   }
   1214   return(base);
   1215 }
   1216 
   1217 
   1218  /* this routine will allocate a circular list of buffers for either */
   1220  /* send or receive operations. each of these buffers will be aligned */
   1221  /* and offset as per the users request. the circumference of this */
   1222  /* ring will be controlled by the setting of send_width. the buffers */
   1223  /* will be filled with data from the file specified in fill_file. if */
   1224  /* fill_file is an empty string, the buffers will not be filled with */
   1225  /* any particular data */
   1226 
   1227 struct ring_elt *
   1228 allocate_buffer_ring(int width, int buffer_size, int alignment, int offset)
   1229 {
   1230 
   1231   struct ring_elt *first_link = NULL;
   1232   struct ring_elt *temp_link  = NULL;
   1233   struct ring_elt *prev_link;
   1234 
   1235   int i;
   1236   int malloc_size;
   1237   int bytes_left;
   1238   int bytes_read;
   1239   int do_fill;
   1240 
   1241   FILE *fill_source;
   1242   char default_fill[] = "netperf";
   1243   int  fill_cursor = 0;
   1244 
   1245   malloc_size = buffer_size + alignment + offset;
   1246 
   1247   /* did the user wish to have the buffers pre-filled with data from a */
   1248   /* particular source? */
   1249   if (strcmp(fill_file,"") == 0) {
   1250     do_fill = 0;
   1251     fill_source = NULL;
   1252   }
   1253   else {
   1254     do_fill = 1;
   1255     fill_source = (FILE *)fopen(fill_file,"r");
   1256     if (fill_source == (FILE *)NULL) {
   1257       perror("Could not open requested fill file");
   1258       exit(1);
   1259     }
   1260   }
   1261 
   1262   assert(width >= 1);
   1263 
   1264   prev_link = NULL;
   1265   for (i = 1; i <= width; i++) {
   1266     /* get the ring element */
   1267     temp_link = (struct ring_elt *)malloc(sizeof(struct ring_elt));
   1268     if (temp_link == NULL) {
   1269       printf("malloc(%u) failed!\n", sizeof(struct ring_elt));
   1270       exit(1);
   1271     }
   1272     /* remember the first one so we can close the ring at the end */
   1273     if (i == 1) {
   1274       first_link = temp_link;
   1275     }
   1276     temp_link->buffer_base = (char *)malloc(malloc_size);
   1277     if (temp_link == NULL) {
   1278       printf("malloc(%d) failed!\n", malloc_size);
   1279       exit(1);
   1280 	}
   1281 
   1282 #ifndef WIN32
   1283     temp_link->buffer_ptr = (char *)(( (long)(temp_link->buffer_base) +
   1284                           (long)alignment - 1) &
   1285                          ~((long)alignment - 1));
   1286 #else
   1287     temp_link->buffer_ptr = (char *)(( (ULONG_PTR)(temp_link->buffer_base) +
   1288                           (ULONG_PTR)alignment - 1) &
   1289                          ~((ULONG_PTR)alignment - 1));
   1290 #endif
   1291     temp_link->buffer_ptr += offset;
   1292     /* is where the buffer fill code goes. */
   1293     if (do_fill) {
   1294       char *bufptr = temp_link->buffer_ptr;
   1295       bytes_left = buffer_size;
   1296       while (bytes_left) {
   1297         if (((bytes_read = (int)fread(bufptr,
   1298 				      1,
   1299 				      bytes_left,
   1300 				      fill_source)) == 0) &&
   1301             (feof(fill_source))){
   1302           rewind(fill_source);
   1303         }
   1304 	bufptr += bytes_read;
   1305         bytes_left -= bytes_read;
   1306       }
   1307     }
   1308     else {
   1309       /* use the default fill to ID our data traffic on the
   1310 	 network. it ain't exactly pretty, but it should work */
   1311       int j;
   1312       char *bufptr = temp_link->buffer_ptr;
   1313       for (j = 0; j < buffer_size; j++) {
   1314 	bufptr[j] = default_fill[fill_cursor];
   1315 	fill_cursor += 1;
   1316 	/* the Windows DDK compiler with an x86_64 target wants a cast
   1317 	   here */
   1318 	if (fill_cursor >  (int)strlen(default_fill)) {
   1319 	  fill_cursor = 0;
   1320 	}
   1321       }
   1322 
   1323     }
   1324     temp_link->next = prev_link;
   1325     prev_link = temp_link;
   1326   }
   1327   if (first_link) {  /* SAF Prefast made me do it... */
   1328     first_link->next = temp_link;
   1329   }
   1330 
   1331   return(first_link); /* it's a circle, doesn't matter which we return */
   1332 }
   1333 
   1334 /* this routine will dirty the first dirty_count bytes of the
   1335    specified buffer and/or read clean_count bytes from the buffer. it
   1336    will go N bytes at a time, the only question is how large should N
   1337    be and if we should be going continguously, or based on some
   1338    assumption of cache line size */
   1339 
   1340 void
   1341 access_buffer(char *buffer_ptr,int length, int dirty_count, int clean_count) {
   1342 
   1343   char *temp_buffer;
   1344   char *limit;
   1345   int  i, dirty_totals;
   1346 
   1347   temp_buffer = buffer_ptr;
   1348   limit = temp_buffer + length;
   1349   dirty_totals = 0;
   1350 
   1351   for (i = 0;
   1352        ((i < dirty_count) && (temp_buffer < limit));
   1353        i++) {
   1354     *temp_buffer += (char)i;
   1355     dirty_totals += *temp_buffer;
   1356     temp_buffer++;
   1357   }
   1358 
   1359   for (i = 0;
   1360        ((i < clean_count) && (temp_buffer < limit));
   1361        i++) {
   1362     dirty_totals += *temp_buffer;
   1363     temp_buffer++;
   1364   }
   1365 
   1366   if (debug > 100) {
   1367     fprintf(where,
   1368 	    "This was here to try to avoid dead-code elimination %d\n",
   1369 	    dirty_totals);
   1370     fflush(where);
   1371   }
   1372 }
   1373 
   1374 
   1376 #ifdef HAVE_ICSC_EXS
   1377 
   1378 #include <sys/mman.h>
   1379 #include <sys/exs.h>
   1380 
   1381  /* this routine will allocate a circular list of buffers for either */
   1382  /* send or receive operations. each of these buffers will be aligned */
   1383  /* and offset as per the users request. the circumference of this */
   1384  /* ring will be controlled by the setting of send_width. the buffers */
   1385  /* will be filled with data from the file specified in fill_file. if */
   1386  /* fill_file is an empty string, the buffers will not be filled with */
   1387  /* any particular data */
   1388 
   1389 struct ring_elt *
   1390 allocate_exs_buffer_ring (int width, int buffer_size, int alignment, int offset, exs_mhandle_t *mhandlep)
   1391 {
   1392 
   1393     struct ring_elt *first_link;
   1394     struct ring_elt *temp_link;
   1395     struct ring_elt *prev_link;
   1396 
   1397     int i;
   1398     int malloc_size;
   1399     int bytes_left;
   1400     int bytes_read;
   1401     int do_fill;
   1402 
   1403     FILE *fill_source;
   1404 
   1405     int mmap_size;
   1406     char *mmap_buffer, *mmap_buffer_aligned;
   1407 
   1408     malloc_size = buffer_size + alignment + offset;
   1409 
   1410     /* did the user wish to have the buffers pre-filled with data from a */
   1411     /* particular source? */
   1412     if (strcmp (fill_file, "") == 0) {
   1413         do_fill = 0;
   1414         fill_source = NULL;
   1415     } else {
   1416         do_fill = 1;
   1417         fill_source = (FILE *) fopen (fill_file, "r");
   1418         if (fill_source == (FILE *) NULL) {
   1419             perror ("Could not open requested fill file");
   1420             exit (1);
   1421         }
   1422     }
   1423 
   1424     assert (width >= 1);
   1425 
   1426     if (debug) {
   1427         fprintf (where, "allocate_exs_buffer_ring: "
   1428                  "width=%d buffer_size=%d alignment=%d offset=%d\n",
   1429                  width, buffer_size, alignment, offset);
   1430     }
   1431 
   1432     /* allocate shared memory */
   1433     mmap_size = width * malloc_size;
   1434     mmap_buffer = (char *) mmap ((caddr_t)NULL, mmap_size+NBPG-1,
   1435                                  PROT_READ|PROT_WRITE,
   1436                                  MAP_SHARED|MAP_ANONYMOUS, -1, 0);
   1437     if (mmap_buffer == NULL) {
   1438         perror ("allocate_exs_buffer_ring: mmap failed");
   1439         exit (1);
   1440     }
   1441     mmap_buffer_aligned = (char *) ((uintptr_t)mmap_buffer & ~(NBPG-1));
   1442     if (debug) {
   1443         fprintf (where, "allocate_exs_buffer_ring: "
   1444                  "mmap buffer size=%d address=0x%p aligned=0x%p\n",
   1445                  mmap_size, mmap_buffer, mmap_buffer_aligned);
   1446     }
   1447 
   1448     /* register shared memory */
   1449     *mhandlep = exs_mregister ((void *)mmap_buffer_aligned, (size_t)mmap_size, 0);
   1450     if (*mhandlep == EXS_MHANDLE_INVALID) {
   1451         perror ("allocate_exs_buffer_ring: exs_mregister failed");
   1452         exit (1);
   1453     }
   1454     if (debug) {
   1455         fprintf (where, "allocate_exs_buffer_ring: mhandle=%d\n",
   1456                  *mhandlep);
   1457     }
   1458 
   1459     /* allocate ring elements */
   1460     first_link = (struct ring_elt *) malloc (width * sizeof (struct ring_elt));
   1461     if (first_link == NULL) {
   1462         printf ("malloc(%d) failed!\n", width * sizeof (struct ring_elt));
   1463         exit (1);
   1464     }
   1465 
   1466     /* initialize buffer ring */
   1467     prev_link = first_link + width - 1;
   1468 
   1469     for (i = 0, temp_link = first_link; i < width; i++, temp_link++) {
   1470 
   1471         temp_link->buffer_base = (char *) mmap_buffer_aligned + (i*malloc_size);
   1472 #ifndef WIN32
   1473         temp_link->buffer_ptr = (char *)
   1474             (((long)temp_link->buffer_base + (long)alignment - 1) &
   1475              ~((long)alignment - 1));
   1476 #else
   1477         temp_link->buffer_ptr = (char *)
   1478             (((ULONG_PTR)temp_link->buffer_base + (ULONG_PTR)alignment - 1) &
   1479              ~((ULONG_PTR)alignment - 1));
   1480 #endif
   1481         temp_link->buffer_ptr += offset;
   1482 
   1483         if (debug) {
   1484             fprintf (where, "allocate_exs_buffer_ring: "
   1485                      "buffer: index=%d base=0x%p ptr=0x%p\n",
   1486                      i, temp_link->buffer_base, temp_link->buffer_ptr);
   1487         }
   1488 
   1489         /* is where the buffer fill code goes. */
   1490         if (do_fill) {
   1491             bytes_left = buffer_size;
   1492             while (bytes_left) {
   1493                 if (((bytes_read = (int) fread (temp_link->buffer_ptr,
   1494                                                 1,
   1495                                                 bytes_left,
   1496                                                 fill_source)) == 0) &&
   1497                     (feof (fill_source))) {
   1498                     rewind (fill_source);
   1499                 }
   1500                 bytes_left -= bytes_read;
   1501             }
   1502         }
   1503 
   1504         /* do linking */
   1505         prev_link->next = temp_link;
   1506         prev_link = temp_link;
   1507     }
   1508 
   1509     return (first_link);        /* it's a circle, doesn't matter which we return */
   1510 }
   1511 
   1512 #endif /* HAVE_ICSC_EXS */
   1513 
   1514 
   1515 
   1517 #ifdef HAVE_SENDFILE
   1518 /* this routine will construct a ring of sendfile_ring_elt structs
   1519    that the routine sendfile_tcp_stream() will use to get parameters
   1520    to its calls to sendfile(). It will setup the ring to point at the
   1521    file specified in the global -F option that is already used to
   1522    pre-fill buffers in the send() case. 08/2000
   1523 
   1524    if there is no file specified in a global -F option, we will create
   1525    a tempoarary file and fill it with random data and use that
   1526    instead.  raj 2007-08-09 */
   1527 
   1528 struct sendfile_ring_elt *
   1529 alloc_sendfile_buf_ring(int width,
   1530                         int buffer_size,
   1531                         int alignment,
   1532                         int offset)
   1533 
   1534 {
   1535 
   1536   struct sendfile_ring_elt *first_link = NULL;
   1537   struct sendfile_ring_elt *temp_link  = NULL;
   1538   struct sendfile_ring_elt *prev_link;
   1539 
   1540   int i;
   1541   int fildes;
   1542   struct stat statbuf;
   1543 
   1544   /* if the user has not specified a file with the -F option, we will
   1545      fail the test. otherwise, go ahead and try to open the
   1546      file. 08/2000 */
   1547   if (strcmp(fill_file,"") == 0) {
   1548     /* use an temp file for the fill file */
   1549     char *temp_file;
   1550     int *temp_buffer;
   1551 
   1552     /* make sure we have at least an ints worth, even if the user is
   1553        using an insane buffer size for a sendfile test. we are
   1554        ass-u-me-ing that malloc will return something at least aligned
   1555        on an int boundary... */
   1556     temp_buffer = (int *) malloc(buffer_size + sizeof(int));
   1557     if (temp_buffer) {
   1558       /* ok, we have the buffer we are going to write, lets get a
   1559 	 temporary filename */
   1560       temp_file = tmpnam(NULL);
   1561       if (NULL != temp_file) {
   1562 	fildes = open(temp_file,O_RDWR | O_EXCL | O_CREAT,0600);
   1563 	if (-1 != fildes) {
   1564 	  int count;
   1565 	  int *int_ptr;
   1566 
   1567 	  /* initialize the random number generator */
   1568 	  srand(getpid());
   1569 
   1570 	  /* unlink the file so it goes poof when we
   1571 	     exit. unless/until shown to be a problem we will
   1572 	     blissfully ignore the return value. raj 2007-08-09 */
   1573 	  unlink(temp_file);
   1574 
   1575 	  /* now fill-out the file with at least buffer_size * width bytes */
   1576 	  for (count = 0; count < width; count++) {
   1577 	    /* fill the buffer with random data.  it doesn't have to be
   1578 	       really random, just "random enough" :) we do this here rather
   1579 	       than up above because we want each write to the file to be
   1580 	       different random data */
   1581 	    int_ptr = temp_buffer;
   1582 	    for (i = 0; i <= buffer_size/sizeof(int); i++) {
   1583 	      *int_ptr = rand();
   1584 	      int_ptr++;
   1585 	    }
   1586 	    if (write(fildes,temp_buffer,buffer_size+sizeof(int)) !=
   1587 		buffer_size + sizeof(int)) {
   1588 	      perror("allocate_sendfile_buf_ring: incomplete write");
   1589 	      exit(-1);
   1590 	    }
   1591 	  }
   1592 	}
   1593 	else {
   1594 	  perror("allocate_sendfile_buf_ring: could not open tempfile");
   1595 	  exit(-1);
   1596 	}
   1597       }
   1598       else {
   1599 	perror("allocate_sendfile_buf_ring: could not allocate temp name");
   1600 	exit(-1);
   1601       }
   1602     }
   1603     else {
   1604       perror("alloc_sendfile_buf_ring: could not allocate buffer for file");
   1605       exit(-1);
   1606     }
   1607   }
   1608   else {
   1609     /* the user pointed us at a file, so try it */
   1610     fildes = open(fill_file , O_RDONLY);
   1611     if (fildes == -1){
   1612       perror("alloc_sendfile_buf_ring: Could not open requested file");
   1613       exit(1);
   1614     }
   1615     /* make sure there is enough file there to allow us to make a
   1616        complete ring. that way we do not need additional logic in the
   1617        ring setup to deal with wrap-around issues. we might want that
   1618        someday, but not just now. 08/2000 */
   1619     if (stat(fill_file,&statbuf) != 0) {
   1620       perror("alloc_sendfile_buf_ring: could not stat file");
   1621       exit(1);
   1622     }
   1623     if (statbuf.st_size < (width * buffer_size)) {
   1624       /* the file is too short */
   1625       fprintf(stderr,"alloc_sendfile_buf_ring: specified file too small.\n");
   1626       fprintf(stderr,"file must be larger than send_width * send_size\n");
   1627       fflush(stderr);
   1628       exit(1);
   1629     }
   1630   }
   1631 
   1632   /* so, at this point we know that fildes is a descriptor which
   1633      references a file of sufficient size for our nefarious
   1634      porpoises. raj 2007-08-09 */
   1635 
   1636   prev_link = NULL;
   1637   for (i = 1; i <= width; i++) {
   1638     /* get the ring element. we should probably make sure the malloc()
   1639      was successful, but for now we'll just let the code bomb
   1640      mysteriously. 08/2000 */
   1641 
   1642     temp_link = (struct sendfile_ring_elt *)
   1643       malloc(sizeof(struct sendfile_ring_elt));
   1644     if (temp_link == NULL) {
   1645       printf("malloc(%u) failed!\n", sizeof(struct sendfile_ring_elt));
   1646       exit(1);
   1647 	}
   1648 
   1649     /* remember the first one so we can close the ring at the end */
   1650 
   1651     if (i == 1) {
   1652       first_link = temp_link;
   1653     }
   1654 
   1655     /* now fill-in the fields of the structure with the apropriate
   1656        stuff. just how should we deal with alignment and offset I
   1657        wonder? until something better comes-up, I think we will just
   1658        ignore them. 08/2000 */
   1659 
   1660     temp_link->fildes = fildes;      /* from which file do we send? */
   1661     temp_link->offset = offset;      /* starting at which offset? */
   1662     offset += buffer_size;           /* get ready for the next elt */
   1663     temp_link->length = buffer_size; /* how many bytes to send */
   1664     temp_link->hdtrl = NULL;         /* no header or trailer */
   1665     temp_link->flags = 0;            /* no flags */
   1666 
   1667     /* is where the buffer fill code went. */
   1668 
   1669     temp_link->next = prev_link;
   1670     prev_link = temp_link;
   1671   }
   1672   /* close the ring */
   1673   first_link->next = temp_link;
   1674 
   1675   return(first_link); /* it's a dummy ring */
   1676 }
   1677 
   1678 #endif /* HAVE_SENDFILE */
   1679 
   1680 
   1681  /***********************************************************************/
   1683  /*                                                                     */
   1684  /*     dump_request()                                                  */
   1685  /*                                                                     */
   1686  /* display the contents of the request array to the user. it will      */
   1687  /* display the contents in decimal, hex, and ascii, with four bytes    */
   1688  /* per line.                                                           */
   1689  /*                                                                     */
   1690  /***********************************************************************/
   1691 
   1692 void
   1693 dump_request()
   1694 {
   1695 int counter = 0;
   1696 fprintf(where,"request contents:\n");
   1697 for (counter = 0; counter < ((sizeof(netperf_request)/4)-3); counter += 4) {
   1698   fprintf(where,"%d:\t%8x %8x %8x %8x \t|%4.4s| |%4.4s| |%4.4s| |%4.4s|\n",
   1699           counter,
   1700           request_array[counter],
   1701           request_array[counter+1],
   1702           request_array[counter+2],
   1703           request_array[counter+3],
   1704           (char *)&request_array[counter],
   1705           (char *)&request_array[counter+1],
   1706           (char *)&request_array[counter+2],
   1707           (char *)&request_array[counter+3]);
   1708 }
   1709 fflush(where);
   1710 }
   1711 
   1712 
   1713  /***********************************************************************/
   1714  /*                                                                     */
   1715  /*     dump_response()                                                 */
   1716  /*                                                                     */
   1717  /* display the content of the response array to the user. it will      */
   1718  /* display the contents in decimal, hex, and ascii, with four bytes    */
   1719  /* per line.                                                           */
   1720  /*                                                                     */
   1721  /***********************************************************************/
   1722 
   1723 void
   1724 dump_response()
   1725 {
   1726 int counter = 0;
   1727 
   1728 fprintf(where,"response contents\n");
   1729 for (counter = 0; counter < ((sizeof(netperf_response)/4)-3); counter += 4) {
   1730   fprintf(where,"%d:\t%8x %8x %8x %8x \t>%4.4s< >%4.4s< >%4.4s< >%4.4s<\n",
   1731           counter,
   1732           response_array[counter],
   1733           response_array[counter+1],
   1734           response_array[counter+2],
   1735           response_array[counter+3],
   1736           (char *)&response_array[counter],
   1737           (char *)&response_array[counter+1],
   1738           (char *)&response_array[counter+2],
   1739           (char *)&response_array[counter+3]);
   1740 }
   1741 fflush(where);
   1742 }
   1743 
   1744  /*
   1745 
   1746       format_number()
   1747 
   1748   return a pointer to a formatted string containing the value passed
   1749   translated into the units specified. It assumes that the base units
   1750   are bytes. If the format calls for bits, it will use SI units (10^)
   1751   if the format calls for bytes, it will use CS units (2^)...  This
   1752   routine should look familiar to uses of the latest ttcp...
   1753 
   1754   we would like to use "t" or "T" for transactions, but probably
   1755   should leave those for terabits and terabytes respectively, so for
   1756   transactions, we will use "x" which will, by default, do absolutely
   1757   nothing to the result.  why?  so we don't have to special case code
   1758   elsewhere such as in the TCP_RR-as-bidirectional test case.
   1759 
   1760  */
   1761 
   1762 
   1763 char *
   1764 format_number(double number)
   1765 {
   1766   static  char    fmtbuf[64];
   1767 
   1768   switch (libfmt) {
   1769   case 'K':
   1770     snprintf(fmtbuf, sizeof(fmtbuf),  "%-7.2f" , number / 1024.0);
   1771     break;
   1772   case 'M':
   1773     snprintf(fmtbuf, sizeof(fmtbuf),  "%-7.2f", number / 1024.0 / 1024.0);
   1774     break;
   1775   case 'G':
   1776     snprintf(fmtbuf, sizeof(fmtbuf),  "%-7.2f", number / 1024.0 / 1024.0 / 1024.0);
   1777     break;
   1778   case 'k':
   1779     snprintf(fmtbuf, sizeof(fmtbuf),  "%-7.2f", number * 8 / 1000.0);
   1780     break;
   1781   case 'm':
   1782     snprintf(fmtbuf, sizeof(fmtbuf),  "%-7.2f", number * 8 / 1000.0 / 1000.0);
   1783     break;
   1784   case 'g':
   1785     snprintf(fmtbuf, sizeof(fmtbuf),  "%-7.2f", number * 8 / 1000.0 / 1000.0 / 1000.0);
   1786     break;
   1787   case 'x':
   1788     snprintf(fmtbuf, sizeof(fmtbuf),  "%-7.2f", number);
   1789     break;
   1790   default:
   1791     snprintf(fmtbuf, sizeof(fmtbuf),  "%-7.2f", number / 1024.0);
   1792   }
   1793 
   1794   return fmtbuf;
   1795 }
   1796 
   1797 char
   1798 format_cpu_method(int method)
   1799 {
   1800 
   1801   char method_char;
   1802 
   1803   switch (method) {
   1804   case CPU_UNKNOWN:
   1805     method_char = 'U';
   1806     break;
   1807   case HP_IDLE_COUNTER:
   1808     method_char = 'I';
   1809     break;
   1810   case PSTAT:
   1811     method_char = 'P';
   1812     break;
   1813   case KSTAT:
   1814     method_char = 'K';
   1815     break;
   1816   case KSTAT_10:
   1817     method_char = 'M';
   1818     break;
   1819   case PERFSTAT:
   1820     method_char = 'E';
   1821     break;
   1822   case TIMES:             /* historical only, completely unsuitable
   1823 			     for netperf's purposes */
   1824     method_char = 'T';
   1825     break;
   1826   case GETRUSAGE:         /* historical only, completely unsuitable
   1827 			     for netperf;s purposes */
   1828     method_char = 'R';
   1829     break;
   1830   case LOOPER:
   1831     method_char = 'L';
   1832     break;
   1833   case NT_METHOD:
   1834     method_char = 'N';
   1835     break;
   1836   case PROC_STAT:
   1837     method_char = 'S';
   1838     break;
   1839   case SYSCTL:
   1840     method_char = 'C';
   1841     break;
   1842   case OSX:
   1843     method_char = 'O';
   1844     break;
   1845   default:
   1846     method_char = '?';
   1847   }
   1848 
   1849   return method_char;
   1850 
   1851 }
   1852 
   1853 char *
   1854 format_units()
   1855 {
   1856   static        char    unitbuf[64];
   1857 
   1858   switch (libfmt) {
   1859   case 'K':
   1860     strcpy(unitbuf, "KBytes");
   1861     break;
   1862   case 'M':
   1863     strcpy(unitbuf, "MBytes");
   1864     break;
   1865   case 'G':
   1866     strcpy(unitbuf, "GBytes");
   1867     break;
   1868   case 'k':
   1869     strcpy(unitbuf, "10^3bits");
   1870     break;
   1871   case 'm':
   1872     strcpy(unitbuf, "10^6bits");
   1873     break;
   1874   case 'g':
   1875     strcpy(unitbuf, "10^9bits");
   1876     break;
   1877   case 'x':
   1878     strcpy(unitbuf, "Trans");
   1879     break;
   1880 
   1881   default:
   1882     strcpy(unitbuf, "KBytes");
   1883   }
   1884 
   1885   return unitbuf;
   1886 }
   1887 
   1888 
   1890 /****************************************************************/
   1891 /*                                                              */
   1892 /*      shutdown_control()                                      */
   1893 /*                                                              */
   1894 /* tear-down the control connection between me and the server.  */
   1895 /****************************************************************/
   1896 
   1897 void
   1898 shutdown_control()
   1899 {
   1900 
   1901   char  *buf = (char *)&netperf_response;
   1902   int   buflen = sizeof(netperf_response);
   1903 
   1904   /* stuff for select, use fd_set for better compliance */
   1905   fd_set        readfds;
   1906   struct        timeval timeout;
   1907 
   1908   if (debug) {
   1909     fprintf(where,
   1910             "shutdown_control: shutdown of control connection requested.\n");
   1911     fflush(where);
   1912   }
   1913 
   1914   /* first, we say that we will be sending no more data on the */
   1915   /* connection */
   1916   if (shutdown(netlib_control,1) == SOCKET_ERROR) {
   1917     Print_errno(where,
   1918             "shutdown_control: error in shutdown");
   1919     fflush(where);
   1920     exit(1);
   1921   }
   1922 
   1923   /* Now, we hang on a select waiting for the socket to become */
   1924   /* readable to receive the shutdown indication from the remote. this */
   1925   /* will be "just" like the recv_response() code */
   1926 
   1927   /* we only select once. it is assumed that if the response is split */
   1928   /* (which should not be happening, that we will receive the whole */
   1929   /* thing and not have a problem ;-) */
   1930 
   1931   FD_ZERO(&readfds);
   1932   FD_SET(netlib_control,&readfds);
   1933   timeout.tv_sec  = 60; /* wait one minute then punt */
   1934   timeout.tv_usec = 0;
   1935 
   1936   /* select had better return one, or there was either a problem or a */
   1937   /* timeout... */
   1938   if (select(FD_SETSIZE,
   1939              &readfds,
   1940              0,
   1941              0,
   1942              &timeout) != 1) {
   1943     Print_errno(where,
   1944             "shutdown_control: no response received");
   1945     fflush(where);
   1946     exit(1);
   1947   }
   1948 
   1949   /* we now assume that the socket has come ready for reading */
   1950   recv(netlib_control, buf, buflen,0);
   1951 
   1952 }
   1953 
   1954 /*
   1955   bind_to_specific_processor will bind the calling process to the
   1956   processor in "processor"  It has lots of ugly ifdefs to deal with
   1957   all the different ways systems do processor affinity.  this is a
   1958   generalization of work initially done by stephen burger.  raj
   1959   2004/12/13 */
   1960 
   1961 void
   1962 bind_to_specific_processor(int processor_affinity, int use_cpu_map)
   1963 {
   1964 
   1965   int mapped_affinity;
   1966 
   1967   /* this is in place because the netcpu_looper processor affinity
   1968      ass-u-me-s a contiguous CPU id space starting with 0. for the
   1969      regular netperf/netserver affinity, we ass-u-me the user has used
   1970      a suitable CPU id even when the space is not contiguous and
   1971      starting from zero */
   1972   if (use_cpu_map) {
   1973     mapped_affinity = lib_cpu_map[processor_affinity];
   1974   }
   1975   else {
   1976     mapped_affinity = processor_affinity;
   1977   }
   1978 
   1979 #ifdef HAVE_MPCTL
   1980   /* indeed, at some point it would be a good idea to check the return
   1981      status and pass-along notification of error... raj 2004/12/13 */
   1982   mpctl(MPC_SETPROCESS_FORCE, mapped_affinity, getpid());
   1983 #elif HAVE_PROCESSOR_BIND
   1984 #include <sys/types.h>
   1985 #include <sys/processor.h>
   1986 #include <sys/procset.h>
   1987   processor_bind(P_PID,P_MYID,mapped_affinity,NULL);
   1988 #elif HAVE_BINDPROCESSOR
   1989 #include <sys/processor.h>
   1990   /* this is the call on AIX.  It takes a "what" of BINDPROCESS or
   1991      BINDTHRAD, then "who" and finally "where" which is a CPU number
   1992      or it seems PROCESSOR_CLASS_ANY there also seems to be a mycpu()
   1993      call to return the current CPU assignment.  this is all based on
   1994      the sys/processor.h include file.  from empirical testing, it
   1995      would seem that the my_cpu() call returns the current CPU on
   1996      which we are running rather than the CPU binding, so it's return
   1997      value will not tell you if you are bound vs unbound. */
   1998   bindprocessor(BINDPROCESS,getpid(),(cpu_t)mapped_affinity);
   1999 #elif HAVE_SCHED_SETAFFINITY
   2000 #include <sched.h>
   2001   /* in theory this should cover systems with more CPUs than bits in a
   2002      long, without having to specify __USE_GNU.  we "cheat" by taking
   2003      defines from /usr/include/bits/sched.h, which we ass-u-me is
   2004      included by <sched.h>.  If they are not there we will just
   2005      fall-back on what we had before, which is to use just the size of
   2006      an unsigned long. raj 2006-09-14 */
   2007 
   2008 #if defined(__CPU_SETSIZE)
   2009 #define NETPERF_CPU_SETSIZE __CPU_SETSIZE
   2010 #define NETPERF_CPU_SET(cpu, cpusetp)  __CPU_SET(cpu, cpusetp)
   2011 #define NETPERF_CPU_ZERO(cpusetp)      __CPU_ZERO (cpusetp)
   2012   typedef cpu_set_t netperf_cpu_set_t;
   2013 #else
   2014 #define NETPERF_CPU_SETSIZE sizeof(unsigned long)
   2015 #define NETPERF_CPU_SET(cpu, cpusetp) *cpusetp = 1 << cpu
   2016 #define NETPERF_CPU_ZERO(cpusetp) *cpusetp = (unsigned long)0
   2017   typedef unsigned long netperf_cpu_set_t;
   2018 #endif
   2019 
   2020   netperf_cpu_set_t   netperf_cpu_set;
   2021   unsigned int        len = sizeof(netperf_cpu_set);
   2022 
   2023   if (mapped_affinity < 8*sizeof(netperf_cpu_set)) {
   2024     NETPERF_CPU_ZERO(&netperf_cpu_set);
   2025     NETPERF_CPU_SET(mapped_affinity,&netperf_cpu_set);
   2026 
   2027     if (sched_setaffinity(getpid(), len, &netperf_cpu_set)) {
   2028       if (debug) {
   2029 	fprintf(stderr, "failed to set PID %d's CPU affinity errno %d\n",
   2030 		getpid(),errno);
   2031 	fflush(stderr);
   2032       }
   2033     }
   2034   }
   2035   else {
   2036     if (debug) {
   2037 	fprintf(stderr,
   2038 		"CPU number larger than pre-compiled limits. Consider a recompile.\n");
   2039 	fflush(stderr);
   2040       }
   2041   }
   2042 
   2043 #elif HAVE_BIND_TO_CPU_ID
   2044   /* this is the one for Tru64 */
   2045 #include <sys/types.h>
   2046 #include <sys/resource.h>
   2047 #include <sys/processor.h>
   2048 
   2049   /* really should be checking a return code one of these days. raj
   2050      2005/08/31 */
   2051 
   2052   bind_to_cpu_id(getpid(), mapped_affinity,0);
   2053 
   2054 #elif WIN32
   2055 
   2056   {
   2057     ULONG_PTR AffinityMask;
   2058     ULONG_PTR ProcessAffinityMask;
   2059     ULONG_PTR SystemAffinityMask;
   2060 
   2061     if ((mapped_affinity < 0) ||
   2062 	(mapped_affinity > MAXIMUM_PROCESSORS)) {
   2063       fprintf(where,
   2064 	      "Invalid processor_affinity specified: %d\n", mapped_affinity);      fflush(where);
   2065       return;
   2066     }
   2067 
   2068     if (!GetProcessAffinityMask(
   2069 				GetCurrentProcess(),
   2070 				&ProcessAffinityMask,
   2071 				&SystemAffinityMask))
   2072       {
   2073 	perror("GetProcessAffinityMask failed");
   2074 	fflush(stderr);
   2075 	exit(1);
   2076       }
   2077 
   2078     AffinityMask = (ULONG_PTR)1 << mapped_affinity;
   2079 
   2080     if (AffinityMask & ProcessAffinityMask) {
   2081       if (!SetThreadAffinityMask( GetCurrentThread(), AffinityMask)) {
   2082 	perror("SetThreadAffinityMask failed");
   2083 	fflush(stderr);
   2084       }
   2085     } else if (debug) {
   2086       fprintf(where,
   2087 	      "Processor affinity set to CPU# %d\n", mapped_affinity);
   2088       fflush(where);
   2089     }
   2090   }
   2091 
   2092 #else
   2093   if (debug) {
   2094     fprintf(where,
   2095 	    "Processor affinity not available for this platform!\n");
   2096     fflush(where);
   2097   }
   2098 #endif
   2099 }
   2100 
   2101 
   2102 /*
   2104  * Sets a socket to non-blocking operation.
   2105  */
   2106 int
   2107 set_nonblock (SOCKET sock)
   2108 {
   2109 #ifdef WIN32
   2110   unsigned long flags = 1;
   2111   return (ioctlsocket(sock, FIONBIO, &flags) != SOCKET_ERROR);
   2112 #else
   2113   return (fcntl(sock, F_SETFL, O_NONBLOCK) != -1);
   2114 #endif
   2115 }
   2116 
   2117 
   2118 
   2120  /***********************************************************************/
   2121  /*                                                                     */
   2122  /*     send_request()                                                  */
   2123  /*                                                                     */
   2124  /* send a netperf request on the control socket to the remote half of  */
   2125  /* the connection. to get us closer to intervendor interoperability,   */
   2126  /* we will call htonl on each of the int that compose the message to   */
   2127  /* be sent. the server-half of the connection will call the ntohl      */
   2128  /* routine to undo any changes that may have been made...              */
   2129  /*                                                                     */
   2130  /***********************************************************************/
   2131 
   2132 void
   2133 send_request()
   2134 {
   2135   int   counter=0;
   2136 
   2137   /* display the contents of the request if the debug level is high */
   2138   /* enough. otherwise, just send the darned thing ;-) */
   2139 
   2140   if (debug > 1) {
   2141     fprintf(where,"entered send_request...contents before htonl:\n");
   2142     dump_request();
   2143   }
   2144 
   2145   /* pass the processor affinity request value to netserver */
   2146   /* this is a kludge and I know it.  sgb 8/11/04           */
   2147 
   2148   netperf_request.content.dummy = remote_proc_affinity;
   2149 
   2150   /* put the entire request array into network order. We do this */
   2151   /* arbitrarily rather than trying to figure-out just how much */
   2152   /* of the request array contains real information. this should */
   2153   /* be simpler, and at any rate, the performance of sending */
   2154   /* control messages for this benchmark is not of any real */
   2155   /* concern. */
   2156 
   2157   for (counter=0;counter < sizeof(netperf_request)/4; counter++) {
   2158     request_array[counter] = htonl(request_array[counter]);
   2159   }
   2160 
   2161   if (debug > 1) {
   2162     fprintf(where,"send_request...contents after htonl:\n");
   2163     dump_request();
   2164 
   2165     fprintf(where,
   2166             "\nsend_request: about to send %u bytes from %p\n",
   2167             sizeof(netperf_request),
   2168             &netperf_request);
   2169     fflush(where);
   2170   }
   2171 
   2172   if (send(netlib_control,
   2173            (char *)&netperf_request,
   2174            sizeof(netperf_request),
   2175            0) != sizeof(netperf_request)) {
   2176     perror("send_request: send call failure");
   2177 
   2178     exit(1);
   2179   }
   2180 }
   2181 
   2182 /***********************************************************************/
   2183  /*                                                                     */
   2184  /*     send_response()                                                 */
   2185  /*                                                                     */
   2186  /* send a netperf response on the control socket to the remote half of */
   2187  /* the connection. to get us closer to intervendor interoperability,   */
   2188  /* we will call htonl on each of the int that compose the message to   */
   2189  /* be sent. the other half of the connection will call the ntohl       */
   2190  /* routine to undo any changes that may have been made...              */
   2191  /*                                                                     */
   2192  /***********************************************************************/
   2193 
   2194 void
   2195 send_response()
   2196 {
   2197   int   counter=0;
   2198   int	bytes_sent;
   2199 
   2200   /* display the contents of the request if the debug level is high */
   2201   /* enough. otherwise, just send the darned thing ;-) */
   2202 
   2203   if (debug > 1) {
   2204     fprintf(where,
   2205             "send_response: contents of %u ints before htonl\n",
   2206             sizeof(netperf_response)/4);
   2207     dump_response();
   2208   }
   2209 
   2210   /* put the entire response_array into network order. We do this */
   2211   /* arbitrarily rather than trying to figure-out just how much of the */
   2212   /* request array contains real information. this should be simpler, */
   2213   /* and at any rate, the performance of sending control messages for */
   2214   /* this benchmark is not of any real concern. */
   2215 
   2216   for (counter=0;counter < sizeof(netperf_response)/4; counter++) {
   2217     response_array[counter] = htonl(response_array[counter]);
   2218   }
   2219 
   2220   if (debug > 1) {
   2221     fprintf(where,
   2222             "send_response: contents after htonl\n");
   2223     dump_response();
   2224     fprintf(where,
   2225             "about to send %u bytes from %p\n",
   2226             sizeof(netperf_response),
   2227             &netperf_response);
   2228     fflush(where);
   2229   }
   2230 
   2231   /*KC*/
   2232   if ((bytes_sent = send(server_sock,
   2233            (char *)&netperf_response,
   2234            sizeof(netperf_response),
   2235            0)) != sizeof(netperf_response)) {
   2236     perror("send_response: send call failure");
   2237 	fprintf(where, "BytesSent: %d\n", bytes_sent);
   2238     exit(1);
   2239   }
   2240 
   2241 }
   2242 
   2243  /***********************************************************************/
   2244  /*                                                                     */
   2245  /*     recv_request()                                                  */
   2246  /*                                                                     */
   2247  /* receive the remote's request on the control socket. we will put     */
   2248  /* the entire response into host order before giving it to the         */
   2249  /* calling routine. hopefully, this will go most of the way to         */
   2250  /* insuring intervendor interoperability. if there are any problems,   */
   2251  /* we will just punt the entire situation.                             */
   2252  /*                                                                     */
   2253  /***********************************************************************/
   2254 
   2255 void
   2256 recv_request()
   2257 {
   2258 int     tot_bytes_recvd,
   2259         bytes_recvd,
   2260         bytes_left;
   2261 char    *buf = (char *)&netperf_request;
   2262 int     buflen = sizeof(netperf_request);
   2263 int     counter;
   2264 
   2265 tot_bytes_recvd = 0;
   2266  bytes_recvd = 0;     /* nt_lint; bytes_recvd uninitialized if buflen == 0 */
   2267 bytes_left      = buflen;
   2268 while ((tot_bytes_recvd != buflen) &&
   2269        ((bytes_recvd = recv(server_sock, buf, bytes_left,0)) > 0 )) {
   2270   tot_bytes_recvd += bytes_recvd;
   2271   buf             += bytes_recvd;
   2272   bytes_left      -= bytes_recvd;
   2273 }
   2274 
   2275 /* put the request into host order */
   2276 
   2277 for (counter = 0; counter < sizeof(netperf_request)/sizeof(int); counter++) {
   2278   request_array[counter] = ntohl(request_array[counter]);
   2279 }
   2280 
   2281 if (debug) {
   2282   fprintf(where,
   2283           "recv_request: received %d bytes of request.\n",
   2284           tot_bytes_recvd);
   2285   fflush(where);
   2286 }
   2287 
   2288 if (bytes_recvd == SOCKET_ERROR) {
   2289   Print_errno(where,
   2290           "recv_request: error on recv");
   2291   fflush(where);
   2292   exit(1);
   2293 }
   2294 
   2295 if (bytes_recvd == 0) {
   2296   /* the remote has shutdown the control connection, we should shut it */
   2297   /* down as well and exit */
   2298 
   2299   if (debug) {
   2300     fprintf(where,
   2301             "recv_request: remote requested shutdown of control\n");
   2302     fflush(where);
   2303   }
   2304 
   2305   if (netlib_control != INVALID_SOCKET) {
   2306         shutdown_control();
   2307   }
   2308   exit(0);
   2309 }
   2310 
   2311 if (tot_bytes_recvd < buflen) {
   2312   if (debug > 1)
   2313     dump_request();
   2314 
   2315   fprintf(where,
   2316           "recv_request: partial request received of %d bytes\n",
   2317           tot_bytes_recvd);
   2318   fflush(where);
   2319   exit(1);
   2320 }
   2321 
   2322  if (debug > 1) {
   2323    dump_request();
   2324  }
   2325 
   2326   /* get the processor affinity request value from netperf */
   2327   /* this is a kludge and I know it.  sgb 8/11/04          */
   2328 
   2329   local_proc_affinity = netperf_request.content.dummy;
   2330 
   2331   if (local_proc_affinity != -1) {
   2332     bind_to_specific_processor(local_proc_affinity,0);
   2333   }
   2334 
   2335 }
   2336 
   2337  /*
   2338 
   2339       recv_response_timed()
   2340 
   2341  receive the remote's response on the control socket. we will put the
   2342  entire response into host order before giving it to the calling
   2343  routine. hopefully, this will go most of the way to insuring
   2344  intervendor interoperability. if there are any problems, we will just
   2345  punt the entire situation.
   2346 
   2347  The call to select at the beginning is to get us out of hang
   2348  situations where the remote gives-up but we don't find-out about
   2349  it. This seems to happen only rarely, but it would be nice to be
   2350  somewhat robust ;-)
   2351 
   2352  The "_timed" part is to allow the caller to add (or I suppose
   2353  subtract) from the length of timeout on the select call. this was
   2354  added since not all the CPU utilization mechanisms require a 40
   2355  second calibration, and we used to have an aribtrary 40 second sleep
   2356  in "calibrate_remote_cpu" - since we don't _always_ need that, we
   2357  want to simply add 40 seconds to the select() timeout from that call,
   2358  but don't want to change all the "recv_response" calls in the code
   2359  right away.  sooo, we push the functionality of the old
   2360  recv_response() into a new recv_response_timed(addl_timout) call, and
   2361  have recv_response() call recv_response_timed(0).  raj 2005-05-16
   2362 
   2363  */
   2364 
   2365 
   2366 void
   2367 recv_response_timed(int addl_time)
   2368 {
   2369 int     tot_bytes_recvd,
   2370         bytes_recvd = 0,
   2371         bytes_left;
   2372 char    *buf = (char *)&netperf_response;
   2373 int     buflen = sizeof(netperf_response);
   2374 int     counter;
   2375 
   2376  /* stuff for select, use fd_set for better compliance */
   2377 fd_set  readfds;
   2378 struct  timeval timeout;
   2379 
   2380 tot_bytes_recvd = 0;
   2381 bytes_left      = buflen;
   2382 
   2383 /* zero out the response structure */
   2384 
   2385 /* BUG FIX SJB 2/4/93 - should be < not <= */
   2386 for (counter = 0; counter < sizeof(netperf_response)/sizeof(int); counter++) {
   2387         response_array[counter] = 0;
   2388 }
   2389 
   2390  /* we only select once. it is assumed that if the response is split */
   2391  /* (which should not be happening, that we will receive the whole */
   2392  /* thing and not have a problem ;-) */
   2393 
   2394 FD_ZERO(&readfds);
   2395 FD_SET(netlib_control,&readfds);
   2396 timeout.tv_sec  = 120 + addl_time;  /* wait at least two minutes
   2397                                       before punting - the USE_LOOPER
   2398                                       CPU stuff may cause remote's to
   2399                                       have a bit longer time of it
   2400                                       than 60 seconds would allow.
   2401                                       triggered by fix from Jeff
   2402                                       Dwork. */
   2403 timeout.tv_usec = 0;
   2404 
   2405  /* select had better return one, or there was either a problem or a */
   2406  /* timeout... */
   2407 
   2408 if ((counter = select(FD_SETSIZE,
   2409                       &readfds,
   2410                       0,
   2411                       0,
   2412                       &timeout)) != 1) {
   2413   fprintf(where,
   2414           "netperf: receive_response: no response received. errno %d counter %d\n",
   2415           errno,
   2416           counter);
   2417   exit(1);
   2418 }
   2419 
   2420 while ((tot_bytes_recvd != buflen) &&
   2421        ((bytes_recvd = recv(netlib_control, buf, bytes_left,0)) > 0 )) {
   2422   tot_bytes_recvd += bytes_recvd;
   2423   buf             += bytes_recvd;
   2424   bytes_left      -= bytes_recvd;
   2425 }
   2426 
   2427 if (debug) {
   2428   fprintf(where,"recv_response: received a %d byte response\n",
   2429           tot_bytes_recvd);
   2430   fflush(where);
   2431 }
   2432 
   2433 /* put the response into host order */
   2434 
   2435 for (counter = 0; counter < sizeof(netperf_response)/sizeof(int); counter++) {
   2436   response_array[counter] = ntohl(response_array[counter]);
   2437 }
   2438 
   2439 if (bytes_recvd == SOCKET_ERROR) {
   2440         perror("recv_response");
   2441         exit(1);
   2442 }
   2443 if (tot_bytes_recvd < buflen) {
   2444   fprintf(stderr,
   2445           "recv_response: partial response received: %d bytes\n",
   2446           tot_bytes_recvd);
   2447   fflush(stderr);
   2448   if (debug > 1)
   2449     dump_response();
   2450   exit(1);
   2451 }
   2452 if (debug > 1) {
   2453   dump_response();
   2454 }
   2455 }
   2456 
   2457 void
   2458 recv_response()
   2459 {
   2460   recv_response_timed(0);
   2461 }
   2462 
   2463 
   2464 
   2466 #if defined(USE_PSTAT) || defined (USE_SYSCTL)
   2467 int
   2468 hi_32(big_int)
   2469      long long *big_int;
   2470 {
   2471   union overlay_u {
   2472     long long  dword;
   2473     long       words[2];
   2474   } *overlay;
   2475 
   2476   overlay = (union overlay_u *)big_int;
   2477   /* on those systems which are byte swapped, we really wish to */
   2478   /* return words[1] - at least I think so - raj 4/95 */
   2479   if (htonl(1L) == 1L) {
   2480     /* we are a "normal" :) machine */
   2481     return(overlay->words[0]);
   2482   }
   2483   else {
   2484     return(overlay->words[1]);
   2485   }
   2486 }
   2487 
   2488 int
   2489 lo_32(big_int)
   2490      long long *big_int;
   2491 {
   2492   union overlay_u {
   2493     long long  dword;
   2494     long       words[2];
   2495   } *overlay;
   2496 
   2497   overlay = (union overlay_u *)big_int;
   2498   /* on those systems which are byte swapped, we really wish to */
   2499   /* return words[0] - at least I think so - raj 4/95 */
   2500   if (htonl(1L) == 1L) {
   2501     /* we are a "normal" :) machine */
   2502     return(overlay->words[1]);
   2503   }
   2504   else {
   2505     return(overlay->words[0]);
   2506   }
   2507 }
   2508 
   2509 #endif /* USE_PSTAT || USE_SYSCTL */
   2510 
   2511 
   2513 void libmain()
   2514 {
   2515 fprintf(where,"hello world\n");
   2516 fprintf(where,"debug: %d\n",debug);
   2517 }
   2518 
   2519 
   2520 void
   2522 set_sock_buffer (SOCKET sd, enum sock_buffer which, int requested_size, int *effective_sizep)
   2523 {
   2524 #ifdef SO_SNDBUF
   2525   int optname = (which == SEND_BUFFER) ? SO_SNDBUF : SO_RCVBUF;
   2526   netperf_socklen_t sock_opt_len;
   2527 
   2528   /* seems that under Windows, setting a value of zero is how one
   2529      tells the stack you wish to enable copy-avoidance. Knuth only
   2530      knows what it will do on other stacks, but it might be
   2531      interesting to find-out, so we won't bother #ifdef'ing the change
   2532      to allow asking for 0 bytes. Courtesy of SAF, 2007-05  raj
   2533      2007-05-31 */
   2534   if (requested_size >= 0) {
   2535     if (setsockopt(sd, SOL_SOCKET, optname,
   2536 		   (char *)&requested_size, sizeof(int)) < 0) {
   2537       fprintf(where, "netperf: set_sock_buffer: %s option: errno %d\n",
   2538 	      (which == SEND_BUFFER) ? "SO_SNDBUF" : "SO_RCVBUF",
   2539 	      errno);
   2540       fflush(where);
   2541       exit(1);
   2542     }
   2543     if (debug > 1) {
   2544       fprintf(where, "netperf: set_sock_buffer: %s of %d requested.\n",
   2545 	      (which == SEND_BUFFER) ? "SO_SNDBUF" : "SO_RCVBUF",
   2546 	      requested_size);
   2547       fflush(where);
   2548     }
   2549   }
   2550 
   2551   /* Now, we will find-out what the size actually became, and report */
   2552   /* that back to the user. If the call fails, we will just report a -1 */
   2553   /* back to the initiator for the recv buffer size. */
   2554 
   2555   sock_opt_len = sizeof(netperf_socklen_t);
   2556   if (getsockopt(sd, SOL_SOCKET, optname, (char *)effective_sizep,
   2557 		 &sock_opt_len) < 0) {
   2558     fprintf(where, "netperf: set_sock_buffer: getsockopt %s: errno %d\n",
   2559 	    (which == SEND_BUFFER) ? "SO_SNDBUF" : "SO_RCVBUF", errno);
   2560     fflush(where);
   2561     *effective_sizep = -1;
   2562   }
   2563 
   2564   if (debug) {
   2565     fprintf(where, "netperf: set_sock_buffer: "
   2566 	    "%s socket size determined to be %d\n",
   2567 	    (which == SEND_BUFFER) ? "send" : "receive", *effective_sizep);
   2568     fflush(where);
   2569   }
   2570 #else /* SO_SNDBUF */
   2571   *effective_size = -1;
   2572 #endif /* SO_SNDBUF */
   2573 }
   2574 
   2575 void
   2576 dump_addrinfo(FILE *dumploc, struct addrinfo *info,
   2577               char *host, char *port, int family)
   2578 {
   2579   struct sockaddr *ai_addr;
   2580   struct addrinfo *temp;
   2581   temp=info;
   2582 
   2583   fprintf(dumploc, "getaddrinfo returned the following for host '%s' ", host);
   2584   fprintf(dumploc, "port '%s' ", port);
   2585   fprintf(dumploc, "family %s\n", inet_ftos(family));
   2586   while (temp) {
   2587     /* seems that Solaris 10 GA bits will not give a canonical name
   2588        for ::0 or 0.0.0.0, and their fprintf() cannot deal with a null
   2589        pointer, so we have to check for a null pointer.  probably a
   2590        safe thing to do anyway, eventhough it was not necessary on
   2591        linux or hp-ux. raj 2005-02-09 */
   2592     if (temp->ai_canonname) {
   2593       fprintf(dumploc,
   2594 	      "\tcannonical name: '%s'\n",temp->ai_canonname);
   2595     }
   2596     else {
   2597       fprintf(dumploc,
   2598 	      "\tcannonical name: '%s'\n","(nil)");
   2599     }
   2600     fprintf(dumploc,
   2601             "\tflags: %x family: %s: socktype: %s protocol %s addrlen %d\n",
   2602             temp->ai_flags,
   2603             inet_ftos(temp->ai_family),
   2604             inet_ttos(temp->ai_socktype),
   2605             inet_ptos(temp->ai_protocol),
   2606             temp->ai_addrlen);
   2607     ai_addr = temp->ai_addr;
   2608     if (ai_addr != NULL) {
   2609       fprintf(dumploc,
   2610               "\tsa_family: %s sadata: %d %d %d %d %d %d\n",
   2611               inet_ftos(ai_addr->sa_family),
   2612               (u_char)ai_addr->sa_data[0],
   2613               (u_char)ai_addr->sa_data[1],
   2614               (u_char)ai_addr->sa_data[2],
   2615               (u_char)ai_addr->sa_data[3],
   2616               (u_char)ai_addr->sa_data[4],
   2617               (u_char)ai_addr->sa_data[5]);
   2618     }
   2619     temp = temp->ai_next;
   2620   }
   2621   fflush(dumploc);
   2622 }
   2623 
   2624 /*
   2625   establish_control()
   2626 
   2627 set-up the control connection between netperf and the netserver so we
   2628 can actually run some tests. if we cannot establish the control
   2629 connection, that may or may not be a good thing, so we will let the
   2630 caller decide what to do.
   2631 
   2632 to assist with pesky end-to-end-unfriendly things like firewalls, we
   2633 allow the caller to specify both the remote hostname and port, and the
   2634 local addressing info.  i believe that in theory it is possible to
   2635 have an IPv4 endpoint and an IPv6 endpoint communicate with one
   2636 another, but for the time being, we are only going to take-in one
   2637 requested address family parameter. this means that the only way
   2638 (iirc) that we might get a mixed-mode connection would be if the
   2639 address family is specified as AF_UNSPEC, and getaddrinfo() returns
   2640 different families for the local and server names.
   2641 
   2642 the "names" can also be IP addresses in ASCII string form.
   2643 
   2644 raj 2003-02-27 */
   2645 
   2646 SOCKET
   2647 establish_control_internal(char *hostname,
   2648 			   char *port,
   2649 			   int   remfam,
   2650 			   char *localhost,
   2651 			   char *localport,
   2652 			   int   locfam)
   2653 {
   2654   int not_connected;
   2655   SOCKET control_sock;
   2656   int count;
   2657   int error;
   2658 
   2659   struct addrinfo   hints;
   2660   struct addrinfo  *local_res;
   2661   struct addrinfo  *remote_res;
   2662   struct addrinfo  *local_res_temp;
   2663   struct addrinfo  *remote_res_temp;
   2664 
   2665   if (debug) {
   2666     fprintf(where,
   2667             "establish_control called with host '%s' port '%s' remfam %s\n",
   2668             hostname,
   2669             port,
   2670             inet_ftos(remfam));
   2671     fprintf(where,
   2672             "\t\tlocal '%s' port '%s' locfam %s\n",
   2673             localhost,
   2674             localport,
   2675             inet_ftos(locfam));
   2676     fflush(where);
   2677   }
   2678 
   2679   /* first, we do the remote */
   2680   memset(&hints, 0, sizeof(hints));
   2681   hints.ai_family = remfam;
   2682   hints.ai_socktype = SOCK_STREAM;
   2683   hints.ai_protocol = IPPROTO_TCP;
   2684   hints.ai_flags = 0|AI_CANONNAME;
   2685   count = 0;
   2686   do {
   2687     error = getaddrinfo((char *)hostname,
   2688                         (char *)port,
   2689                         &hints,
   2690                         &remote_res);
   2691     count += 1;
   2692     if (error == EAI_AGAIN) {
   2693       if (debug) {
   2694         fprintf(where,"Sleeping on getaddrinfo EAI_AGAIN\n");
   2695         fflush(where);
   2696       }
   2697       sleep(1);
   2698     }
   2699   } while ((error == EAI_AGAIN) && (count <= 5));
   2700 
   2701   if (error) {
   2702     printf("establish control: could not resolve remote '%s' port '%s' af %s",
   2703            hostname,
   2704            port,
   2705            inet_ftos(remfam));
   2706     printf("\n\tgetaddrinfo returned %d %s\n",
   2707            error,
   2708            gai_strerror(error));
   2709     return(INVALID_SOCKET);
   2710   }
   2711 
   2712   if (debug) {
   2713     dump_addrinfo(where, remote_res, hostname, port, remfam);
   2714   }
   2715 
   2716   /* now we do the local */
   2717   memset(&hints, 0, sizeof(hints));
   2718   hints.ai_family = locfam;
   2719   hints.ai_socktype = SOCK_STREAM;
   2720   hints.ai_protocol = IPPROTO_TCP;
   2721   hints.ai_flags = AI_PASSIVE|AI_CANONNAME;
   2722   count = 0;
   2723   do {
   2724     count += 1;
   2725     error = getaddrinfo((char *)localhost,
   2726                            (char *)localport,
   2727                            &hints,
   2728                            &local_res);
   2729     if (error == EAI_AGAIN) {
   2730       if (debug) {
   2731         fprintf(where,
   2732                 "Sleeping on getaddrinfo(%s,%s) EAI_AGAIN count %d \n",
   2733                 localhost,
   2734                 localport,
   2735                 count);
   2736         fflush(where);
   2737       }
   2738       sleep(1);
   2739     }
   2740   } while ((error == EAI_AGAIN) && (count <= 5));
   2741 
   2742   if (error) {
   2743     printf("establish control: could not resolve local '%s' port '%s' af %s",
   2744            localhost,
   2745            localport,
   2746            inet_ftos(locfam));
   2747     printf("\n\tgetaddrinfo returned %d %s\n",
   2748            error,
   2749            gai_strerror(error));
   2750     return(INVALID_SOCKET);
   2751   }
   2752 
   2753   if (debug) {
   2754     dump_addrinfo(where, local_res, localhost, localport, locfam);
   2755   }
   2756 
   2757   not_connected = 1;
   2758   local_res_temp = local_res;
   2759   remote_res_temp = remote_res;
   2760   /* we want to loop through all the possibilities. looping on the
   2761      local addresses will be handled within the while loop.  I suppose
   2762      these is some more "C-expert" way to code this, but it has not
   2763      lept to mind just yet :)  raj 2003-02024 */
   2764 
   2765   while (remote_res_temp != NULL) {
   2766 
   2767     /* I am guessing that we should use the address family of the
   2768        local endpoint, and we will not worry about mixed family types
   2769        - presumeably the stack or other transition mechanisms will be
   2770        able to deal with that for us. famous last words :)  raj 2003-02-26 */
   2771     control_sock = socket(local_res_temp->ai_family,
   2772                           SOCK_STREAM,
   2773                           0);
   2774     if (control_sock == INVALID_SOCKET) {
   2775       /* at some point we'll need a more generic "display error"
   2776          message for when/if we use GUIs and the like. unlike a bind
   2777          or connect failure, failure to allocate a socket is
   2778          "immediately fatal" and so we return to the caller. raj 2003-02-24 */
   2779       if (debug) {
   2780         perror("establish_control: unable to allocate control socket");
   2781       }
   2782       return(INVALID_SOCKET);
   2783     }
   2784 
   2785     /* if we are going to control the local enpoint addressing, we
   2786        need to call bind. of course, we should probably be setting one
   2787        of the SO_REUSEmumble socket options? raj 2005-02-04 */
   2788     if (bind(control_sock,
   2789 	     local_res_temp->ai_addr,
   2790 	     local_res_temp->ai_addrlen) == 0) {
   2791       if (debug) {
   2792 	fprintf(where,
   2793 		"bound control socket to %s and %s\n",
   2794 		localhost,
   2795 		localport);
   2796       }
   2797 
   2798       if (connect(control_sock,
   2799 		  remote_res_temp->ai_addr,
   2800 		  remote_res_temp->ai_addrlen) == 0) {
   2801 	/* we have successfully connected to the remote netserver */
   2802 	if (debug) {
   2803 	  fprintf(where,
   2804 		  "successful connection to remote netserver at %s and %s\n",
   2805 		  hostname,
   2806 		  port);
   2807 	}
   2808 	not_connected = 0;
   2809 	/* this should get us out of the while loop */
   2810 	break;
   2811       } else {
   2812 	/* the connect call failed */
   2813 	if (debug) {
   2814 	  fprintf(where,
   2815 		  "establish_control: connect failed, errno %d %s\n",
   2816 		  errno,
   2817 		  strerror(errno));
   2818 	  fprintf(where, "    trying next address combination\n");
   2819 	  fflush(where);
   2820 	}
   2821       }
   2822     }
   2823     else {
   2824       /* the bind failed */
   2825       if (debug) {
   2826 	fprintf(where,
   2827 		"establish_control: bind failed, errno %d %s\n",
   2828 		errno,
   2829 		strerror(errno));
   2830 	fprintf(where, "    trying next address combination\n");
   2831 	fflush(where);
   2832       }
   2833     }
   2834 
   2835     if ((local_res_temp = local_res_temp->ai_next) == NULL) {
   2836       /* wrap the local and move to the next server, don't forget to
   2837          close the current control socket. raj 2003-02-24 */
   2838       local_res_temp = local_res;
   2839       /* the outer while conditions will deal with the case when we
   2840          get to the end of all the possible remote addresses. */
   2841       remote_res_temp = remote_res_temp->ai_next;
   2842       /* it is simplest here to just close the control sock. since
   2843          this is not a performance critical section of code, we
   2844          don't worry about overheads for socket allocation or
   2845          close. raj 2003-02-24 */
   2846     }
   2847     close(control_sock);
   2848   }
   2849 
   2850   /* we no longer need the addrinfo stuff */
   2851   freeaddrinfo(local_res);
   2852   freeaddrinfo(remote_res);
   2853 
   2854   /* so, we are either connected or not */
   2855   if (not_connected) {
   2856     fprintf(where, "establish control: are you sure there is a netserver listening on %s at port %s?\n",hostname,port);
   2857     fflush(where);
   2858     return(INVALID_SOCKET);
   2859   }
   2860   /* at this point, we are connected.  we probably want some sort of
   2861      version check with the remote at some point. raj 2003-02-24 */
   2862   return(control_sock);
   2863 }
   2864 
   2865 void
   2866 establish_control(char *hostname,
   2867 		  char *port,
   2868 		  int   remfam,
   2869 		  char *localhost,
   2870 		  char *localport,
   2871 		  int   locfam)
   2872 
   2873 {
   2874 
   2875   netlib_control = establish_control_internal(hostname,
   2876 					      port,
   2877 					      remfam,
   2878 					      localhost,
   2879 					      localport,
   2880 					      locfam);
   2881   if (netlib_control == INVALID_SOCKET) {
   2882     fprintf(where,
   2883 	    "establish_control could not establish the control connection from %s port %s address family %s to %s port %s address family %s\n",
   2884 	    localhost,localport,inet_ftos(locfam),
   2885 	    hostname,port,inet_ftos(remfam));
   2886     fflush(where);
   2887     exit(INVALID_SOCKET);
   2888   }
   2889 }
   2890 
   2891 
   2892 
   2894 
   2895  /***********************************************************************/
   2896  /*                                                                     */
   2897  /*     get_id()                                                        */
   2898  /*                                                                     */
   2899  /* Return a string to the calling routine that contains the            */
   2900  /* identifying information for the host we are running on. This        */
   2901  /* information will then either be displayed locally, or returned to   */
   2902  /* a remote caller for display there.                                  */
   2903  /*                                                                     */
   2904  /***********************************************************************/
   2905 
   2906 char *
   2907 get_id()
   2908 {
   2909 	static char id_string[80];
   2910 #ifdef WIN32
   2911 char                    system_name[MAX_COMPUTERNAME_LENGTH+1] ;
   2912 DWORD                   name_len = MAX_COMPUTERNAME_LENGTH + 1 ;
   2913 #else
   2914 struct  utsname         system_name;
   2915 #endif /* WIN32 */
   2916 
   2917 #ifdef WIN32
   2918  SYSTEM_INFO SystemInfo;
   2919  GetSystemInfo( &SystemInfo ) ;
   2920  if ( !GetComputerName(system_name , &name_len) )
   2921    strcpy(system_name , "no_name") ;
   2922 #else
   2923  if (uname(&system_name) <0) {
   2924    perror("identify_local: uname");
   2925    exit(1);
   2926  }
   2927 #endif /* WIN32 */
   2928 
   2929  snprintf(id_string, sizeof(id_string),
   2930 #ifdef WIN32
   2931 	  "%-15s%-15s%d.%d%d",
   2932 	  "Windows NT",
   2933 	  system_name ,
   2934 	  GetVersion() & 0xFF ,
   2935 	  GetVersion() & 0xFF00 ,
   2936 	  SystemInfo.dwProcessorType
   2937 
   2938 #else
   2939 	  "%-15s%-15s%-15s%-15s%-15s",
   2940 	  system_name.sysname,
   2941 	  system_name.nodename,
   2942 	  system_name.release,
   2943 	  system_name.version,
   2944 	  system_name.machine
   2945 #endif /* WIN32 */
   2946 	  );
   2947  return (id_string);
   2948 }
   2949 
   2950 
   2951  /***********************************************************************/
   2952  /*                                                                     */
   2953  /*     identify_local()                                                */
   2954  /*                                                                     */
   2955  /* Display identifying information about the local host to the user.   */
   2956  /* At first release, this information will be the same as that which   */
   2957  /* is returned by the uname -a command, with the exception of the      */
   2958  /* idnumber field, which seems to be a non-POSIX item, and hence       */
   2959  /* non-portable.                                                       */
   2960  /*                                                                     */
   2961  /***********************************************************************/
   2962 
   2963 void
   2964 identify_local()
   2965 {
   2966 
   2967 char *local_id;
   2968 
   2969 local_id = get_id();
   2970 
   2971 fprintf(where,"Local Information \n\
   2972 Sysname       Nodename       Release        Version        Machine\n");
   2973 
   2974 fprintf(where,"%s\n",
   2975        local_id);
   2976 
   2977 }
   2978 
   2979 
   2980  /***********************************************************************/
   2981  /*                                                                     */
   2982  /*     identify_remote()                                               */
   2983  /*                                                                     */
   2984  /* Display identifying information about the remote host to the user.  */
   2985  /* At first release, this information will be the same as that which   */
   2986  /* is returned by the uname -a command, with the exception of the      */
   2987  /* idnumber field, which seems to be a non-POSIX item, and hence       */
   2988  /* non-portable. A request is sent to the remote side, which will      */
   2989  /* return a string containing the utsname information in a             */
   2990  /* pre-formatted form, which is then displayed after the header.       */
   2991  /*                                                                     */
   2992  /***********************************************************************/
   2993 
   2994 void
   2995 identify_remote()
   2996 {
   2997 
   2998 char    *remote_id="";
   2999 
   3000 /* send a request for node info to the remote */
   3001 netperf_request.content.request_type = NODE_IDENTIFY;
   3002 
   3003 send_request();
   3004 
   3005 /* and now wait for the reply to come back */
   3006 
   3007 recv_response();
   3008 
   3009 if (netperf_response.content.serv_errno) {
   3010         Set_errno(netperf_response.content.serv_errno);
   3011         perror("identify_remote: on remote");
   3012         exit(1);
   3013 }
   3014 
   3015 fprintf(where,"Remote Information \n\
   3016 Sysname       Nodename       Release        Version        Machine\n");
   3017 
   3018 fprintf(where,"%s",
   3019        remote_id);
   3020 }
   3021 
   3022 void
   3023 cpu_start(int measure_cpu)
   3024 {
   3025 
   3026   gettimeofday(&time1,
   3027                &tz);
   3028 
   3029   if (measure_cpu) {
   3030     cpu_util_init();
   3031     measuring_cpu = 1;
   3032     cpu_method = get_cpu_method();
   3033     cpu_start_internal();
   3034   }
   3035 }
   3036 
   3037 
   3038 void
   3040 cpu_stop(int measure_cpu, float *elapsed)
   3041 
   3042 {
   3043 
   3044   int     sec,
   3045     usec;
   3046 
   3047   if (measure_cpu) {
   3048     cpu_stop_internal();
   3049     cpu_util_terminate();
   3050   }
   3051 
   3052   gettimeofday(&time2,
   3053 	       &tz);
   3054 
   3055   if (time2.tv_usec < time1.tv_usec) {
   3056     time2.tv_usec += 1000000;
   3057     time2.tv_sec  -= 1;
   3058   }
   3059 
   3060   sec     = time2.tv_sec - time1.tv_sec;
   3061   usec    = time2.tv_usec - time1.tv_usec;
   3062   lib_elapsed     = (float)sec + ((float)usec/(float)1000000.0);
   3063 
   3064   *elapsed = lib_elapsed;
   3065 
   3066 }
   3067 
   3068 
   3069 double
   3070 calc_thruput_interval(double units_received,double elapsed)
   3071 
   3072 {
   3073   double        divisor;
   3074 
   3075   /* We will calculate the thruput in libfmt units/second */
   3076   switch (libfmt) {
   3077   case 'K':
   3078     divisor = 1024.0;
   3079     break;
   3080   case 'M':
   3081     divisor = 1024.0 * 1024.0;
   3082     break;
   3083   case 'G':
   3084     divisor = 1024.0 * 1024.0 * 1024.0;
   3085     break;
   3086   case 'k':
   3087     divisor = 1000.0 / 8.0;
   3088     break;
   3089   case 'm':
   3090     divisor = 1000.0 * 1000.0 / 8.0;
   3091     break;
   3092   case 'g':
   3093     divisor = 1000.0 * 1000.0 * 1000.0 / 8.0;
   3094     break;
   3095 
   3096   default:
   3097     divisor = 1024.0;
   3098   }
   3099 
   3100   return (units_received / divisor / elapsed);
   3101 
   3102 }
   3103 
   3104 double
   3105 calc_thruput(double units_received)
   3106 
   3107 {
   3108   return(calc_thruput_interval(units_received,lib_elapsed));
   3109 }
   3110 
   3111 /* these "_omni" versions are ones which understand 'x' as a unit,
   3112    meaning transactions/s.  we have a separate routine rather than
   3113    convert the existing routine so we don't have to go and change
   3114    _all_ the nettest_foo.c files at one time.  raj 2007-06-08 */
   3115 
   3116 double
   3117 calc_thruput_interval_omni(double units_received,double elapsed)
   3118 
   3119 {
   3120   double        divisor;
   3121 
   3122   /* We will calculate the thruput in libfmt units/second */
   3123   switch (libfmt) {
   3124   case 'K':
   3125     divisor = 1024.0;
   3126     break;
   3127   case 'M':
   3128     divisor = 1024.0 * 1024.0;
   3129     break;
   3130   case 'G':
   3131     divisor = 1024.0 * 1024.0 * 1024.0;
   3132     break;
   3133   case 'k':
   3134     divisor = 1000.0 / 8.0;
   3135     break;
   3136   case 'm':
   3137     divisor = 1000.0 * 1000.0 / 8.0;
   3138     break;
   3139   case 'g':
   3140     divisor = 1000.0 * 1000.0 * 1000.0 / 8.0;
   3141     break;
   3142   case 'x':
   3143     divisor = 1.0;
   3144     break;
   3145 
   3146   default:
   3147     fprintf(where,
   3148 	    "WARNING calc_throughput_internal_omni: unknown units %c\n",
   3149 	    libfmt);
   3150     fflush(where);
   3151     divisor = 1024.0;
   3152   }
   3153 
   3154   return (units_received / divisor / elapsed);
   3155 
   3156 }
   3157 
   3158 double
   3159 calc_thruput_omni(double units_received)
   3160 
   3161 {
   3162   return(calc_thruput_interval_omni(units_received,lib_elapsed));
   3163 }
   3164 
   3165 
   3166 
   3168 
   3169 
   3170 float
   3171 calc_cpu_util(float elapsed_time)
   3172 {
   3173   return(calc_cpu_util_internal(elapsed_time));
   3174 }
   3175 
   3176 float
   3177 calc_service_demand_internal(double unit_divisor,
   3178 			     double units_sent,
   3179 			     float elapsed_time,
   3180 			     float cpu_utilization,
   3181 			     int num_cpus)
   3182 
   3183 {
   3184 
   3185   double service_demand;
   3186   double thruput;
   3187 
   3188   if (debug) {
   3189     fprintf(where,"calc_service_demand called:  units_sent = %f\n",
   3190             units_sent);
   3191     fprintf(where,"                             elapsed_time = %f\n",
   3192             elapsed_time);
   3193     fprintf(where,"                             cpu_util = %f\n",
   3194             cpu_utilization);
   3195     fprintf(where,"                             num cpu = %d\n",
   3196             num_cpus);
   3197     fflush(where);
   3198   }
   3199 
   3200   if (num_cpus == 0) num_cpus = lib_num_loc_cpus;
   3201 
   3202   if (elapsed_time == 0.0) {
   3203     elapsed_time = lib_elapsed;
   3204   }
   3205   if (cpu_utilization == 0.0) {
   3206     cpu_utilization = lib_local_cpu_util;
   3207   }
   3208 
   3209   thruput = (units_sent /
   3210              (double) unit_divisor /
   3211              (double) elapsed_time);
   3212 
   3213   /* on MP systems, it is necessary to multiply the service demand by */
   3214   /* the number of CPU's. at least, I believe that to be the case:) */
   3215   /* raj 10/95 */
   3216 
   3217   /* thruput has a "per second" component. if we were using 100% ( */
   3218   /* 100.0) of the CPU in a second, that would be 1 second, or 1 */
   3219   /* millisecond, so we multiply cpu_utilization by 10 to go to */
   3220   /* milliseconds, or 10,000 to go to micro seconds. With revision */
   3221   /* 2.1, the service demand measure goes to microseconds per unit. */
   3222   /* raj 12/95 */
   3223   service_demand = (cpu_utilization*10000.0/thruput) *
   3224     (float) num_cpus;
   3225 
   3226   if (debug) {
   3227     fprintf(where,"calc_service_demand using:   units_sent = %f\n",
   3228             units_sent);
   3229     fprintf(where,"                             elapsed_time = %f\n",
   3230             elapsed_time);
   3231     fprintf(where,"                             cpu_util = %f\n",
   3232             cpu_utilization);
   3233     fprintf(where,"                             num cpu = %d\n",
   3234             num_cpus);
   3235     fprintf(where,"calc_service_demand got:     thruput = %f\n",
   3236             thruput);
   3237     fprintf(where,"                             servdem = %f\n",
   3238             service_demand);
   3239     fflush(where);
   3240   }
   3241   return (float)service_demand;
   3242 }
   3243 
   3244 float calc_service_demand(double units_sent,
   3245                           float elapsed_time,
   3246                           float cpu_utilization,
   3247                           int num_cpus)
   3248 
   3249 {
   3250 
   3251   double unit_divisor = (double)1024.0;
   3252 
   3253   return(calc_service_demand_internal(unit_divisor,
   3254 				      units_sent,
   3255 				      elapsed_time,
   3256 				      cpu_utilization,
   3257 				      num_cpus));
   3258 }
   3259 
   3260 float calc_service_demand_trans(double units_sent,
   3261 				float elapsed_time,
   3262 				float cpu_utilization,
   3263 				int num_cpus)
   3264 
   3265 {
   3266 
   3267   double unit_divisor = (double)1.0;
   3268 
   3269   return(calc_service_demand_internal(unit_divisor,
   3270 				      units_sent,
   3271 				      elapsed_time,
   3272 				      cpu_utilization,
   3273 				      num_cpus));
   3274 }
   3275 
   3276 
   3277 
   3279 float
   3280 calibrate_local_cpu(float local_cpu_rate)
   3281 {
   3282 
   3283   lib_num_loc_cpus = get_num_cpus();
   3284 
   3285   lib_use_idle = 0;
   3286 #ifdef USE_LOOPER
   3287   cpu_util_init();
   3288   lib_use_idle = 1;
   3289 #endif /* USE_LOOPER */
   3290 
   3291   if (local_cpu_rate > 0) {
   3292     /* The user think that he knows what the cpu rate is. We assume */
   3293     /* that all the processors of an MP system are essentially the */
   3294     /* same - for this reason we do not have a per processor maxrate. */
   3295     /* if the machine has processors which are different in */
   3296     /* performance, the CPU utilization will be skewed. raj 4/95 */
   3297     lib_local_maxrate = local_cpu_rate;
   3298   }
   3299   else {
   3300     /* if neither USE_LOOPER nor USE_PSTAT are defined, we return a */
   3301     /* 0.0 to indicate that times or getrusage should be used. raj */
   3302     /* 4/95 */
   3303     lib_local_maxrate = (float)0.0;
   3304 #if defined(USE_PROC_STAT) || defined(USE_LOOPER) || defined(USE_PSTAT) || defined(USE_KSTAT) || defined(USE_PERFSTAT) || defined(USE_SYSCTL)
   3305     lib_local_maxrate = calibrate_idle_rate(4,10);
   3306 #endif
   3307   }
   3308   return lib_local_maxrate;
   3309 }
   3310 
   3311 
   3312 float
   3313 calibrate_remote_cpu()
   3314 {
   3315   float remrate;
   3316 
   3317   netperf_request.content.request_type = CPU_CALIBRATE;
   3318   send_request();
   3319   /* we know that calibration will last at least 40 seconds, so go to */
   3320   /* sleep for that long so the 60 second select in recv_response will */
   3321   /* not pop. raj 7/95 */
   3322 
   3323   /* we know that CPU calibration may last as long as 40 seconds, so
   3324      make sure we "select" for at least that long while looking for
   3325      the response. raj 2005-05-16 */
   3326   recv_response_timed(40);
   3327 
   3328   if (netperf_response.content.serv_errno) {
   3329     /* initially, silently ignore remote errors and pass */
   3330     /* back a zero to the caller this should allow us to */
   3331     /* mix rev 1.0 and rev 1.1 netperfs... */
   3332     return((float)0.0);
   3333   }
   3334   else {
   3335     /* the rate is the first word of the test_specific data */
   3336     bcopy((char *)netperf_response.content.test_specific_data,
   3337           (char *)&remrate,
   3338           sizeof(remrate));
   3339     bcopy((char *)netperf_response.content.test_specific_data + sizeof(remrate),
   3340 	  (char *)&lib_num_rem_cpus,
   3341 	  sizeof(lib_num_rem_cpus));
   3342 /*    remrate = (float) netperf_response.content.test_specific_data[0]; */
   3343     return(remrate);
   3344   }
   3345 }
   3346 
   3347 #ifndef WIN32
   3349 /* WIN32 requires that at least one of the file sets to select be non-null. */
   3350 /* Since msec_sleep routine is only called by nettest_dlpi & nettest_unix,  */
   3351 /* let's duck this issue. */
   3352 
   3353 int
   3354 msec_sleep( int msecs )
   3355 {
   3356   int           rval ;
   3357 
   3358   struct timeval timeout;
   3359 
   3360   timeout.tv_sec = msecs / 1000;
   3361   timeout.tv_usec = (msecs - (msecs/1000) *1000) * 1000;
   3362   if ((rval = select(0,
   3363              0,
   3364              0,
   3365              0,
   3366              &timeout))) {
   3367     if ( SOCKET_EINTR(rval) ) {
   3368       return(1);
   3369     }
   3370     perror("msec_sleep: select");
   3371     exit(1);
   3372   }
   3373   return(0);
   3374 }
   3375 #endif /* WIN32 */
   3376 
   3377 #ifdef WANT_HISTOGRAM
   3378 /* hist.c
   3379 
   3380    Given a time difference in microseconds, increment one of 61
   3381    different buckets:
   3382 
   3383    0 - 9 in increments of 1 usec
   3384    0 - 9 in increments of 10 usecs
   3385    0 - 9 in increments of 100 usecs
   3386    1 - 9 in increments of 1 msec
   3387    1 - 9 in increments of 10 msecs
   3388    1 - 9 in increments of 100 msecs
   3389    1 - 9 in increments of 1 sec
   3390    1 - 9 in increments of 10 sec
   3391    > 100 secs
   3392 
   3393    This will allow any time to be recorded to within an accuracy of
   3394    10%, and provides a compact  representation for capturing the
   3395    distribution of a large number of time differences (e.g.
   3396    request-response latencies).
   3397 
   3398    Colin Low  10/6/93
   3399    Rick Jones 2004-06-15 extend to unit and ten usecs
   3400 */
   3401 
   3402 /* #include "sys.h" */
   3403 
   3404 /*#define HIST_TEST*/
   3405 
   3406 HIST
   3407 HIST_new(void){
   3408    HIST h;
   3409    if((h = (HIST) malloc(sizeof(struct histogram_struct))) == NULL) {
   3410      perror("HIST_new - malloc failed");
   3411      exit(1);
   3412    }
   3413    HIST_clear(h);
   3414    return h;
   3415 }
   3416 
   3417 void
   3418 HIST_clear(HIST h){
   3419    int i;
   3420    for(i = 0; i < 10; i++){
   3421       h->unit_usec[i] = 0;
   3422       h->ten_usec[i] = 0;
   3423       h->hundred_usec[i] = 0;
   3424       h->unit_msec[i] = 0;
   3425       h->ten_msec[i] = 0;
   3426       h->hundred_msec[i] = 0;
   3427       h->unit_sec[i] = 0;
   3428       h->ten_sec[i] = 0;
   3429    }
   3430    h->ridiculous = 0;
   3431    h->total = 0;
   3432 }
   3433 
   3434 void
   3435 HIST_add(register HIST h, int time_delta){
   3436    register int val;
   3437    h->total++;
   3438    val = time_delta;
   3439    if(val <= 9) h->unit_usec[val]++;
   3440    else {
   3441      val = val/10;
   3442      if(val <= 9) h->ten_usec[val]++;
   3443      else {
   3444        val = val/10;
   3445        if(val <= 9) h->hundred_usec[val]++;
   3446        else {
   3447 	 val = val/10;
   3448 	 if(val <= 9) h->unit_msec[val]++;
   3449 	 else {
   3450 	   val = val/10;
   3451 	   if(val <= 9) h->ten_msec[val]++;
   3452 	   else {
   3453 	     val = val/10;
   3454 	     if(val <= 9) h->hundred_msec[val]++;
   3455 	     else {
   3456                val = val/10;
   3457                if(val <= 9) h->unit_sec[val]++;
   3458                else {
   3459 		 val = val/10;
   3460 		 if(val <= 9) h->ten_sec[val]++;
   3461 		 else h->ridiculous++;
   3462                }
   3463 	     }
   3464 	   }
   3465 	 }
   3466        }
   3467      }
   3468    }
   3469 }
   3470 
   3471 #define RB_printf printf
   3472 
   3473 void
   3474 output_row(FILE *fd, char *title, int *row){
   3475    register int i;
   3476    RB_printf("%s", title);
   3477    for(i = 0; i < 10; i++) RB_printf(": %4d", row[i]);
   3478    RB_printf("\n");
   3479 }
   3480 
   3481 int
   3482 sum_row(int *row) {
   3483   int sum = 0;
   3484   int i;
   3485   for (i = 0; i < 10; i++) sum += row[i];
   3486   return(sum);
   3487 }
   3488 
   3489 void
   3490 HIST_report(HIST h){
   3491 #ifndef OLD_HISTOGRAM
   3492    output_row(stdout, "UNIT_USEC     ", h->unit_usec);
   3493    output_row(stdout, "TEN_USEC      ", h->ten_usec);
   3494    output_row(stdout, "HUNDRED_USEC  ", h->hundred_usec);
   3495 #else
   3496    h->hundred_usec[0] += sum_row(h->unit_usec);
   3497    h->hundred_usec[0] += sum_row(h->ten_usec);
   3498    output_row(stdout, "TENTH_MSEC    ", h->hundred_usec);
   3499 #endif
   3500    output_row(stdout, "UNIT_MSEC     ", h->unit_msec);
   3501    output_row(stdout, "TEN_MSEC      ", h->ten_msec);
   3502    output_row(stdout, "HUNDRED_MSEC  ", h->hundred_msec);
   3503    output_row(stdout, "UNIT_SEC      ", h->unit_sec);
   3504    output_row(stdout, "TEN_SEC       ", h->ten_sec);
   3505    RB_printf(">100_SECS: %d\n", h->ridiculous);
   3506    RB_printf("HIST_TOTAL:      %d\n", h->total);
   3507 }
   3508 
   3509 #endif
   3510 
   3511 /* with the advent of sit-and-spin intervals support, we might as well
   3512    make these things available all the time, not just for demo or
   3513    histogram modes. raj 2006-02-06 */
   3514 #ifdef HAVE_GETHRTIME
   3515 
   3516 void
   3517 HIST_timestamp(hrtime_t *timestamp)
   3518 {
   3519   *timestamp = gethrtime();
   3520 }
   3521 
   3522 int
   3523 delta_micro(hrtime_t *begin, hrtime_t *end)
   3524 {
   3525   long nsecs;
   3526   nsecs = (*end) - (*begin);
   3527   return(nsecs/1000);
   3528 }
   3529 
   3530 #elif defined(HAVE_GET_HRT)
   3531 #include "hrt.h"
   3532 
   3533 void
   3534 HIST_timestamp(hrt_t *timestamp)
   3535 {
   3536   *timestamp = get_hrt();
   3537 }
   3538 
   3539 int
   3540 delta_micro(hrt_t *begin, hrt_t *end)
   3541 {
   3542 
   3543   return((int)get_hrt_delta(*end,*begin));
   3544 
   3545 }
   3546 #elif defined(WIN32)
   3547 void HIST_timestamp(LARGE_INTEGER *timestamp)
   3548 {
   3549 	QueryPerformanceCounter(timestamp);
   3550 }
   3551 
   3552 int delta_micro(LARGE_INTEGER *begin, LARGE_INTEGER *end)
   3553 {
   3554 	LARGE_INTEGER DeltaTimestamp;
   3555 	static LARGE_INTEGER TickHz = {0,0};
   3556 
   3557 	if (TickHz.QuadPart == 0)
   3558 	{
   3559 		QueryPerformanceFrequency(&TickHz);
   3560 	}
   3561 
   3562 	/*+*+ Rick; this will overflow after ~2000 seconds, is that
   3563 	  good enough? Spencer: Yes, that should be more than good
   3564 	  enough for histogram support */
   3565 
   3566 	DeltaTimestamp.QuadPart = (end->QuadPart - begin->QuadPart) *
   3567 	  1000000/TickHz.QuadPart;
   3568 	assert((DeltaTimestamp.HighPart == 0) &&
   3569 	       ((int)DeltaTimestamp.LowPart >= 0));
   3570 
   3571 	return (int)DeltaTimestamp.LowPart;
   3572 }
   3573 
   3574 #else
   3575 
   3576 void
   3577 HIST_timestamp(struct timeval *timestamp)
   3578 {
   3579   gettimeofday(timestamp,NULL);
   3580 }
   3581 
   3582  /* return the difference (in micro seconds) between two timeval */
   3583  /* timestamps */
   3584 int
   3585 delta_micro(struct timeval *begin,struct timeval *end)
   3586 
   3587 {
   3588 
   3589   int usecs, secs;
   3590 
   3591   if (end->tv_usec < begin->tv_usec) {
   3592     /* borrow a second from the tv_sec */
   3593     end->tv_usec += 1000000;
   3594     end->tv_sec--;
   3595   }
   3596   usecs = end->tv_usec - begin->tv_usec;
   3597   secs  = end->tv_sec - begin->tv_sec;
   3598 
   3599   usecs += (secs * 1000000);
   3600 
   3601   return(usecs);
   3602 
   3603 }
   3604 #endif /* HAVE_GETHRTIME */
   3605 
   3606 
   3607 #ifdef WANT_DLPI
   3609 
   3610 int
   3611 put_control(fd, len, pri, ack)
   3612      int fd, len, pri, ack;
   3613 {
   3614   int error;
   3615   int flags = 0;
   3616   dl_error_ack_t *err_ack = (dl_error_ack_t *)control_data;
   3617 
   3618   control_message.len = len;
   3619 
   3620   if ((error = putmsg(fd, &control_message, 0, pri)) < 0 ) {
   3621     fprintf(where,"put_control: putmsg error %d\n",error);
   3622     fflush(where);
   3623     return(-1);
   3624   }
   3625   if ((error = getmsg(fd, &control_message, 0, &flags)) < 0) {
   3626     fprintf(where,"put_control: getsmg error %d\n",error);
   3627     fflush(where);
   3628     return(-1);
   3629   }
   3630   if (err_ack->dl_primitive != ack) {
   3631     fprintf(where,"put_control: acknowledgement error wanted %u got %u \n",
   3632             ack,err_ack->dl_primitive);
   3633     if (err_ack->dl_primitive == DL_ERROR_ACK) {
   3634       fprintf(where,"             dl_error_primitive: %u\n",
   3635               err_ack->dl_error_primitive);
   3636       fprintf(where,"             dl_errno:           %u\n",
   3637               err_ack->dl_errno);
   3638       fprintf(where,"             dl_unix_errno       %u\n",
   3639               err_ack->dl_unix_errno);
   3640     }
   3641     fflush(where);
   3642     return(-1);
   3643   }
   3644 
   3645   return(0);
   3646 }
   3647 
   3648 int
   3649 dl_open(char devfile[], int ppa)
   3650 {
   3651   int fd;
   3652   dl_attach_req_t *attach_req = (dl_attach_req_t *)control_data;
   3653 
   3654   if ((fd = open(devfile, O_RDWR)) == -1) {
   3655     fprintf(where,"netperf: dl_open: open of %s failed, errno = %d\n",
   3656             devfile,
   3657             errno);
   3658     return(-1);
   3659   }
   3660 
   3661   attach_req->dl_primitive = DL_ATTACH_REQ;
   3662   attach_req->dl_ppa = ppa;
   3663 
   3664   if (put_control(fd, sizeof(dl_attach_req_t), 0, DL_OK_ACK) < 0) {
   3665     fprintf(where,
   3666             "netperf: dl_open: could not send control message, errno = %d\n",
   3667             errno);
   3668     return(-1);
   3669   }
   3670   return(fd);
   3671 }
   3672 
   3673 int
   3674 dl_bind(int fd, int sap, int mode, char *dlsap_ptr, int *dlsap_len)
   3675 {
   3676   dl_bind_req_t *bind_req = (dl_bind_req_t *)control_data;
   3677   dl_bind_ack_t *bind_ack = (dl_bind_ack_t *)control_data;
   3678 
   3679   bind_req->dl_primitive = DL_BIND_REQ;
   3680   bind_req->dl_sap = sap;
   3681   bind_req->dl_max_conind = 1;
   3682   bind_req->dl_service_mode = mode;
   3683   bind_req->dl_conn_mgmt = 0;
   3684   bind_req->dl_xidtest_flg = 0;
   3685 
   3686   if (put_control(fd, sizeof(dl_bind_req_t), 0, DL_BIND_ACK) < 0) {
   3687     fprintf(where,
   3688             "netperf: dl_bind: could not send control message, errno = %d\n",
   3689             errno);
   3690     return(-1);
   3691   }
   3692 
   3693   /* at this point, the control_data portion of the control message */
   3694   /* structure should contain a DL_BIND_ACK, which will have a full */
   3695   /* DLSAP in it. we want to extract this and pass it up so that    */
   3696   /* it can be passed around. */
   3697   if (*dlsap_len >= bind_ack->dl_addr_length) {
   3698     bcopy((char *)bind_ack+bind_ack->dl_addr_offset,
   3699           dlsap_ptr,
   3700           bind_ack->dl_addr_length);
   3701     *dlsap_len = bind_ack->dl_addr_length;
   3702     return(0);
   3703   }
   3704   else {
   3705     return (-1);
   3706   }
   3707 }
   3708 
   3709 int
   3710 dl_connect(int fd, unsigned char *remote_addr, int remote_addr_len)
   3711 {
   3712   dl_connect_req_t *connection_req = (dl_connect_req_t *)control_data;
   3713   dl_connect_con_t *connection_con = (dl_connect_con_t *)control_data;
   3714   struct pollfd pinfo;
   3715 
   3716   int flags = 0;
   3717 
   3718   /* this is here on the off chance that we really want some data */
   3719   u_long data_area[512];
   3720   struct strbuf data_message;
   3721 
   3722   int error;
   3723 
   3724   data_message.maxlen = 2048;
   3725   data_message.len = 0;
   3726   data_message.buf = (char *)data_area;
   3727 
   3728   connection_req->dl_primitive = DL_CONNECT_REQ;
   3729   connection_req->dl_dest_addr_length = remote_addr_len;
   3730   connection_req->dl_dest_addr_offset = sizeof(dl_connect_req_t);
   3731   connection_req->dl_qos_length = 0;
   3732   connection_req->dl_qos_offset = 0;
   3733   bcopy (remote_addr,
   3734          (unsigned char *)control_data + sizeof(dl_connect_req_t),
   3735          remote_addr_len);
   3736 
   3737   /* well, I would call the put_control routine here, but the sequence */
   3738   /* of connection stuff with DLPI is a bit screwey with all this */
   3739   /* message passing - Toto, I don't think were in Berkeley anymore. */
   3740 
   3741   control_message.len = sizeof(dl_connect_req_t) + remote_addr_len;
   3742   if ((error = putmsg(fd,&control_message,0,0)) !=0) {
   3743     fprintf(where,"dl_connect: putmsg failure, errno = %d, error 0x%x \n",
   3744             errno,error);
   3745     fflush(where);
   3746     return(-1);
   3747   };
   3748 
   3749   pinfo.fd = fd;
   3750   pinfo.events = POLLIN | POLLPRI;
   3751   pinfo.revents = 0;
   3752 
   3753   if ((error = getmsg(fd,&control_message,&data_message,&flags)) != 0) {
   3754     fprintf(where,"dl_connect: getmsg failure, errno = %d, error 0x%x \n",
   3755             errno,error);
   3756     fflush(where);
   3757     return(-1);
   3758   }
   3759   while (control_data[0] == DL_TEST_CON) {
   3760     /* i suppose we spin until we get an error, or a connection */
   3761     /* indication */
   3762     if((error = getmsg(fd,&control_message,&data_message,&flags)) !=0) {
   3763        fprintf(where,"dl_connect: getmsg failure, errno = %d, error = 0x%x\n",
   3764                errno,error);
   3765        fflush(where);
   3766        return(-1);
   3767     }
   3768   }
   3769 
   3770   /* we are out - it either worked or it didn't - which was it? */
   3771   if (control_data[0] == DL_CONNECT_CON) {
   3772     return(0);
   3773   }
   3774   else {
   3775     return(-1);
   3776   }
   3777 }
   3778 
   3779 int
   3780 dl_accept(fd, remote_addr, remote_addr_len)
   3781      int fd;
   3782      unsigned char *remote_addr;
   3783      int remote_addr_len;
   3784 {
   3785   dl_connect_ind_t *connect_ind = (dl_connect_ind_t *)control_data;
   3786   dl_connect_res_t *connect_res = (dl_connect_res_t *)control_data;
   3787   int tmp_cor;
   3788   int flags = 0;
   3789 
   3790   /* hang around and wait for a connection request */
   3791   getmsg(fd,&control_message,0,&flags);
   3792   while (control_data[0] != DL_CONNECT_IND) {
   3793     getmsg(fd,&control_message,0,&flags);
   3794   }
   3795 
   3796   /* now respond to the request. at some point, we may want to be sure */
   3797   /* that the connection came from the correct station address, but */
   3798   /* will assume that we do not have to worry about it just now. */
   3799 
   3800   tmp_cor = connect_ind->dl_correlation;
   3801 
   3802   connect_res->dl_primitive = DL_CONNECT_RES;
   3803   connect_res->dl_correlation = tmp_cor;
   3804   connect_res->dl_resp_token = 0;
   3805   connect_res->dl_qos_length = 0;
   3806   connect_res->dl_qos_offset = 0;
   3807   connect_res->dl_growth = 0;
   3808 
   3809   return(put_control(fd, sizeof(dl_connect_res_t), 0, DL_OK_ACK));
   3810 
   3811 }
   3812 
   3813 int
   3814 dl_set_window(fd, window)
   3815      int fd, window;
   3816 {
   3817   return(0);
   3818 }
   3819 
   3820 void
   3821 dl_stats(fd)
   3822      int fd;
   3823 {
   3824 }
   3825 
   3826 int
   3827 dl_send_disc(fd)
   3828      int fd;
   3829 {
   3830 }
   3831 
   3832 int
   3833 dl_recv_disc(fd)
   3834      int fd;
   3835 {
   3836 }
   3837 #endif /* WANT_DLPI*/
   3838 
   3839  /* these routines for confidence intervals are courtesy of IBM. They */
   3840  /* have been modified slightly for more general usage beyond TCP/UDP */
   3841  /* tests. raj 11/94 I would suspect that this code carries an IBM */
   3842  /* copyright that is much the same as that for the original HP */
   3843  /* netperf code */
   3844 int     confidence_iterations; /* for iterations */
   3845 
   3846 double
   3847   result_confid=-10.0,
   3848   loc_cpu_confid=-10.0,
   3849   rem_cpu_confid=-10.0,
   3850 
   3851   measured_sum_result=0.0,
   3852   measured_square_sum_result=0.0,
   3853   measured_mean_result=0.0,
   3854   measured_var_result=0.0,
   3855 
   3856   measured_sum_local_cpu=0.0,
   3857   measured_square_sum_local_cpu=0.0,
   3858   measured_mean_local_cpu=0.0,
   3859   measured_var_local_cpu=0.0,
   3860 
   3861   measured_sum_remote_cpu=0.0,
   3862   measured_square_sum_remote_cpu=0.0,
   3863   measured_mean_remote_cpu=0.0,
   3864   measured_var_remote_cpu=0.0,
   3865 
   3866   measured_sum_local_service_demand=0.0,
   3867   measured_square_sum_local_service_demand=0.0,
   3868   measured_mean_local_service_demand=0.0,
   3869   measured_var_local_service_demand=0.0,
   3870 
   3871   measured_sum_remote_service_demand=0.0,
   3872   measured_square_sum_remote_service_demand=0.0,
   3873   measured_mean_remote_service_demand=0.0,
   3874   measured_var_remote_service_demand=0.0,
   3875 
   3876   measured_sum_local_time=0.0,
   3877   measured_square_sum_local_time=0.0,
   3878   measured_mean_local_time=0.0,
   3879   measured_var_local_time=0.0,
   3880 
   3881   measured_mean_remote_time=0.0,
   3882 
   3883   measured_fails,
   3884   measured_local_results,
   3885   confidence=-10.0;
   3886 /*  interval=0.1; */
   3887 
   3888 /************************************************************************/
   3889 /*                                                                      */
   3890 /*      Constants for Confidence Intervals                              */
   3891 /*                                                                      */
   3892 /************************************************************************/
   3893 void
   3894 init_stat()
   3895 {
   3896         measured_sum_result=0.0;
   3897         measured_square_sum_result=0.0;
   3898         measured_mean_result=0.0;
   3899         measured_var_result=0.0;
   3900 
   3901         measured_sum_local_cpu=0.0;
   3902         measured_square_sum_local_cpu=0.0;
   3903         measured_mean_local_cpu=0.0;
   3904         measured_var_local_cpu=0.0;
   3905 
   3906         measured_sum_remote_cpu=0.0;
   3907         measured_square_sum_remote_cpu=0.0;
   3908         measured_mean_remote_cpu=0.0;
   3909         measured_var_remote_cpu=0.0;
   3910 
   3911         measured_sum_local_service_demand=0.0;
   3912         measured_square_sum_local_service_demand=0.0;
   3913         measured_mean_local_service_demand=0.0;
   3914         measured_var_local_service_demand=0.0;
   3915 
   3916         measured_sum_remote_service_demand=0.0;
   3917         measured_square_sum_remote_service_demand=0.0;
   3918         measured_mean_remote_service_demand=0.0;
   3919         measured_var_remote_service_demand=0.0;
   3920 
   3921         measured_sum_local_time=0.0;
   3922         measured_square_sum_local_time=0.0;
   3923         measured_mean_local_time=0.0;
   3924         measured_var_local_time=0.0;
   3925 
   3926         measured_mean_remote_time=0.0;
   3927 
   3928         measured_fails = 0.0;
   3929         measured_local_results=0.0,
   3930         confidence=-10.0;
   3931 }
   3932 
   3933  /* this routine does a simple table lookup for some statistical */
   3934  /* function that I would remember if I stayed awake in my probstats */
   3935  /* class... raj 11/94 */
   3936 double
   3937 confid(int level, int freedom)
   3938 {
   3939 double  t99[35],t95[35];
   3940 
   3941    t95[1]=12.706;
   3942    t95[2]= 4.303;
   3943    t95[3]= 3.182;
   3944    t95[4]= 2.776;
   3945    t95[5]= 2.571;
   3946    t95[6]= 2.447;
   3947    t95[7]= 2.365;
   3948    t95[8]= 2.306;
   3949    t95[9]= 2.262;
   3950    t95[10]= 2.228;
   3951    t95[11]= 2.201;
   3952    t95[12]= 2.179;
   3953    t95[13]= 2.160;
   3954    t95[14]= 2.145;
   3955    t95[15]= 2.131;
   3956    t95[16]= 2.120;
   3957    t95[17]= 2.110;
   3958    t95[18]= 2.101;
   3959    t95[19]= 2.093;
   3960    t95[20]= 2.086;
   3961    t95[21]= 2.080;
   3962    t95[22]= 2.074;
   3963    t95[23]= 2.069;
   3964    t95[24]= 2.064;
   3965    t95[25]= 2.060;
   3966    t95[26]= 2.056;
   3967    t95[27]= 2.052;
   3968    t95[28]= 2.048;
   3969    t95[29]= 2.045;
   3970    t95[30]= 2.042;
   3971 
   3972    t99[1]=63.657;
   3973    t99[2]= 9.925;
   3974    t99[3]= 5.841;
   3975    t99[4]= 4.604;
   3976    t99[5]= 4.032;
   3977    t99[6]= 3.707;
   3978    t99[7]= 3.499;
   3979    t99[8]= 3.355;
   3980    t99[9]= 3.250;
   3981    t99[10]= 3.169;
   3982    t99[11]= 3.106;
   3983    t99[12]= 3.055;
   3984    t99[13]= 3.012;
   3985    t99[14]= 2.977;
   3986    t99[15]= 2.947;
   3987    t99[16]= 2.921;
   3988    t99[17]= 2.898;
   3989    t99[18]= 2.878;
   3990    t99[19]= 2.861;
   3991    t99[20]= 2.845;
   3992    t99[21]= 2.831;
   3993    t99[22]= 2.819;
   3994    t99[23]= 2.807;
   3995    t99[24]= 2.797;
   3996    t99[25]= 2.787;
   3997    t99[26]= 2.779;
   3998    t99[27]= 2.771;
   3999    t99[28]= 2.763;
   4000    t99[29]= 2.756;
   4001    t99[30]= 2.750;
   4002 
   4003    if(level==95){
   4004         return(t95[freedom]);
   4005    } else if(level==99){
   4006         return(t99[freedom]);
   4007    } else{
   4008         return(0);
   4009    }
   4010 }
   4011 
   4012 void
   4013 calculate_confidence(int confidence_iterations,
   4014                      float time,
   4015                      double result,
   4016                      float loc_cpu,
   4017                      float rem_cpu,
   4018                      float loc_sd,
   4019                      float rem_sd)
   4020 {
   4021 
   4022   if (debug) {
   4023     fprintf(where,
   4024             "calculate_confidence: itr  %d; time %f; res  %f\n",
   4025             confidence_iterations,
   4026             time,
   4027             result);
   4028     fprintf(where,
   4029             "                               lcpu %f; rcpu %f\n",
   4030             loc_cpu,
   4031             rem_cpu);
   4032     fprintf(where,
   4033             "                               lsdm %f; rsdm %f\n",
   4034             loc_sd,
   4035             rem_sd);
   4036     fflush(where);
   4037   }
   4038 
   4039   /* the test time */
   4040   measured_sum_local_time               +=
   4041     (double) time;
   4042   measured_square_sum_local_time        +=
   4043     (double) time*time;
   4044   measured_mean_local_time              =
   4045     (double) measured_sum_local_time/confidence_iterations;
   4046   measured_var_local_time               =
   4047     (double) measured_square_sum_local_time/confidence_iterations
   4048       -measured_mean_local_time*measured_mean_local_time;
   4049 
   4050   /* the test result */
   4051   measured_sum_result           +=
   4052     (double) result;
   4053   measured_square_sum_result    +=
   4054     (double) result*result;
   4055   measured_mean_result          =
   4056     (double) measured_sum_result/confidence_iterations;
   4057   measured_var_result           =
   4058     (double) measured_square_sum_result/confidence_iterations
   4059       -measured_mean_result*measured_mean_result;
   4060 
   4061   /* local cpu utilization */
   4062   measured_sum_local_cpu        +=
   4063     (double) loc_cpu;
   4064   measured_square_sum_local_cpu +=
   4065     (double) loc_cpu*loc_cpu;
   4066   measured_mean_local_cpu       =
   4067     (double) measured_sum_local_cpu/confidence_iterations;
   4068   measured_var_local_cpu        =
   4069     (double) measured_square_sum_local_cpu/confidence_iterations
   4070       -measured_mean_local_cpu*measured_mean_local_cpu;
   4071 
   4072   /* remote cpu util */
   4073   measured_sum_remote_cpu       +=
   4074     (double) rem_cpu;
   4075   measured_square_sum_remote_cpu+=
   4076     (double) rem_cpu*rem_cpu;
   4077   measured_mean_remote_cpu      =
   4078     (double) measured_sum_remote_cpu/confidence_iterations;
   4079   measured_var_remote_cpu       =
   4080     (double) measured_square_sum_remote_cpu/confidence_iterations
   4081       -measured_mean_remote_cpu*measured_mean_remote_cpu;
   4082 
   4083   /* local service demand */
   4084   measured_sum_local_service_demand     +=
   4085     (double) loc_sd;
   4086   measured_square_sum_local_service_demand+=
   4087     (double) loc_sd*loc_sd;
   4088   measured_mean_local_service_demand    =
   4089     (double) measured_sum_local_service_demand/confidence_iterations;
   4090   measured_var_local_service_demand     =
   4091     (double) measured_square_sum_local_service_demand/confidence_iterations
   4092       -measured_mean_local_service_demand*measured_mean_local_service_demand;
   4093 
   4094   /* remote service demand */
   4095   measured_sum_remote_service_demand    +=
   4096     (double) rem_sd;
   4097   measured_square_sum_remote_service_demand+=
   4098     (double) rem_sd*rem_sd;
   4099   measured_mean_remote_service_demand   =
   4100     (double) measured_sum_remote_service_demand/confidence_iterations;
   4101   measured_var_remote_service_demand    =
   4102     (double) measured_square_sum_remote_service_demand/confidence_iterations
   4103       -measured_mean_remote_service_demand*measured_mean_remote_service_demand;
   4104 
   4105   if(confidence_iterations>1){
   4106      result_confid= (double) interval -
   4107        2.0 * confid(confidence_level,confidence_iterations-1)*
   4108          sqrt(measured_var_result/(confidence_iterations-1.0)) /
   4109            measured_mean_result;
   4110 
   4111      loc_cpu_confid= (double) interval -
   4112        2.0 * confid(confidence_level,confidence_iterations-1)*
   4113          sqrt(measured_var_local_cpu/(confidence_iterations-1.0)) /
   4114            measured_mean_local_cpu;
   4115 
   4116      rem_cpu_confid= (double) interval -
   4117        2.0 * confid(confidence_level,confidence_iterations-1)*
   4118          sqrt(measured_var_remote_cpu/(confidence_iterations-1.0)) /
   4119            measured_mean_remote_cpu;
   4120 
   4121      if(debug){
   4122        printf("Conf_itvl %2d: results:%4.1f%% loc_cpu:%4.1f%% rem_cpu:%4.1f%%\n",
   4123               confidence_iterations,
   4124               (interval-result_confid)*100.0,
   4125               (interval-loc_cpu_confid)*100.0,
   4126               (interval-rem_cpu_confid)*100.0);
   4127      }
   4128 
   4129      /* if the user has requested that we only wait for the result to
   4130 	be confident rather than the result and CPU util(s) then do
   4131 	so. raj 2007-08-08 */
   4132      if (!result_confidence_only) {
   4133        confidence = min(min(result_confid,loc_cpu_confid),rem_cpu_confid);
   4134      }
   4135      else {
   4136        confidence = result_confid;
   4137      }
   4138   }
   4139 }
   4140 
   4141  /* here ends the IBM code */
   4142 
   4143 void
   4144 retrieve_confident_values(float *elapsed_time,
   4145                           double *thruput,
   4146                           float *local_cpu_utilization,
   4147                           float *remote_cpu_utilization,
   4148                           float *local_service_demand,
   4149                           float *remote_service_demand)
   4150 
   4151 {
   4152   *elapsed_time            = (float)measured_mean_local_time;
   4153   *thruput                 = measured_mean_result;
   4154   *local_cpu_utilization   = (float)measured_mean_local_cpu;
   4155   *remote_cpu_utilization  = (float)measured_mean_remote_cpu;
   4156   *local_service_demand    = (float)measured_mean_local_service_demand;
   4157   *remote_service_demand   = (float)measured_mean_remote_service_demand;
   4158 }
   4159 
   4160  /* display_confidence() is called when we could not achieve the */
   4161  /* desirec confidence in the results. it will print the achieved */
   4162  /* confidence to "where" raj 11/94 */
   4163 void
   4164 display_confidence()
   4165 
   4166 {
   4167   fprintf(where,
   4168           "!!! WARNING\n");
   4169   fprintf(where,
   4170           "!!! Desired confidence was not achieved within ");
   4171   fprintf(where,
   4172           "the specified iterations.\n");
   4173   fprintf(where,
   4174           "!!! This implies that there was variability in ");
   4175   fprintf(where,
   4176           "the test environment that\n");
   4177   fprintf(where,
   4178           "!!! must be investigated before going further.\n");
   4179   fprintf(where,
   4180           "!!! Confidence intervals: Throughput      : %4.1f%%\n",
   4181           100.0 * (interval - result_confid));
   4182   fprintf(where,
   4183           "!!!                       Local CPU util  : %4.1f%%\n",
   4184           100.0 * (interval - loc_cpu_confid));
   4185   fprintf(where,
   4186           "!!!                       Remote CPU util : %4.1f%%\n\n",
   4187           100.0 * (interval - rem_cpu_confid));
   4188 }
   4189 
   4190