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