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